Skip to content

Commit f5747f4

Browse files
authored
Merge pull request #121 from bact/add-ajv-test
jsonschema: Add JSON Schema compatibility test
2 parents 53b622f + af787fb commit f5747f4

7 files changed

Lines changed: 191 additions & 3 deletions

File tree

.github/workflows/coverage-generate.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ jobs:
2828
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
2929
with:
3030
python-version: "3.11"
31+
- name: Setup Node
32+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
33+
with:
34+
node-version: 24
3135
- name: Install dependencies
3236
run: |
3337
sudo apt install -y build-essential doxygen graphviz
38+
npm install -g jsonld-cli
39+
npm --prefix scripts ci
3440
- name: Install package
3541
run: |
3642
pip install -e .[dev]

.github/workflows/test.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ jobs:
3939
python -m pip install --upgrade pip
4040
pip install build
4141
npm install -g jsonld-cli
42+
npm --prefix scripts ci
4243
- name: Install Linux packages
4344
if: runner.os == 'Linux'
4445
run: |

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Node
2+
node_modules/
3+
14
# Byte-compiled / optimized / DLL files
25
__pycache__/
36
*.py[cod]

scripts/ajv-compile.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env node
2+
// SPDX-FileContributor: Arthit Suriyawongkul
3+
// SPDX-FileCopyrightText: 2026 Joshua Watt
4+
// SPDX-FileType: SOURCE
5+
// SPDX-License-Identifier: MIT
6+
//
7+
// Validate a JSON Schema file against its meta-schema using ajv v8.
8+
// Usage: ajv-compile.js <schema.json> [draft-version]
9+
// draft-version: 2020-12 or 2019-09 (default: inferred from "$schema")
10+
const fs = require("fs");
11+
12+
const schemaFile = process.argv[2];
13+
const draftArg = process.argv[3];
14+
15+
if (!schemaFile) {
16+
console.error("Usage: ajv-compile.js <schema.json> [draft-version]");
17+
process.exit(2);
18+
}
19+
20+
const draftMap = {
21+
"2020-12": "ajv/dist/2020",
22+
"2019-09": "ajv/dist/2019",
23+
};
24+
25+
const schemaUriMap = {
26+
"https://json-schema.org/draft/2020-12/schema": "2020-12",
27+
"http://json-schema.org/draft/2020-12/schema": "2020-12",
28+
"https://json-schema.org/draft/2019-09/schema": "2019-09",
29+
"http://json-schema.org/draft/2019-09/schema": "2019-09",
30+
};
31+
32+
let schema;
33+
try {
34+
schema = JSON.parse(fs.readFileSync(schemaFile, "utf8"));
35+
} catch (e) {
36+
console.error(`Failed to read/parse "${schemaFile}": ${e.message}`);
37+
process.exit(2);
38+
}
39+
40+
let draft = draftArg;
41+
if (!draft) {
42+
draft = schemaUriMap[schema.$schema?.replace(/#$/, "")];
43+
if (!draft) {
44+
console.error(
45+
`Unable to infer draft version from "$schema": ${schema.$schema}. ` +
46+
"Pass the draft version explicitly as the second argument.",
47+
);
48+
process.exit(2);
49+
}
50+
}
51+
52+
const ajvModule = draftMap[draft];
53+
if (!ajvModule) {
54+
console.error(`Unsupported draft version: ${draft}. Supported: ${Object.keys(draftMap).join(", ")}`);
55+
process.exit(2);
56+
}
57+
58+
let Ajv;
59+
try {
60+
Ajv = require(ajvModule);
61+
} catch (e) {
62+
console.error(
63+
`Failed to load "${ajvModule}": ${e.message}\n` +
64+
'Run "npm --prefix scripts install" to install dependencies.',
65+
);
66+
process.exit(2);
67+
}
68+
69+
const ajv = new Ajv();
70+
try {
71+
ajv.compile(schema);
72+
console.log("schema is valid");
73+
} catch (e) {
74+
console.error("schema is invalid:", e.message);
75+
process.exit(1);
76+
}

scripts/package-lock.json

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "shacl2code-scripts",
3+
"private": true,
4+
"description": "Node dependencies for shacl2code test/build scripts",
5+
"dependencies": {
6+
"ajv": "8.20.0"
7+
}
8+
}

tests/test_jsonschema.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#
2-
# Copyright (c) 2024 Joshua Watt
3-
#
1+
# SPDX-FileContributor: Arthit Suriyawongkul
2+
# SPDX-FileContributor: Joshua Watt
3+
# SPDX-FileCopyrightText: 2024 Joshua Watt
4+
# SPDX-FileType: SOURCE
45
# SPDX-License-Identifier: MIT
56

67
import json
@@ -56,6 +57,33 @@ def test_output_syntax(self, args):
5657

5758
json.loads(p.stdout)
5859

60+
def test_ajv_compile(self, tmp_path, args):
61+
"""
62+
Validates the generated schema against the JSON Schema meta-schema using ajv
63+
"""
64+
schema_file = tmp_path / "schema.json"
65+
subprocess.run(
66+
[
67+
"shacl2code",
68+
"generate",
69+
]
70+
+ args
71+
+ [
72+
"jsonschema",
73+
"--output",
74+
schema_file,
75+
],
76+
check=True,
77+
)
78+
subprocess.run(
79+
[
80+
"node",
81+
THIS_DIR.parent / "scripts" / "ajv-compile.js",
82+
str(schema_file),
83+
],
84+
check=True,
85+
)
86+
5987
def test_trailing_whitespace(self, args):
6088
"""
6189
Tests that the generated file does not have trailing whitespace

0 commit comments

Comments
 (0)