Skip to content

Commit 50abcbf

Browse files
committed
Use full schema (schema-base) for tests
1 parent 94f4b26 commit 50abcbf

File tree

3 files changed

+138
-14
lines changed

3 files changed

+138
-14
lines changed

scripts/schema-test-coverage.mjs

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import { readFileSync } from "node:fs";
12
import { readdir, readFile } from "node:fs/promises";
23
import YAML from "yaml";
34
import { join } from "node:path";
45
import { argv } from "node:process";
5-
import { validate } from "@hyperjump/json-schema/draft-2020-12";
6+
import { registerSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
67
import "@hyperjump/json-schema/draft-04";
7-
import { BASIC } from "@hyperjump/json-schema/experimental";
8+
import { BASIC, addKeyword, defineVocabulary } from "@hyperjump/json-schema/experimental";
89

910
/**
1011
* @import { EvaluationPlugin } from "@hyperjump/json-schema/experimental"
@@ -45,7 +46,14 @@ class TestCoveragePlugin {
4546
this.allLocations = [];
4647

4748
for (const schemaLocation in context.ast) {
48-
if (schemaLocation === "metaData") {
49+
if (
50+
schemaLocation === "metaData" ||
51+
// Do not require coverage of standard JSON Schema
52+
schemaLocation.includes("json-schema.org") ||
53+
// Do not require coverage of default $dynamicAnchor
54+
// schemas, as they are not expected to be reached
55+
schemaLocation.endsWith("/schema/WORK-IN-PROGRESS#/$defs/schema")
56+
) {
4957
continue;
5058
}
5159

@@ -110,6 +118,68 @@ const runTests = async (schemaUri, testDirectory) => {
110118
};
111119
};
112120

121+
addKeyword({
122+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/discriminator",
123+
interpret: (discriminator, instance, context) => {
124+
return true;
125+
},
126+
/* discriminator is not exactly an annotation, but it's not allowed
127+
* to change the validation outcome (hence returing true from interopret())
128+
* and for our purposes of testing, this is sufficient.
129+
*/
130+
annotation: (discriminator) => {
131+
return discriminator;
132+
},
133+
});
134+
135+
addKeyword({
136+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/example",
137+
interpret: (example, instance, context) => {
138+
return true;
139+
},
140+
annotation: (example) => {
141+
return example;
142+
},
143+
});
144+
145+
addKeyword({
146+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/externalDocs",
147+
interpret: (externalDocs, instance, context) => {
148+
return true;
149+
},
150+
annotation: (externalDocs) => {
151+
return externalDocs;
152+
},
153+
});
154+
155+
addKeyword({
156+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/xml",
157+
interpret: (xml, instance, context) => {
158+
return true;
159+
},
160+
annotation: (xml) => {
161+
return xml;
162+
},
163+
});
164+
165+
defineVocabulary(
166+
"https://spec.openapis.org/oas/3.2/vocab/base",
167+
{
168+
"discriminator": "https://spec.openapis.org/oas/schema/vocab/keyword/discriminator",
169+
"example": "https://spec.openapis.org/oas/schema/vocab/keyword/example",
170+
"externalDocs": "https://spec.openapis.org/oas/schema/vocab/keyword/externalDocs",
171+
"xml": "https://spec.openapis.org/oas/schema/vocab/keyword/xml",
172+
},
173+
);
174+
175+
const parseYamlFromFile = (filePath) => {
176+
const schemaYaml = readFileSync(filePath, "utf8");
177+
return YAML.parse(schemaYaml, { prettyErrors: true });
178+
};
179+
registerSchema(parseYamlFromFile("./src/schemas/validation/meta.yaml"));
180+
registerSchema(parseYamlFromFile("./src/schemas/validation/dialect.yaml"));
181+
registerSchema(parseYamlFromFile("./src/schemas/validation/schema.yaml"));
182+
113183
///////////////////////////////////////////////////////////////////////////////
114184

115185
const { allLocations, visitedLocations } = await runTests(argv[2], argv[3]);
@@ -122,16 +192,13 @@ if (notCovered.length > 0) {
122192
const firstNotCovered = notCovered.slice(0, maxNotCovered);
123193
if (notCovered.length > maxNotCovered) firstNotCovered.push("...");
124194
console.log(firstNotCovered);
195+
process.exitCode = 1;
125196
}
126197

127198
console.log(
128199
"Covered:",
129-
visitedLocations.size,
200+
(allLocations.length - notCovered.length),
130201
"of",
131202
allLocations.length,
132-
"(" + Math.floor((visitedLocations.size / allLocations.length) * 100) + "%)",
203+
"(" + Math.floor(((allLocations.length - notCovered.length) / allLocations.length) * 100) + "%)",
133204
);
134-
135-
if (visitedLocations.size != allLocations.length) {
136-
process.exitCode = 1;
137-
}

scripts/schema-test-coverage.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ echo
1212
echo "Schema Test Coverage"
1313
echo
1414

15-
node scripts/schema-test-coverage.mjs src/schemas/validation/schema.yaml tests/schema/pass
15+
node scripts/schema-test-coverage.mjs src/schemas/validation/schema-base.yaml tests/schema/pass
1616
rc=$?
1717

1818
[[ "$branch" == "dev" ]] || exit $rc

tests/schema/schema.test.mjs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { readdirSync, readFileSync } from "node:fs";
22
import YAML from "yaml";
3-
import { validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1";
4-
import { BASIC } from "@hyperjump/json-schema/experimental";
3+
import { registerSchema, validate, setMetaSchemaOutputFormat } from "@hyperjump/json-schema/openapi-3-1";
4+
import { BASIC, addKeyword, defineVocabulary } from "@hyperjump/json-schema/experimental";
55
import { describe, test, expect } from "vitest";
66

77
import contentTypeParser from "content-type";
@@ -26,10 +26,67 @@ const parseYamlFromFile = (filePath) => {
2626

2727
setMetaSchemaOutputFormat(BASIC);
2828

29-
const validateOpenApi = await validate("./src/schemas/validation/schema.yaml");
29+
addKeyword({
30+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/discriminator",
31+
interpret: (discriminator, instance, context) => {
32+
return true;
33+
},
34+
/* discriminator is not exactly an annotation, but it's not allowed
35+
* to change the validation outcome (hence returing true from interopret())
36+
* and for our purposes of testing, this is sufficient.
37+
*/
38+
annotation: (discriminator) => {
39+
return discriminator;
40+
},
41+
});
42+
43+
addKeyword({
44+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/example",
45+
interpret: (example, instance, context) => {
46+
return true;
47+
},
48+
annotation: (example) => {
49+
return example;
50+
},
51+
});
52+
53+
addKeyword({
54+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/externalDocs",
55+
interpret: (externalDocs, instance, context) => {
56+
return true;
57+
},
58+
annotation: (externalDocs) => {
59+
return externalDocs;
60+
},
61+
});
62+
63+
addKeyword({
64+
id: "https://spec.openapis.org/oas/schema/vocab/keyword/xml",
65+
interpret: (xml, instance, context) => {
66+
return true;
67+
},
68+
annotation: (xml) => {
69+
return xml;
70+
},
71+
});
72+
73+
defineVocabulary(
74+
"https://spec.openapis.org/oas/3.2/vocab/base",
75+
{
76+
"discriminator": "https://spec.openapis.org/oas/schema/vocab/keyword/discriminator",
77+
"example": "https://spec.openapis.org/oas/schema/vocab/keyword/example",
78+
"externalDocs": "https://spec.openapis.org/oas/schema/vocab/keyword/externalDocs",
79+
"xml": "https://spec.openapis.org/oas/schema/vocab/keyword/xml",
80+
},
81+
);
82+
83+
registerSchema(parseYamlFromFile("./src/schemas/validation/meta.yaml"));
84+
registerSchema(parseYamlFromFile("./src/schemas/validation/dialect.yaml"));
85+
registerSchema(parseYamlFromFile("./src/schemas/validation/schema.yaml"));
86+
const validateOpenApi = await validate("./src/schemas/validation/schema-base.yaml");
3087
const fixtures = './tests/schema';
3188

32-
describe("v3.1", () => {
89+
describe("v3.2", () => {
3390
describe("Pass", () => {
3491
readdirSync(`${fixtures}/pass`, { withFileTypes: true })
3592
.filter((entry) => entry.isFile() && /\.yaml$/.test(entry.name))

0 commit comments

Comments
 (0)