feat: generate OpenAPI without peer repositories
Backend security / security (pull_request) Successful in 7s
Backend verify / verify (pull_request) Successful in 2m28s
Conventional commits / commits (pull_request) Successful in 25s
Backend security / security (push) Successful in 6s
Backend verify / verify (push) Successful in 2m16s
Backend security / security (pull_request) Successful in 7s
Backend verify / verify (pull_request) Successful in 2m28s
Conventional commits / commits (pull_request) Successful in 25s
Backend security / security (push) Successful in 6s
Backend verify / verify (push) Successful in 2m16s
This commit was merged in pull request #19.
This commit is contained in:
@@ -1,22 +1,12 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { resolve } from 'node:path';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { configureApp } from '../src/main';
|
||||
|
||||
function canonicalize(value: unknown): unknown {
|
||||
if (Array.isArray(value)) return value.map(canonicalize);
|
||||
if (value && typeof value === 'object') {
|
||||
return Object.fromEntries(
|
||||
Object.entries(value)
|
||||
.sort(([left], [right]) => left.localeCompare(right))
|
||||
.map(([key, nestedValue]) => [key, canonicalize(nestedValue)]),
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
import { createOpenApiDocument } from '../src/openapi';
|
||||
|
||||
describe('OpenAPI contract (integration)', () => {
|
||||
let app: INestApplication;
|
||||
@@ -32,21 +22,38 @@ describe('OpenAPI contract (integration)', () => {
|
||||
|
||||
afterAll(() => app.close());
|
||||
|
||||
it('matches the committed frontend OpenAPI snapshot', async () => {
|
||||
const runtimeDocument = SwaggerModule.createDocument(
|
||||
app,
|
||||
new DocumentBuilder()
|
||||
.setTitle('WealthLedger API')
|
||||
.setVersion('v1')
|
||||
.build(),
|
||||
);
|
||||
const snapshot = JSON.parse(
|
||||
await readFile(
|
||||
resolve(__dirname, '../../frontend/src/shared/api/spec/openapi.json'),
|
||||
'utf8',
|
||||
),
|
||||
) as unknown;
|
||||
|
||||
expect(canonicalize(runtimeDocument)).toEqual(canonicalize(snapshot));
|
||||
it('generates the runtime contract without server startup or deployment configuration', async () => {
|
||||
const directory = await mkdtemp(resolve(tmpdir(), 'wealthledger-openapi-'));
|
||||
try {
|
||||
const networkGuard = resolve(directory, 'no-network.cjs');
|
||||
await writeFile(
|
||||
networkGuard,
|
||||
`
|
||||
const net = require('node:net');
|
||||
const forbidden = () => { throw new Error('Schema generation must not use the network'); };
|
||||
net.Server.prototype.listen = forbidden;
|
||||
net.Socket.prototype.connect = forbidden;
|
||||
`,
|
||||
);
|
||||
execFileSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--require',
|
||||
networkGuard,
|
||||
resolve(__dirname, '../scripts/generate-openapi.cjs'),
|
||||
],
|
||||
{
|
||||
cwd: directory,
|
||||
env: { PATH: process.env.PATH },
|
||||
timeout: 30_000,
|
||||
},
|
||||
);
|
||||
const generated = JSON.parse(
|
||||
await readFile(resolve(directory, 'openapi.json'), 'utf8'),
|
||||
) as unknown;
|
||||
expect(generated).toEqual(createOpenApiDocument(app));
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user