import { test, afterEach } from 'node:test' import assert from 'node:assert/strict' import { migrate } from '../src/migrate.mjs' const realFetch = globalThis.fetch afterEach(() => { globalThis.fetch = realFetch }) const reply = (status, body) => new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } }) // A stand-in for the PDS and appview; getSiteConfig answers with `configStatus`. function fakeTangled(configStatus) { const writes = [] globalThis.fetch = async (input, opts = {}) => { const url = String(input) if (url.endsWith('/xrpc/_health')) return reply(200, { version: 'test' }) if (url.includes('plc.directory/')) return reply(200, { service: [{ id: '#atproto_pds', serviceEndpoint: 'https://pds.test' }] }) if (url.includes('createSession')) return reply(200, { did: 'did:plc:me', accessJwt: 'jwt' }) if (url.includes('getServiceAuth')) return reply(200, { token: 'svc' }) if (url.includes('getDomainClaim')) return reply(200, { domain: 'd.tngl.io' }) if (url.includes('listRecords')) return reply(200, { records: [ { uri: 'at://did:plc:me/sh.tangled.repo/site', value: { name: 'site', knot: 'k', repoDid: 'did:plc:r' } }, ], }) if (url.includes('getSiteConfig')) return configStatus === 200 ? reply(200, { config: { branch: 'main', dir: '/' } }) : reply(configStatus, { error: 'x' }) if (url.includes('updateSiteConfig')) { writes.push(JSON.parse(opts.body)) return reply(200, {}) } throw new Error(`unexpected fetch ${url}`) } return writes } const thePlan = { domain: 'd.tngl.io', entries: [{ name: 'site', branch: 'main', dir: '/', isIndex: false }], } const run = async () => (await migrate(thePlan, { handle: 'did:plc:me', password: 'pw', apply: true })).results test('a server error reading the site config skips the repo instead of overwriting', async () => { const writes = fakeTangled(500) const results = await run() assert.equal(results[0].status, 'failed') assert.match(results[0].detail, /could not read the current site config/) assert.deepEqual(writes, []) }) test('an auth failure reading the site config also skips the repo', async () => { const writes = fakeTangled(401) assert.equal((await run())[0].status, 'failed') assert.deepEqual(writes, []) }) test('a 404 means no site yet, so apply deploys', async () => { const writes = fakeTangled(404) assert.equal((await run())[0].status, 'deployed') assert.equal(writes.length, 1) }) test('an existing config is left alone without --force', async () => { const writes = fakeTangled(200) assert.equal((await run())[0].status, 'exists') assert.deepEqual(writes, []) })