1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01:00
unleash.unleash/src/lib/openapi/meta-schema-rules.test.ts
Gastón Fournier 2c55e929ae
chore: merge one of with properties (#4763)
## About the changes
Open API code generator does not get along with `oneOf` alongside
`properties`:
```shell
$ openapi-generator-cli validate -i modified-openapi.json --recommend
Validating spec (modified-openapi.json)
Warnings: 
        - Schemas defining properties and oneOf are not clearly defined in the OpenAPI
          Specification. While our tooling supports this, it may cause issues with other tools.
```


bab67e44e4/modules/openapi-generator/src/main/java/org/openapitools/codegen/validations/oas/OpenApiSchemaValidations.java (L25-L29)

This PR adds a meta-schema rule to validate this and fixes one issue
2023-09-18 15:43:01 +02:00

139 lines
4.3 KiB
TypeScript

import Ajv, { Schema } from 'ajv';
import { schemas } from '.';
const ajv = new Ajv();
type SchemaNames = keyof typeof schemas;
type Rule = {
name: string;
match?: (
schemaName: string,
schema: typeof schemas[SchemaNames],
) => boolean;
metaSchema: Schema;
knownExceptions?: string[];
};
/**
* These rules are applied to all schemas in the spec.
*
* The rules usually start as a meta schema, which is a schema that describes
* the shape of the OpenAPI schemas. Usually they look like this:
*
* <code>
* const metaSchema: Schema = {
* type: 'object',
* properties: {
* // what we want to specify about the schema
* }
* }
* </code>
*/
const metaRules: Rule[] = [
{
name: 'should have a type',
metaSchema: {
type: 'object',
properties: {
type: { type: 'string', enum: ['object', 'array'] },
},
required: ['type'],
},
knownExceptions: ['dateSchema'],
},
{
name: 'should have an $id with the expected format',
metaSchema: {
type: 'object',
properties: {
$id: {
type: 'string',
pattern: '^#/components/schemas/[a-z][a-zA-Z]+$',
},
},
required: ['$id'],
},
},
{
name: 'should have properties with descriptions',
match: (_, schema) =>
// only match schemas that have a properties field
'properties' in schema,
metaSchema: {
type: 'object',
// properties of the meta schema
properties: {
// the schema should have a field called properties
properties: {
type: 'object', // properties of the schema should be an object
additionalProperties: {
// with the following shape
anyOf: [
{
type: 'object',
properties: {
description: { type: 'string' },
},
required: ['description'],
},
{
type: 'object',
properties: {
$ref: { type: 'string' },
},
required: ['$ref'],
},
],
},
},
},
},
knownExceptions: [],
},
{
name: 'should either have oneOf or properties, instead extract them in commonProps',
match: (_, schema) =>
// only match schemas that have a properties field
'properties' in schema && 'oneOf' in schema,
metaSchema: {
type: 'object',
additionalProperties: false, // this is a shortcut to say: it should fail
},
knownExceptions: [],
},
{
name: 'should have a description',
metaSchema: {
type: 'object',
properties: {
description: { type: 'string' },
},
required: ['description'],
},
knownExceptions: [],
},
];
describe.each(metaRules)('OpenAPI schemas $name', (rule) => {
const validateMetaSchema = ajv.compile(rule.metaSchema);
// test all schemas against the rule
Object.entries(schemas).forEach(([schemaName, schema]) => {
if (!rule.match || rule.match(schemaName, schema)) {
it(`${schemaName}`, () => {
validateMetaSchema(schema);
// note: whenever you resolve an exception please remove it from the list
if (rule.knownExceptions?.includes(schemaName)) {
console.warn(
`${schemaName} is a known exception to rule "${rule.name}" that should be fixed`,
);
expect(validateMetaSchema.errors).not.toBeNull();
} else {
expect(validateMetaSchema.errors).toBeNull();
}
});
}
});
});