From 57cd90c235980dab60990469873849025b648601 Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Thu, 6 Feb 2025 11:03:55 +0100 Subject: [PATCH 1/5] Reduce duplication within each test, separate test for src --- scripts/schema-test-coverage.sh | 5 +- tests/v3.0/schema.test.mjs | 2 +- tests/v3.1/schema.test.mjs | 13 +++-- tests/vNext/fail/invalid_schema_types.yaml | 13 +++++ tests/vNext/fail/no_containers.yaml | 7 +++ tests/vNext/fail/server_enum_empty.yaml | 14 +++++ tests/vNext/fail/servers.yaml | 11 ++++ tests/vNext/fail/unknown_container.yaml | 8 +++ tests/vNext/pass/comp_pathitems.yaml | 6 ++ tests/vNext/pass/info_summary.yaml | 6 ++ tests/vNext/pass/license_identifier.yaml | 9 +++ tests/vNext/pass/mega.yaml | 49 ++++++++++++++++ tests/vNext/pass/minimal_comp.yaml | 5 ++ tests/vNext/pass/minimal_hooks.yaml | 5 ++ tests/vNext/pass/minimal_paths.yaml | 5 ++ tests/vNext/pass/non-oauth-scopes.yaml | 19 +++++++ tests/vNext/pass/path_no_response.yaml | 7 +++ tests/vNext/pass/path_var_empty_pathitem.yaml | 6 ++ tests/vNext/pass/schema.yaml | 55 ++++++++++++++++++ tests/vNext/pass/servers.yaml | 10 ++++ tests/vNext/pass/valid_schema_types.yaml | 14 +++++ tests/vNext/pass/webhook-example.yaml | 35 ++++++++++++ tests/vNext/schema.test.mjs | 56 +++++++++++++++++++ 23 files changed, 352 insertions(+), 8 deletions(-) create mode 100644 tests/vNext/fail/invalid_schema_types.yaml create mode 100644 tests/vNext/fail/no_containers.yaml create mode 100644 tests/vNext/fail/server_enum_empty.yaml create mode 100644 tests/vNext/fail/servers.yaml create mode 100644 tests/vNext/fail/unknown_container.yaml create mode 100644 tests/vNext/pass/comp_pathitems.yaml create mode 100644 tests/vNext/pass/info_summary.yaml create mode 100644 tests/vNext/pass/license_identifier.yaml create mode 100644 tests/vNext/pass/mega.yaml create mode 100644 tests/vNext/pass/minimal_comp.yaml create mode 100644 tests/vNext/pass/minimal_hooks.yaml create mode 100644 tests/vNext/pass/minimal_paths.yaml create mode 100644 tests/vNext/pass/non-oauth-scopes.yaml create mode 100644 tests/vNext/pass/path_no_response.yaml create mode 100644 tests/vNext/pass/path_var_empty_pathitem.yaml create mode 100644 tests/vNext/pass/schema.yaml create mode 100644 tests/vNext/pass/servers.yaml create mode 100644 tests/vNext/pass/valid_schema_types.yaml create mode 100644 tests/vNext/pass/webhook-example.yaml create mode 100644 tests/vNext/schema.test.mjs diff --git a/scripts/schema-test-coverage.sh b/scripts/schema-test-coverage.sh index 0e4ed3883e..34716762a7 100755 --- a/scripts/schema-test-coverage.sh +++ b/scripts/schema-test-coverage.sh @@ -15,4 +15,7 @@ for schemaDir in schemas/v3* ; do node scripts/schema-test-coverage.mjs $schemaDir/schema.yaml tests/$version/pass echo -done \ No newline at end of file +done + +echo vNext +node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/vNext/pass diff --git a/tests/v3.0/schema.test.mjs b/tests/v3.0/schema.test.mjs index edc1bf7c42..2f852669e0 100644 --- a/tests/v3.0/schema.test.mjs +++ b/tests/v3.0/schema.test.mjs @@ -36,7 +36,7 @@ describe("pass", async () => { test(entry.name, () => { const instance = parseYamlFromFile(folder + entry.name); const output = validateOpenApi(instance, BASIC); - expect(output.valid).to.equal(true); + expect(output).to.deep.equal({ valid: true }); }); }); }); diff --git a/tests/v3.1/schema.test.mjs b/tests/v3.1/schema.test.mjs index 17a8b8a18b..d35363bc49 100644 --- a/tests/v3.1/schema.test.mjs +++ b/tests/v3.1/schema.test.mjs @@ -26,27 +26,28 @@ const parseYamlFromFile = (filePath) => { setMetaSchemaOutputFormat(BASIC); -const validateOpenApi = await validate("./src/schemas/validation/schema.yaml"); +const validateOpenApi = await validate("./schemas/v3.1/schema.yaml"); +const folder = './tests/v3.1'; describe("v3.1", () => { describe("Pass", () => { - readdirSync(`./tests/v3.1/pass`, { withFileTypes: true }) + readdirSync(`${folder}/pass`, { withFileTypes: true }) .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) .forEach((entry) => { test(entry.name, () => { - const instance = parseYamlFromFile(`./tests/v3.1/pass/${entry.name}`); + const instance = parseYamlFromFile(`${folder}/pass/${entry.name}`); const output = validateOpenApi(instance, BASIC); - expect(output.valid).to.equal(true); + expect(output).to.deep.equal({ valid: true }); }); }); }); describe("Fail", () => { - readdirSync(`./tests/v3.1/fail`, { withFileTypes: true }) + readdirSync(`${folder}/fail`, { withFileTypes: true }) .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) .forEach((entry) => { test(entry.name, () => { - const instance = parseYamlFromFile(`./tests/v3.1/fail/${entry.name}`); + const instance = parseYamlFromFile(`${folder}/fail/${entry.name}`); const output = validateOpenApi(instance, BASIC); expect(output.valid).to.equal(false); }); diff --git a/tests/vNext/fail/invalid_schema_types.yaml b/tests/vNext/fail/invalid_schema_types.yaml new file mode 100644 index 0000000000..d295b1f0ed --- /dev/null +++ b/tests/vNext/fail/invalid_schema_types.yaml @@ -0,0 +1,13 @@ +openapi: 3.1.1 + +# this example shows invalid types for the schemaObject + +info: + title: API + version: 1.0.0 +components: + schemas: + invalid_null: null + invalid_number: 0 + invalid_array: [] + diff --git a/tests/vNext/fail/no_containers.yaml b/tests/vNext/fail/no_containers.yaml new file mode 100644 index 0000000000..c158bcb2b6 --- /dev/null +++ b/tests/vNext/fail/no_containers.yaml @@ -0,0 +1,7 @@ +openapi: 3.1.0 + +# this example should fail as there are no paths, components or webhooks containers (at least one of which must be present) + +info: + title: API + version: 1.0.0 diff --git a/tests/vNext/fail/server_enum_empty.yaml b/tests/vNext/fail/server_enum_empty.yaml new file mode 100644 index 0000000000..cd6d30eb3e --- /dev/null +++ b/tests/vNext/fail/server_enum_empty.yaml @@ -0,0 +1,14 @@ +openapi: 3.1.0 + +# this example should fail as the server variable enum is empty, and so does not contain the default value + +info: + title: API + version: 1.0.0 +servers: + - url: https://example.com/{var} + variables: + var: + enum: [] + default: a +components: {} diff --git a/tests/vNext/fail/servers.yaml b/tests/vNext/fail/servers.yaml new file mode 100644 index 0000000000..1470fe1ec8 --- /dev/null +++ b/tests/vNext/fail/servers.yaml @@ -0,0 +1,11 @@ +openapi: 3.1.0 + +# this example should fail, as servers must be an array, not an object + +info: + title: API + version: 1.0.0 +paths: {} +servers: + url: /v1 + description: Run locally. diff --git a/tests/vNext/fail/unknown_container.yaml b/tests/vNext/fail/unknown_container.yaml new file mode 100644 index 0000000000..7f31e86053 --- /dev/null +++ b/tests/vNext/fail/unknown_container.yaml @@ -0,0 +1,8 @@ +openapi: 3.1.0 + +# this example should fail as overlays is not a valid top-level object/keyword + +info: + title: API + version: 1.0.0 +overlays: {} diff --git a/tests/vNext/pass/comp_pathitems.yaml b/tests/vNext/pass/comp_pathitems.yaml new file mode 100644 index 0000000000..502ca1fca2 --- /dev/null +++ b/tests/vNext/pass/comp_pathitems.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + pathItems: {} diff --git a/tests/vNext/pass/info_summary.yaml b/tests/vNext/pass/info_summary.yaml new file mode 100644 index 0000000000..30d224afc2 --- /dev/null +++ b/tests/vNext/pass/info_summary.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + summary: My lovely API + version: 1.0.0 +components: {} diff --git a/tests/vNext/pass/license_identifier.yaml b/tests/vNext/pass/license_identifier.yaml new file mode 100644 index 0000000000..fbdba5efbe --- /dev/null +++ b/tests/vNext/pass/license_identifier.yaml @@ -0,0 +1,9 @@ +openapi: 3.1.0 +info: + title: API + summary: My lovely API + version: 1.0.0 + license: + name: Apache + identifier: Apache-2.0 +components: {} diff --git a/tests/vNext/pass/mega.yaml b/tests/vNext/pass/mega.yaml new file mode 100644 index 0000000000..8838c03a6d --- /dev/null +++ b/tests/vNext/pass/mega.yaml @@ -0,0 +1,49 @@ +openapi: 3.1.0 +info: + summary: My API's summary + title: My API + version: 1.0.0 + license: + name: Apache 2.0 + identifier: Apache-2.0 +jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base +paths: + /: + get: + parameters: [] + /{pathTest}: {} +webhooks: + myWebhook: + $ref: '#/components/pathItems/myPathItem' + description: Overriding description +components: + securitySchemes: + mtls: + type: mutualTLS + pathItems: + myPathItem: + post: + requestBody: + required: true + content: + 'application/json': + schema: + type: object + properties: + type: + type: string + int: + type: integer + exclusiveMaximum: 100 + exclusiveMinimum: 0 + none: + type: 'null' + arr: + type: array + $comment: Array without items keyword + either: + type: ['string','null'] + discriminator: + propertyName: type + x-extension: true + myArbitraryKeyword: true diff --git a/tests/vNext/pass/minimal_comp.yaml b/tests/vNext/pass/minimal_comp.yaml new file mode 100644 index 0000000000..4553689ab4 --- /dev/null +++ b/tests/vNext/pass/minimal_comp.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: {} diff --git a/tests/vNext/pass/minimal_hooks.yaml b/tests/vNext/pass/minimal_hooks.yaml new file mode 100644 index 0000000000..e67b2889de --- /dev/null +++ b/tests/vNext/pass/minimal_hooks.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +webhooks: {} diff --git a/tests/vNext/pass/minimal_paths.yaml b/tests/vNext/pass/minimal_paths.yaml new file mode 100644 index 0000000000..016e86796f --- /dev/null +++ b/tests/vNext/pass/minimal_paths.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} diff --git a/tests/vNext/pass/non-oauth-scopes.yaml b/tests/vNext/pass/non-oauth-scopes.yaml new file mode 100644 index 0000000000..e757452f38 --- /dev/null +++ b/tests/vNext/pass/non-oauth-scopes.yaml @@ -0,0 +1,19 @@ +openapi: 3.1.0 +info: + title: Non-oAuth Scopes example + version: 1.0.0 +paths: + /users: + get: + security: + - bearerAuth: + - 'read:users' + - 'public' +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt + description: 'note: non-oauth scopes are not defined at the securityScheme level' + diff --git a/tests/vNext/pass/path_no_response.yaml b/tests/vNext/pass/path_no_response.yaml new file mode 100644 index 0000000000..334608f111 --- /dev/null +++ b/tests/vNext/pass/path_no_response.yaml @@ -0,0 +1,7 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /: + get: {} diff --git a/tests/vNext/pass/path_var_empty_pathitem.yaml b/tests/vNext/pass/path_var_empty_pathitem.yaml new file mode 100644 index 0000000000..ba92742f10 --- /dev/null +++ b/tests/vNext/pass/path_var_empty_pathitem.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /{var}: {} diff --git a/tests/vNext/pass/schema.yaml b/tests/vNext/pass/schema.yaml new file mode 100644 index 0000000000..e192529a68 --- /dev/null +++ b/tests/vNext/pass/schema.yaml @@ -0,0 +1,55 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +components: + schemas: + model: + type: object + properties: + one: + description: type array + type: + - integer + - string + two: + description: type 'null' + type: "null" + three: + description: type array including 'null' + type: + - string + - "null" + four: + description: array with no items + type: array + five: + description: singular example + type: string + examples: + - exampleValue + six: + description: exclusiveMinimum true + exclusiveMinimum: 10 + seven: + description: exclusiveMinimum false + minimum: 10 + eight: + description: exclusiveMaximum true + exclusiveMaximum: 20 + nine: + description: exclusiveMaximum false + maximum: 20 + ten: + description: nullable string + type: + - string + - "null" + eleven: + description: x-nullable string + type: + - string + - "null" + twelve: + description: file/binary diff --git a/tests/vNext/pass/servers.yaml b/tests/vNext/pass/servers.yaml new file mode 100644 index 0000000000..77a20498da --- /dev/null +++ b/tests/vNext/pass/servers.yaml @@ -0,0 +1,10 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +servers: + - url: /v1 + description: Run locally. + - url: https://production.com/v1 + description: Run on production server. diff --git a/tests/vNext/pass/valid_schema_types.yaml b/tests/vNext/pass/valid_schema_types.yaml new file mode 100644 index 0000000000..4431adcda5 --- /dev/null +++ b/tests/vNext/pass/valid_schema_types.yaml @@ -0,0 +1,14 @@ +openapi: 3.1.1 + +# this example shows that top-level schemaObjects MAY be booleans + +info: + title: API + version: 1.0.0 +components: + schemas: + anything_boolean: true + nothing_boolean: false + anything_object: {} + nothing_object: { not: {} } + diff --git a/tests/vNext/pass/webhook-example.yaml b/tests/vNext/pass/webhook-example.yaml new file mode 100644 index 0000000000..2ac1cda985 --- /dev/null +++ b/tests/vNext/pass/webhook-example.yaml @@ -0,0 +1,35 @@ +openapi: 3.1.0 +info: + title: Webhook Example + version: 1.0.0 +# Since OAS 3.1.0 the paths element isn't necessary. Now a valid OpenAPI Document can describe only paths, webhooks, or even only reusable components +webhooks: + # Each webhook needs a name + newPet: + # This is a Path Item Object, the only difference is that the request is initiated by the API provider + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + "200": + description: Return a 200 status to indicate that the data was received successfully + +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + diff --git a/tests/vNext/schema.test.mjs b/tests/vNext/schema.test.mjs new file mode 100644 index 0000000000..1e4bd73680 --- /dev/null +++ b/tests/vNext/schema.test.mjs @@ -0,0 +1,56 @@ +import { readdirSync, readFileSync } from "node:fs"; +import YAML from "yaml"; +import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; +import { BASIC } from "@hyperjump/json-schema/experimental"; +import { describe, test, expect } from "vitest"; + +import contentTypeParser from "content-type"; +import { addMediaTypePlugin } from "@hyperjump/browser"; +import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; + +addMediaTypePlugin("application/schema+yaml", { + parse: async (response) => { + const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); + const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; + + const foo = YAML.parse(await response.text()); + return buildSchemaDocument(foo, response.url, contextDialectId); + }, + fileMatcher: (path) => path.endsWith(".yaml") + }); + +const parseYamlFromFile = (filePath) => { + const schemaYaml = readFileSync(filePath, "utf8"); + return YAML.parse(schemaYaml, { prettyErrors: true }); +}; + +setMetaSchemaOutputFormat(BASIC); + +const validateOpenApi = await validate("./src/schemas/validation/schema.yaml"); +const folder = './tests/vNext'; + +describe("vNext", () => { + describe("Pass", () => { + readdirSync(`${folder}/pass`, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) + .forEach((entry) => { + test(entry.name, () => { + const instance = parseYamlFromFile(`${folder}/pass/${entry.name}`); + const output = validateOpenApi(instance, BASIC); + expect(output).to.deep.equal({ valid: true }); + }); + }); + }); + + describe("Fail", () => { + readdirSync(`${folder}/fail`, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) + .forEach((entry) => { + test(entry.name, () => { + const instance = parseYamlFromFile(`${folder}/fail/${entry.name}`); + const output = validateOpenApi(instance, BASIC); + expect(output.valid).to.equal(false); + }); + }); + }); +}); From 8440252f504fe06c71f942a0f93d3ff7a3b11913 Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Thu, 6 Feb 2025 12:15:29 +0100 Subject: [PATCH 2/5] Common test script for v3.1 and vNext --- scripts/schema-test-coverage.sh | 4 +- tests/schemas/schema.test.mjs | 64 +++++++++++++++++++ .../v3.0/pass/api-with-examples.yaml | 0 .../v3.0/pass/callback-example.yaml | 0 .../{ => schemas}/v3.0/pass/link-example.yaml | 0 .../v3.0/pass/petstore-expanded.yaml | 0 tests/{ => schemas}/v3.0/pass/petstore.yaml | 0 tests/{ => schemas}/v3.0/pass/uspto.yaml | 0 tests/{ => schemas}/v3.0/schema.test.mjs | 2 +- .../v3.1/fail/invalid_schema_types.yaml | 0 .../v3.1/fail/no_containers.yaml | 0 .../v3.1/fail/server_enum_empty.yaml | 0 tests/{ => schemas}/v3.1/fail/servers.yaml | 0 .../v3.1/fail/unknown_container.yaml | 0 .../v3.1/pass/comp_pathitems.yaml | 0 .../{ => schemas}/v3.1/pass/info_summary.yaml | 0 .../v3.1/pass/license_identifier.yaml | 0 tests/{ => schemas}/v3.1/pass/mega.yaml | 0 .../{ => schemas}/v3.1/pass/minimal_comp.yaml | 0 .../v3.1/pass/minimal_hooks.yaml | 0 .../v3.1/pass/minimal_paths.yaml | 0 .../v3.1/pass/non-oauth-scopes.yaml | 0 .../v3.1/pass/path_no_response.yaml | 0 .../v3.1/pass/path_var_empty_pathitem.yaml | 0 tests/{ => schemas}/v3.1/pass/schema.yaml | 0 tests/{ => schemas}/v3.1/pass/servers.yaml | 0 .../v3.1/pass/valid_schema_types.yaml | 0 .../v3.1/pass/webhook-example.yaml | 0 .../vNext/fail/invalid_schema_types.yaml | 0 .../vNext/fail/no_containers.yaml | 0 .../vNext/fail/server_enum_empty.yaml | 0 tests/{ => schemas}/vNext/fail/servers.yaml | 0 .../vNext/fail/unknown_container.yaml | 0 .../vNext/pass/comp_pathitems.yaml | 0 .../vNext/pass/info_summary.yaml | 0 .../vNext/pass/license_identifier.yaml | 0 tests/{ => schemas}/vNext/pass/mega.yaml | 0 .../vNext/pass/minimal_comp.yaml | 0 .../vNext/pass/minimal_hooks.yaml | 0 .../vNext/pass/minimal_paths.yaml | 0 .../vNext/pass/non-oauth-scopes.yaml | 0 .../vNext/pass/path_no_response.yaml | 0 .../vNext/pass/path_var_empty_pathitem.yaml | 0 tests/{ => schemas}/vNext/pass/schema.yaml | 0 tests/{ => schemas}/vNext/pass/servers.yaml | 0 .../vNext/pass/valid_schema_types.yaml | 0 .../vNext/pass/webhook-example.yaml | 0 tests/v3.1/schema.test.mjs | 56 ---------------- tests/vNext/schema.test.mjs | 56 ---------------- 49 files changed, 67 insertions(+), 115 deletions(-) create mode 100644 tests/schemas/schema.test.mjs rename tests/{ => schemas}/v3.0/pass/api-with-examples.yaml (100%) rename tests/{ => schemas}/v3.0/pass/callback-example.yaml (100%) rename tests/{ => schemas}/v3.0/pass/link-example.yaml (100%) rename tests/{ => schemas}/v3.0/pass/petstore-expanded.yaml (100%) rename tests/{ => schemas}/v3.0/pass/petstore.yaml (100%) rename tests/{ => schemas}/v3.0/pass/uspto.yaml (100%) rename tests/{ => schemas}/v3.0/schema.test.mjs (97%) rename tests/{ => schemas}/v3.1/fail/invalid_schema_types.yaml (100%) rename tests/{ => schemas}/v3.1/fail/no_containers.yaml (100%) rename tests/{ => schemas}/v3.1/fail/server_enum_empty.yaml (100%) rename tests/{ => schemas}/v3.1/fail/servers.yaml (100%) rename tests/{ => schemas}/v3.1/fail/unknown_container.yaml (100%) rename tests/{ => schemas}/v3.1/pass/comp_pathitems.yaml (100%) rename tests/{ => schemas}/v3.1/pass/info_summary.yaml (100%) rename tests/{ => schemas}/v3.1/pass/license_identifier.yaml (100%) rename tests/{ => schemas}/v3.1/pass/mega.yaml (100%) rename tests/{ => schemas}/v3.1/pass/minimal_comp.yaml (100%) rename tests/{ => schemas}/v3.1/pass/minimal_hooks.yaml (100%) rename tests/{ => schemas}/v3.1/pass/minimal_paths.yaml (100%) rename tests/{ => schemas}/v3.1/pass/non-oauth-scopes.yaml (100%) rename tests/{ => schemas}/v3.1/pass/path_no_response.yaml (100%) rename tests/{ => schemas}/v3.1/pass/path_var_empty_pathitem.yaml (100%) rename tests/{ => schemas}/v3.1/pass/schema.yaml (100%) rename tests/{ => schemas}/v3.1/pass/servers.yaml (100%) rename tests/{ => schemas}/v3.1/pass/valid_schema_types.yaml (100%) rename tests/{ => schemas}/v3.1/pass/webhook-example.yaml (100%) rename tests/{ => schemas}/vNext/fail/invalid_schema_types.yaml (100%) rename tests/{ => schemas}/vNext/fail/no_containers.yaml (100%) rename tests/{ => schemas}/vNext/fail/server_enum_empty.yaml (100%) rename tests/{ => schemas}/vNext/fail/servers.yaml (100%) rename tests/{ => schemas}/vNext/fail/unknown_container.yaml (100%) rename tests/{ => schemas}/vNext/pass/comp_pathitems.yaml (100%) rename tests/{ => schemas}/vNext/pass/info_summary.yaml (100%) rename tests/{ => schemas}/vNext/pass/license_identifier.yaml (100%) rename tests/{ => schemas}/vNext/pass/mega.yaml (100%) rename tests/{ => schemas}/vNext/pass/minimal_comp.yaml (100%) rename tests/{ => schemas}/vNext/pass/minimal_hooks.yaml (100%) rename tests/{ => schemas}/vNext/pass/minimal_paths.yaml (100%) rename tests/{ => schemas}/vNext/pass/non-oauth-scopes.yaml (100%) rename tests/{ => schemas}/vNext/pass/path_no_response.yaml (100%) rename tests/{ => schemas}/vNext/pass/path_var_empty_pathitem.yaml (100%) rename tests/{ => schemas}/vNext/pass/schema.yaml (100%) rename tests/{ => schemas}/vNext/pass/servers.yaml (100%) rename tests/{ => schemas}/vNext/pass/valid_schema_types.yaml (100%) rename tests/{ => schemas}/vNext/pass/webhook-example.yaml (100%) delete mode 100644 tests/v3.1/schema.test.mjs delete mode 100644 tests/vNext/schema.test.mjs diff --git a/scripts/schema-test-coverage.sh b/scripts/schema-test-coverage.sh index 34716762a7..70e61fc7c2 100755 --- a/scripts/schema-test-coverage.sh +++ b/scripts/schema-test-coverage.sh @@ -12,10 +12,10 @@ for schemaDir in schemas/v3* ; do version=$(basename "$schemaDir") echo $version - node scripts/schema-test-coverage.mjs $schemaDir/schema.yaml tests/$version/pass + node scripts/schema-test-coverage.mjs $schemaDir/schema.yaml tests/schemas/$version/pass echo done echo vNext -node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/vNext/pass +node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/schemas/vNext/pass diff --git a/tests/schemas/schema.test.mjs b/tests/schemas/schema.test.mjs new file mode 100644 index 0000000000..3986749d16 --- /dev/null +++ b/tests/schemas/schema.test.mjs @@ -0,0 +1,64 @@ +import { readdirSync, readFileSync } from "node:fs"; +import YAML from "yaml"; +import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; +import { BASIC } from "@hyperjump/json-schema/experimental"; +import { describe, test, expect } from "vitest"; + +import contentTypeParser from "content-type"; +import { addMediaTypePlugin } from "@hyperjump/browser"; +import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; + +addMediaTypePlugin("application/schema+yaml", { + parse: async (response) => { + const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); + const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; + + const foo = YAML.parse(await response.text()); + return buildSchemaDocument(foo, response.url, contextDialectId); + }, + fileMatcher: (path) => path.endsWith(".yaml") +}); + +const parseYamlFromFile = (filePath) => { + const schemaYaml = readFileSync(filePath, "utf8"); + return YAML.parse(schemaYaml, { prettyErrors: true }); +}; + +setMetaSchemaOutputFormat(BASIC); + +const SCHEMAS = [ + { schema: "./schemas/v3.1/schema.yaml", tests: "./tests/schemas/v3.1" }, + { schema: "./src/schemas/validation/schema.yaml", tests: "./tests/schemas/vNext" } +]; + + +for (const s of SCHEMAS) { + const validateOpenApi = await validate(s.schema); + const folder = s.tests; + + describe(folder, () => { + describe("Pass", () => { + readdirSync(`${folder}/pass`, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) + .forEach((entry) => { + test(entry.name, () => { + const instance = parseYamlFromFile(`${folder}/pass/${entry.name}`); + const output = validateOpenApi(instance, BASIC); + expect(output).to.deep.equal({ valid: true }); + }); + }); + }); + + describe("Fail", () => { + readdirSync(`${folder}/fail`, { withFileTypes: true }) + .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) + .forEach((entry) => { + test(entry.name, () => { + const instance = parseYamlFromFile(`${folder}/fail/${entry.name}`); + const output = validateOpenApi(instance, BASIC); + expect(output.valid).to.equal(false); + }); + }); + }); + }); +} diff --git a/tests/v3.0/pass/api-with-examples.yaml b/tests/schemas/v3.0/pass/api-with-examples.yaml similarity index 100% rename from tests/v3.0/pass/api-with-examples.yaml rename to tests/schemas/v3.0/pass/api-with-examples.yaml diff --git a/tests/v3.0/pass/callback-example.yaml b/tests/schemas/v3.0/pass/callback-example.yaml similarity index 100% rename from tests/v3.0/pass/callback-example.yaml rename to tests/schemas/v3.0/pass/callback-example.yaml diff --git a/tests/v3.0/pass/link-example.yaml b/tests/schemas/v3.0/pass/link-example.yaml similarity index 100% rename from tests/v3.0/pass/link-example.yaml rename to tests/schemas/v3.0/pass/link-example.yaml diff --git a/tests/v3.0/pass/petstore-expanded.yaml b/tests/schemas/v3.0/pass/petstore-expanded.yaml similarity index 100% rename from tests/v3.0/pass/petstore-expanded.yaml rename to tests/schemas/v3.0/pass/petstore-expanded.yaml diff --git a/tests/v3.0/pass/petstore.yaml b/tests/schemas/v3.0/pass/petstore.yaml similarity index 100% rename from tests/v3.0/pass/petstore.yaml rename to tests/schemas/v3.0/pass/petstore.yaml diff --git a/tests/v3.0/pass/uspto.yaml b/tests/schemas/v3.0/pass/uspto.yaml similarity index 100% rename from tests/v3.0/pass/uspto.yaml rename to tests/schemas/v3.0/pass/uspto.yaml diff --git a/tests/v3.0/schema.test.mjs b/tests/schemas/v3.0/schema.test.mjs similarity index 97% rename from tests/v3.0/schema.test.mjs rename to tests/schemas/v3.0/schema.test.mjs index 2f852669e0..40514a56fa 100644 --- a/tests/v3.0/schema.test.mjs +++ b/tests/schemas/v3.0/schema.test.mjs @@ -27,7 +27,7 @@ const parseYamlFromFile = (filePath) => { setMetaSchemaOutputFormat(BASIC); const validateOpenApi = await validate("./schemas/v3.0/schema.yaml"); -const folder = './tests/v3.0/pass/'; +const folder = './tests/schemas/v3.0/pass/'; describe("pass", async () => { readdirSync(folder, { withFileTypes: true }) diff --git a/tests/v3.1/fail/invalid_schema_types.yaml b/tests/schemas/v3.1/fail/invalid_schema_types.yaml similarity index 100% rename from tests/v3.1/fail/invalid_schema_types.yaml rename to tests/schemas/v3.1/fail/invalid_schema_types.yaml diff --git a/tests/v3.1/fail/no_containers.yaml b/tests/schemas/v3.1/fail/no_containers.yaml similarity index 100% rename from tests/v3.1/fail/no_containers.yaml rename to tests/schemas/v3.1/fail/no_containers.yaml diff --git a/tests/v3.1/fail/server_enum_empty.yaml b/tests/schemas/v3.1/fail/server_enum_empty.yaml similarity index 100% rename from tests/v3.1/fail/server_enum_empty.yaml rename to tests/schemas/v3.1/fail/server_enum_empty.yaml diff --git a/tests/v3.1/fail/servers.yaml b/tests/schemas/v3.1/fail/servers.yaml similarity index 100% rename from tests/v3.1/fail/servers.yaml rename to tests/schemas/v3.1/fail/servers.yaml diff --git a/tests/v3.1/fail/unknown_container.yaml b/tests/schemas/v3.1/fail/unknown_container.yaml similarity index 100% rename from tests/v3.1/fail/unknown_container.yaml rename to tests/schemas/v3.1/fail/unknown_container.yaml diff --git a/tests/v3.1/pass/comp_pathitems.yaml b/tests/schemas/v3.1/pass/comp_pathitems.yaml similarity index 100% rename from tests/v3.1/pass/comp_pathitems.yaml rename to tests/schemas/v3.1/pass/comp_pathitems.yaml diff --git a/tests/v3.1/pass/info_summary.yaml b/tests/schemas/v3.1/pass/info_summary.yaml similarity index 100% rename from tests/v3.1/pass/info_summary.yaml rename to tests/schemas/v3.1/pass/info_summary.yaml diff --git a/tests/v3.1/pass/license_identifier.yaml b/tests/schemas/v3.1/pass/license_identifier.yaml similarity index 100% rename from tests/v3.1/pass/license_identifier.yaml rename to tests/schemas/v3.1/pass/license_identifier.yaml diff --git a/tests/v3.1/pass/mega.yaml b/tests/schemas/v3.1/pass/mega.yaml similarity index 100% rename from tests/v3.1/pass/mega.yaml rename to tests/schemas/v3.1/pass/mega.yaml diff --git a/tests/v3.1/pass/minimal_comp.yaml b/tests/schemas/v3.1/pass/minimal_comp.yaml similarity index 100% rename from tests/v3.1/pass/minimal_comp.yaml rename to tests/schemas/v3.1/pass/minimal_comp.yaml diff --git a/tests/v3.1/pass/minimal_hooks.yaml b/tests/schemas/v3.1/pass/minimal_hooks.yaml similarity index 100% rename from tests/v3.1/pass/minimal_hooks.yaml rename to tests/schemas/v3.1/pass/minimal_hooks.yaml diff --git a/tests/v3.1/pass/minimal_paths.yaml b/tests/schemas/v3.1/pass/minimal_paths.yaml similarity index 100% rename from tests/v3.1/pass/minimal_paths.yaml rename to tests/schemas/v3.1/pass/minimal_paths.yaml diff --git a/tests/v3.1/pass/non-oauth-scopes.yaml b/tests/schemas/v3.1/pass/non-oauth-scopes.yaml similarity index 100% rename from tests/v3.1/pass/non-oauth-scopes.yaml rename to tests/schemas/v3.1/pass/non-oauth-scopes.yaml diff --git a/tests/v3.1/pass/path_no_response.yaml b/tests/schemas/v3.1/pass/path_no_response.yaml similarity index 100% rename from tests/v3.1/pass/path_no_response.yaml rename to tests/schemas/v3.1/pass/path_no_response.yaml diff --git a/tests/v3.1/pass/path_var_empty_pathitem.yaml b/tests/schemas/v3.1/pass/path_var_empty_pathitem.yaml similarity index 100% rename from tests/v3.1/pass/path_var_empty_pathitem.yaml rename to tests/schemas/v3.1/pass/path_var_empty_pathitem.yaml diff --git a/tests/v3.1/pass/schema.yaml b/tests/schemas/v3.1/pass/schema.yaml similarity index 100% rename from tests/v3.1/pass/schema.yaml rename to tests/schemas/v3.1/pass/schema.yaml diff --git a/tests/v3.1/pass/servers.yaml b/tests/schemas/v3.1/pass/servers.yaml similarity index 100% rename from tests/v3.1/pass/servers.yaml rename to tests/schemas/v3.1/pass/servers.yaml diff --git a/tests/v3.1/pass/valid_schema_types.yaml b/tests/schemas/v3.1/pass/valid_schema_types.yaml similarity index 100% rename from tests/v3.1/pass/valid_schema_types.yaml rename to tests/schemas/v3.1/pass/valid_schema_types.yaml diff --git a/tests/v3.1/pass/webhook-example.yaml b/tests/schemas/v3.1/pass/webhook-example.yaml similarity index 100% rename from tests/v3.1/pass/webhook-example.yaml rename to tests/schemas/v3.1/pass/webhook-example.yaml diff --git a/tests/vNext/fail/invalid_schema_types.yaml b/tests/schemas/vNext/fail/invalid_schema_types.yaml similarity index 100% rename from tests/vNext/fail/invalid_schema_types.yaml rename to tests/schemas/vNext/fail/invalid_schema_types.yaml diff --git a/tests/vNext/fail/no_containers.yaml b/tests/schemas/vNext/fail/no_containers.yaml similarity index 100% rename from tests/vNext/fail/no_containers.yaml rename to tests/schemas/vNext/fail/no_containers.yaml diff --git a/tests/vNext/fail/server_enum_empty.yaml b/tests/schemas/vNext/fail/server_enum_empty.yaml similarity index 100% rename from tests/vNext/fail/server_enum_empty.yaml rename to tests/schemas/vNext/fail/server_enum_empty.yaml diff --git a/tests/vNext/fail/servers.yaml b/tests/schemas/vNext/fail/servers.yaml similarity index 100% rename from tests/vNext/fail/servers.yaml rename to tests/schemas/vNext/fail/servers.yaml diff --git a/tests/vNext/fail/unknown_container.yaml b/tests/schemas/vNext/fail/unknown_container.yaml similarity index 100% rename from tests/vNext/fail/unknown_container.yaml rename to tests/schemas/vNext/fail/unknown_container.yaml diff --git a/tests/vNext/pass/comp_pathitems.yaml b/tests/schemas/vNext/pass/comp_pathitems.yaml similarity index 100% rename from tests/vNext/pass/comp_pathitems.yaml rename to tests/schemas/vNext/pass/comp_pathitems.yaml diff --git a/tests/vNext/pass/info_summary.yaml b/tests/schemas/vNext/pass/info_summary.yaml similarity index 100% rename from tests/vNext/pass/info_summary.yaml rename to tests/schemas/vNext/pass/info_summary.yaml diff --git a/tests/vNext/pass/license_identifier.yaml b/tests/schemas/vNext/pass/license_identifier.yaml similarity index 100% rename from tests/vNext/pass/license_identifier.yaml rename to tests/schemas/vNext/pass/license_identifier.yaml diff --git a/tests/vNext/pass/mega.yaml b/tests/schemas/vNext/pass/mega.yaml similarity index 100% rename from tests/vNext/pass/mega.yaml rename to tests/schemas/vNext/pass/mega.yaml diff --git a/tests/vNext/pass/minimal_comp.yaml b/tests/schemas/vNext/pass/minimal_comp.yaml similarity index 100% rename from tests/vNext/pass/minimal_comp.yaml rename to tests/schemas/vNext/pass/minimal_comp.yaml diff --git a/tests/vNext/pass/minimal_hooks.yaml b/tests/schemas/vNext/pass/minimal_hooks.yaml similarity index 100% rename from tests/vNext/pass/minimal_hooks.yaml rename to tests/schemas/vNext/pass/minimal_hooks.yaml diff --git a/tests/vNext/pass/minimal_paths.yaml b/tests/schemas/vNext/pass/minimal_paths.yaml similarity index 100% rename from tests/vNext/pass/minimal_paths.yaml rename to tests/schemas/vNext/pass/minimal_paths.yaml diff --git a/tests/vNext/pass/non-oauth-scopes.yaml b/tests/schemas/vNext/pass/non-oauth-scopes.yaml similarity index 100% rename from tests/vNext/pass/non-oauth-scopes.yaml rename to tests/schemas/vNext/pass/non-oauth-scopes.yaml diff --git a/tests/vNext/pass/path_no_response.yaml b/tests/schemas/vNext/pass/path_no_response.yaml similarity index 100% rename from tests/vNext/pass/path_no_response.yaml rename to tests/schemas/vNext/pass/path_no_response.yaml diff --git a/tests/vNext/pass/path_var_empty_pathitem.yaml b/tests/schemas/vNext/pass/path_var_empty_pathitem.yaml similarity index 100% rename from tests/vNext/pass/path_var_empty_pathitem.yaml rename to tests/schemas/vNext/pass/path_var_empty_pathitem.yaml diff --git a/tests/vNext/pass/schema.yaml b/tests/schemas/vNext/pass/schema.yaml similarity index 100% rename from tests/vNext/pass/schema.yaml rename to tests/schemas/vNext/pass/schema.yaml diff --git a/tests/vNext/pass/servers.yaml b/tests/schemas/vNext/pass/servers.yaml similarity index 100% rename from tests/vNext/pass/servers.yaml rename to tests/schemas/vNext/pass/servers.yaml diff --git a/tests/vNext/pass/valid_schema_types.yaml b/tests/schemas/vNext/pass/valid_schema_types.yaml similarity index 100% rename from tests/vNext/pass/valid_schema_types.yaml rename to tests/schemas/vNext/pass/valid_schema_types.yaml diff --git a/tests/vNext/pass/webhook-example.yaml b/tests/schemas/vNext/pass/webhook-example.yaml similarity index 100% rename from tests/vNext/pass/webhook-example.yaml rename to tests/schemas/vNext/pass/webhook-example.yaml diff --git a/tests/v3.1/schema.test.mjs b/tests/v3.1/schema.test.mjs deleted file mode 100644 index d35363bc49..0000000000 --- a/tests/v3.1/schema.test.mjs +++ /dev/null @@ -1,56 +0,0 @@ -import { readdirSync, readFileSync } from "node:fs"; -import YAML from "yaml"; -import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; -import { BASIC } from "@hyperjump/json-schema/experimental"; -import { describe, test, expect } from "vitest"; - -import contentTypeParser from "content-type"; -import { addMediaTypePlugin } from "@hyperjump/browser"; -import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; - -addMediaTypePlugin("application/schema+yaml", { - parse: async (response) => { - const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); - const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; - - const foo = YAML.parse(await response.text()); - return buildSchemaDocument(foo, response.url, contextDialectId); - }, - fileMatcher: (path) => path.endsWith(".yaml") - }); - -const parseYamlFromFile = (filePath) => { - const schemaYaml = readFileSync(filePath, "utf8"); - return YAML.parse(schemaYaml, { prettyErrors: true }); -}; - -setMetaSchemaOutputFormat(BASIC); - -const validateOpenApi = await validate("./schemas/v3.1/schema.yaml"); -const folder = './tests/v3.1'; - -describe("v3.1", () => { - describe("Pass", () => { - readdirSync(`${folder}/pass`, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) - .forEach((entry) => { - test(entry.name, () => { - const instance = parseYamlFromFile(`${folder}/pass/${entry.name}`); - const output = validateOpenApi(instance, BASIC); - expect(output).to.deep.equal({ valid: true }); - }); - }); - }); - - describe("Fail", () => { - readdirSync(`${folder}/fail`, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) - .forEach((entry) => { - test(entry.name, () => { - const instance = parseYamlFromFile(`${folder}/fail/${entry.name}`); - const output = validateOpenApi(instance, BASIC); - expect(output.valid).to.equal(false); - }); - }); - }); -}); diff --git a/tests/vNext/schema.test.mjs b/tests/vNext/schema.test.mjs deleted file mode 100644 index 1e4bd73680..0000000000 --- a/tests/vNext/schema.test.mjs +++ /dev/null @@ -1,56 +0,0 @@ -import { readdirSync, readFileSync } from "node:fs"; -import YAML from "yaml"; -import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; -import { BASIC } from "@hyperjump/json-schema/experimental"; -import { describe, test, expect } from "vitest"; - -import contentTypeParser from "content-type"; -import { addMediaTypePlugin } from "@hyperjump/browser"; -import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; - -addMediaTypePlugin("application/schema+yaml", { - parse: async (response) => { - const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); - const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; - - const foo = YAML.parse(await response.text()); - return buildSchemaDocument(foo, response.url, contextDialectId); - }, - fileMatcher: (path) => path.endsWith(".yaml") - }); - -const parseYamlFromFile = (filePath) => { - const schemaYaml = readFileSync(filePath, "utf8"); - return YAML.parse(schemaYaml, { prettyErrors: true }); -}; - -setMetaSchemaOutputFormat(BASIC); - -const validateOpenApi = await validate("./src/schemas/validation/schema.yaml"); -const folder = './tests/vNext'; - -describe("vNext", () => { - describe("Pass", () => { - readdirSync(`${folder}/pass`, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) - .forEach((entry) => { - test(entry.name, () => { - const instance = parseYamlFromFile(`${folder}/pass/${entry.name}`); - const output = validateOpenApi(instance, BASIC); - expect(output).to.deep.equal({ valid: true }); - }); - }); - }); - - describe("Fail", () => { - readdirSync(`${folder}/fail`, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) - .forEach((entry) => { - test(entry.name, () => { - const instance = parseYamlFromFile(`${folder}/fail/${entry.name}`); - const output = validateOpenApi(instance, BASIC); - expect(output.valid).to.equal(false); - }); - }); - }); -}); From 64dc09a88cfaa582ebc36e1d53c4bb6339aa4240 Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Thu, 6 Feb 2025 12:35:55 +0100 Subject: [PATCH 3/5] one test script for all schema versions --- tests/schemas/schema.test.mjs | 6 ++++- tests/schemas/v3.0/fail/empty.yaml | 1 + tests/schemas/v3.0/schema.test.mjs | 42 ------------------------------ 3 files changed, 6 insertions(+), 43 deletions(-) create mode 100644 tests/schemas/v3.0/fail/empty.yaml delete mode 100644 tests/schemas/v3.0/schema.test.mjs diff --git a/tests/schemas/schema.test.mjs b/tests/schemas/schema.test.mjs index 3986749d16..e172c609e7 100644 --- a/tests/schemas/schema.test.mjs +++ b/tests/schemas/schema.test.mjs @@ -1,12 +1,14 @@ import { readdirSync, readFileSync } from "node:fs"; import YAML from "yaml"; -import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; +import { validate as validate30 } from "@hyperjump/json-schema/openapi-3-0"; +import { validate as validate31, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1"; import { BASIC } from "@hyperjump/json-schema/experimental"; import { describe, test, expect } from "vitest"; import contentTypeParser from "content-type"; import { addMediaTypePlugin } from "@hyperjump/browser"; import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; +import { validate } from "mdv"; addMediaTypePlugin("application/schema+yaml", { parse: async (response) => { @@ -27,12 +29,14 @@ const parseYamlFromFile = (filePath) => { setMetaSchemaOutputFormat(BASIC); const SCHEMAS = [ + { schema: "./schemas/v3.0/schema.yaml", tests: "./tests/schemas/v3.0", validate: validate30 }, { schema: "./schemas/v3.1/schema.yaml", tests: "./tests/schemas/v3.1" }, { schema: "./src/schemas/validation/schema.yaml", tests: "./tests/schemas/vNext" } ]; for (const s of SCHEMAS) { + const validate = s.validate || validate31; const validateOpenApi = await validate(s.schema); const folder = s.tests; diff --git a/tests/schemas/v3.0/fail/empty.yaml b/tests/schemas/v3.0/fail/empty.yaml new file mode 100644 index 0000000000..bcad7ef2c0 --- /dev/null +++ b/tests/schemas/v3.0/fail/empty.yaml @@ -0,0 +1 @@ +# this example doesn't have any of the required fields diff --git a/tests/schemas/v3.0/schema.test.mjs b/tests/schemas/v3.0/schema.test.mjs deleted file mode 100644 index 40514a56fa..0000000000 --- a/tests/schemas/v3.0/schema.test.mjs +++ /dev/null @@ -1,42 +0,0 @@ -import { readdirSync, readFileSync } from "node:fs"; -import YAML from "yaml"; -import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-0"; -import { BASIC } from "@hyperjump/json-schema/experimental"; -import { describe, test, expect } from "vitest"; - -import contentTypeParser from "content-type"; -import { addMediaTypePlugin } from "@hyperjump/browser"; -import { buildSchemaDocument } from "@hyperjump/json-schema/experimental"; - -addMediaTypePlugin("application/schema+yaml", { - parse: async (response) => { - const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? ""); - const contextDialectId = contentType.parameters.schema ?? contentType.parameters.profile; - - const foo = YAML.parse(await response.text()); - return buildSchemaDocument(foo, response.url, contextDialectId); - }, - fileMatcher: (path) => path.endsWith(".yaml") - }); - -const parseYamlFromFile = (filePath) => { - const schemaYaml = readFileSync(filePath, "utf8"); - return YAML.parse(schemaYaml, { prettyErrors: true }); -}; - -setMetaSchemaOutputFormat(BASIC); - -const validateOpenApi = await validate("./schemas/v3.0/schema.yaml"); -const folder = './tests/schemas/v3.0/pass/'; - -describe("pass", async () => { - readdirSync(folder, { withFileTypes: true }) - .filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name)) - .forEach((entry) => { - test(entry.name, () => { - const instance = parseYamlFromFile(folder + entry.name); - const output = validateOpenApi(instance, BASIC); - expect(output).to.deep.equal({ valid: true }); - }); - }); -}); From 0c81771bb73c988114d078100d0d01f5d3d86713 Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Thu, 6 Feb 2025 12:57:46 +0100 Subject: [PATCH 4/5] improved naming --- tests/schemas/schema.test.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/schemas/schema.test.mjs b/tests/schemas/schema.test.mjs index e172c609e7..b60e53be11 100644 --- a/tests/schemas/schema.test.mjs +++ b/tests/schemas/schema.test.mjs @@ -29,16 +29,16 @@ const parseYamlFromFile = (filePath) => { setMetaSchemaOutputFormat(BASIC); const SCHEMAS = [ - { schema: "./schemas/v3.0/schema.yaml", tests: "./tests/schemas/v3.0", validate: validate30 }, - { schema: "./schemas/v3.1/schema.yaml", tests: "./tests/schemas/v3.1" }, - { schema: "./src/schemas/validation/schema.yaml", tests: "./tests/schemas/vNext" } + { schema: "./schemas/v3.0/schema.yaml", fixtures: "./tests/schemas/v3.0", validate: validate30 }, + { schema: "./schemas/v3.1/schema.yaml", fixtures: "./tests/schemas/v3.1" }, + { schema: "./src/schemas/validation/schema.yaml", fixtures: "./tests/schemas/vNext" } ]; for (const s of SCHEMAS) { const validate = s.validate || validate31; const validateOpenApi = await validate(s.schema); - const folder = s.tests; + const folder = s.fixtures; describe(folder, () => { describe("Pass", () => { From 066a9401b73db600ef42d49fc27a151f4d7d3ef2 Mon Sep 17 00:00:00 2001 From: Ralf Handl Date: Fri, 7 Feb 2025 11:15:09 +0100 Subject: [PATCH 5/5] Test fixtures for src schema in dev folder --- scripts/schema-test-coverage.sh | 4 ++-- tests/schemas/{vNext => dev}/fail/invalid_schema_types.yaml | 0 tests/schemas/{vNext => dev}/fail/no_containers.yaml | 0 tests/schemas/{vNext => dev}/fail/server_enum_empty.yaml | 0 tests/schemas/{vNext => dev}/fail/servers.yaml | 0 tests/schemas/{vNext => dev}/fail/unknown_container.yaml | 0 tests/schemas/{vNext => dev}/pass/comp_pathitems.yaml | 0 tests/schemas/{vNext => dev}/pass/info_summary.yaml | 0 tests/schemas/{vNext => dev}/pass/license_identifier.yaml | 0 tests/schemas/{vNext => dev}/pass/mega.yaml | 0 tests/schemas/{vNext => dev}/pass/minimal_comp.yaml | 0 tests/schemas/{vNext => dev}/pass/minimal_hooks.yaml | 0 tests/schemas/{vNext => dev}/pass/minimal_paths.yaml | 0 tests/schemas/{vNext => dev}/pass/non-oauth-scopes.yaml | 0 tests/schemas/{vNext => dev}/pass/path_no_response.yaml | 0 .../schemas/{vNext => dev}/pass/path_var_empty_pathitem.yaml | 0 tests/schemas/{vNext => dev}/pass/schema.yaml | 0 tests/schemas/{vNext => dev}/pass/servers.yaml | 0 tests/schemas/{vNext => dev}/pass/valid_schema_types.yaml | 0 tests/schemas/{vNext => dev}/pass/webhook-example.yaml | 0 tests/schemas/schema.test.mjs | 2 +- 21 files changed, 3 insertions(+), 3 deletions(-) rename tests/schemas/{vNext => dev}/fail/invalid_schema_types.yaml (100%) rename tests/schemas/{vNext => dev}/fail/no_containers.yaml (100%) rename tests/schemas/{vNext => dev}/fail/server_enum_empty.yaml (100%) rename tests/schemas/{vNext => dev}/fail/servers.yaml (100%) rename tests/schemas/{vNext => dev}/fail/unknown_container.yaml (100%) rename tests/schemas/{vNext => dev}/pass/comp_pathitems.yaml (100%) rename tests/schemas/{vNext => dev}/pass/info_summary.yaml (100%) rename tests/schemas/{vNext => dev}/pass/license_identifier.yaml (100%) rename tests/schemas/{vNext => dev}/pass/mega.yaml (100%) rename tests/schemas/{vNext => dev}/pass/minimal_comp.yaml (100%) rename tests/schemas/{vNext => dev}/pass/minimal_hooks.yaml (100%) rename tests/schemas/{vNext => dev}/pass/minimal_paths.yaml (100%) rename tests/schemas/{vNext => dev}/pass/non-oauth-scopes.yaml (100%) rename tests/schemas/{vNext => dev}/pass/path_no_response.yaml (100%) rename tests/schemas/{vNext => dev}/pass/path_var_empty_pathitem.yaml (100%) rename tests/schemas/{vNext => dev}/pass/schema.yaml (100%) rename tests/schemas/{vNext => dev}/pass/servers.yaml (100%) rename tests/schemas/{vNext => dev}/pass/valid_schema_types.yaml (100%) rename tests/schemas/{vNext => dev}/pass/webhook-example.yaml (100%) diff --git a/scripts/schema-test-coverage.sh b/scripts/schema-test-coverage.sh index 70e61fc7c2..8bb5d0ba95 100755 --- a/scripts/schema-test-coverage.sh +++ b/scripts/schema-test-coverage.sh @@ -17,5 +17,5 @@ for schemaDir in schemas/v3* ; do echo done -echo vNext -node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/schemas/vNext/pass +echo src +node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/schemas/dev/pass diff --git a/tests/schemas/vNext/fail/invalid_schema_types.yaml b/tests/schemas/dev/fail/invalid_schema_types.yaml similarity index 100% rename from tests/schemas/vNext/fail/invalid_schema_types.yaml rename to tests/schemas/dev/fail/invalid_schema_types.yaml diff --git a/tests/schemas/vNext/fail/no_containers.yaml b/tests/schemas/dev/fail/no_containers.yaml similarity index 100% rename from tests/schemas/vNext/fail/no_containers.yaml rename to tests/schemas/dev/fail/no_containers.yaml diff --git a/tests/schemas/vNext/fail/server_enum_empty.yaml b/tests/schemas/dev/fail/server_enum_empty.yaml similarity index 100% rename from tests/schemas/vNext/fail/server_enum_empty.yaml rename to tests/schemas/dev/fail/server_enum_empty.yaml diff --git a/tests/schemas/vNext/fail/servers.yaml b/tests/schemas/dev/fail/servers.yaml similarity index 100% rename from tests/schemas/vNext/fail/servers.yaml rename to tests/schemas/dev/fail/servers.yaml diff --git a/tests/schemas/vNext/fail/unknown_container.yaml b/tests/schemas/dev/fail/unknown_container.yaml similarity index 100% rename from tests/schemas/vNext/fail/unknown_container.yaml rename to tests/schemas/dev/fail/unknown_container.yaml diff --git a/tests/schemas/vNext/pass/comp_pathitems.yaml b/tests/schemas/dev/pass/comp_pathitems.yaml similarity index 100% rename from tests/schemas/vNext/pass/comp_pathitems.yaml rename to tests/schemas/dev/pass/comp_pathitems.yaml diff --git a/tests/schemas/vNext/pass/info_summary.yaml b/tests/schemas/dev/pass/info_summary.yaml similarity index 100% rename from tests/schemas/vNext/pass/info_summary.yaml rename to tests/schemas/dev/pass/info_summary.yaml diff --git a/tests/schemas/vNext/pass/license_identifier.yaml b/tests/schemas/dev/pass/license_identifier.yaml similarity index 100% rename from tests/schemas/vNext/pass/license_identifier.yaml rename to tests/schemas/dev/pass/license_identifier.yaml diff --git a/tests/schemas/vNext/pass/mega.yaml b/tests/schemas/dev/pass/mega.yaml similarity index 100% rename from tests/schemas/vNext/pass/mega.yaml rename to tests/schemas/dev/pass/mega.yaml diff --git a/tests/schemas/vNext/pass/minimal_comp.yaml b/tests/schemas/dev/pass/minimal_comp.yaml similarity index 100% rename from tests/schemas/vNext/pass/minimal_comp.yaml rename to tests/schemas/dev/pass/minimal_comp.yaml diff --git a/tests/schemas/vNext/pass/minimal_hooks.yaml b/tests/schemas/dev/pass/minimal_hooks.yaml similarity index 100% rename from tests/schemas/vNext/pass/minimal_hooks.yaml rename to tests/schemas/dev/pass/minimal_hooks.yaml diff --git a/tests/schemas/vNext/pass/minimal_paths.yaml b/tests/schemas/dev/pass/minimal_paths.yaml similarity index 100% rename from tests/schemas/vNext/pass/minimal_paths.yaml rename to tests/schemas/dev/pass/minimal_paths.yaml diff --git a/tests/schemas/vNext/pass/non-oauth-scopes.yaml b/tests/schemas/dev/pass/non-oauth-scopes.yaml similarity index 100% rename from tests/schemas/vNext/pass/non-oauth-scopes.yaml rename to tests/schemas/dev/pass/non-oauth-scopes.yaml diff --git a/tests/schemas/vNext/pass/path_no_response.yaml b/tests/schemas/dev/pass/path_no_response.yaml similarity index 100% rename from tests/schemas/vNext/pass/path_no_response.yaml rename to tests/schemas/dev/pass/path_no_response.yaml diff --git a/tests/schemas/vNext/pass/path_var_empty_pathitem.yaml b/tests/schemas/dev/pass/path_var_empty_pathitem.yaml similarity index 100% rename from tests/schemas/vNext/pass/path_var_empty_pathitem.yaml rename to tests/schemas/dev/pass/path_var_empty_pathitem.yaml diff --git a/tests/schemas/vNext/pass/schema.yaml b/tests/schemas/dev/pass/schema.yaml similarity index 100% rename from tests/schemas/vNext/pass/schema.yaml rename to tests/schemas/dev/pass/schema.yaml diff --git a/tests/schemas/vNext/pass/servers.yaml b/tests/schemas/dev/pass/servers.yaml similarity index 100% rename from tests/schemas/vNext/pass/servers.yaml rename to tests/schemas/dev/pass/servers.yaml diff --git a/tests/schemas/vNext/pass/valid_schema_types.yaml b/tests/schemas/dev/pass/valid_schema_types.yaml similarity index 100% rename from tests/schemas/vNext/pass/valid_schema_types.yaml rename to tests/schemas/dev/pass/valid_schema_types.yaml diff --git a/tests/schemas/vNext/pass/webhook-example.yaml b/tests/schemas/dev/pass/webhook-example.yaml similarity index 100% rename from tests/schemas/vNext/pass/webhook-example.yaml rename to tests/schemas/dev/pass/webhook-example.yaml diff --git a/tests/schemas/schema.test.mjs b/tests/schemas/schema.test.mjs index b60e53be11..bd08f7fa65 100644 --- a/tests/schemas/schema.test.mjs +++ b/tests/schemas/schema.test.mjs @@ -31,7 +31,7 @@ setMetaSchemaOutputFormat(BASIC); const SCHEMAS = [ { schema: "./schemas/v3.0/schema.yaml", fixtures: "./tests/schemas/v3.0", validate: validate30 }, { schema: "./schemas/v3.1/schema.yaml", fixtures: "./tests/schemas/v3.1" }, - { schema: "./src/schemas/validation/schema.yaml", fixtures: "./tests/schemas/vNext" } + { schema: "./src/schemas/validation/schema.yaml", fixtures: "./tests/schemas/dev" } ];