docusaurus-plugin-generate-schema-docs 1.1.1 → 1.3.0

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 (81) hide show
  1. package/README.md +60 -2
  2. package/__tests__/ExampleDataLayer.test.js +92 -0
  3. package/__tests__/__fixtures__/static/schemas/add-to-cart-event.json +44 -0
  4. package/__tests__/__fixtures__/static/schemas/choice-event.json +72 -0
  5. package/__tests__/__fixtures__/static/schemas/components/dataLayer.json +56 -0
  6. package/__tests__/__fixtures__/static/schemas/components/product.json +125 -0
  7. package/__tests__/__fixtures__/static/schemas/nested/child-event.json +10 -0
  8. package/__tests__/__fixtures__/static/schemas/nested/grandchild-a.json +9 -0
  9. package/__tests__/__fixtures__/static/schemas/nested/grandchild-b.json +9 -0
  10. package/__tests__/__fixtures__/static/schemas/nested/parent-event.json +7 -0
  11. package/__tests__/__fixtures__/static/schemas/root-any-of-event.json +34 -0
  12. package/__tests__/__fixtures__/static/schemas/root-choice-event.json +36 -0
  13. package/__tests__/__fixtures__/validateSchemas/circular-schema.json +8 -0
  14. package/__tests__/__fixtures__/validateSchemas/components/referenced.json +10 -0
  15. package/__tests__/__fixtures__/validateSchemas/invalid-example-schema.json +8 -0
  16. package/__tests__/__fixtures__/validateSchemas/main-schema-with-missing-ref.json +8 -0
  17. package/__tests__/__fixtures__/validateSchemas/main-schema-with-ref.json +8 -0
  18. package/__tests__/__fixtures__/validateSchemas/no-example-schema.json +12 -0
  19. package/__tests__/__fixtures__/validateSchemas/schema-A.json +7 -0
  20. package/__tests__/__fixtures__/validateSchemas/schema-B.json +7 -0
  21. package/__tests__/__fixtures__/validateSchemas/valid-schema.json +8 -0
  22. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/add-to-cart-event.json +44 -0
  23. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/components/dataLayer.json +56 -0
  24. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/components/product.json +125 -0
  25. package/__tests__/__fixtures_versioned__/static/schemas/next/add-to-cart-event.json +44 -0
  26. package/__tests__/__fixtures_versioned__/static/schemas/next/components/dataLayer.json +56 -0
  27. package/__tests__/__fixtures_versioned__/static/schemas/next/components/product.json +125 -0
  28. package/__tests__/__fixtures_versioned__/versions.json +1 -0
  29. package/__tests__/__snapshots__/ExampleDataLayer.test.js.snap +117 -0
  30. package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +92 -0
  31. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +151 -0
  32. package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +53 -0
  33. package/__tests__/components/FoldableRows.test.js +330 -0
  34. package/__tests__/components/PropertiesTable.test.js +41 -0
  35. package/__tests__/components/PropertyRow.test.js +487 -0
  36. package/__tests__/components/SchemaJsonViewer.test.js +36 -0
  37. package/__tests__/components/SchemaRows.test.js +110 -0
  38. package/__tests__/components/SchemaViewer.test.js +44 -0
  39. package/__tests__/components/TableHeader.test.js +20 -0
  40. package/__tests__/generateEventDocs.nested.test.js +80 -0
  41. package/__tests__/generateEventDocs.test.js +90 -0
  42. package/__tests__/generateEventDocs.versioned.test.js +69 -0
  43. package/__tests__/helpers/buildExampleFromSchema.test.js +188 -0
  44. package/__tests__/helpers/file-system.test.js +44 -0
  45. package/__tests__/helpers/getConstraints.test.js +58 -0
  46. package/__tests__/helpers/loadSchema.test.js +20 -0
  47. package/__tests__/helpers/path-helpers.test.js +34 -0
  48. package/__tests__/helpers/processSchema.test.js +56 -0
  49. package/__tests__/helpers/schema-processing.test.js +82 -0
  50. package/__tests__/helpers/schemaToExamples.test.js +56 -0
  51. package/__tests__/helpers/schemaToTableData.filtering.test.js +65 -0
  52. package/__tests__/helpers/schemaToTableData.hierarchicalLines.test.js +539 -0
  53. package/__tests__/helpers/schemaToTableData.test.js +222 -0
  54. package/__tests__/helpers/update-schema-ids.test.js +107 -0
  55. package/__tests__/update-schema-ids.test.js +39 -0
  56. package/__tests__/validateSchemas.test.js +137 -0
  57. package/components/ExampleDataLayer.js +60 -27
  58. package/components/FoldableRows.js +164 -0
  59. package/components/PropertiesTable.js +12 -14
  60. package/components/PropertyRow.js +183 -0
  61. package/components/SchemaJsonViewer.js +8 -7
  62. package/components/SchemaRows.css +250 -0
  63. package/components/SchemaRows.js +24 -69
  64. package/components/SchemaViewer.js +21 -13
  65. package/components/TableHeader.js +15 -0
  66. package/generateEventDocs.js +141 -60
  67. package/helpers/buildExampleFromSchema.js +59 -73
  68. package/helpers/choice-index-template.js +22 -0
  69. package/helpers/file-system.js +32 -0
  70. package/helpers/getConstraints.js +52 -0
  71. package/helpers/loadSchema.js +11 -0
  72. package/helpers/path-helpers.js +22 -0
  73. package/helpers/processSchema.js +32 -0
  74. package/helpers/schema-doc-template.js +36 -0
  75. package/helpers/schema-processing.js +75 -0
  76. package/helpers/schemaToExamples.js +99 -0
  77. package/helpers/schemaToTableData.js +311 -0
  78. package/helpers/update-schema-ids.js +47 -0
  79. package/index.js +146 -47
  80. package/package.json +6 -3
  81. package/validateSchemas.js +56 -70
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import generateEventDocs from '../generateEventDocs';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+
9
+ jest.mock('fs', () => {
10
+ const memfs = require('memfs');
11
+ return memfs;
12
+ });
13
+
14
+ describe('generateEventDocs (nested oneOf)', () => {
15
+ const testSiteDir = path.resolve(__dirname, '__fixtures_nested__');
16
+ const options = {
17
+ organizationName: 'test-org',
18
+ projectName: 'test-project',
19
+ siteDir: testSiteDir,
20
+ url: 'https://tracking-docs-demo.buchert.digital',
21
+ };
22
+ const baseOutputDir = path.join(options.siteDir, 'docs');
23
+
24
+ beforeEach(() => {
25
+ fs.vol.reset();
26
+ const realFs = jest.requireActual('fs');
27
+ const nestedSchemasDir = path.resolve(
28
+ __dirname,
29
+ '__fixtures__/static/schemas/nested',
30
+ );
31
+ const targetSchemasDir = path.join(testSiteDir, 'static/schemas');
32
+ fs.vol.mkdirSync(targetSchemasDir, { recursive: true });
33
+
34
+ const files = realFs.readdirSync(nestedSchemasDir, { withFileTypes: true });
35
+ for (const file of files) {
36
+ const filePath = path.join(nestedSchemasDir, file.name);
37
+ const content = realFs.readFileSync(filePath);
38
+ fs.vol.writeFileSync(path.join(targetSchemasDir, file.name), content);
39
+ }
40
+ });
41
+
42
+ it('should generate nested documentation correctly', async () => {
43
+ console.log = jest.fn(); // suppress console.log
44
+
45
+ await generateEventDocs(options);
46
+
47
+ const parentDir = path.join(baseOutputDir, 'parent-event');
48
+ // The child directory is prefixed because it's an item in the parent's oneOf
49
+ const childDir = path.join(parentDir, '01-child-event');
50
+
51
+ // Check for directory structure
52
+ expect(fs.existsSync(parentDir)).toBe(true);
53
+ expect(fs.existsSync(childDir)).toBe(true);
54
+
55
+ const parentIndex = fs.readFileSync(
56
+ path.join(parentDir, 'index.mdx'),
57
+ 'utf-8',
58
+ );
59
+ expect(parentIndex).toMatchSnapshot();
60
+
61
+ const childIndex = fs.readFileSync(
62
+ path.join(childDir, 'index.mdx'),
63
+ 'utf-8',
64
+ );
65
+ expect(childIndex).toMatchSnapshot();
66
+
67
+ // Check content of generated files
68
+ const grandchildA = fs.readFileSync(
69
+ path.join(childDir, '01-grandchild-a.mdx'),
70
+ 'utf-8',
71
+ );
72
+ expect(grandchildA).toMatchSnapshot();
73
+
74
+ const grandchildB = fs.readFileSync(
75
+ path.join(childDir, '02-grandchild-b.mdx'),
76
+ 'utf-8',
77
+ );
78
+ expect(grandchildB).toMatchSnapshot();
79
+ });
80
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import generateEventDocs from '../generateEventDocs';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+
9
+ jest.mock('fs', () => {
10
+ const memfs = require('memfs');
11
+ return memfs;
12
+ });
13
+
14
+ describe('generateEventDocs (non-versioned)', () => {
15
+ const options = {
16
+ organizationName: 'test-org',
17
+ projectName: 'test-project',
18
+ // Use the fixtures directory as the siteDir for tests
19
+ siteDir: path.resolve(__dirname, '__fixtures__'),
20
+ url: 'https://tracking-docs-demo.buchert.digital',
21
+ };
22
+ const outputDir = path.join(options.siteDir, 'docs');
23
+
24
+ beforeEach(() => {
25
+ fs.vol.reset();
26
+ const realFs = jest.requireActual('fs');
27
+ const fixturesDir = path.resolve(__dirname, '__fixtures__');
28
+
29
+ function readDirRecursive(dir) {
30
+ const files = realFs.readdirSync(dir, { withFileTypes: true });
31
+ for (const file of files) {
32
+ const filePath = path.join(dir, file.name);
33
+ if (file.isDirectory()) {
34
+ fs.vol.mkdirSync(filePath, { recursive: true });
35
+ readDirRecursive(filePath);
36
+ } else {
37
+ const content = realFs.readFileSync(filePath);
38
+ fs.vol.writeFileSync(filePath, content);
39
+ }
40
+ }
41
+ }
42
+ readDirRecursive(fixturesDir);
43
+ });
44
+
45
+ it('should generate documentation correctly', async () => {
46
+ console.log = jest.fn(); // suppress console.log
47
+
48
+ await generateEventDocs(options);
49
+
50
+ const choiceEventDir = path.join(outputDir, 'root-choice-event');
51
+ expect(fs.existsSync(choiceEventDir)).toBe(true);
52
+
53
+ // Check content of generated files
54
+ const addToCart = fs.readFileSync(
55
+ path.join(outputDir, 'add-to-cart-event.mdx'),
56
+ 'utf-8',
57
+ );
58
+ expect(addToCart).toMatchSnapshot();
59
+
60
+ const choiceEvent = fs.readFileSync(
61
+ path.join(outputDir, 'choice-event.mdx'),
62
+ 'utf-8',
63
+ );
64
+ expect(choiceEvent).toMatchSnapshot();
65
+
66
+ const rootAnyOf = fs.readFileSync(
67
+ path.join(outputDir, 'root-any-of-event.mdx'),
68
+ 'utf-8',
69
+ );
70
+ expect(rootAnyOf).toMatchSnapshot();
71
+
72
+ const rootChoiceIndex = fs.readFileSync(
73
+ path.join(choiceEventDir, 'index.mdx'),
74
+ 'utf-8',
75
+ );
76
+ expect(rootChoiceIndex).toMatchSnapshot();
77
+
78
+ const rootChoiceA = fs.readFileSync(
79
+ path.join(choiceEventDir, '01-option-a.mdx'),
80
+ 'utf-8',
81
+ );
82
+ expect(rootChoiceA).toMatchSnapshot();
83
+
84
+ const rootChoiceB = fs.readFileSync(
85
+ path.join(choiceEventDir, '02-option-b.mdx'),
86
+ 'utf-8',
87
+ );
88
+ expect(rootChoiceB).toMatchSnapshot();
89
+ });
90
+ });
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import generateEventDocs from '../generateEventDocs';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+
9
+ jest.mock('fs', () => {
10
+ const originalFs = jest.requireActual('fs');
11
+ return {
12
+ ...originalFs,
13
+ writeFileSync: jest.fn(),
14
+ mkdirSync: jest.fn(),
15
+ existsSync: jest.fn(),
16
+ readdirSync: originalFs.readdirSync,
17
+ readFileSync: originalFs.readFileSync,
18
+ };
19
+ });
20
+
21
+ describe('generateEventDocs (versioned)', () => {
22
+ const options = {
23
+ organizationName: 'test-org',
24
+ projectName: 'test-project',
25
+ url: 'https://tracking-docs-demo.buchert.digital/',
26
+ // Use the fixtures_versioned directory as the siteDir for tests
27
+ siteDir: path.resolve(__dirname, '__fixtures_versioned__'),
28
+ };
29
+ const partialsDir = path.join(options.siteDir, 'docs/partials');
30
+
31
+ beforeEach(() => {
32
+ // Clear all instances and calls to constructor and all methods:
33
+ fs.writeFileSync.mockClear();
34
+ fs.mkdirSync.mockClear();
35
+ fs.existsSync.mockClear();
36
+ });
37
+
38
+ it('should generate documentation for "current" version', async () => {
39
+ // Mock fs.writeFileSync to capture the output
40
+ fs.writeFileSync = jest.fn();
41
+
42
+ const currentOptions = { ...options, version: 'current' };
43
+ await generateEventDocs(currentOptions);
44
+
45
+ expect(fs.writeFileSync).toHaveBeenCalled();
46
+ const [filePath, content] = fs.writeFileSync.mock.calls[0];
47
+ const outputDir = path.join(options.siteDir, 'docs');
48
+ expect(filePath).toBe(path.join(outputDir, 'add-to-cart-event.mdx'));
49
+ expect(content).toMatchSnapshot();
50
+ });
51
+
52
+ it('should generate documentation for a specific version', async () => {
53
+ // Mock fs.writeFileSync to capture the output
54
+ fs.writeFileSync = jest.fn();
55
+
56
+ const versionedOptions = { ...options, version: '1.1.1' };
57
+ await generateEventDocs(versionedOptions);
58
+
59
+ expect(fs.writeFileSync).toHaveBeenCalled();
60
+ const [filePath, content] = fs.writeFileSync.mock.calls[0];
61
+ const outputDir = path.join(
62
+ options.siteDir,
63
+ 'versioned_docs',
64
+ 'version-1.1.1',
65
+ );
66
+ expect(filePath).toBe(path.join(outputDir, 'add-to-cart-event.mdx'));
67
+ expect(content).toMatchSnapshot();
68
+ });
69
+ });
@@ -0,0 +1,188 @@
1
+ import buildExampleFromSchema from '../../helpers/buildExampleFromSchema.js';
2
+
3
+ describe('buildExampleFromSchema', () => {
4
+ it('should build a basic example from a schema', () => {
5
+ const schema = {
6
+ type: 'object',
7
+ properties: {
8
+ name: { type: 'string' },
9
+ age: { type: 'integer' },
10
+ isStudent: { type: 'boolean' },
11
+ },
12
+ };
13
+
14
+ const example = buildExampleFromSchema(schema);
15
+
16
+ expect(example).toEqual({
17
+ name: '',
18
+ age: 0,
19
+ isStudent: false,
20
+ });
21
+ });
22
+
23
+ it('should handle nested objects and arrays', () => {
24
+ const schema = {
25
+ type: 'object',
26
+ properties: {
27
+ user: {
28
+ type: 'object',
29
+ properties: {
30
+ name: { type: 'string' },
31
+ },
32
+ },
33
+ posts: {
34
+ type: 'array',
35
+ items: {
36
+ type: 'object',
37
+ properties: {
38
+ title: { type: 'string' },
39
+ tags: {
40
+ type: 'array',
41
+ items: { type: 'string' },
42
+ },
43
+ },
44
+ },
45
+ },
46
+ },
47
+ };
48
+
49
+ const example = buildExampleFromSchema(schema);
50
+
51
+ expect(example).toEqual({
52
+ user: {
53
+ name: '',
54
+ },
55
+ posts: [
56
+ {
57
+ title: '',
58
+ tags: [''],
59
+ },
60
+ ],
61
+ });
62
+ });
63
+
64
+ it('should use examples, const, and default values', () => {
65
+ const schema = {
66
+ type: 'object',
67
+ properties: {
68
+ name: {
69
+ type: 'string',
70
+ examples: ['John Doe'],
71
+ },
72
+ role: {
73
+ type: 'string',
74
+ const: 'admin',
75
+ },
76
+ level: {
77
+ type: 'integer',
78
+ default: 1,
79
+ },
80
+ },
81
+ };
82
+
83
+ const example = buildExampleFromSchema(schema);
84
+
85
+ expect(example).toEqual({
86
+ name: 'John Doe',
87
+ role: 'admin',
88
+ level: 1,
89
+ });
90
+ });
91
+
92
+ it('should build a complex example', () => {
93
+ const schema = {
94
+ type: 'object',
95
+ properties: {
96
+ event: {
97
+ type: 'string',
98
+ examples: ['purchase'],
99
+ },
100
+ ecommerce: {
101
+ type: 'object',
102
+ properties: {
103
+ transaction_id: {
104
+ type: 'string',
105
+ examples: ['T_12345'],
106
+ },
107
+ value: {
108
+ type: 'number',
109
+ default: 10.0,
110
+ },
111
+ items: {
112
+ type: 'array',
113
+ items: {
114
+ type: 'object',
115
+ properties: {
116
+ item_id: { type: 'string', examples: ['SKU_123'] },
117
+ item_name: { type: 'string', examples: ['Stan Smith Shoes'] },
118
+ price: { type: 'number' },
119
+ quantity: { type: 'integer', default: 1 },
120
+ },
121
+ },
122
+ },
123
+ },
124
+ },
125
+ },
126
+ };
127
+
128
+ const example = buildExampleFromSchema(schema);
129
+
130
+ expect(example).toEqual({
131
+ event: 'purchase',
132
+ ecommerce: {
133
+ transaction_id: 'T_12345',
134
+ value: 10.0,
135
+ items: [
136
+ {
137
+ item_id: 'SKU_123',
138
+ item_name: 'Stan Smith Shoes',
139
+ price: 0,
140
+ quantity: 1,
141
+ },
142
+ ],
143
+ },
144
+ });
145
+ });
146
+ it('should not include empty objects for properties with no defined value', () => {
147
+ const schema = {
148
+ type: 'object',
149
+ properties: {
150
+ event: { type: 'string', examples: ['test_event'] },
151
+ user_data: {
152
+ type: 'object',
153
+ },
154
+ ecommerce: {
155
+ type: 'object',
156
+ properties: {
157
+ items: {
158
+ type: 'array',
159
+ items: {
160
+ type: 'object',
161
+ properties: {
162
+ item_id: { type: 'string', examples: ['SKU_123'] },
163
+ },
164
+ },
165
+ },
166
+ },
167
+ },
168
+ empty_object: {
169
+ type: 'object',
170
+ properties: {},
171
+ },
172
+ },
173
+ };
174
+
175
+ const example = buildExampleFromSchema(schema);
176
+
177
+ expect(example).toEqual({
178
+ event: 'test_event',
179
+ ecommerce: {
180
+ items: [
181
+ {
182
+ item_id: 'SKU_123',
183
+ },
184
+ ],
185
+ },
186
+ });
187
+ });
188
+ });
@@ -0,0 +1,44 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { readSchemas, writeDoc, createDir } from '../../helpers/file-system';
4
+
5
+ jest.mock('fs', () => {
6
+ const memfs = require('memfs');
7
+ return memfs;
8
+ });
9
+
10
+ describe('file-system helpers', () => {
11
+ beforeEach(() => {
12
+ fs.vol.reset();
13
+ fs.vol.fromJSON({
14
+ '/schemas/schema1.json': '{}',
15
+ '/schemas/schema2.json': '{}',
16
+ '/schemas/not-a-schema.txt': 'hello',
17
+ });
18
+ });
19
+
20
+ describe('readSchemas', () => {
21
+ it('should read all json files from a directory', () => {
22
+ const schemas = readSchemas('/schemas');
23
+ expect(schemas).toHaveLength(2);
24
+ expect(schemas[0].fileName).toBe('schema1.json');
25
+ expect(schemas[1].fileName).toBe('schema2.json');
26
+ });
27
+ });
28
+
29
+ describe('writeDoc', () => {
30
+ it('should write a file to the specified directory', () => {
31
+ fs.mkdirSync('/output', { recursive: true });
32
+ writeDoc('/output', 'doc1.mdx', 'content');
33
+ const content = fs.readFileSync('/output/doc1.mdx', 'utf-8');
34
+ expect(content).toBe('content');
35
+ });
36
+ });
37
+
38
+ describe('createDir', () => {
39
+ it('should create a directory if it does not exist', () => {
40
+ createDir('/new-dir');
41
+ expect(fs.existsSync('/new-dir')).toBe(true);
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,58 @@
1
+ import { getConstraints } from '../../helpers/getConstraints';
2
+
3
+ describe('getConstraints', () => {
4
+ it('should return "required" if isReq is true', () => {
5
+ const constraints = getConstraints({}, true);
6
+ expect(constraints).toContain('required');
7
+ });
8
+
9
+ it('should handle simple key-value constraints', () => {
10
+ const prop = {
11
+ minLength: 1,
12
+ maxLength: 10,
13
+ minimum: 0,
14
+ maximum: 100,
15
+ minItems: 1,
16
+ maxItems: 5,
17
+ };
18
+ const constraints = getConstraints(prop, false);
19
+ expect(constraints).toEqual([
20
+ 'minLength: 1',
21
+ 'maxLength: 10',
22
+ 'minimum: 0',
23
+ 'maximum: 100',
24
+ 'minItems: 1',
25
+ 'maxItems: 5',
26
+ ]);
27
+ });
28
+
29
+ it('should handle pattern constraint', () => {
30
+ const prop = { pattern: '^[a-z]+$' };
31
+ const constraints = getConstraints(prop, false);
32
+ expect(constraints).toContain('pattern: /^[a-z]+$/');
33
+ });
34
+
35
+ it('should handle uniqueItems constraint', () => {
36
+ const prop = { uniqueItems: true };
37
+ const constraints = getConstraints(prop, false);
38
+ expect(constraints).toContain('uniqueItems: true');
39
+ });
40
+
41
+ it('should handle additionalProperties constraint', () => {
42
+ const prop = { additionalProperties: false };
43
+ const constraints = getConstraints(prop, false);
44
+ expect(constraints).toContain('additionalProperties: false');
45
+ });
46
+
47
+ it('should handle enum constraint', () => {
48
+ const prop = { enum: ['a', 'b', 'c'] };
49
+ const constraints = getConstraints(prop, false);
50
+ expect(constraints).toContain('enum: [a, b, c]');
51
+ });
52
+
53
+ it('should handle const constraint', () => {
54
+ const prop = { const: 'a' };
55
+ const constraints = getConstraints(prop, false);
56
+ expect(constraints).toContain('const: "a"');
57
+ });
58
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import loadSchema from '../../helpers/loadSchema';
7
+
8
+ describe('loadSchema', () => {
9
+ it('should load and parse a JSON file', () => {
10
+ const filePath = path.join(
11
+ __dirname,
12
+ '..',
13
+ '__fixtures__',
14
+ 'validateSchemas',
15
+ 'circular-schema.json',
16
+ );
17
+ const schema = loadSchema(filePath);
18
+ expect(schema.title).toBe('Circular Schema');
19
+ });
20
+ });
@@ -0,0 +1,34 @@
1
+ import { getPathsForVersion } from '../../helpers/path-helpers';
2
+ import path from 'path';
3
+
4
+ describe('getPathsForVersion', () => {
5
+ const siteDir = '/test/site';
6
+
7
+ it('should return paths for a specific version', () => {
8
+ const version = '1.0.0';
9
+ const { schemaDir, outputDir } = getPathsForVersion(version, siteDir);
10
+ expect(schemaDir).toBe(path.join(siteDir, 'static/schemas', version));
11
+ expect(outputDir).toBe(
12
+ path.join(siteDir, 'versioned_docs', `version-${version}`),
13
+ );
14
+ });
15
+
16
+ it('should return paths for the "current" version', () => {
17
+ const version = 'current';
18
+ const { schemaDir, outputDir } = getPathsForVersion(version, siteDir);
19
+ expect(schemaDir).toBe(path.join(siteDir, 'static/schemas', 'next'));
20
+ expect(outputDir).toBe(path.join(siteDir, 'docs'));
21
+ });
22
+
23
+ it('should return paths for a non-versioned site', () => {
24
+ const { schemaDir, outputDir } = getPathsForVersion(null, siteDir);
25
+ expect(schemaDir).toBe(path.join(siteDir, 'static/schemas'));
26
+ expect(outputDir).toBe(path.join(siteDir, 'docs'));
27
+ });
28
+
29
+ it('should handle undefined version', () => {
30
+ const { schemaDir, outputDir } = getPathsForVersion(undefined, siteDir);
31
+ expect(schemaDir).toBe(path.join(siteDir, 'static/schemas'));
32
+ expect(outputDir).toBe(path.join(siteDir, 'docs'));
33
+ });
34
+ });
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import processSchema from '../../helpers/processSchema';
7
+
8
+ describe('processSchema', () => {
9
+ it('should bundle refs and return a merged schema', async () => {
10
+ const filePath = path.join(
11
+ __dirname,
12
+ '..',
13
+ '__fixtures__',
14
+ 'validateSchemas',
15
+ 'main-schema-with-ref.json',
16
+ );
17
+ const mergedSchema = await processSchema(filePath);
18
+
19
+ expect(mergedSchema.title).toBe('Main Schema with Ref');
20
+ expect(mergedSchema.properties.component.$ref).toBeUndefined();
21
+ expect(mergedSchema.properties.component.type).toBe('object');
22
+ expect(mergedSchema.properties.component.properties.prop.type).toBe(
23
+ 'string',
24
+ );
25
+ });
26
+
27
+ it('should handle circular references correctly', async () => {
28
+ const filePath = path.join(
29
+ __dirname,
30
+ '..',
31
+ '__fixtures__',
32
+ 'validateSchemas',
33
+ 'circular-schema.json',
34
+ );
35
+ const mergedSchema = await processSchema(filePath);
36
+
37
+ expect(mergedSchema.title).toBe('Circular Schema');
38
+ expect(mergedSchema.properties.parent.$ref).toBe('#');
39
+ });
40
+
41
+ it('should handle multi-file circular references and produce a self-contained schema', async () => {
42
+ const filePath = path.join(
43
+ __dirname,
44
+ '..',
45
+ '__fixtures__',
46
+ 'validateSchemas',
47
+ 'schema-A.json',
48
+ );
49
+ const mergedSchema = await processSchema(filePath);
50
+
51
+ expect(mergedSchema.title).toBe('Schema A');
52
+ expect(mergedSchema.properties.b.$ref).toBeUndefined();
53
+ expect(mergedSchema.properties.b.title).toBe('Schema B');
54
+ expect(mergedSchema.properties.b.properties.a.$ref).toBe('#');
55
+ });
56
+ });