doc-detective 3.0.17 → 3.1.0-dev.2
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/.github/workflows/auto-dev-release.yml +174 -0
- package/.github/workflows/update-core.yaml +70 -5
- package/package.json +4 -4
- package/reference.png +0 -0
- package/src/index.js +1 -1
- package/src/utils.js +128 -10
- package/test/utils.test.js +27 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
name: Auto Dev Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
# Don't trigger on release events to avoid conflicts with main release workflow
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
# Allow manual triggering for testing
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
auto-dev-release:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 10
|
|
15
|
+
# Skip if this is a release commit or docs-only changes
|
|
16
|
+
if: |
|
|
17
|
+
!contains(github.event.head_commit.message, '[skip ci]') &&
|
|
18
|
+
!contains(github.event.head_commit.message, 'Release') &&
|
|
19
|
+
github.event_name != 'release'
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout code
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
# Need full history for proper version bumping
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
# Use a token that can push back to the repo
|
|
28
|
+
token: ${{ secrets.DD_DEP_UPDATE_TOKEN }}
|
|
29
|
+
|
|
30
|
+
- name: Setup Node.js
|
|
31
|
+
uses: actions/setup-node@v4
|
|
32
|
+
with:
|
|
33
|
+
node-version: '18'
|
|
34
|
+
cache: 'npm'
|
|
35
|
+
cache-dependency-path: package-lock.json
|
|
36
|
+
registry-url: 'https://registry.npmjs.org/'
|
|
37
|
+
|
|
38
|
+
- name: Check for documentation-only changes
|
|
39
|
+
id: check_changes
|
|
40
|
+
run: |
|
|
41
|
+
# Always release on workflow_dispatch
|
|
42
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
43
|
+
echo "skip_release=false" >> $GITHUB_OUTPUT
|
|
44
|
+
echo "Manual trigger: proceeding with release"
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Get list of changed files
|
|
49
|
+
CHANGED_FILES=$(git diff --name-only ${{ github.event.before }}..${{ github.event.after }})
|
|
50
|
+
|
|
51
|
+
echo "Changed files:"
|
|
52
|
+
echo "$CHANGED_FILES"
|
|
53
|
+
|
|
54
|
+
# Check if only documentation files changed
|
|
55
|
+
if echo "$CHANGED_FILES" | grep -v -E '\.(md|txt|yml|yaml)$|^\.github/' | grep -q .; then
|
|
56
|
+
echo "skip_release=false" >> $GITHUB_OUTPUT
|
|
57
|
+
echo "Code changes detected, proceeding with release"
|
|
58
|
+
else
|
|
59
|
+
echo "skip_release=true" >> $GITHUB_OUTPUT
|
|
60
|
+
echo "Only documentation changes detected, skipping release"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
- name: Validate package.json
|
|
64
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
65
|
+
run: |
|
|
66
|
+
# Validate package.json exists and is valid JSON
|
|
67
|
+
if [ ! -f "package.json" ]; then
|
|
68
|
+
echo "❌ package.json not found"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Validate JSON syntax
|
|
73
|
+
if ! node -p "JSON.parse(require('fs').readFileSync('package.json', 'utf8'))" > /dev/null 2>&1; then
|
|
74
|
+
echo "❌ package.json is not valid JSON"
|
|
75
|
+
exit 1
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Check for required fields
|
|
79
|
+
if ! node -p "require('./package.json').name" > /dev/null 2>&1; then
|
|
80
|
+
echo "❌ package.json missing 'name' field"
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if ! node -p "require('./package.json').version" > /dev/null 2>&1; then
|
|
85
|
+
echo "❌ package.json missing 'version' field"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
echo "✅ package.json validation passed"
|
|
90
|
+
|
|
91
|
+
- name: Install dependencies
|
|
92
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
93
|
+
run: npm ci
|
|
94
|
+
|
|
95
|
+
- name: Run tests
|
|
96
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
97
|
+
run: npm test
|
|
98
|
+
|
|
99
|
+
- name: Configure Git
|
|
100
|
+
run: |
|
|
101
|
+
git config --global user.name 'github-actions[bot]'
|
|
102
|
+
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
|
103
|
+
|
|
104
|
+
- name: Generate dev version
|
|
105
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
106
|
+
id: version
|
|
107
|
+
run: |
|
|
108
|
+
# Get current version from package.json
|
|
109
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
110
|
+
echo "Current version: $CURRENT_VERSION"
|
|
111
|
+
|
|
112
|
+
# Extract base version (remove existing -dev.X suffix if present)
|
|
113
|
+
BASE_VERSION=$(echo $CURRENT_VERSION | sed 's/-dev\.[0-9]*$//')
|
|
114
|
+
echo "Base version: $BASE_VERSION"
|
|
115
|
+
|
|
116
|
+
# Check if we need to get the latest dev version from npm
|
|
117
|
+
LATEST_DEV=$(npm view doc-detective@dev version 2>/dev/null || echo "")
|
|
118
|
+
|
|
119
|
+
if [ -n "$LATEST_DEV" ] && [[ $LATEST_DEV == $BASE_VERSION-dev.* ]]; then
|
|
120
|
+
# Extract the dev number and increment it
|
|
121
|
+
DEV_NUM=$(echo $LATEST_DEV | grep -o 'dev\.[0-9]*$' | grep -o '[0-9]*$')
|
|
122
|
+
NEW_DEV_NUM=$((DEV_NUM + 1))
|
|
123
|
+
else
|
|
124
|
+
# Start with dev.1
|
|
125
|
+
NEW_DEV_NUM=1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
NEW_VERSION="$BASE_VERSION-dev.$NEW_DEV_NUM"
|
|
129
|
+
echo "New version: $NEW_VERSION"
|
|
130
|
+
|
|
131
|
+
# Update package.json
|
|
132
|
+
npm version $NEW_VERSION --no-git-tag-version
|
|
133
|
+
|
|
134
|
+
# Set outputs
|
|
135
|
+
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
136
|
+
echo "base_version=$BASE_VERSION" >> $GITHUB_OUTPUT
|
|
137
|
+
|
|
138
|
+
- name: Commit version change
|
|
139
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
140
|
+
run: |
|
|
141
|
+
git add package.json package-lock.json
|
|
142
|
+
git commit -m "Auto dev release: v${{ steps.version.outputs.version }} [skip ci]"
|
|
143
|
+
|
|
144
|
+
- name: Create and push git tag
|
|
145
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
146
|
+
run: |
|
|
147
|
+
git tag "v${{ steps.version.outputs.version }}"
|
|
148
|
+
git push origin "v${{ steps.version.outputs.version }}"
|
|
149
|
+
git push origin main
|
|
150
|
+
|
|
151
|
+
- name: Publish to npm
|
|
152
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
153
|
+
run: |
|
|
154
|
+
# Add error handling for npm publish
|
|
155
|
+
set -e
|
|
156
|
+
echo "📦 Publishing to npm with 'dev' tag..."
|
|
157
|
+
npm publish --tag dev
|
|
158
|
+
echo "✅ Successfully published to npm"
|
|
159
|
+
env:
|
|
160
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
161
|
+
|
|
162
|
+
- name: Summary
|
|
163
|
+
if: steps.check_changes.outputs.skip_release == 'false'
|
|
164
|
+
run: |
|
|
165
|
+
echo "✅ Auto dev release completed successfully!"
|
|
166
|
+
echo "📦 Version: v${{ steps.version.outputs.version }}"
|
|
167
|
+
echo "🏷️ NPM Tag: dev"
|
|
168
|
+
echo "📋 Install with: npm install doc-detective@dev"
|
|
169
|
+
|
|
170
|
+
- name: Skip summary
|
|
171
|
+
if: steps.check_changes.outputs.skip_release == 'true'
|
|
172
|
+
run: |
|
|
173
|
+
echo "⏭️ Auto dev release skipped"
|
|
174
|
+
echo "📝 Only documentation changes detected"
|
|
@@ -46,6 +46,7 @@ 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
|
|
49
50
|
|
|
50
51
|
- name: Test the installation
|
|
51
52
|
run: |
|
|
@@ -64,24 +65,88 @@ jobs:
|
|
|
64
65
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
65
66
|
fi
|
|
66
67
|
|
|
67
|
-
- name: Bump
|
|
68
|
+
- name: Bump or sync version
|
|
68
69
|
id: patch
|
|
69
70
|
if: steps.commit.outputs.has_changes == 'true'
|
|
70
71
|
run: |
|
|
71
72
|
git checkout -- .
|
|
72
73
|
git clean -fd
|
|
73
|
-
|
|
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"
|
|
74
93
|
git push
|
|
94
|
+
git tag "v$(node -p \"require('./package.json').version\")"
|
|
75
95
|
git push --tags
|
|
76
|
-
echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
|
96
|
+
echo "version=$(node -p \"require('./package.json').version\")" >> $GITHUB_OUTPUT
|
|
77
97
|
|
|
78
98
|
- name: Create release
|
|
99
|
+
if: steps.commit.outputs.has_changes == 'true'
|
|
100
|
+
# Install GitHub CLI for fetching PRs and release notes
|
|
101
|
+
run: |
|
|
102
|
+
sudo apt-get update && sudo apt-get install -y gh jq
|
|
103
|
+
|
|
104
|
+
- name: Gather merged PRs since last release
|
|
105
|
+
id: merged_prs
|
|
106
|
+
run: |
|
|
107
|
+
# Get previous tag (before the new one)
|
|
108
|
+
PREV_TAG=$(git tag --sort=-creatordate | grep -v "v${{ steps.patch.outputs.version }}" | head -n1)
|
|
109
|
+
CURR_TAG="v${{ steps.patch.outputs.version }}"
|
|
110
|
+
echo "Previous tag: $PREV_TAG, Current tag: $CURR_TAG"
|
|
111
|
+
if [ -z "$PREV_TAG" ]; then
|
|
112
|
+
echo "No previous tag found. Skipping PR list."
|
|
113
|
+
echo "prs=No previous release found." >> $GITHUB_OUTPUT
|
|
114
|
+
else
|
|
115
|
+
PRS=$(gh pr list --state merged --search "merged:>=$(git log -1 --format=%aI $PREV_TAG)" --json number,title,url --jq '.[] | "- [#\(.number)](\(.url)): \(.title)"')
|
|
116
|
+
if [ -z "$PRS" ]; then
|
|
117
|
+
PRS=""
|
|
118
|
+
fi
|
|
119
|
+
echo "prs<<EOF" >> $GITHUB_OUTPUT
|
|
120
|
+
echo "$PRS" >> $GITHUB_OUTPUT
|
|
121
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
- name: Fetch doc-detective-core release notes
|
|
125
|
+
id: core_release
|
|
126
|
+
run: |
|
|
127
|
+
CORE_VERSION=${{ steps.version.outputs.version }}
|
|
128
|
+
# Remove ^ or ~ if present
|
|
129
|
+
CORE_VERSION_CLEAN=$(echo "$CORE_VERSION" | sed 's/^[^0-9]*//')
|
|
130
|
+
# Query GitHub API for release notes
|
|
131
|
+
RELEASE_INFO=$(gh release view "v$CORE_VERSION_CLEAN" --repo doc-detective/doc-detective-core --json body --jq .body || echo "No release notes found.")
|
|
132
|
+
echo "release_notes<<EOF" >> $GITHUB_OUTPUT
|
|
133
|
+
echo "$RELEASE_INFO" >> $GITHUB_OUTPUT
|
|
134
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
135
|
+
|
|
136
|
+
- name: Create release with detailed notes
|
|
79
137
|
if: steps.commit.outputs.has_changes == 'true'
|
|
80
138
|
uses: softprops/action-gh-release@v2
|
|
81
139
|
with:
|
|
82
|
-
body:
|
|
140
|
+
body: |
|
|
141
|
+
# What's new
|
|
142
|
+
|
|
143
|
+
- Updated doc-detective-core to v${{ steps.patch.outputs.version }}:
|
|
144
|
+
|
|
145
|
+
${{ steps.core_release.outputs.release_notes }}
|
|
146
|
+
|
|
147
|
+
${{ steps.merged_prs.outputs.prs }}
|
|
83
148
|
tag_name: "v${{ steps.patch.outputs.version }}"
|
|
84
149
|
name: "v${{ steps.patch.outputs.version }}"
|
|
85
|
-
generate_release_notes:
|
|
150
|
+
generate_release_notes: false
|
|
86
151
|
token: ${{ secrets.DD_DEP_UPDATE_TOKEN }}
|
|
87
152
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doc-detective",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.1.0-dev.2",
|
|
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.0.
|
|
37
|
-
"doc-detective-core": "^3.0.
|
|
36
|
+
"doc-detective-common": "^3.1.0-dev.1",
|
|
37
|
+
"doc-detective-core": "^3.1.0-dev.2",
|
|
38
38
|
"yargs": "^17.7.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"chai": "^5.2.0",
|
|
42
|
-
"mocha": "^11.
|
|
42
|
+
"mocha": "^11.7.0"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/reference.png
ADDED
|
Binary file
|
package/src/index.js
CHANGED
package/src/utils.js
CHANGED
|
@@ -39,6 +39,11 @@ function setArgs(args) {
|
|
|
39
39
|
"Detail level of logging events. Accepted values: silent, error, warning, info (default), debug",
|
|
40
40
|
type: "string",
|
|
41
41
|
})
|
|
42
|
+
.option("allow-unsafe", {
|
|
43
|
+
description:
|
|
44
|
+
"Allow execution of potentially unsafe tests",
|
|
45
|
+
type: "boolean",
|
|
46
|
+
})
|
|
42
47
|
.help()
|
|
43
48
|
.alias("help", "h").argv;
|
|
44
49
|
|
|
@@ -111,6 +116,9 @@ async function setConfig({ configPath, args }) {
|
|
|
111
116
|
if (args.logLevel) {
|
|
112
117
|
config.logLevel = args.logLevel;
|
|
113
118
|
}
|
|
119
|
+
if (typeof args.allowUnsafe === "boolean") {
|
|
120
|
+
config.allowUnsafeTests = args.allowUnsafe;
|
|
121
|
+
}
|
|
114
122
|
// Resolve paths
|
|
115
123
|
config = await resolvePaths({
|
|
116
124
|
config: config,
|
|
@@ -222,6 +230,10 @@ const reporters = {
|
|
|
222
230
|
(contexts && contexts.fail > 0) ||
|
|
223
231
|
(steps && steps.fail > 0);
|
|
224
232
|
|
|
233
|
+
// Any skipped overall?
|
|
234
|
+
const allSpecsSkipped =
|
|
235
|
+
specs && specs.pass === 0 && specs.fail === 0 && specs.skipped > 0;
|
|
236
|
+
|
|
225
237
|
console.log(
|
|
226
238
|
`\n${colors.bold}===== Doc Detective Results Summary =====${colors.reset}`
|
|
227
239
|
);
|
|
@@ -230,7 +242,11 @@ const reporters = {
|
|
|
230
242
|
if (specs) {
|
|
231
243
|
console.log(`\n${colors.bold}Specs:${colors.reset}`);
|
|
232
244
|
console.log(`Total: ${totalSpecs}`);
|
|
233
|
-
|
|
245
|
+
if (specs.pass > 0) {
|
|
246
|
+
console.log(`${colors.green}Passed: ${specs.pass}${colors.reset}`);
|
|
247
|
+
} else {
|
|
248
|
+
console.log(`Passed: ${specs.pass}`);
|
|
249
|
+
}
|
|
234
250
|
console.log(
|
|
235
251
|
`${specs.fail > 0 ? colors.red : colors.green}Failed: ${specs.fail}${
|
|
236
252
|
colors.reset
|
|
@@ -240,14 +256,19 @@ const reporters = {
|
|
|
240
256
|
console.log(
|
|
241
257
|
`${colors.yellow}Warnings: ${specs.warning}${colors.reset}`
|
|
242
258
|
);
|
|
243
|
-
if (specs.skipped > 0)
|
|
259
|
+
if (specs.skipped > 0)
|
|
260
|
+
console.log(`${colors.yellow}Skipped: ${specs.skipped}${colors.reset}`);
|
|
244
261
|
}
|
|
245
262
|
|
|
246
263
|
// Print tests summary if available
|
|
247
264
|
if (tests) {
|
|
248
265
|
console.log(`\n${colors.bold}Tests:${colors.reset}`);
|
|
249
266
|
console.log(`Total: ${totalTests}`);
|
|
250
|
-
|
|
267
|
+
if (tests.pass > 0) {
|
|
268
|
+
console.log(`${colors.green}Passed: ${tests.pass}${colors.reset}`);
|
|
269
|
+
} else {
|
|
270
|
+
console.log(`Passed: ${tests.pass}`);
|
|
271
|
+
}
|
|
251
272
|
console.log(
|
|
252
273
|
`${tests.fail > 0 ? colors.red : colors.green}Failed: ${tests.fail}${
|
|
253
274
|
colors.reset
|
|
@@ -257,14 +278,19 @@ const reporters = {
|
|
|
257
278
|
console.log(
|
|
258
279
|
`${colors.yellow}Warnings: ${tests.warning}${colors.reset}`
|
|
259
280
|
);
|
|
260
|
-
if (tests.skipped > 0)
|
|
281
|
+
if (tests.skipped > 0)
|
|
282
|
+
console.log(`${colors.yellow}Skipped: ${tests.skipped}${colors.reset}`);
|
|
261
283
|
}
|
|
262
284
|
|
|
263
285
|
// Print contexts summary if available
|
|
264
286
|
if (contexts) {
|
|
265
287
|
console.log(`\n${colors.bold}Contexts:${colors.reset}`);
|
|
266
288
|
console.log(`Total: ${totalContexts}`);
|
|
267
|
-
|
|
289
|
+
if (contexts.pass > 0) {
|
|
290
|
+
console.log(`${colors.green}Passed: ${contexts.pass}${colors.reset}`);
|
|
291
|
+
} else {
|
|
292
|
+
console.log(`Passed: ${contexts.pass}`);
|
|
293
|
+
}
|
|
268
294
|
console.log(
|
|
269
295
|
`${contexts.fail > 0 ? colors.red : colors.green}Failed: ${
|
|
270
296
|
contexts.fail
|
|
@@ -274,14 +300,19 @@ const reporters = {
|
|
|
274
300
|
console.log(
|
|
275
301
|
`${colors.yellow}Warnings: ${contexts.warning}${colors.reset}`
|
|
276
302
|
);
|
|
277
|
-
if (contexts.skipped > 0)
|
|
303
|
+
if (contexts.skipped > 0)
|
|
304
|
+
console.log(`${colors.yellow}Skipped: ${contexts.skipped}${colors.reset}`);
|
|
278
305
|
}
|
|
279
306
|
|
|
280
307
|
// Print steps summary if available
|
|
281
308
|
if (steps) {
|
|
282
309
|
console.log(`\n${colors.bold}Steps:${colors.reset}`);
|
|
283
310
|
console.log(`Total: ${totalSteps}`);
|
|
284
|
-
|
|
311
|
+
if (steps.pass > 0) {
|
|
312
|
+
console.log(`${colors.green}Passed: ${steps.pass}${colors.reset}`);
|
|
313
|
+
} else {
|
|
314
|
+
console.log(`Passed: ${steps.pass}`);
|
|
315
|
+
}
|
|
285
316
|
console.log(
|
|
286
317
|
`${steps.fail > 0 ? colors.red : colors.green}Failed: ${steps.fail}${
|
|
287
318
|
colors.reset
|
|
@@ -291,7 +322,13 @@ const reporters = {
|
|
|
291
322
|
console.log(
|
|
292
323
|
`${colors.yellow}Warnings: ${steps.warning}${colors.reset}`
|
|
293
324
|
);
|
|
294
|
-
if (steps.skipped > 0)
|
|
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}`);
|
|
295
332
|
}
|
|
296
333
|
|
|
297
334
|
// If we have specs with failures, display them
|
|
@@ -306,7 +343,13 @@ const reporters = {
|
|
|
306
343
|
const failedContexts = [];
|
|
307
344
|
const failedSteps = [];
|
|
308
345
|
|
|
309
|
-
//
|
|
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
|
|
310
353
|
results.specs.forEach((spec, specIndex) => {
|
|
311
354
|
// Check if spec has failed
|
|
312
355
|
if (spec.result === "FAIL") {
|
|
@@ -315,6 +358,13 @@ const reporters = {
|
|
|
315
358
|
id: spec.specId || `Spec ${specIndex + 1}`,
|
|
316
359
|
});
|
|
317
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
|
+
}
|
|
318
368
|
|
|
319
369
|
// Process tests in this spec
|
|
320
370
|
if (spec.tests && spec.tests.length > 0) {
|
|
@@ -328,6 +378,15 @@ const reporters = {
|
|
|
328
378
|
id: test.testId || `Test ${testIndex + 1}`,
|
|
329
379
|
});
|
|
330
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
|
+
}
|
|
331
390
|
|
|
332
391
|
// Process contexts in this test
|
|
333
392
|
if (test.contexts && test.contexts.length > 0) {
|
|
@@ -349,6 +408,23 @@ const reporters = {
|
|
|
349
408
|
: "unknown",
|
|
350
409
|
});
|
|
351
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
|
+
}
|
|
352
428
|
|
|
353
429
|
// Process steps in this context
|
|
354
430
|
if (context.steps && context.steps.length > 0) {
|
|
@@ -370,6 +446,22 @@ const reporters = {
|
|
|
370
446
|
error: step.resultDescription || "Unknown error",
|
|
371
447
|
});
|
|
372
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
|
+
}
|
|
373
465
|
});
|
|
374
466
|
}
|
|
375
467
|
});
|
|
@@ -419,7 +511,33 @@ const reporters = {
|
|
|
419
511
|
console.log(` Error: ${item.error}`);
|
|
420
512
|
});
|
|
421
513
|
}
|
|
422
|
-
|
|
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) {
|
|
423
541
|
// Celebration when all tests pass
|
|
424
542
|
console.log(`\n${colors.green}🎉 All items passed! 🎉${colors.reset}`);
|
|
425
543
|
}
|
package/test/utils.test.js
CHANGED
|
@@ -60,6 +60,19 @@ describe("Util tests", function () {
|
|
|
60
60
|
c: "config.json",
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
args: [
|
|
65
|
+
"node",
|
|
66
|
+
"runTests.js",
|
|
67
|
+
"--input",
|
|
68
|
+
"input.spec.json",
|
|
69
|
+
"--allow-unsafe",
|
|
70
|
+
],
|
|
71
|
+
expected: {
|
|
72
|
+
i: "input.spec.json",
|
|
73
|
+
allowUnsafe: true,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
63
76
|
];
|
|
64
77
|
argSets.forEach((argSet) => {
|
|
65
78
|
expect(setArgs(argSet.args)).to.deep.include(argSet.expected);
|
|
@@ -144,6 +157,20 @@ describe("Util tests", function () {
|
|
|
144
157
|
output: process.cwd(),
|
|
145
158
|
recursive: true,
|
|
146
159
|
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
// allow-unsafe override
|
|
163
|
+
args: [
|
|
164
|
+
"node",
|
|
165
|
+
"runTests.js",
|
|
166
|
+
"--input",
|
|
167
|
+
"input.spec.json",
|
|
168
|
+
"--allow-unsafe",
|
|
169
|
+
],
|
|
170
|
+
expected: {
|
|
171
|
+
input: [path.resolve(process.cwd(), "input.spec.json")],
|
|
172
|
+
allowUnsafeTests: true,
|
|
173
|
+
},
|
|
147
174
|
}
|
|
148
175
|
];
|
|
149
176
|
|