doc-detective 3.4.1 → 3.5.0-dev.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 (43) hide show
  1. package/.github/FUNDING.yml +14 -14
  2. package/.github/dependabot.yml +11 -11
  3. package/.github/workflows/auto-dev-release.yml +173 -173
  4. package/.github/workflows/npm-test.yaml +96 -96
  5. package/.github/workflows/update-core.yaml +131 -131
  6. package/CONTRIBUTIONS.md +27 -27
  7. package/LICENSE +661 -661
  8. package/README.md +110 -110
  9. package/dev/dev.config.json +8 -8
  10. package/dev/dev.spec.json +30 -30
  11. package/dev/index.js +5 -5
  12. package/package.json +47 -47
  13. package/samples/.doc-detective.json +94 -94
  14. package/samples/doc-content-detect.md +10 -10
  15. package/samples/doc-content-inline-tests.md +23 -23
  16. package/samples/docker-hello.spec.json +15 -15
  17. package/samples/env +2 -2
  18. package/samples/http.spec.yaml +37 -37
  19. package/samples/kitten-search-detect.md +7 -7
  20. package/samples/kitten-search-inline.md +15 -15
  21. package/samples/kitten-search.spec.json +28 -28
  22. package/samples/local-gui.md +5 -5
  23. package/samples/tests.spec.json +70 -70
  24. package/samples/variables.env +4 -4
  25. package/scripts/bump-sync-version-core.js +110 -108
  26. package/src/checkDependencies.js +84 -84
  27. package/src/index.js +72 -72
  28. package/src/utils.js +1023 -1023
  29. package/test/artifacts/cleanup.spec.json +18 -18
  30. package/test/artifacts/config.json +6 -6
  31. package/test/artifacts/doc-content.md +23 -23
  32. package/test/artifacts/env +2 -2
  33. package/test/artifacts/httpRequest.spec.yaml +37 -37
  34. package/test/artifacts/runShell.spec.json +29 -29
  35. package/test/artifacts/setup.spec.json +18 -18
  36. package/test/artifacts/test.spec.json +46 -46
  37. package/test/resolvedTests.test.js +193 -193
  38. package/test/runTests.test.js +53 -53
  39. package/test/server/index.js +185 -185
  40. package/test/server/public/index.html +174 -174
  41. package/test/test-config.json +12 -12
  42. package/test/test-results.json +124 -124
  43. package/test/utils.test.js +298 -298
@@ -1,193 +1,193 @@
1
- const { createServer } = require("./server");
2
- const path = require("path");
3
- const { spawnCommand } = require("../src/utils");
4
- const assert = require("assert").strict;
5
- const fs = require("fs");
6
- const artifactPath = path.resolve(__dirname, "./artifacts");
7
- const outputFile = path.resolve(`${artifactPath}/resolvedTestsResults.json`);
8
-
9
- // Create a server with custom options
10
- const server = createServer({
11
- port: 8093,
12
- staticDir: "./test/server/public",
13
- });
14
-
15
- // Start the server before tests
16
- before(async () => {
17
- try {
18
- await server.start();
19
- } catch (error) {
20
- console.error(`Failed to start test server: ${error.message}`);
21
- throw error;
22
- }
23
- });
24
-
25
- // Stop the server after tests
26
- after(async () => {
27
- try {
28
- await server.stop();
29
- } catch (error) {
30
- console.error(`Failed to stop test server: ${error.message}`);
31
- }
32
- });
33
-
34
- describe("DOC_DETECTIVE_API environment variable", function () {
35
- // Set indefinite timeout
36
- this.timeout(0);
37
-
38
- it("Should fetch and run resolved tests from API", async () => {
39
- const apiConfig = {
40
- accountId: "test-account",
41
- url: "http://localhost:8093/api/resolved-tests",
42
- token: "test-token-123",
43
- contextIds: "test-context",
44
- };
45
-
46
- // Set environment variable
47
- const originalEnv = process.env.DOC_DETECTIVE_API;
48
- process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfig);
49
-
50
- try {
51
- const result = await spawnCommand(
52
- `node ./src/index.js -o ${outputFile}`
53
- );
54
-
55
- // Wait until the file is written
56
- let waitCount = 0;
57
- while (!fs.existsSync(outputFile) && waitCount < 50) {
58
- await new Promise((resolve) => setTimeout(resolve, 100));
59
- waitCount++;
60
- }
61
-
62
- if (fs.existsSync(outputFile)) {
63
- const testResult = require(outputFile);
64
- console.log(
65
- "API Result summary:",
66
- JSON.stringify(testResult.summary, null, 2)
67
- );
68
- // Clean up the require cache
69
- delete require.cache[require.resolve(outputFile)];
70
- fs.unlinkSync(outputFile);
71
-
72
- // Check that tests were run
73
- assert.ok(testResult.summary);
74
- assert.ok(testResult.specs);
75
- }
76
- } finally {
77
- // Restore original env
78
- if (originalEnv !== undefined) {
79
- process.env.DOC_DETECTIVE_API = originalEnv;
80
- } else {
81
- delete process.env.DOC_DETECTIVE_API;
82
- }
83
- }
84
- });
85
-
86
- it("Should reject API config without required fields", async () => {
87
- const invalidApiConfig = {
88
- accountId: "test-account",
89
- // Missing url and token
90
- };
91
-
92
- const originalEnv = process.env.DOC_DETECTIVE_API;
93
- process.env.DOC_DETECTIVE_API = JSON.stringify(invalidApiConfig);
94
-
95
- try {
96
- const result = await spawnCommand(
97
- `node ./src/index.js -o ${outputFile}`
98
- );
99
-
100
- // Should exit with non-zero code
101
- assert.notEqual(result.exitCode, 0);
102
- } finally {
103
- // Restore original env
104
- if (originalEnv !== undefined) {
105
- process.env.DOC_DETECTIVE_API = originalEnv;
106
- } else {
107
- delete process.env.DOC_DETECTIVE_API;
108
- }
109
- }
110
- });
111
-
112
- it("Should reject unauthorized API requests", async () => {
113
- const apiConfigBadToken = {
114
- accountId: "test-account",
115
- url: "http://localhost:8093/api/resolved-tests",
116
- token: "wrong-token",
117
- contextIds: "test-context",
118
- };
119
-
120
- const originalEnv = process.env.DOC_DETECTIVE_API;
121
- process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfigBadToken);
122
-
123
- try {
124
- const result = await spawnCommand(
125
- `node ./src/index.js -o ${outputFile}`
126
- );
127
-
128
- // Should exit with non-zero code due to 401 response
129
- assert.notEqual(result.exitCode, 0);
130
- } finally {
131
- // Restore original env
132
- if (originalEnv !== undefined) {
133
- process.env.DOC_DETECTIVE_API = originalEnv;
134
- } else {
135
- delete process.env.DOC_DETECTIVE_API;
136
- }
137
- }
138
- });
139
-
140
- it("Should apply config overrides from DOC_DETECTIVE_CONFIG to API-fetched tests", async () => {
141
- const apiConfig = {
142
- accountId: "test-account",
143
- url: "http://localhost:8093/api/resolved-tests",
144
- token: "test-token-123",
145
- contextIds: "test-context",
146
- };
147
-
148
- const configOverride = {
149
- logLevel: "debug",
150
- };
151
-
152
- const originalApiEnv = process.env.DOC_DETECTIVE_API;
153
- const originalConfigEnv = process.env.DOC_DETECTIVE_CONFIG;
154
- process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfig);
155
- process.env.DOC_DETECTIVE_CONFIG = JSON.stringify(configOverride);
156
-
157
- try {
158
- await spawnCommand(
159
- `node ./src/index.js -o ${outputFile}`
160
- );
161
-
162
- // Wait until the file is written
163
- let waitCount = 0;
164
- while (!fs.existsSync(outputFile) && waitCount < 50) {
165
- await new Promise((resolve) => setTimeout(resolve, 100));
166
- waitCount++;
167
- }
168
-
169
- if (fs.existsSync(outputFile)) {
170
- const testResult = require(outputFile);
171
- // Clean up the require cache
172
- delete require.cache[require.resolve(outputFile)];
173
- fs.unlinkSync(outputFile);
174
-
175
- // Check that tests were run
176
- assert.ok(testResult.summary);
177
- assert.ok(testResult.specs);
178
- }
179
- } finally {
180
- // Restore original env
181
- if (originalApiEnv !== undefined) {
182
- process.env.DOC_DETECTIVE_API = originalApiEnv;
183
- } else {
184
- delete process.env.DOC_DETECTIVE_API;
185
- }
186
- if (originalConfigEnv !== undefined) {
187
- process.env.DOC_DETECTIVE_CONFIG = originalConfigEnv;
188
- } else {
189
- delete process.env.DOC_DETECTIVE_CONFIG;
190
- }
191
- }
192
- });
193
- });
1
+ const { createServer } = require("./server");
2
+ const path = require("path");
3
+ const { spawnCommand } = require("../src/utils");
4
+ const assert = require("assert").strict;
5
+ const fs = require("fs");
6
+ const artifactPath = path.resolve(__dirname, "./artifacts");
7
+ const outputFile = path.resolve(`${artifactPath}/resolvedTestsResults.json`);
8
+
9
+ // Create a server with custom options
10
+ const server = createServer({
11
+ port: 8093,
12
+ staticDir: "./test/server/public",
13
+ });
14
+
15
+ // Start the server before tests
16
+ before(async () => {
17
+ try {
18
+ await server.start();
19
+ } catch (error) {
20
+ console.error(`Failed to start test server: ${error.message}`);
21
+ throw error;
22
+ }
23
+ });
24
+
25
+ // Stop the server after tests
26
+ after(async () => {
27
+ try {
28
+ await server.stop();
29
+ } catch (error) {
30
+ console.error(`Failed to stop test server: ${error.message}`);
31
+ }
32
+ });
33
+
34
+ describe("DOC_DETECTIVE_API environment variable", function () {
35
+ // Set indefinite timeout
36
+ this.timeout(0);
37
+
38
+ it("Should fetch and run resolved tests from API", async () => {
39
+ const apiConfig = {
40
+ accountId: "test-account",
41
+ url: "http://localhost:8093/api/resolved-tests",
42
+ token: "test-token-123",
43
+ contextIds: "test-context",
44
+ };
45
+
46
+ // Set environment variable
47
+ const originalEnv = process.env.DOC_DETECTIVE_API;
48
+ process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfig);
49
+
50
+ try {
51
+ const result = await spawnCommand(
52
+ `node ./src/index.js -o ${outputFile}`
53
+ );
54
+
55
+ // Wait until the file is written
56
+ let waitCount = 0;
57
+ while (!fs.existsSync(outputFile) && waitCount < 50) {
58
+ await new Promise((resolve) => setTimeout(resolve, 100));
59
+ waitCount++;
60
+ }
61
+
62
+ if (fs.existsSync(outputFile)) {
63
+ const testResult = require(outputFile);
64
+ console.log(
65
+ "API Result summary:",
66
+ JSON.stringify(testResult.summary, null, 2)
67
+ );
68
+ // Clean up the require cache
69
+ delete require.cache[require.resolve(outputFile)];
70
+ fs.unlinkSync(outputFile);
71
+
72
+ // Check that tests were run
73
+ assert.ok(testResult.summary);
74
+ assert.ok(testResult.specs);
75
+ }
76
+ } finally {
77
+ // Restore original env
78
+ if (originalEnv !== undefined) {
79
+ process.env.DOC_DETECTIVE_API = originalEnv;
80
+ } else {
81
+ delete process.env.DOC_DETECTIVE_API;
82
+ }
83
+ }
84
+ });
85
+
86
+ it("Should reject API config without required fields", async () => {
87
+ const invalidApiConfig = {
88
+ accountId: "test-account",
89
+ // Missing url and token
90
+ };
91
+
92
+ const originalEnv = process.env.DOC_DETECTIVE_API;
93
+ process.env.DOC_DETECTIVE_API = JSON.stringify(invalidApiConfig);
94
+
95
+ try {
96
+ const result = await spawnCommand(
97
+ `node ./src/index.js -o ${outputFile}`
98
+ );
99
+
100
+ // Should exit with non-zero code
101
+ assert.notEqual(result.exitCode, 0);
102
+ } finally {
103
+ // Restore original env
104
+ if (originalEnv !== undefined) {
105
+ process.env.DOC_DETECTIVE_API = originalEnv;
106
+ } else {
107
+ delete process.env.DOC_DETECTIVE_API;
108
+ }
109
+ }
110
+ });
111
+
112
+ it("Should reject unauthorized API requests", async () => {
113
+ const apiConfigBadToken = {
114
+ accountId: "test-account",
115
+ url: "http://localhost:8093/api/resolved-tests",
116
+ token: "wrong-token",
117
+ contextIds: "test-context",
118
+ };
119
+
120
+ const originalEnv = process.env.DOC_DETECTIVE_API;
121
+ process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfigBadToken);
122
+
123
+ try {
124
+ const result = await spawnCommand(
125
+ `node ./src/index.js -o ${outputFile}`
126
+ );
127
+
128
+ // Should exit with non-zero code due to 401 response
129
+ assert.notEqual(result.exitCode, 0);
130
+ } finally {
131
+ // Restore original env
132
+ if (originalEnv !== undefined) {
133
+ process.env.DOC_DETECTIVE_API = originalEnv;
134
+ } else {
135
+ delete process.env.DOC_DETECTIVE_API;
136
+ }
137
+ }
138
+ });
139
+
140
+ it("Should apply config overrides from DOC_DETECTIVE_CONFIG to API-fetched tests", async () => {
141
+ const apiConfig = {
142
+ accountId: "test-account",
143
+ url: "http://localhost:8093/api/resolved-tests",
144
+ token: "test-token-123",
145
+ contextIds: "test-context",
146
+ };
147
+
148
+ const configOverride = {
149
+ logLevel: "debug",
150
+ };
151
+
152
+ const originalApiEnv = process.env.DOC_DETECTIVE_API;
153
+ const originalConfigEnv = process.env.DOC_DETECTIVE_CONFIG;
154
+ process.env.DOC_DETECTIVE_API = JSON.stringify(apiConfig);
155
+ process.env.DOC_DETECTIVE_CONFIG = JSON.stringify(configOverride);
156
+
157
+ try {
158
+ await spawnCommand(
159
+ `node ./src/index.js -o ${outputFile}`
160
+ );
161
+
162
+ // Wait until the file is written
163
+ let waitCount = 0;
164
+ while (!fs.existsSync(outputFile) && waitCount < 50) {
165
+ await new Promise((resolve) => setTimeout(resolve, 100));
166
+ waitCount++;
167
+ }
168
+
169
+ if (fs.existsSync(outputFile)) {
170
+ const testResult = require(outputFile);
171
+ // Clean up the require cache
172
+ delete require.cache[require.resolve(outputFile)];
173
+ fs.unlinkSync(outputFile);
174
+
175
+ // Check that tests were run
176
+ assert.ok(testResult.summary);
177
+ assert.ok(testResult.specs);
178
+ }
179
+ } finally {
180
+ // Restore original env
181
+ if (originalApiEnv !== undefined) {
182
+ process.env.DOC_DETECTIVE_API = originalApiEnv;
183
+ } else {
184
+ delete process.env.DOC_DETECTIVE_API;
185
+ }
186
+ if (originalConfigEnv !== undefined) {
187
+ process.env.DOC_DETECTIVE_CONFIG = originalConfigEnv;
188
+ } else {
189
+ delete process.env.DOC_DETECTIVE_CONFIG;
190
+ }
191
+ }
192
+ });
193
+ });
@@ -1,53 +1,53 @@
1
- const { createServer } = require("./server");
2
- const path = require("path");
3
- const { spawnCommand } = require("../src/utils");
4
- const assert = require("assert").strict;
5
- const fs = require("fs");
6
- const artifactPath = path.resolve(__dirname, "./artifacts");
7
- const outputFile = path.resolve(`${artifactPath}/testResults.json`);
8
-
9
- // Create a server with custom options
10
- const server = createServer({
11
- port: 8092,
12
- staticDir: './test/server/public',
13
- modifyResponse: (req, body) => {
14
- // Optional modification of responses
15
- return { ...body, extraField: 'added by server' };
16
- }
17
- });
18
-
19
- // Start the server before tests
20
- before(async () => {
21
- try {
22
- await server.start();
23
- } catch (error) {
24
- console.error(`Failed to start test server: ${error.message}`);
25
- throw error;
26
- }
27
- });
28
-
29
- // Stop the server after tests
30
- after(async () => {
31
- try {
32
- await server.stop();
33
- } catch (error) {
34
- console.error(`Failed to stop test server: ${error.message}`);
35
- // Don't rethrow here to avoid masking test failures
36
- }
37
- });
38
-
39
- describe("Run tests successfully", function () {
40
- // Set indefinite timeout
41
- this.timeout(0);
42
- it("All specs pass", async () => {
43
- await spawnCommand(
44
- `node ./src/index.js -c ${artifactPath}/config.json -i ${artifactPath} -o ${outputFile}`
45
- );
46
- // Wait until the file is written
47
- while (!fs.existsSync(outputFile)) {}
48
- const result = require(outputFile);
49
- console.log(JSON.stringify(result, null, 2));
50
- fs.unlinkSync(outputFile);
51
- assert.equal(result.summary.specs.fail, 0);
52
- });
53
- });
1
+ const { createServer } = require("./server");
2
+ const path = require("path");
3
+ const { spawnCommand } = require("../src/utils");
4
+ const assert = require("assert").strict;
5
+ const fs = require("fs");
6
+ const artifactPath = path.resolve(__dirname, "./artifacts");
7
+ const outputFile = path.resolve(`${artifactPath}/testResults.json`);
8
+
9
+ // Create a server with custom options
10
+ const server = createServer({
11
+ port: 8092,
12
+ staticDir: './test/server/public',
13
+ modifyResponse: (req, body) => {
14
+ // Optional modification of responses
15
+ return { ...body, extraField: 'added by server' };
16
+ }
17
+ });
18
+
19
+ // Start the server before tests
20
+ before(async () => {
21
+ try {
22
+ await server.start();
23
+ } catch (error) {
24
+ console.error(`Failed to start test server: ${error.message}`);
25
+ throw error;
26
+ }
27
+ });
28
+
29
+ // Stop the server after tests
30
+ after(async () => {
31
+ try {
32
+ await server.stop();
33
+ } catch (error) {
34
+ console.error(`Failed to stop test server: ${error.message}`);
35
+ // Don't rethrow here to avoid masking test failures
36
+ }
37
+ });
38
+
39
+ describe("Run tests successfully", function () {
40
+ // Set indefinite timeout
41
+ this.timeout(0);
42
+ it("All specs pass", async () => {
43
+ await spawnCommand(
44
+ `node ./src/index.js -c ${artifactPath}/config.json -i ${artifactPath} -o ${outputFile}`
45
+ );
46
+ // Wait until the file is written
47
+ while (!fs.existsSync(outputFile)) {}
48
+ const result = require(outputFile);
49
+ console.log(JSON.stringify(result, null, 2));
50
+ fs.unlinkSync(outputFile);
51
+ assert.equal(result.summary.specs.fail, 0);
52
+ });
53
+ });