docusaurus-plugin-generate-schema-docs 1.8.3 → 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.
- package/README.md +12 -0
- package/__tests__/__fixtures__/validateSchemas/main-schema-with-not-allof.json +11 -0
- package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof-multi.json +12 -0
- package/__tests__/__fixtures__/validateSchemas/schema-with-not-anyof.json +30 -0
- package/__tests__/__fixtures__/validateSchemas/schema-with-not-edge-cases.json +24 -0
- package/__tests__/__fixtures__/validateSchemas/schema-with-not-non-object.json +15 -0
- package/__tests__/__snapshots__/generateEventDocs.anchor.test.js.snap +6 -0
- package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +6 -0
- package/__tests__/__snapshots__/generateEventDocs.test.js.snap +15 -0
- package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +6 -0
- package/__tests__/components/PropertiesTable.test.js +66 -0
- package/__tests__/components/PropertyRow.test.js +85 -4
- package/__tests__/components/SchemaJsonViewer.test.js +118 -0
- package/__tests__/generateEventDocs.anchor.test.js +1 -1
- package/__tests__/generateEventDocs.nested.test.js +1 -1
- package/__tests__/generateEventDocs.partials.test.js +1 -1
- package/__tests__/generateEventDocs.test.js +506 -1
- package/__tests__/generateEventDocs.versioned.test.js +1 -1
- package/__tests__/helpers/buildExampleFromSchema.test.js +240 -0
- package/__tests__/helpers/constraintSchemaPaths.test.js +208 -0
- package/__tests__/helpers/continuingLinesStyle.test.js +492 -0
- package/__tests__/helpers/example-helper.test.js +12 -0
- package/__tests__/helpers/exampleModel.test.js +209 -0
- package/__tests__/helpers/file-system.test.js +73 -1
- package/__tests__/helpers/getConstraints.test.js +43 -0
- package/__tests__/helpers/mergeSchema.test.js +94 -0
- package/__tests__/helpers/processSchema.test.js +309 -1
- package/__tests__/helpers/schema-doc-template.test.js +54 -0
- package/__tests__/helpers/schema-processing.test.js +122 -2
- package/__tests__/helpers/schemaToExamples.test.js +1007 -0
- package/__tests__/helpers/schemaToTableData.mutations.test.js +970 -0
- package/__tests__/helpers/schemaToTableData.test.js +157 -0
- package/__tests__/helpers/schemaTraversal.test.js +110 -0
- package/__tests__/helpers/snippetTargets.test.js +432 -0
- package/__tests__/helpers/trackingTargets.test.js +319 -0
- package/__tests__/helpers/validator.test.js +385 -1
- package/__tests__/index.test.js +436 -0
- package/__tests__/syncGtm.test.js +366 -6
- package/__tests__/update-schema-ids.test.js +70 -1
- package/__tests__/validateSchemas-integration.test.js +2 -2
- package/__tests__/validateSchemas.test.js +192 -1
- package/components/PropertiesTable.js +32 -2
- package/components/PropertyRow.js +29 -2
- package/components/SchemaJsonViewer.js +234 -131
- package/components/SchemaRows.css +40 -0
- package/components/SchemaViewer.js +11 -2
- package/generateEventDocs.js +21 -1
- package/helpers/constraintSchemaPaths.js +10 -14
- package/helpers/example-helper.js +2 -2
- package/helpers/getConstraints.js +20 -0
- package/helpers/processSchema.js +32 -1
- package/helpers/schema-doc-template.js +4 -0
- package/helpers/schemaToExamples.js +29 -35
- package/helpers/schemaToTableData.js +538 -492
- package/helpers/schemaTraversal.cjs +148 -0
- package/helpers/trackingTargets.js +26 -3
- package/helpers/validator.js +18 -4
- package/index.js +1 -2
- package/package.json +1 -1
- package/scripts/sync-gtm.js +65 -34
- package/test-data/payloadContracts.js +35 -0
- package/validateSchemas.js +1 -1
|
@@ -17,6 +17,32 @@ describe('trackingTargets', () => {
|
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
it('returns all supported target IDs when configured', () => {
|
|
21
|
+
const schema = {
|
|
22
|
+
'x-tracking-targets': [
|
|
23
|
+
'web-datalayer-js',
|
|
24
|
+
'android-firebase-kotlin-sdk',
|
|
25
|
+
'android-firebase-java-sdk',
|
|
26
|
+
'ios-firebase-swift-sdk',
|
|
27
|
+
'ios-firebase-objc-sdk',
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
32
|
+
|
|
33
|
+
expect(result).toEqual({
|
|
34
|
+
targets: [
|
|
35
|
+
'web-datalayer-js',
|
|
36
|
+
'android-firebase-kotlin-sdk',
|
|
37
|
+
'android-firebase-java-sdk',
|
|
38
|
+
'ios-firebase-swift-sdk',
|
|
39
|
+
'ios-firebase-objc-sdk',
|
|
40
|
+
],
|
|
41
|
+
warning: null,
|
|
42
|
+
errors: [],
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
20
46
|
it('falls back to default target when key is missing', () => {
|
|
21
47
|
const result = resolveTrackingTargets(
|
|
22
48
|
{},
|
|
@@ -28,6 +54,85 @@ describe('trackingTargets', () => {
|
|
|
28
54
|
expect(result.warning).toContain(DEFAULT_TRACKING_TARGET);
|
|
29
55
|
});
|
|
30
56
|
|
|
57
|
+
it('does not warn for top-level reference schemas that aggregate via oneOf', () => {
|
|
58
|
+
const schema = {
|
|
59
|
+
type: 'object',
|
|
60
|
+
allOf: [{ $ref: './web/components/dataLayer.json' }],
|
|
61
|
+
oneOf: [
|
|
62
|
+
{ $ref: './web/add-to-cart-event.json' },
|
|
63
|
+
{ $ref: './web/purchase-event.json' },
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const result = resolveTrackingTargets(schema, {
|
|
68
|
+
schemaFile: 'event-reference.json',
|
|
69
|
+
isQuiet: false,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(result).toEqual({
|
|
73
|
+
targets: [DEFAULT_TRACKING_TARGET],
|
|
74
|
+
warning: null,
|
|
75
|
+
errors: [],
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('still warns when oneOf schemas define their own properties', () => {
|
|
80
|
+
const schema = {
|
|
81
|
+
type: 'object',
|
|
82
|
+
properties: {
|
|
83
|
+
event: { type: 'string' },
|
|
84
|
+
},
|
|
85
|
+
oneOf: [{ $ref: './option-a.json' }, { $ref: './option-b.json' }],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const result = resolveTrackingTargets(schema, {
|
|
89
|
+
schemaFile: 'event.json',
|
|
90
|
+
isQuiet: false,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
94
|
+
expect(result.errors).toEqual([]);
|
|
95
|
+
expect(result.warning).toContain('event.json');
|
|
96
|
+
expect(result.warning).toContain('x-tracking-targets');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('does not warn for aggregators when properties is an empty object', () => {
|
|
100
|
+
const schema = {
|
|
101
|
+
type: 'object',
|
|
102
|
+
properties: {},
|
|
103
|
+
anyOf: [{ $ref: './option-a.json' }, { $ref: './option-b.json' }],
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const result = resolveTrackingTargets(schema, {
|
|
107
|
+
schemaFile: 'reference.json',
|
|
108
|
+
isQuiet: false,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
expect(result).toEqual({
|
|
112
|
+
targets: [DEFAULT_TRACKING_TARGET],
|
|
113
|
+
warning: null,
|
|
114
|
+
errors: [],
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('still warns when properties is present but not an object map', () => {
|
|
119
|
+
const schema = {
|
|
120
|
+
type: 'object',
|
|
121
|
+
properties: 'invalid',
|
|
122
|
+
oneOf: [{ $ref: './option-a.json' }, { $ref: './option-b.json' }],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const result = resolveTrackingTargets(schema, {
|
|
126
|
+
schemaFile: 'event.json',
|
|
127
|
+
isQuiet: false,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
131
|
+
expect(result.errors).toEqual([]);
|
|
132
|
+
expect(result.warning).toContain('event.json');
|
|
133
|
+
expect(result.warning).toContain('x-tracking-targets');
|
|
134
|
+
});
|
|
135
|
+
|
|
31
136
|
it('returns an error for unknown targets', () => {
|
|
32
137
|
const schema = {
|
|
33
138
|
'x-tracking-targets': ['web-not-supported-js'],
|
|
@@ -39,4 +144,218 @@ describe('trackingTargets', () => {
|
|
|
39
144
|
expect(result.errors).toHaveLength(1);
|
|
40
145
|
expect(result.errors[0]).toContain('web-not-supported-js');
|
|
41
146
|
});
|
|
147
|
+
|
|
148
|
+
it('joins multiple unsupported targets with comma-space formatting', () => {
|
|
149
|
+
const schema = {
|
|
150
|
+
'x-tracking-targets': ['web-not-supported-js', 'ios-not-supported-sdk'],
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
154
|
+
|
|
155
|
+
expect(result.errors).toContain(
|
|
156
|
+
'x-tracking-targets contains unsupported target(s): web-not-supported-js, ios-not-supported-sdk.',
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// L17: optional chaining — x-tracking-targets explicitly set to null
|
|
161
|
+
it('falls back to default when x-tracking-targets is null', () => {
|
|
162
|
+
const schema = { 'x-tracking-targets': null };
|
|
163
|
+
const result = resolveTrackingTargets(schema, {
|
|
164
|
+
schemaFile: 'event.json',
|
|
165
|
+
isQuiet: false,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
169
|
+
expect(result.errors).toEqual([]);
|
|
170
|
+
expect(result.warning).not.toBeNull();
|
|
171
|
+
expect(result.warning).toContain('event.json');
|
|
172
|
+
expect(result.warning).toContain(DEFAULT_TRACKING_TARGET);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// L17: optional chaining — schema itself is null/undefined
|
|
176
|
+
it('falls back to default when schema is null', () => {
|
|
177
|
+
const result = resolveTrackingTargets(null, {
|
|
178
|
+
schemaFile: 'missing.json',
|
|
179
|
+
isQuiet: false,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
183
|
+
expect(result.errors).toEqual([]);
|
|
184
|
+
expect(result.warning).toContain('missing.json');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// L15, L60-63: warning contains schemaFile name
|
|
188
|
+
it('warning message includes the schemaFile name', () => {
|
|
189
|
+
const result = resolveTrackingTargets(
|
|
190
|
+
{},
|
|
191
|
+
{ schemaFile: 'my-custom-event.json', isQuiet: false },
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
expect(result.warning).toContain('my-custom-event.json');
|
|
195
|
+
expect(result.warning).toContain('x-tracking-targets');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// L15: isQuiet suppresses the warning (null instead of string)
|
|
199
|
+
it('returns null warning when isQuiet is true and key is missing', () => {
|
|
200
|
+
const result = resolveTrackingTargets(
|
|
201
|
+
{},
|
|
202
|
+
{ schemaFile: 'event.json', isQuiet: true },
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
206
|
+
expect(result.warning).toBeNull();
|
|
207
|
+
expect(result.errors).toEqual([]);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// L31 first condition: x-tracking-targets is not an array
|
|
211
|
+
it('returns an error when x-tracking-targets is not an array', () => {
|
|
212
|
+
const schema = { 'x-tracking-targets': 'web-datalayer-js' };
|
|
213
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
214
|
+
|
|
215
|
+
expect(result.targets).toEqual([]);
|
|
216
|
+
expect(result.errors).toHaveLength(1);
|
|
217
|
+
expect(result.errors[0]).toContain('non-empty array');
|
|
218
|
+
expect(result.warning).toBeNull();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// L31 length === 0: x-tracking-targets is empty array
|
|
222
|
+
it('returns an error when x-tracking-targets is an empty array', () => {
|
|
223
|
+
const schema = { 'x-tracking-targets': [] };
|
|
224
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
225
|
+
|
|
226
|
+
expect(result.targets).toEqual([]);
|
|
227
|
+
expect(result.errors).toHaveLength(1);
|
|
228
|
+
expect(result.errors[0]).toContain('non-empty array');
|
|
229
|
+
expect(result.warning).toBeNull();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// L33: x-tracking-targets contains non-string values
|
|
233
|
+
it('returns an error when x-tracking-targets contains non-string values', () => {
|
|
234
|
+
const schema = { 'x-tracking-targets': [42, true] };
|
|
235
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
236
|
+
|
|
237
|
+
expect(result.targets).toEqual([]);
|
|
238
|
+
expect(result.errors).toHaveLength(1);
|
|
239
|
+
expect(result.errors[0]).toContain('non-empty array of string target IDs');
|
|
240
|
+
expect(result.warning).toBeNull();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// L33: mixed array with at least one non-string
|
|
244
|
+
it('returns an error when x-tracking-targets mixes strings and non-strings', () => {
|
|
245
|
+
const schema = { 'x-tracking-targets': ['web-datalayer-js', 99] };
|
|
246
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
247
|
+
|
|
248
|
+
expect(result.targets).toEqual([]);
|
|
249
|
+
expect(result.errors).toHaveLength(1);
|
|
250
|
+
expect(result.errors[0]).toContain('non-empty array of string target IDs');
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// L52: error message text for unsupported targets
|
|
254
|
+
it('error for unsupported targets mentions "unsupported target(s)"', () => {
|
|
255
|
+
const schema = { 'x-tracking-targets': ['foo-bar-baz'] };
|
|
256
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
257
|
+
|
|
258
|
+
expect(result.targets).toEqual([]);
|
|
259
|
+
expect(result.errors.some((e) => e.includes('unsupported target(s)'))).toBe(
|
|
260
|
+
true,
|
|
261
|
+
);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// L58: badly formatted target ID (does not match kebab-case pattern)
|
|
265
|
+
it('returns an error for badly formatted target IDs', () => {
|
|
266
|
+
// Provide a target that passes the supported check but fails the pattern check
|
|
267
|
+
// by simulating a value that would be "known" but wrongly formatted.
|
|
268
|
+
// Since SUPPORTED_TRACKING_TARGETS are all valid, use a value that fails the regex.
|
|
269
|
+
const schema = { 'x-tracking-targets': ['UPPERCASE-TARGET-ID'] };
|
|
270
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
271
|
+
|
|
272
|
+
expect(result.targets).toEqual([]);
|
|
273
|
+
// Should have at least one error (unsupported, and also badly formatted)
|
|
274
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// L60: error message contains the invalid value
|
|
278
|
+
it('badly formatted error message lists the invalid values', () => {
|
|
279
|
+
const schema = { 'x-tracking-targets': ['bad_format'] };
|
|
280
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
281
|
+
|
|
282
|
+
const formatError = result.errors.find((e) =>
|
|
283
|
+
e.includes('lowercase kebab-case'),
|
|
284
|
+
);
|
|
285
|
+
expect(formatError).toBeDefined();
|
|
286
|
+
expect(formatError).toContain('bad_format');
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('joins multiple badly formatted values with comma-space formatting', () => {
|
|
290
|
+
const schema = { 'x-tracking-targets': ['bad_format', 'another_bad'] };
|
|
291
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
292
|
+
|
|
293
|
+
expect(result.errors).toContain(
|
|
294
|
+
'x-tracking-targets must use lowercase kebab-case IDs like "web-datalayer-js". Invalid value(s): bad_format, another_bad.',
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('rejects target IDs with leading punctuation even when the core pattern matches', () => {
|
|
299
|
+
const schema = { 'x-tracking-targets': ['!web-datalayer-js'] };
|
|
300
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
301
|
+
|
|
302
|
+
const formatError = result.errors.find((e) =>
|
|
303
|
+
e.includes('lowercase kebab-case'),
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
expect(formatError).toBeDefined();
|
|
307
|
+
expect(formatError).toContain('!web-datalayer-js');
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('rejects target IDs with trailing punctuation even when the core pattern matches', () => {
|
|
311
|
+
const schema = { 'x-tracking-targets': ['web-datalayer-js!'] };
|
|
312
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
313
|
+
|
|
314
|
+
const formatError = result.errors.find((e) =>
|
|
315
|
+
e.includes('lowercase kebab-case'),
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
expect(formatError).toBeDefined();
|
|
319
|
+
expect(formatError).toContain('web-datalayer-js!');
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// targets are returned only when there are no errors
|
|
323
|
+
it('returns empty targets array when there are errors', () => {
|
|
324
|
+
const schema = { 'x-tracking-targets': ['invalid_format'] };
|
|
325
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
326
|
+
|
|
327
|
+
expect(result.targets).toEqual([]);
|
|
328
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// targets are returned when there are no errors (the ternary on last return)
|
|
332
|
+
it('returns the configured targets when no errors are found', () => {
|
|
333
|
+
const schema = { 'x-tracking-targets': ['web-datalayer-js'] };
|
|
334
|
+
const result = resolveTrackingTargets(schema, { schemaFile: 'event.json' });
|
|
335
|
+
|
|
336
|
+
expect(result.targets).toEqual(['web-datalayer-js']);
|
|
337
|
+
expect(result.errors).toEqual([]);
|
|
338
|
+
expect(result.warning).toBeNull();
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// L15: default-arg — omit second argument entirely to trigger = {} default
|
|
342
|
+
it('uses default options when second argument is omitted', () => {
|
|
343
|
+
const result = resolveTrackingTargets({});
|
|
344
|
+
|
|
345
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
346
|
+
expect(result.errors).toEqual([]);
|
|
347
|
+
// schemaFile defaults to 'schema', isQuiet defaults to false
|
|
348
|
+
expect(result.warning).toContain('schema');
|
|
349
|
+
expect(result.warning).toContain(DEFAULT_TRACKING_TARGET);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// L15: default-arg — provide options object without schemaFile or isQuiet
|
|
353
|
+
it('uses default schemaFile and isQuiet when keys are omitted from options', () => {
|
|
354
|
+
const result = resolveTrackingTargets({}, {});
|
|
355
|
+
|
|
356
|
+
expect(result.targets).toEqual([DEFAULT_TRACKING_TARGET]);
|
|
357
|
+
expect(result.errors).toEqual([]);
|
|
358
|
+
// schemaFile defaults to 'schema'
|
|
359
|
+
expect(result.warning).toContain('schema');
|
|
360
|
+
});
|
|
42
361
|
});
|