fix(investments): align roles and date contracts
Backend security / security (push) Successful in 9s
Backend verify / verify (push) Successful in 10m23s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Successful in 10m39s
Conventional commits / commits (pull_request) Successful in 29s
Backend security / security (push) Successful in 9s
Backend verify / verify (push) Successful in 10m23s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Successful in 10m39s
Conventional commits / commits (pull_request) Successful in 29s
Identify income dependencies by role and document screen-specific dates. Convert inclusive calendar days into half-open source ranges while preserving operation timestamps and existing stored coverage.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
@@ -22,6 +23,109 @@ describe('OpenAPI contract (integration)', () => {
|
||||
|
||||
afterAll(() => app.close());
|
||||
|
||||
it('distinguishes calendar screen dates from operation instants in requests and responses', () => {
|
||||
const document = createOpenApiDocument(app);
|
||||
const schemas = document.components?.schemas;
|
||||
const screenSchema = {
|
||||
oneOf: [
|
||||
{ $ref: '#/components/schemas/IncomeInvestmentScreenDto' },
|
||||
{ $ref: '#/components/schemas/EventsInvestmentScreenDto' },
|
||||
{ $ref: '#/components/schemas/TimestampInvestmentScreenDto' },
|
||||
],
|
||||
discriminator: {
|
||||
propertyName: 'screen',
|
||||
mapping: {
|
||||
income: '#/components/schemas/IncomeInvestmentScreenDto',
|
||||
events: '#/components/schemas/EventsInvestmentScreenDto',
|
||||
operations: '#/components/schemas/TimestampInvestmentScreenDto',
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
document.paths['/api/v1/tbank-sync'].post?.requestBody,
|
||||
).toMatchObject({
|
||||
content: { 'application/json': { schema: screenSchema } },
|
||||
});
|
||||
expect(schemas?.TbankSyncAcceptedDto).toMatchObject({
|
||||
properties: { scope: screenSchema },
|
||||
});
|
||||
expect(schemas?.TbankSyncStatusDto).toMatchObject({
|
||||
properties: { scope: { ...screenSchema, nullable: true } },
|
||||
});
|
||||
for (const [model, screen] of [
|
||||
['IncomeInvestmentScreenDto', 'income'],
|
||||
['EventsInvestmentScreenDto', 'events'],
|
||||
]) {
|
||||
const schema = schemas?.[model];
|
||||
assert(schema && !('$ref' in schema));
|
||||
expect(schema.required).toContain('screen');
|
||||
expect(schema.required).toContain('accountId');
|
||||
expect(schema).toMatchObject({
|
||||
properties: {
|
||||
screen: { enum: [screen] },
|
||||
from: { type: 'string', format: 'date' },
|
||||
to: { type: 'string', format: 'date' },
|
||||
},
|
||||
});
|
||||
}
|
||||
expect(schemas?.TimestampInvestmentScreenDto).toMatchObject({
|
||||
properties: {
|
||||
from: { type: 'string', format: 'date-time' },
|
||||
to: { type: 'string', format: 'date-time' },
|
||||
},
|
||||
});
|
||||
expect(schemas).not.toHaveProperty('InvestmentScreenDto');
|
||||
for (const scope of ['all', '{accountId}']) {
|
||||
for (const [resource, format] of [
|
||||
['income-analytics', 'date'],
|
||||
['events', 'date'],
|
||||
['operations', 'date-time'],
|
||||
]) {
|
||||
const parameters =
|
||||
document.paths[`/api/v1/brokerage-accounts/${scope}/${resource}`].get
|
||||
?.parameters;
|
||||
for (const name of ['from', 'to'])
|
||||
expect(
|
||||
parameters?.find(
|
||||
(parameter) => 'name' in parameter && parameter.name === name,
|
||||
),
|
||||
).toMatchObject({
|
||||
name,
|
||||
in: 'query',
|
||||
schema: { format },
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('exposes required semantic income dependency roles', () => {
|
||||
const schemas = createOpenApiDocument(app).components?.schemas;
|
||||
expect(schemas?.IncomeAnalyticsResourceDto).toMatchObject({
|
||||
properties: {
|
||||
meta: { $ref: '#/components/schemas/IncomeAnalyticsMetaDto' },
|
||||
},
|
||||
});
|
||||
const meta = schemas?.IncomeAnalyticsMetaDto;
|
||||
assert(meta && !('$ref' in meta));
|
||||
expect(meta.required).toContain('dependencies');
|
||||
expect(meta).toMatchObject({
|
||||
properties: {
|
||||
dependencies: {
|
||||
type: 'array',
|
||||
items: { $ref: '#/components/schemas/IncomeDependencyDto' },
|
||||
},
|
||||
},
|
||||
});
|
||||
const dependency = schemas?.IncomeDependencyDto;
|
||||
assert(dependency && !('$ref' in dependency));
|
||||
expect(dependency.required).toContain('role');
|
||||
expect(dependency).toMatchObject({
|
||||
properties: {
|
||||
role: { type: 'string', enum: ['selected', 'previous', 'year'] },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('generates the runtime contract without server startup or deployment configuration', async () => {
|
||||
const directory = await mkdtemp(resolve(tmpdir(), 'wealthledger-openapi-'));
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user