Files
photo-live/packages/contracts/src/__tests__/ads.test.ts
T

48 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// packages/contracts/src/__tests__/ads.test.ts
// 广告位契约守护:openapi.yaml 中三处硬编码的广告图字节上限(maximum: 2097152)
// 必须与 constants.ts 的 AD_UPLOAD_MAX_BYTES 恒等(1:1 守护,对照 events.test.ts
// 的枚举同步守护)。契约文件无 js-yaml 依赖(pnpm 严格 node_modules),按文件
// 既有的固定缩进块风格做文本切片解析:schema 名 4 空格、属性名 8 空格、
// 属性约束 10 空格——缩进漂移会令定位失败而报错,本身就是守护的一部分。
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { AD_UPLOAD_MAX_BYTES } from '../constants.js';
const openapiYaml = readFileSync(
resolve(__dirname, '../../openapi.yaml'),
'utf8',
);
/** 取 components/schemas 下指定 schema 的文本块(至下一个 4 空格缩进的键)。 */
function schemaBlock(name: string): string {
const start = openapiYaml.indexOf(`\n ${name}:`);
if (start === -1) {
throw new Error(`openapi.yaml 缺少 schema:${name}`);
}
const body = openapiYaml.slice(start + 1);
const next = body.search(/\n [A-Za-z]/);
return next === -1 ? body : body.slice(0, next);
}
/** 取 schema 块内指定属性的 maximum 约束值(属性块内首个 maximum)。 */
function maximumOf(name: string, prop: string): number {
const block = schemaBlock(name);
const match = block.match(
new RegExp(`^ {8}${prop}:\\n(?: {10}[^\\n]+\\n)*? {10}maximum: (\\d+)`, 'm'),
);
if (match === null) {
throw new Error(`${name}.${prop} 缺少 maximum 约束`);
}
return Number(match[1]);
}
describe('openapi 广告图上限 ↔ AD_UPLOAD_MAX_BYTES 同步', () => {
it.each([
['AdCreateRequest', 'imageBytes'],
['AdUpdateRequest', 'imageBytes'],
['AdUploadInitRequest', 'bytes'],
] as const)('%s.%s 的 maximum 恒等于 AD_UPLOAD_MAX_BYTES', (schema, prop) => {
expect(maximumOf(schema, prop)).toBe(AD_UPLOAD_MAX_BYTES);
});
});