diff options
Diffstat (limited to 'bskylink/tests/index.ts')
-rw-r--r-- | bskylink/tests/index.ts | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/bskylink/tests/index.ts b/bskylink/tests/index.ts new file mode 100644 index 000000000..51449c21b --- /dev/null +++ b/bskylink/tests/index.ts @@ -0,0 +1,84 @@ +import assert from 'node:assert' +import {AddressInfo} from 'node:net' +import {after, before, describe, it} from 'node:test' + +import {Database, envToCfg, LinkService, readEnv} from '../src/index.js' + +describe('link service', async () => { + let linkService: LinkService + let baseUrl: string + before(async () => { + const env = readEnv() + const cfg = envToCfg({ + ...env, + hostnames: ['test.bsky.link'], + appHostname: 'test.bsky.app', + dbPostgresSchema: 'link_test', + dbPostgresUrl: process.env.DB_POSTGRES_URL, + }) + const migrateDb = Database.postgres({ + url: cfg.db.url, + schema: cfg.db.schema, + }) + await migrateDb.migrateToLatestOrThrow() + await migrateDb.close() + linkService = await LinkService.create(cfg) + await linkService.start() + const {port} = linkService.server?.address() as AddressInfo + baseUrl = `http://localhost:${port}` + }) + + after(async () => { + await linkService?.destroy() + }) + + it('creates a starter pack link', async () => { + const link = await getLink('/start/did:example:alice/xxx') + const url = new URL(link) + assert.strictEqual(url.origin, 'https://test.bsky.link') + assert.match(url.pathname, /^\/[a-z0-9]+$/i) + }) + + it('normalizes input paths and provides same link each time.', async () => { + const link1 = await getLink('/start/did%3Aexample%3Abob/yyy') + const link2 = await getLink('/start/did:example:bob/yyy/') + assert.strictEqual(link1, link2) + }) + + it('serves permanent redirect, preserving query params.', async () => { + const link = await getLink('/start/did:example:carol/zzz/') + const [status, location] = await getRedirect(`${link}?a=b`) + assert.strictEqual(status, 301) + const locationUrl = new URL(location) + assert.strictEqual( + locationUrl.pathname + locationUrl.search, + '/start/did:example:carol/zzz?a=b', + ) + }) + + async function getRedirect(link: string): Promise<[number, string]> { + const url = new URL(link) + const base = new URL(baseUrl) + url.protocol = base.protocol + url.host = base.host + const res = await fetch(url, {redirect: 'manual'}) + await res.arrayBuffer() // drain + assert( + res.status === 301 || res.status === 303, + 'response was not a redirect', + ) + return [res.status, res.headers.get('location') ?? ''] + } + + async function getLink(path: string): Promise<string> { + const res = await fetch(new URL('/link', baseUrl), { + method: 'post', + headers: {'content-type': 'application/json'}, + body: JSON.stringify({path}), + }) + assert.strictEqual(res.status, 200) + const payload = await res.json() + assert(typeof payload.url === 'string') + return payload.url + } +}) |