// The fragment generator's derivation, checked. // // `scripts/swaggerFragment.js` decides the prefix of every path core will publish // on this module's behalf, and it decides it from `server/index.js`'s own // registration call rather than from a table. That derivation is what these // assert. The generator's OUTPUT — whether those prefixes are the URLs a real // core serves — is `frozenManifest.js`'s question, because answering it needs a // core; here the question is whether the machinery reads the module correctly. const test = require('node:test') const assert = require('node:assert') const { mountedRouters, prefixPaths, TIER_BASE, SLOT_MOUNT } = require('../scripts/swaggerFragment') test('every registered mount is discovered, and resolved to a source file', () => { const mounts = mountedRouters() // Six: five `registerRoutes` prefixes plus the filled extension slot. assert.strictEqual(mounts.length, 6) for (const { file, prefix } of mounts) { assert.match(file, /server[\\/]router[\\/]/, 'a mounted router resolved to a file outside router/') assert.match(prefix, /^\/api\/v1\/(public|admin|player)\//) } }) test('the prefixes come from the registration, not from a list here', () => { // Change `registerRoutes` in server/index.js and this list changes with it — // which is the property being asserted. The manifest declares the same five // prefixes and the loader rejects a mismatch between the two, so this is the // third and last place they could disagree. const byPrefix = mountedRouters().map((m) => m.prefix).sort() assert.deepStrictEqual(byPrefix, [ '/api/v1/admin/shard', '/api/v1/admin/uo-link', '/api/v1/admin/users/:id', '/api/v1/player/shard', '/api/v1/public/atlas', '/api/v1/public/shard', ]) }) test('the tier bases and the slot mount are §2.4\'s, spelled as core mounts them', () => { assert.deepStrictEqual(TIER_BASE, { public: '/api/v1/public', admin: '/api/v1/admin', player: '/api/v1/player', }) assert.deepStrictEqual(SLOT_MOUNT, { 'admin.users.detail': '/api/v1/admin/users/:id' }) }) test('re-rooting converts express params to OpenAPI\'s', () => { const paths = prefixPaths({ paths: { '/shard/link': { get: {} } } }, '/api/v1/admin/users/:id') assert.deepStrictEqual(Object.keys(paths), ['/api/v1/admin/users/{id}/shard/link']) }) test('re-rooting drops the trailing slash a collection route would produce', () => { // `router.get('/')` under a prefix concatenates to `/api/v1/public/shard/`, a // URL no client calls and the manifest does not record. const paths = prefixPaths({ paths: { '/': { get: {} } } }, '/api/v1/public/shard') assert.deepStrictEqual(Object.keys(paths), ['/api/v1/public/shard']) }) test('the prefix\'s own parameters are ordered ahead of the route\'s', () => { // swagger-autogen orders parameters by where they appeared in the path it saw, // and it only ever saw the tail — so without this every slot route would churn // the committed fragment by a reorder that means nothing. const paths = prefixPaths( { paths: { '/shard/link/{account}': { delete: { parameters: [{ name: 'account', in: 'path' }, { name: 'id', in: 'path' }] }, }, }, }, '/api/v1/admin/users/:id', ) const params = paths['/api/v1/admin/users/{id}/shard/link/{account}'].delete.parameters assert.deepStrictEqual(params.map((p) => p.name), ['id', 'account']) }) test('a parameter the prefix does not name keeps its position', () => { const paths = prefixPaths( { paths: { '/thing': { get: { parameters: [{ name: 'limit' }, { name: 'offset' }, { name: 'id' }] } }, }, }, '/api/v1/admin/users/:id', ) const params = paths['/api/v1/admin/users/{id}/thing'].get.parameters assert.deepStrictEqual(params.map((p) => p.name), ['id', 'limit', 'offset']) })