* * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION * DEFGROUP: MokoStandards.Tests.Enterprise * INGROUP: MokoStandards.Tests * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /tests/Enterprise/GitPlatformAdapterTest.php * BRIEF: Tests verifying both adapters implement GitPlatformAdapter correctly */ declare(strict_types=1); require_once __DIR__ . '/../../../vendor/autoload.php'; use MokoEnterprise\ApiClient; use MokoEnterprise\Config; use MokoEnterprise\GitPlatformAdapter; use MokoEnterprise\GitHubAdapter; use MokoEnterprise\MokoGiteaAdapter; use MokoEnterprise\PlatformAdapterFactory; echo "Testing GitPlatformAdapter Interface Compliance\n"; echo str_repeat('=', 60) . "\n\n"; $passed = 0; $failed = 0; function assert_true(bool $condition, string $label): void { global $passed, $failed; if ($condition) { echo " ✓ {$label}\n"; $passed++; } else { echo " ✗ FAILED: {$label}\n"; $failed++; } } // ── Test 1: GitHubAdapter implements GitPlatformAdapter ───────────────── echo "1. Testing GitHubAdapter interface compliance...\n"; $ghClient = new ApiClient( baseUrl: 'https://api.github.com', authToken: 'test-token', enableCaching: false, authScheme: 'Bearer' ); $ghAdapter = new GitHubAdapter($ghClient); assert_true($ghAdapter instanceof GitPlatformAdapter, 'GitHubAdapter implements GitPlatformAdapter'); assert_true($ghAdapter->getPlatformName() === 'github', 'getPlatformName() returns "github"'); assert_true($ghAdapter->getBaseUrl() === 'https://api.github.com', 'getBaseUrl() returns GitHub API URL'); assert_true($ghAdapter->getWorkflowDir() === '.github/workflows', 'getWorkflowDir() returns .github/workflows'); assert_true($ghAdapter->getApiClient() === $ghClient, 'getApiClient() returns injected client'); echo "\n"; // ── Test 2: MokoGiteaAdapter implements GitPlatformAdapter ────────────────── echo "2. Testing MokoGiteaAdapter interface compliance...\n"; $giteaClient = new ApiClient( baseUrl: 'https://git.mokoconsulting.tech/api/v1', authToken: 'test-token', enableCaching: false, authScheme: 'token' ); $giteaAdapter = new MokoGiteaAdapter($giteaClient); assert_true($giteaAdapter instanceof GitPlatformAdapter, 'MokoGiteaAdapter implements GitPlatformAdapter'); assert_true($giteaAdapter->getPlatformName() === 'gitea', 'getPlatformName() returns "gitea"'); assert_true($giteaAdapter->getBaseUrl() === 'https://git.mokoconsulting.tech/api/v1', 'getBaseUrl() returns Gitea API URL'); assert_true($giteaAdapter->getWorkflowDir() === '.mokogitea/workflows', 'getWorkflowDir() returns .gitea/workflows'); assert_true($giteaAdapter->getApiClient() === $giteaClient, 'getApiClient() returns injected client'); echo "\n"; // ── Test 3: All interface methods exist on both adapters ──────────────── echo "3. Testing all interface methods are implemented...\n"; $requiredMethods = [ 'getPlatformName', 'getBaseUrl', 'getWorkflowDir', 'listOrgRepos', 'getRepo', 'createOrgRepo', 'archiveRepo', 'setRepoTopics', 'getRepoTopics', 'getFileContents', 'createOrUpdateFile', 'deleteFile', 'listPullRequests', 'createPullRequest', 'updatePullRequest', 'listIssues', 'createIssue', 'addIssueComment', 'closeIssue', 'listLabels', 'createLabel', 'addIssueLabels', 'setBranchProtection', 'listBranchProtections', 'resolveRef', 'getTree', 'paginateAll', 'migrateRepository', 'getApiClient', ]; foreach ($requiredMethods as $method) { $ghHas = method_exists($ghAdapter, $method); $giteaHas = method_exists($giteaAdapter, $method); if ($ghHas && $giteaHas) { $passed++; } else { echo " ✗ FAILED: {$method} — GitHub=" . ($ghHas ? 'yes' : 'NO') . " Gitea=" . ($giteaHas ? 'yes' : 'NO') . "\n"; $failed++; } } echo " ✓ All " . count($requiredMethods) . " interface methods implemented on both adapters\n\n"; // ── Test 4: PlatformAdapterFactory ────────────────────────────────────── echo "4. Testing PlatformAdapterFactory...\n"; // Test GitHub creation putenv('GH_TOKEN=test-github-token'); putenv('GIT_PLATFORM=github'); $config = Config::load(); $config->set('github.token', 'test-github-token'); try { $adapter = PlatformAdapterFactory::create($config, 'github'); assert_true($adapter instanceof GitHubAdapter, 'Factory creates GitHubAdapter for platform=github'); assert_true($adapter->getPlatformName() === 'github', 'Created adapter identifies as github'); } catch (\Exception $e) { assert_true(false, 'Factory creates GitHubAdapter: ' . $e->getMessage()); } // Test Gitea creation $config->set('gitea.token', 'test-gitea-token'); try { $adapter = PlatformAdapterFactory::create($config, 'gitea'); assert_true($adapter instanceof MokoGiteaAdapter, 'Factory creates MokoGiteaAdapter for platform=gitea'); assert_true($adapter->getPlatformName() === 'gitea', 'Created adapter identifies as gitea'); } catch (\Exception $e) { assert_true(false, 'Factory creates MokoGiteaAdapter: ' . $e->getMessage()); } // Test invalid platform try { PlatformAdapterFactory::create($config, 'bitbucket'); assert_true(false, 'Factory should throw for unsupported platform'); } catch (\RuntimeException $e) { assert_true(str_contains($e->getMessage(), 'Unsupported'), 'Factory throws RuntimeException for unsupported platform'); } echo "\n"; // ── Test 5: Config platform defaults ──────────────────────────────────── echo "5. Testing Config platform configuration...\n"; $config = new Config([ 'platform' => 'github', 'github' => ['organization' => 'mokoconsulting-tech', 'rate_limit' => 5000], 'gitea' => ['url' => 'https://git.mokoconsulting.tech', 'organization' => 'mokoconsulting-tech', 'rate_limit' => 5000], ]); assert_true($config->getString('platform') === 'github', 'Default platform is github'); assert_true($config->getString('gitea.url') === 'https://git.mokoconsulting.tech', 'Gitea URL configured'); assert_true($config->getString('gitea.organization') === 'mokoconsulting-tech', 'Gitea org configured'); assert_true($config->getInt('gitea.rate_limit') === 5000, 'Gitea rate limit configured'); echo "\n"; // ── Test 6: ApiClient auth scheme ─────────────────────────────────────── echo "6. Testing ApiClient auth scheme parameter...\n"; $bearerClient = new ApiClient( baseUrl: 'https://api.github.com', authToken: 'test', enableCaching: false, authScheme: 'Bearer' ); assert_true($bearerClient instanceof ApiClient, 'ApiClient accepts Bearer auth scheme'); $tokenClient = new ApiClient( baseUrl: 'https://git.mokoconsulting.tech/api/v1', authToken: 'test', enableCaching: false, authScheme: 'token' ); assert_true($tokenClient instanceof ApiClient, 'ApiClient accepts token auth scheme'); echo "\n"; // ── Test 7: GitHubAdapter migration throws ────────────────────────────── echo "7. Testing platform-specific behavior...\n"; try { $ghAdapter->migrateRepository([]); assert_true(false, 'GitHubAdapter.migrateRepository() should throw'); } catch (\RuntimeException $e) { assert_true(true, 'GitHubAdapter.migrateRepository() throws RuntimeException'); } // MokoGiteaAdapter.migrateRepository() should NOT throw (it calls the API) // We can't test it without a real server, but verify the method exists assert_true(method_exists($giteaAdapter, 'migrateRepository'), 'MokoGiteaAdapter.migrateRepository() exists'); echo "\n"; // ── Summary ───────────────────────────────────────────────────────────── echo str_repeat('=', 60) . "\n"; echo "Results: {$passed} passed, {$failed} failed\n"; echo str_repeat('=', 60) . "\n"; exit($failed > 0 ? 1 : 0);