import { test, before, after } from 'node:test' import assert from 'node:assert/strict' import fs from 'node:fs/promises' import os from 'node:os' import path from 'node:path' import { startFakeGitea } from './helpers/fakeGitea.js' import { startFakeAppwrite } from './helpers/fakeAppwrite.js' import { readEnvFile, setupOrganisation } from '../scripts/gitea-organisation-setup.mjs' let gitea let aw let tmp let originalCwd let envPath let backupDir let migrateRepos const now = new Date('2026-09-30T10:00:00Z') before(async () => { gitea = await startFakeGitea({ repos: [ { full_name: 'knso/emmas-schatzkiste' }, { full_name: 'JUSN/D-ner-Nation' }, ], hooks: { 'knso/emmas-schatzkiste': [{ id: 110, url: 'https://project.webklar.com/webhook/gitea', events: ['push'] }], }, contents: { 'knso/emmas-schatzkiste:.webklar-preview.json': JSON.stringify({ enabled: true, type: 'static', branch: 'main', displayName: 'Emmas Schatzkiste', subdomain: 'emmas-schatzkiste', }), }, }) aw = await startFakeAppwrite({ seed: { websiteProjects: [ { $id: 'p1', repoFullName: 'knso/emmas-schatzkiste', projectName: 'Emmas Schatzkiste', projectType: 'website', subdomain: 'emmas-schatzkiste', customerId: '', ticketId: '', }, { $id: 'p2', repoFullName: 'JUSN/D-ner-Nation', projectName: 'D-ner-Nation', projectType: 'preview', subdomain: 'doener-nation', customerId: '', ticketId: '', }, ], }, }) originalCwd = process.cwd() tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'gitea-scripts-')) process.chdir(tmp) envPath = path.join(tmp, '.env') backupDir = path.join(tmp, 'gitea-org') 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: '', }) // server/config.js liest die Umgebung beim Import - erst danach das Migrationsskript laden. ;({ migrateRepos } = await import('../scripts/gitea-organisation-migrate.mjs')) }) after(async () => { process.chdir(originalCwd) await gitea.close() await aw.close() await fs.rm(tmp, { recursive: true, force: true }) }) test('Einrichtung legt Organisation, Mitglieder und Webhook an', async () => { const r = await setupOrganisation({ baseUrl: gitea.baseUrl, token: 't', secret: 's3cret' }) assert.deepEqual(r, { orgCreated: true, membersAdded: ['knso', 'jusn', 'andj'], hookCreated: true }) assert.deepEqual( gitea.calls.find((c) => c.method === 'POST' && c.path === '/api/v1/orgs').body, { username: 'WEBklar', full_name: 'WEBklar', visibility: 'public' } ) assert.deepEqual( gitea.calls.find((c) => c.path === '/api/v1/orgs/WEBklar/hooks' && c.method === 'POST').body, { type: 'gitea', active: true, events: ['push'], branch_filter: '*', config: { url: 'https://project.webklar.com/webhook/gitea', content_type: 'json', secret: 's3cret' }, } ) }) test('Einrichtung ist wiederholbar', async () => { assert.deepEqual( await setupOrganisation({ baseUrl: gitea.baseUrl, token: 't', secret: 's3cret' }), { orgCreated: false, membersAdded: [], hookCreated: false } ) }) test('readEnvFile', async () => { await fs.writeFile(envPath, '# x\nGITEA_SYSTEM_TOKEN="abc"\nGITEA_WEBHOOK_TOKEN=def\n') assert.deepEqual(readEnvFile(envPath), { GITEA_SYSTEM_TOKEN: 'abc', GITEA_WEBHOOK_TOKEN: 'def' }) }) test('Umzug sichert Webhooks und schreibt fehlende Preview-Einstellung', async () => { const r = await migrateRepos({ repoFullNames: ['knso/emmas-schatzkiste', 'JUSN/D-ner-Nation'], backupDir, now }) assert.deepEqual(r.map((x) => [x.to, x.previewConfigWritten]), [ ['WEBklar/emmas-schatzkiste', false], ['WEBklar/D-ner-Nation', true], ]) const [file] = await fs.readdir(backupDir) assert.equal(JSON.parse(await fs.readFile(path.join(backupDir, file), 'utf8'))['knso/emmas-schatzkiste'][0].id, 110) })