docusaurus-plugin-generate-schema-docs 1.8.4 → 1.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +10 -0
  2. package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof-multi.json +12 -0
  3. package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof.json +30 -0
  4. package/__tests__/__fixtures__/validateSchemas/schema-with-not-edge-cases.json +24 -0
  5. package/__tests__/__fixtures__/validateSchemas/schema-with-not-non-object.json +15 -0
  6. package/__tests__/generateEventDocs.anchor.test.js +1 -1
  7. package/__tests__/generateEventDocs.nested.test.js +1 -1
  8. package/__tests__/generateEventDocs.partials.test.js +1 -1
  9. package/__tests__/generateEventDocs.test.js +506 -1
  10. package/__tests__/generateEventDocs.versioned.test.js +1 -1
  11. package/__tests__/helpers/buildExampleFromSchema.test.js +240 -0
  12. package/__tests__/helpers/constraintSchemaPaths.test.js +208 -0
  13. package/__tests__/helpers/continuingLinesStyle.test.js +492 -0
  14. package/__tests__/helpers/exampleModel.test.js +209 -0
  15. package/__tests__/helpers/file-system.test.js +73 -1
  16. package/__tests__/helpers/getConstraints.test.js +27 -0
  17. package/__tests__/helpers/mergeSchema.test.js +94 -0
  18. package/__tests__/helpers/processSchema.test.js +291 -1
  19. package/__tests__/helpers/schema-doc-template.test.js +54 -0
  20. package/__tests__/helpers/schema-processing.test.js +122 -2
  21. package/__tests__/helpers/schemaToExamples.test.js +1007 -0
  22. package/__tests__/helpers/schemaToTableData.mutations.test.js +970 -0
  23. package/__tests__/helpers/schemaToTableData.test.js +157 -0
  24. package/__tests__/helpers/snippetTargets.test.js +432 -0
  25. package/__tests__/helpers/trackingTargets.test.js +319 -0
  26. package/__tests__/helpers/validator.test.js +385 -1
  27. package/__tests__/index.test.js +436 -0
  28. package/__tests__/syncGtm.test.js +139 -3
  29. package/__tests__/update-schema-ids.test.js +70 -1
  30. package/__tests__/validateSchemas-integration.test.js +2 -2
  31. package/__tests__/validateSchemas.test.js +142 -1
  32. package/generateEventDocs.js +21 -1
  33. package/helpers/constraintSchemaPaths.js +10 -14
  34. package/helpers/schemaToTableData.js +538 -492
  35. package/helpers/trackingTargets.js +26 -3
  36. package/helpers/validator.js +18 -4
  37. package/index.js +1 -2
  38. package/package.json +1 -1
  39. package/scripts/sync-gtm.js +25 -7
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @jest-environment node
2
+ * @jest-environment @stryker-mutator/jest-runner/jest-env/node
3
3
  */
4
4
 
5
5
  import fs from 'fs';
@@ -21,6 +21,75 @@ describe('updateSchemaIds', () => {
21
21
  fs.rmSync(tempSiteDir, { recursive: true });
22
22
  });
23
23
 
24
+ it('skips versions whose schema directory does not exist (L33)', () => {
25
+ // Add a version that has no corresponding directory
26
+ const versionsPath = path.join(tempSiteDir, 'versions.json');
27
+ fs.writeFileSync(versionsPath, JSON.stringify(['1.1.1', '9.9.9']));
28
+
29
+ // Should not throw; 9.9.9 directory doesn't exist and is skipped
30
+ expect(() => updateSchemaIds(tempSiteDir, url)).not.toThrow();
31
+
32
+ // The existing 1.1.1 schemas should still be updated
33
+ const schemaPath = path.join(
34
+ tempSiteDir,
35
+ 'static/schemas',
36
+ '1.1.1',
37
+ 'add-to-cart-event.json',
38
+ );
39
+ const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
40
+ expect(schema.$id).toBe(
41
+ 'https://tracking-docs-demo.buchert.digital/schemas/1.1.1/add-to-cart-event.json',
42
+ );
43
+ });
44
+
45
+ it('skips non-.json files in schema directories (L19)', () => {
46
+ // Create a non-json file in the schema directory
47
+ const nonJsonPath = path.join(
48
+ tempSiteDir,
49
+ 'static/schemas',
50
+ '1.1.1',
51
+ 'readme.txt',
52
+ );
53
+ fs.writeFileSync(nonJsonPath, 'This is not a JSON file');
54
+
55
+ expect(() => updateSchemaIds(tempSiteDir, url)).not.toThrow();
56
+
57
+ // The non-json file should remain unchanged
58
+ const content = fs.readFileSync(nonJsonPath, 'utf8');
59
+ expect(content).toBe('This is not a JSON file');
60
+ });
61
+
62
+ it('accepts a specific version parameter (L27-28)', () => {
63
+ updateSchemaIds(tempSiteDir, url, '1.1.1');
64
+
65
+ const schemaPath = path.join(
66
+ tempSiteDir,
67
+ 'static/schemas',
68
+ '1.1.1',
69
+ 'add-to-cart-event.json',
70
+ );
71
+ const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
72
+ expect(schema.$id).toBe(
73
+ 'https://tracking-docs-demo.buchert.digital/schemas/1.1.1/add-to-cart-event.json',
74
+ );
75
+ });
76
+
77
+ it('returns early when versions.json does not exist (L6-8)', () => {
78
+ const noVersionsDir = path.resolve(__dirname, '__temp_no_versions__');
79
+ fs.mkdirSync(noVersionsDir, { recursive: true });
80
+
81
+ try {
82
+ const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
83
+ updateSchemaIds(noVersionsDir, url);
84
+ expect(consoleSpy).toHaveBeenCalledWith(
85
+ 'No versions.json file found, skipping schema ID update.',
86
+ );
87
+ consoleSpy.mockRestore();
88
+ } finally {
89
+ fs.rmSync(noVersionsDir, { recursive: true });
90
+ }
91
+ });
92
+
24
93
  it('should update the $id of the schemas in the versioned directories', () => {
25
94
  updateSchemaIds(tempSiteDir, url);
26
95
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @jest-environment node
2
+ * @jest-environment @stryker-mutator/jest-runner/jest-env/node
3
3
  */
4
4
 
5
5
  import path from 'path';
@@ -25,5 +25,5 @@ describe('validateSchemas - Integration', () => {
25
25
  const { schemaDir } = getPathsForVersion('next', siteDir);
26
26
  const result = await validateSchemas(schemaDir);
27
27
  expect(result).toBe(true);
28
- });
28
+ }, 60000);
29
29
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @jest-environment node
2
+ * @jest-environment @stryker-mutator/jest-runner/jest-env/node
3
3
  */
4
4
 
5
5
  import path from 'path';
@@ -152,4 +152,145 @@ describe('validateSchemas', () => {
152
152
  const result = await validateSchemas(schemaDir);
153
153
  expect(result).toBe(true);
154
154
  });
155
+
156
+ it('should return false and log errors when a schema produces no examples', async () => {
157
+ const fixturePath = path.resolve(
158
+ __dirname,
159
+ '__fixtures__',
160
+ 'validateSchemas',
161
+ 'no-example-schema.json',
162
+ );
163
+ const schemaDir = path.join(tmpDir, 'schemas');
164
+ fs.mkdirSync(schemaDir, { recursive: true });
165
+ fs.copyFileSync(
166
+ fixturePath,
167
+ path.join(schemaDir, 'no-example-schema.json'),
168
+ );
169
+
170
+ const result = await validateSchemas(schemaDir);
171
+ expect(result).toBe(false);
172
+ expect(consoleErrorSpy).toHaveBeenCalled();
173
+ const errorMessages = consoleErrorSpy.mock.calls
174
+ .map((c) => c[0])
175
+ .join('\n');
176
+ expect(errorMessages).toContain('does not produce any examples');
177
+ });
178
+
179
+ it('should return false and log error when processing a schema throws', async () => {
180
+ const fixturePath = path.resolve(
181
+ __dirname,
182
+ '__fixtures__',
183
+ 'validateSchemas',
184
+ 'main-schema-with-missing-ref.json',
185
+ );
186
+ const schemaDir = path.join(tmpDir, 'schemas');
187
+ fs.mkdirSync(schemaDir, { recursive: true });
188
+ fs.copyFileSync(
189
+ fixturePath,
190
+ path.join(schemaDir, 'main-schema-with-missing-ref.json'),
191
+ );
192
+
193
+ const result = await validateSchemas(schemaDir);
194
+ expect(result).toBe(false);
195
+ expect(consoleErrorSpy).toHaveBeenCalled();
196
+ const errorMessages = consoleErrorSpy.mock.calls
197
+ .map((c) => c[0])
198
+ .join('\n');
199
+ expect(errorMessages).toContain('Error processing');
200
+ });
201
+
202
+ it('should report errors for all failing schemas when multiple schemas exist', async () => {
203
+ const schemaDir = path.join(tmpDir, 'schemas');
204
+ fs.mkdirSync(schemaDir, { recursive: true });
205
+
206
+ // First schema: valid
207
+ fs.writeFileSync(
208
+ path.join(schemaDir, 'valid.json'),
209
+ JSON.stringify({
210
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
211
+ type: 'object',
212
+ properties: { event: { type: 'string', const: 'ok' } },
213
+ required: ['event'],
214
+ }),
215
+ );
216
+
217
+ // Second schema: no examples produced
218
+ fs.writeFileSync(
219
+ path.join(schemaDir, 'no-examples.json'),
220
+ JSON.stringify({
221
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
222
+ type: 'object',
223
+ properties: { untyped: { description: 'no type or example' } },
224
+ required: ['untyped'],
225
+ }),
226
+ );
227
+
228
+ const result = await validateSchemas(schemaDir);
229
+ expect(result).toBe(false);
230
+ expect(consoleErrorSpy).toHaveBeenCalled();
231
+ });
232
+
233
+ it('should return false when a oneOf option produces an undefined example', async () => {
234
+ const schemaDir = path.join(tmpDir, 'schemas');
235
+ fs.mkdirSync(schemaDir, { recursive: true });
236
+
237
+ // Schema with a oneOf where one option has no resolvable example
238
+ fs.writeFileSync(
239
+ path.join(schemaDir, 'undef-option.json'),
240
+ JSON.stringify({
241
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
242
+ type: 'object',
243
+ oneOf: [
244
+ {
245
+ title: 'ValidOption',
246
+ properties: { event: { type: 'string', const: 'test' } },
247
+ required: ['event'],
248
+ },
249
+ {
250
+ title: 'UndefinedOption',
251
+ properties: { mystery: { description: 'no type, no example' } },
252
+ required: ['mystery'],
253
+ },
254
+ ],
255
+ }),
256
+ );
257
+
258
+ const result = await validateSchemas(schemaDir);
259
+ expect(result).toBe(false);
260
+ expect(consoleErrorSpy).toHaveBeenCalled();
261
+ const errorMessages = consoleErrorSpy.mock.calls
262
+ .map((c) => c[0])
263
+ .join('\n');
264
+ expect(errorMessages).toContain('does not produce a valid example');
265
+ });
266
+
267
+ it('should report all examples invalid when every example fails validation', async () => {
268
+ const schemaDir = path.join(tmpDir, 'schemas');
269
+ fs.mkdirSync(schemaDir, { recursive: true });
270
+
271
+ // Schema where every oneOf option produces an example that fails schema validation
272
+ fs.writeFileSync(
273
+ path.join(schemaDir, 'all-invalid.json'),
274
+ JSON.stringify({
275
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
276
+ type: 'object',
277
+ properties: {
278
+ count: {
279
+ type: 'integer',
280
+ minimum: 100,
281
+ example: 1,
282
+ },
283
+ },
284
+ required: ['count'],
285
+ }),
286
+ );
287
+
288
+ const result = await validateSchemas(schemaDir);
289
+ expect(result).toBe(false);
290
+ expect(consoleErrorSpy).toHaveBeenCalled();
291
+ const errorMessages = consoleErrorSpy.mock.calls
292
+ .map((c) => c[0])
293
+ .join('\n');
294
+ expect(errorMessages).toContain('example data failed validation');
295
+ });
155
296
  });
@@ -7,7 +7,7 @@ import {
7
7
  writeDoc,
8
8
  createDir,
9
9
  } from './helpers/file-system.js';
10
- import { processOneOfSchema, slugify } from './helpers/schema-processing.js';
10
+ import { processOneOfSchema } from './helpers/schema-processing.js';
11
11
  import SchemaDocTemplate from './helpers/schema-doc-template.js';
12
12
  import ChoiceIndexTemplate from './helpers/choice-index-template.js';
13
13
  import processSchema from './helpers/processSchema.js';
@@ -233,6 +233,26 @@ async function generateOneOfDocs(
233
233
 
234
234
  const processed = await processOneOfSchema(schema, filePath);
235
235
 
236
+ // Remove stale files/dirs from previous runs that are no longer in the schema
237
+ const expectedNames = new Set(['index.mdx']);
238
+ for (const [
239
+ index,
240
+ { slug, schema: processedSchema },
241
+ ] of processed.entries()) {
242
+ const prefixedSlug = `${(index + 1).toString().padStart(2, '0')}-${slug}`;
243
+ expectedNames.add(
244
+ processedSchema.oneOf ? prefixedSlug : `${prefixedSlug}.mdx`,
245
+ );
246
+ }
247
+ for (const entry of fs.readdirSync(eventOutputDir, { withFileTypes: true })) {
248
+ if (!expectedNames.has(entry.name)) {
249
+ const fullPath = path.join(eventOutputDir, entry.name);
250
+ entry.isDirectory()
251
+ ? fs.rmSync(fullPath, { recursive: true })
252
+ : fs.unlinkSync(fullPath);
253
+ }
254
+ }
255
+
236
256
  const indexPageContent = ChoiceIndexTemplate({
237
257
  schema,
238
258
  processedOptions: processed,
@@ -1,22 +1,18 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs';
3
3
 
4
+ function buildCandidatePaths(baseSegments, packageName) {
5
+ return [
6
+ path.resolve(process.cwd(), ...baseSegments, packageName),
7
+ path.resolve(process.cwd(), '..', ...baseSegments, packageName),
8
+ path.resolve(process.cwd(), '..', '..', ...baseSegments, packageName),
9
+ ];
10
+ }
11
+
4
12
  function getConstraintsPackageRoot() {
5
13
  const candidates = [
6
- path.resolve(process.cwd(), 'packages', 'tracking-target-constraints'),
7
- path.resolve(
8
- process.cwd(),
9
- '..',
10
- 'packages',
11
- 'tracking-target-constraints',
12
- ),
13
- path.resolve(
14
- process.cwd(),
15
- '..',
16
- '..',
17
- 'packages',
18
- 'tracking-target-constraints',
19
- ),
14
+ ...buildCandidatePaths(['packages'], 'tracking-target-constraints'),
15
+ ...buildCandidatePaths(['node_modules'], 'tracking-target-constraints'),
20
16
  ];
21
17
 
22
18
  return candidates.find((candidate) => fs.existsSync(candidate));