import { test, before, after } from 'node:test' import assert from 'node:assert/strict' import { startFakeGitea } from './helpers/fakeGitea.js' import { startFakeAppwrite } from './helpers/fakeAppwrite.js' let gitea let aw let config let listAllAccessibleRepos let importNewRepos let syncReposToAppwrite let isHostedProject let ensureRepoPreviewConfig before(async () => { gitea = await startFakeGitea({ repos: [ { full_name: 'knso/alt' }, { full_name: 'JUSN/neu', description: 'Döner Nation' }, { full_name: 'JUSN/archiv', archived: true }, { full_name: 'knso/privat', private: true }, { full_name: 'knso/synced-sub' }, { full_name: 'knso/lead' }, ], }) aw = await startFakeAppwrite({ seed: { websiteProjects: [ { repoFullName: 'knso/alt', projectName: 'alt', subdomain: 'alt' }, { repoFullName: 'knso/synced-sub', projectName: 'synced-sub', status: 'synced', subdomain: 'synced-sub' }, { repoFullName: 'knso/lead', projectName: 'lead', status: 'deployed', subdomain: 'lead' }, ], }, }) Object.assign(process.env, { GITEA_BASE_URL: gitea.baseUrl, GITEA_API_TOKEN: 'test-token', APPWRITE_ENDPOINT: aw.endpoint, APPWRITE_API_KEY: 'test-key', PREVIEW_DEPLOY_ROOT: '', TRAEFIK_DYNAMIC_DIR: '', }) // config.js liest die Umgebung beim Import ;({ config } = await import('../server/config.js')) ;({ listAllAccessibleRepos, importNewRepos, syncReposToAppwrite, isHostedProject, ensureRepoPreviewConfig } = await import('../server/services/giteaAdmin.js')) }) after(async () => { await gitea.close() await aw.close() }) test('importNewRepos legt nur fehlende an', async () => { assert.deepEqual(await importNewRepos(), { created: 2 }) const neu = aw.all('websiteProjects').find((d) => d.repoFullName === 'JUSN/neu') assert.deepEqual([neu.projectName, neu.status, neu.subdomain || '', neu.previewUrl || ''], ['Döner Nation', 'synced', '', '']) assert.ok(aw.all('websiteProjects').some((d) => d.repoFullName === 'knso/privat')) assert.ok(!aw.all('websiteProjects').some((d) => d.repoFullName === 'JUSN/archiv')) assert.equal(aw.calls.filter((c) => c.method === 'PATCH').length, 0) }) test('importNewRepos läuft nie doppelt', async () => { gitea.addRepo({ full_name: 'ANDJ/zweimal' }) await Promise.all([importNewRepos(), importNewRepos()]) assert.equal(aw.all('websiteProjects').filter((d) => d.repoFullName === 'ANDJ/zweimal').length, 1) }) test('Abgleich vergibt keine Subdomain mehr', async () => { gitea.addRepo({ full_name: 'ANDJ/sync-neu' }) await syncReposToAppwrite() const d = aw.all('websiteProjects').find((x) => x.repoFullName === 'ANDJ/sync-neu') assert.equal(d.subdomain || '', ''); assert.equal(d.previewUrl || '', '') assert.equal(aw.all('websiteProjects').find((x) => x.repoFullName === 'knso/alt').subdomain, 'alt') }) test('isHostedProject', () => { for (const [doc, want] of [[{ projectType: 'preview' }, true], [{ projectType: 'website' }, true], [{ projectType: 'template' }, true], [{ status: 'deployed' }, true], [{ status: 'pending' }, true], [{ status: 'synced', subdomain: 'x' }, false], [{}, false]]) { assert.equal(isHostedProject(doc), want, JSON.stringify(doc)) } }) test('Selbstheilung nur für gehostete Projekte', async () => { assert.equal(await ensureRepoPreviewConfig('knso/synced-sub', 'main'), null) assert.equal(gitea.calls.filter((c) => c.path.includes('synced-sub/contents')).length, 0) const cfg = await ensureRepoPreviewConfig('knso/lead', 'main') assert.equal(cfg.subdomain, 'lead') assert.ok(gitea.calls.some((c) => c.method === 'POST' && c.path.includes('knso/lead/contents/.webklar-preview.json'))) }) test('Repo-Liste hat eine Obergrenze', async () => { // R8: eigener Fake-Server + kurzzeitig umgebogene config.gitea.baseUrl (statt in `gitea` oben // Tausende Repos zu seeden) - sonst wuerden importNewRepos/syncReposToAppwrite in den Tests // darueber auf einmal Tausende zusaetzliche, unbenannte Repos mitverarbeiten. const capRepos = [] for (let i = 0; i < 2005; i++) capRepos.push({ full_name: `cap/repo${i}` }) const capGitea = await startFakeGitea({ repos: capRepos }) const originalBaseUrl = config.gitea.baseUrl const originalWarn = console.warn console.warn = () => {} config.gitea.baseUrl = capGitea.baseUrl let repos try { repos = await listAllAccessibleRepos() } finally { config.gitea.baseUrl = originalBaseUrl console.warn = originalWarn await capGitea.close() } assert.equal(repos.length, 2000) assert.equal(capGitea.calls.filter((c) => c.path === '/api/v1/repos/search').length, 40) })