UNPKG

5.65 kBJavaScriptView Raw
1/*
2 * Copyright 2019 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12const assert = require('assert');
13const {
14 root, heading, paragraph, text, link, table, tableRow, tableCell, inlineCode,
15} = require('mdast-builder');
16const unified = require('unified');
17const stringify = require('remark-stringify');
18const gfm = require('remark-gfm');
19const fs = require('fs-extra');
20const { report } = require('../lib/keywords');
21/* eslint-env mocha */
22const expected = [
23 'examples',
24 'allOf',
25 'json-pointer',
26 'relative-json-pointer',
27 'regex',
28 'uri-template',
29 'default',
30];
31
32const allkeywords = {
33 'The JSON Schema Core Vocabulary, https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.8.1': [
34 '$schema',
35 '$vocabulary',
36 '$id',
37 '$anchor',
38 '$ref',
39 '$recursiveRef',
40 '$recursiveAnchor',
41 '$defs',
42 '$comment',
43 ],
44 'A Vocabulary for Applying Subschemas, https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9': [
45 'additionalProperties',
46 'properties',
47 'patternProperties',
48 'unevaluatedProperties',
49 'additionalItems',
50 'items',
51 'unevaluatedItems',
52 'allOf',
53 'anyOf',
54 'oneOf',
55 'not',
56 'if',
57 'then',
58 'else',
59 'dependentSchemas',
60 'contains',
61 'propertyNames',
62 ],
63 'Validation Keywords for Any Instance Type, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.1': [
64 'type',
65 'enum',
66 'const',
67 ],
68 'Validation Keywords for Numeric Instances, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.2': [
69 'multipleOf',
70 'maximum',
71 'exclusiveMaximum',
72 'minimum',
73 'exclusiveMinimum',
74 ],
75 'Validation Keywords for Strings, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.3': [
76 'maxLength',
77 'minLength',
78 'pattern',
79 ],
80 'Validation Keywords for Arrays, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.4': [
81 'maxItems',
82 'minItems',
83 'uniqueItems',
84 'maxContains',
85 'minContains',
86 ],
87 'Validation Keywords for Objects, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6.5': [
88 'maxProperties',
89 'minProperties',
90 'required',
91 'dependentRequired',
92 ],
93 'Defined Formats, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3': [
94 'date-time',
95 'date',
96 'time',
97 'duration',
98 'email',
99 'idn-email',
100 'hostname',
101 'idn-hostname',
102 'ipv4',
103 'ipv6',
104 'uri',
105 'uri-reference',
106 'iri',
107 'iri-reference',
108 'uuid',
109 'uri-template',
110 'json-pointer',
111 'relative-json-pointer',
112 'regex',
113 ],
114 'A Vocabulary for the Contents of String-Encoded Data, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.8': [
115 'contentEncoding',
116 'contentMediaType',
117 'contentSchema',
118 ],
119 'A Vocabulary for Basic Meta-Data Annotations, https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9': [
120 'title',
121 'description',
122 'default',
123 'deprecated',
124 'readOnly',
125 'writeOnly',
126 'examples',
127 ],
128};
129
130after('Generating Schema Coverage Report', () => {
131 const allkeywordsplain = Array.from(new Set(Object
132 .values(allkeywords)
133 .reduce((p, v) => [...p, ...v], [])));
134 const allkeywordssupported = allkeywordsplain
135 .filter((keyword) => report().has(keyword));
136
137 const overall = Math.floor((100 * allkeywordssupported.length) / allkeywordsplain.length);
138
139 const sections = Object.entries(allkeywords).map(([name, keywords]) => {
140 const [label, url] = name.split(', ');
141 const coverage = Math.floor(
142 (100
143 * keywords.filter((keyword) => report().has(keyword)).length)
144 / keywords.length,
145 );
146 return [
147 heading(2, text(label)),
148 paragraph([text('Coverage for '), link(url, '', text(label)), text(` is ${coverage}%.`)]),
149 table('left', [
150 tableRow([
151 tableCell(text('Keyword')),
152 tableCell(text('Supported')),
153 ]),
154 ...keywords.sort().map((keyword) => tableRow([
155 tableCell(inlineCode(keyword)),
156 tableCell(text(report().has(keyword) ? 'Yes' : 'No')),
157 ])),
158 ]),
159 ];
160 }).reduce((p, v) => [...p, ...v], []);
161
162 const mdast = root([
163 heading(1, text('JSON Schema Spec Coverage Report')),
164 paragraph(text(`This report lists the keywords of the JSON Schema spec that are covered in the tests. The overall coverage is ${overall}%`)),
165 ...sections,
166 ]);
167
168 const processor = unified()
169 .use(gfm)
170 .use(stringify);
171
172 const output = processor.stringify(mdast);
173
174 fs.writeFileSync('schemasupport.md', output);
175
176 const lowerlimit = 50;
177 assert.ok(overall > lowerlimit, `Expected minumum spec coverage of ${lowerlimit}%, got only ${overall}%`);
178});
179
180describe('Checking JSON Schema Spec coverage', () => {
181 expected.forEach((keyword) => {
182 it(`keyword ${keyword}`, () => {
183 assert.ok(report().has(keyword), `keyword ${keyword} not used in tests`);
184 });
185 });
186});