doc-detective 3.1.0-dev.1 → 3.1.0-dev.3

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.
@@ -46,57 +46,31 @@ jobs:
46
46
  echo "Failed to install doc-detective-core@${{ steps.version.outputs.version }} or doc-detective-common@${{ steps.common_version.outputs.common_version }}"
47
47
  exit 1
48
48
  }
49
- npm audit fix
50
49
 
51
50
  - name: Test the installation
52
51
  run: |
53
52
  npm test
54
53
 
55
- - name: Commit changes
56
- id: commit
54
+ - name: Stage changes
55
+ id: stage
57
56
  run: |
58
57
  git add package.json package-lock.json
59
58
  if git diff --staged --quiet; then
60
59
  echo "No changes to commit"
61
60
  echo "has_changes=false" >> $GITHUB_OUTPUT
62
61
  else
63
- git commit -m "chore: bump doc-detective-core version to ${{ steps.version.outputs.version }}"
64
- git push
65
62
  echo "has_changes=true" >> $GITHUB_OUTPUT
66
63
  fi
67
64
 
68
65
  - name: Bump or sync version
69
66
  id: patch
70
- if: steps.commit.outputs.has_changes == 'true'
67
+ if: steps.stage.outputs.has_changes == 'true'
71
68
  run: |
72
- git checkout -- .
73
- git clean -fd
74
- # Get current project version
75
- PROJ_VERSION=$(node -p "require('./package.json').version")
76
- # Get doc-detective-core version (strip ^ or ~)
77
- CORE_VERSION=$(node -p "(require('./package.json').dependencies['doc-detective-core'] || require('./package.json').devDependencies['doc-detective-core'] || '').replace(/^[^\\d]*/, '')")
78
- # Parse versions
79
- PROJ_MAJOR=$(echo $PROJ_VERSION | cut -d. -f1)
80
- PROJ_MINOR=$(echo $PROJ_VERSION | cut -d. -f2)
81
- core_MAJOR=$(echo $CORE_VERSION | cut -d. -f1)
82
- core_MINOR=$(echo $CORE_VERSION | cut -d. -f2)
83
- if [ "$PROJ_MAJOR" != "$core_MAJOR" ] || [ "$PROJ_MINOR" != "$core_MINOR" ]; then
84
- # Major or minor mismatch: set version to match doc-detective-core major.minor.0
85
- NEW_VERSION="$core_MAJOR.$core_MINOR.0"
86
- npm version --no-git-tag-version "$NEW_VERSION"
87
- else
88
- # Only patch changed: bump patch
89
- npm version patch --no-git-tag-version
90
- fi
91
- git add package.json package-lock.json
92
- git commit -m "bump version to match doc-detective-core"
93
- git push
94
- git tag "v$(node -p \"require('./package.json').version\")"
95
- git push --tags
96
- echo "version=$(node -p \"require('./package.json').version\")" >> $GITHUB_OUTPUT
69
+ node scripts/bump-sync-version-core.js
70
+ version=$(node -p 'require("./package.json").version') && echo "version=$version" >> $GITHUB_OUTPUT
97
71
 
98
- - name: Create release
99
- if: steps.commit.outputs.has_changes == 'true'
72
+ - name: Install GitHub CLI
73
+ if: steps.stage.outputs.has_changes == 'true'
100
74
  # Install GitHub CLI for fetching PRs and release notes
101
75
  run: |
102
76
  sudo apt-get update && sudo apt-get install -y gh jq
@@ -120,9 +94,11 @@ jobs:
120
94
  echo "$PRS" >> $GITHUB_OUTPUT
121
95
  echo "EOF" >> $GITHUB_OUTPUT
122
96
  fi
97
+ env:
98
+ GITHUB_TOKEN: ${{ secrets.DD_DEP_UPDATE_TOKEN }}
123
99
 
124
100
  - name: Fetch doc-detective-core release notes
125
- id: core_release
101
+ id: CORE_release
126
102
  run: |
127
103
  CORE_VERSION=${{ steps.version.outputs.version }}
128
104
  # Remove ^ or ~ if present
@@ -132,9 +108,11 @@ jobs:
132
108
  echo "release_notes<<EOF" >> $GITHUB_OUTPUT
133
109
  echo "$RELEASE_INFO" >> $GITHUB_OUTPUT
134
110
  echo "EOF" >> $GITHUB_OUTPUT
111
+ env:
112
+ GITHUB_TOKEN: ${{ secrets.DD_DEP_UPDATE_TOKEN }}
135
113
 
136
114
  - name: Create release with detailed notes
137
- if: steps.commit.outputs.has_changes == 'true'
115
+ if: steps.stage.outputs.has_changes == 'true'
138
116
  uses: softprops/action-gh-release@v2
139
117
  with:
140
118
  body: |
@@ -142,7 +120,7 @@ jobs:
142
120
 
143
121
  - Updated doc-detective-core to v${{ steps.patch.outputs.version }}:
144
122
 
145
- ${{ steps.core_release.outputs.release_notes }}
123
+ ${{ steps.CORE_release.outputs.release_notes }}
146
124
 
147
125
  ${{ steps.merged_prs.outputs.prs }}
148
126
  tag_name: "v${{ steps.patch.outputs.version }}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc-detective",
3
- "version": "3.1.0-dev.1",
3
+ "version": "3.1.0-dev.3",
4
4
  "description": "Treat doc content as testable assertions to validate doc accuracy and product UX.",
5
5
  "bin": {
6
6
  "doc-detective": "src/index.js"
@@ -33,12 +33,12 @@
33
33
  "homepage": "https://github.com/doc-detective/doc-detective#readme",
34
34
  "dependencies": {
35
35
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
36
- "doc-detective-common": "^3.1.0-dev.1",
37
- "doc-detective-core": "^3.0.0-dev.4",
36
+ "doc-detective-common": "^3.1.0",
37
+ "doc-detective-core": "^3.1.0",
38
38
  "yargs": "^17.7.2"
39
39
  },
40
40
  "devDependencies": {
41
41
  "chai": "^5.2.0",
42
- "mocha": "^11.6.0"
42
+ "mocha": "^11.7.0"
43
43
  }
44
44
  }
package/reference.png ADDED
Binary file
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require("child_process");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const semver = require("semver");
7
+
8
+ function execCommand(command, options = {}) {
9
+ try {
10
+ return execSync(command, {
11
+ encoding: "utf8",
12
+ stdio: "inherit",
13
+ ...options,
14
+ });
15
+ } catch (error) {
16
+ console.error(`Error executing command: ${command}`);
17
+ process.exit(1);
18
+ }
19
+ }
20
+
21
+ function main() {
22
+ // Clean git state
23
+ execCommand("git checkout -- .");
24
+ execCommand("git clean -fd");
25
+
26
+ // Get current project version
27
+ const packageJsonPath = path.join(process.cwd(), "package.json");
28
+
29
+ if (!fs.existsSync(packageJsonPath)) {
30
+ console.error("Error: package.json not found");
31
+ process.exit(1);
32
+ }
33
+
34
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
35
+ const projVersion = semver.minVersion(packageJson.version);
36
+
37
+ // Get doc-detective-core version
38
+ const coreVersion = semver.minVersion(
39
+ packageJson.dependencies?.["doc-detective-core"] ||
40
+ packageJson.devDependencies?.["doc-detective-core"] ||
41
+ ""
42
+ );
43
+
44
+ if (!coreVersion) {
45
+ console.error("Error: doc-detective-core dependency not found");
46
+ process.exit(1);
47
+ }
48
+
49
+ if (!semver.valid(projVersion)) {
50
+ console.error(`Error: Invalid project version format: ${projVersion}`);
51
+ process.exit(1);
52
+ }
53
+
54
+ // Extract major and minor versions using semver
55
+ const projMajor = semver.major(projVersion);
56
+ const projMinor = semver.minor(projVersion);
57
+ const coreMajor = semver.major(coreVersion);
58
+ const coreMinor = semver.minor(coreVersion);
59
+
60
+ console.log(`Project version: ${projMajor}.${projMinor}.x`);
61
+ console.log(`core version: ${coreMajor}.${coreMinor}.x`);
62
+
63
+ let newVersion;
64
+
65
+ if (projMajor !== coreMajor || projMinor !== coreMinor) {
66
+ // Major or minor mismatch: set version to match doc-detective-core major.minor.0
67
+ newVersion = `${coreMajor}.${coreMinor}.0`;
68
+
69
+ // Validate the new version before setting it
70
+ if (!semver.valid(newVersion)) {
71
+ console.error(`Error: Generated invalid version: ${newVersion}`);
72
+ process.exit(1);
73
+ }
74
+
75
+ console.log(`Version mismatch detected. Setting version to: ${newVersion}`);
76
+ execCommand(`npm version --no-git-tag-version ${newVersion}`);
77
+ } else {
78
+ // Project version is already equal or greater than core version, just bump patch
79
+ console.log("Project version is current or ahead. Bumping patch version.");
80
+ execCommand("npm version patch --no-git-tag-version");
81
+ // Get the new version after bumping
82
+ const updatedPackageJson = JSON.parse(
83
+ fs.readFileSync(packageJsonPath, "utf8")
84
+ );
85
+ newVersion = updatedPackageJson.version;
86
+ }
87
+
88
+ // Commit changes
89
+ execCommand("git add package.json package-lock.json");
90
+ execCommand(
91
+ 'git commit -m "update doc-detective-core [skip ci]"'
92
+ );
93
+
94
+ // Create tag
95
+ execCommand(`git tag "v${newVersion}"`);
96
+
97
+ // Push changes and tags
98
+ execCommand("git push");
99
+ execCommand("git push --tags");
100
+
101
+ // Output version (equivalent to echo in bash script)
102
+ console.log(`version=${newVersion}`);
103
+ }
104
+
105
+ // Run the script
106
+ if (require.main === module) {
107
+ main();
108
+ }
109
+
110
+ module.exports = { main };
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ async function main(argv) {
35
35
  : null;
36
36
 
37
37
  // Set config
38
- config = await setConfig({ configPath: configPath, args: argv });
38
+ const config = await setConfig({ configPath: configPath, args: argv });
39
39
 
40
40
  // Run tests
41
41
  const output = config.output;
package/src/utils.js CHANGED
@@ -116,8 +116,8 @@ async function setConfig({ configPath, args }) {
116
116
  if (args.logLevel) {
117
117
  config.logLevel = args.logLevel;
118
118
  }
119
- if (args.allowUnsafe) {
120
- config.allowUnsafeTests = true;
119
+ if (typeof args.allowUnsafe === "boolean") {
120
+ config.allowUnsafeSteps = args.allowUnsafe;
121
121
  }
122
122
  // Resolve paths
123
123
  config = await resolvePaths({
@@ -230,6 +230,10 @@ const reporters = {
230
230
  (contexts && contexts.fail > 0) ||
231
231
  (steps && steps.fail > 0);
232
232
 
233
+ // Any skipped overall?
234
+ const allSpecsSkipped =
235
+ specs && specs.pass === 0 && specs.fail === 0 && specs.skipped > 0;
236
+
233
237
  console.log(
234
238
  `\n${colors.bold}===== Doc Detective Results Summary =====${colors.reset}`
235
239
  );
@@ -238,7 +242,11 @@ const reporters = {
238
242
  if (specs) {
239
243
  console.log(`\n${colors.bold}Specs:${colors.reset}`);
240
244
  console.log(`Total: ${totalSpecs}`);
241
- console.log(`${colors.green}Passed: ${specs.pass}${colors.reset}`);
245
+ if (specs.pass > 0) {
246
+ console.log(`${colors.green}Passed: ${specs.pass}${colors.reset}`);
247
+ } else {
248
+ console.log(`Passed: ${specs.pass}`);
249
+ }
242
250
  console.log(
243
251
  `${specs.fail > 0 ? colors.red : colors.green}Failed: ${specs.fail}${
244
252
  colors.reset
@@ -248,14 +256,19 @@ const reporters = {
248
256
  console.log(
249
257
  `${colors.yellow}Warnings: ${specs.warning}${colors.reset}`
250
258
  );
251
- if (specs.skipped > 0) console.log(`Skipped: ${specs.skipped}`);
259
+ if (specs.skipped > 0)
260
+ console.log(`${colors.yellow}Skipped: ${specs.skipped}${colors.reset}`);
252
261
  }
253
262
 
254
263
  // Print tests summary if available
255
264
  if (tests) {
256
265
  console.log(`\n${colors.bold}Tests:${colors.reset}`);
257
266
  console.log(`Total: ${totalTests}`);
258
- console.log(`${colors.green}Passed: ${tests.pass}${colors.reset}`);
267
+ if (tests.pass > 0) {
268
+ console.log(`${colors.green}Passed: ${tests.pass}${colors.reset}`);
269
+ } else {
270
+ console.log(`Passed: ${tests.pass}`);
271
+ }
259
272
  console.log(
260
273
  `${tests.fail > 0 ? colors.red : colors.green}Failed: ${tests.fail}${
261
274
  colors.reset
@@ -265,14 +278,19 @@ const reporters = {
265
278
  console.log(
266
279
  `${colors.yellow}Warnings: ${tests.warning}${colors.reset}`
267
280
  );
268
- if (tests.skipped > 0) console.log(`Skipped: ${tests.skipped}`);
281
+ if (tests.skipped > 0)
282
+ console.log(`${colors.yellow}Skipped: ${tests.skipped}${colors.reset}`);
269
283
  }
270
284
 
271
285
  // Print contexts summary if available
272
286
  if (contexts) {
273
287
  console.log(`\n${colors.bold}Contexts:${colors.reset}`);
274
288
  console.log(`Total: ${totalContexts}`);
275
- console.log(`${colors.green}Passed: ${contexts.pass}${colors.reset}`);
289
+ if (contexts.pass > 0) {
290
+ console.log(`${colors.green}Passed: ${contexts.pass}${colors.reset}`);
291
+ } else {
292
+ console.log(`Passed: ${contexts.pass}`);
293
+ }
276
294
  console.log(
277
295
  `${contexts.fail > 0 ? colors.red : colors.green}Failed: ${
278
296
  contexts.fail
@@ -282,14 +300,19 @@ const reporters = {
282
300
  console.log(
283
301
  `${colors.yellow}Warnings: ${contexts.warning}${colors.reset}`
284
302
  );
285
- if (contexts.skipped > 0) console.log(`Skipped: ${contexts.skipped}`);
303
+ if (contexts.skipped > 0)
304
+ console.log(`${colors.yellow}Skipped: ${contexts.skipped}${colors.reset}`);
286
305
  }
287
306
 
288
307
  // Print steps summary if available
289
308
  if (steps) {
290
309
  console.log(`\n${colors.bold}Steps:${colors.reset}`);
291
310
  console.log(`Total: ${totalSteps}`);
292
- console.log(`${colors.green}Passed: ${steps.pass}${colors.reset}`);
311
+ if (steps.pass > 0) {
312
+ console.log(`${colors.green}Passed: ${steps.pass}${colors.reset}`);
313
+ } else {
314
+ console.log(`Passed: ${steps.pass}`);
315
+ }
293
316
  console.log(
294
317
  `${steps.fail > 0 ? colors.red : colors.green}Failed: ${steps.fail}${
295
318
  colors.reset
@@ -299,7 +322,13 @@ const reporters = {
299
322
  console.log(
300
323
  `${colors.yellow}Warnings: ${steps.warning}${colors.reset}`
301
324
  );
302
- if (steps.skipped > 0) console.log(`Skipped: ${steps.skipped}`);
325
+ if (steps.skipped > 0)
326
+ console.log(`${colors.yellow}Skipped: ${steps.skipped}${colors.reset}`);
327
+ }
328
+
329
+ // If all specs were skipped, call it out
330
+ if (allSpecsSkipped) {
331
+ console.log(`\n${colors.yellow}⚠️ All items were skipped. No specs passed or failed. ⚠️${colors.reset}`);
303
332
  }
304
333
 
305
334
  // If we have specs with failures, display them
@@ -314,7 +343,13 @@ const reporters = {
314
343
  const failedContexts = [];
315
344
  const failedSteps = [];
316
345
 
317
- // Process specs array to collect failures
346
+ // Collect skipped
347
+ const skippedSpecs = [];
348
+ const skippedTests = [];
349
+ const skippedContexts = [];
350
+ const skippedSteps = [];
351
+
352
+ // Process specs array to collect failures and skipped
318
353
  results.specs.forEach((spec, specIndex) => {
319
354
  // Check if spec has failed
320
355
  if (spec.result === "FAIL") {
@@ -323,6 +358,13 @@ const reporters = {
323
358
  id: spec.specId || `Spec ${specIndex + 1}`,
324
359
  });
325
360
  }
361
+ // Check if spec was skipped
362
+ if (spec.result === "SKIPPED") {
363
+ skippedSpecs.push({
364
+ index: specIndex,
365
+ id: spec.specId || `Spec ${specIndex + 1}`,
366
+ });
367
+ }
326
368
 
327
369
  // Process tests in this spec
328
370
  if (spec.tests && spec.tests.length > 0) {
@@ -336,6 +378,15 @@ const reporters = {
336
378
  id: test.testId || `Test ${testIndex + 1}`,
337
379
  });
338
380
  }
381
+ // Check if test was skipped
382
+ if (test.result === "SKIPPED") {
383
+ skippedTests.push({
384
+ specIndex,
385
+ testIndex,
386
+ specId: spec.specId || `Spec ${specIndex + 1}`,
387
+ id: test.testId || `Test ${testIndex + 1}`,
388
+ });
389
+ }
339
390
 
340
391
  // Process contexts in this test
341
392
  if (test.contexts && test.contexts.length > 0) {
@@ -357,6 +408,23 @@ const reporters = {
357
408
  : "unknown",
358
409
  });
359
410
  }
411
+ // Check if context was skipped
412
+ if (
413
+ context.result === "SKIPPED" ||
414
+ (context.result && context.result.status === "SKIPPED")
415
+ ) {
416
+ skippedContexts.push({
417
+ specIndex,
418
+ testIndex,
419
+ contextIndex,
420
+ specId: spec.specId || `Spec ${specIndex + 1}`,
421
+ testId: test.testId || `Test ${testIndex + 1}`,
422
+ platform: context.platform || "unknown",
423
+ browser: context.browser
424
+ ? context.browser.name
425
+ : "unknown",
426
+ });
427
+ }
360
428
 
361
429
  // Process steps in this context
362
430
  if (context.steps && context.steps.length > 0) {
@@ -378,6 +446,22 @@ const reporters = {
378
446
  error: step.resultDescription || "Unknown error",
379
447
  });
380
448
  }
449
+ // Check if step was skipped
450
+ if (step.result === "SKIPPED") {
451
+ skippedSteps.push({
452
+ specIndex,
453
+ testIndex,
454
+ contextIndex,
455
+ stepIndex,
456
+ specId: spec.specId || `Spec ${specIndex + 1}`,
457
+ testId: test.testId || `Test ${testIndex + 1}`,
458
+ platform: context.platform || "unknown",
459
+ browser: context.browser
460
+ ? context.browser.name
461
+ : "unknown",
462
+ stepId: step.stepId || `Step ${stepIndex + 1}`,
463
+ });
464
+ }
381
465
  });
382
466
  }
383
467
  });
@@ -427,7 +511,33 @@ const reporters = {
427
511
  console.log(` Error: ${item.error}`);
428
512
  });
429
513
  }
430
- } else if (!hasFailures) {
514
+
515
+ // Display skipped items in yellow
516
+ if (skippedSpecs.length > 0) {
517
+ console.log(`\n${colors.yellow}Skipped Specs:${colors.reset}`);
518
+ skippedSpecs.forEach((item, i) => {
519
+ console.log(`${colors.yellow}${i + 1}. ${item.id}${colors.reset}`);
520
+ });
521
+ }
522
+ if (skippedTests.length > 0) {
523
+ console.log(`\n${colors.yellow}Skipped Tests:${colors.reset}`);
524
+ skippedTests.forEach((item, i) => {
525
+ console.log(`${colors.yellow}${i + 1}. ${item.id} (from ${item.specId})${colors.reset}`);
526
+ });
527
+ }
528
+ if (skippedContexts.length > 0) {
529
+ console.log(`\n${colors.yellow}Skipped Contexts:${colors.reset}`);
530
+ skippedContexts.forEach((item, i) => {
531
+ console.log(`${colors.yellow}${i + 1}. ${item.platform}/${item.browser} (from ${item.testId})${colors.reset}`);
532
+ });
533
+ }
534
+ if (skippedSteps.length > 0) {
535
+ console.log(`\n${colors.yellow}Skipped Steps:${colors.reset}`);
536
+ skippedSteps.forEach((item, i) => {
537
+ console.log(`${colors.yellow}${i + 1}. ${item.platform}/${item.browser} - ${item.stepId}${colors.reset}`);
538
+ });
539
+ }
540
+ } else if (!hasFailures && !allSpecsSkipped) {
431
541
  // Celebration when all tests pass
432
542
  console.log(`\n${colors.green}🎉 All items passed! 🎉${colors.reset}`);
433
543
  }
@@ -169,7 +169,7 @@ describe("Util tests", function () {
169
169
  ],
170
170
  expected: {
171
171
  input: [path.resolve(process.cwd(), "input.spec.json")],
172
- allowUnsafeTests: true,
172
+ allowUnsafeSteps: true,
173
173
  },
174
174
  }
175
175
  ];