@freshworks/shiftleft-tools 1.1.8

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 (106) hide show
  1. package/README.md +351 -0
  2. package/bin/shiftleft.js +95 -0
  3. package/package.json +57 -0
  4. package/src/commands/doctor.js +208 -0
  5. package/src/commands/init-postman.js +298 -0
  6. package/src/commands/init-rules.js +78 -0
  7. package/src/commands/link.js +172 -0
  8. package/src/commands/protect.js +61 -0
  9. package/src/commands/run-tests.js +182 -0
  10. package/src/commands/setup-pipeline.js +209 -0
  11. package/src/commands/update.js +203 -0
  12. package/src/index.js +4 -0
  13. package/src/utils/copy-tree.js +98 -0
  14. package/src/utils/gitignore.js +26 -0
  15. package/src/utils/logger.js +9 -0
  16. package/src/utils/manifest.js +145 -0
  17. package/src/utils/stack.js +80 -0
  18. package/src/utils/template.js +135 -0
  19. package/templates/AGENTS.md +109 -0
  20. package/templates/CLAUDE.md +3 -0
  21. package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
  22. package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
  23. package/templates/postman/.husky/pre-commit +19 -0
  24. package/templates/postman/.prettierrc.json +5 -0
  25. package/templates/postman/README.md.ejs +147 -0
  26. package/templates/postman/collections/01-core.json.ejs +91 -0
  27. package/templates/postman/config/local.json.ejs +12 -0
  28. package/templates/postman/config/staging.json.ejs +26 -0
  29. package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
  30. package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
  31. package/templates/postman/gitignore +16 -0
  32. package/templates/postman/npmrc +31 -0
  33. package/templates/postman/package.json.ejs +66 -0
  34. package/templates/postman/run-all-shim.sh +16 -0
  35. package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
  36. package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
  37. package/templates/postman/scripts/infra/start-mocks.sh +138 -0
  38. package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
  39. package/templates/postman/scripts/lib/api_coverage.py +1122 -0
  40. package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
  41. package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
  42. package/templates/postman/scripts/lib/report_combined.py +527 -0
  43. package/templates/postman/scripts/lib/report_consolidated.py +363 -0
  44. package/templates/postman/scripts/lib/report_generator.py +121 -0
  45. package/templates/postman/scripts/lib/report_migration.py +156 -0
  46. package/templates/postman/scripts/lib/report_mutation.py +110 -0
  47. package/templates/postman/scripts/lib/report_unit.py +353 -0
  48. package/templates/postman/scripts/lib/report_utils.py +973 -0
  49. package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
  50. package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
  51. package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
  52. package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
  53. package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
  54. package/templates/postman/scripts/run-all.sh +452 -0
  55. package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
  56. package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
  57. package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
  58. package/templates/postman-node/README.md.ejs +26 -0
  59. package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
  60. package/templates/postman-node/config/local.json.ejs +46 -0
  61. package/templates/postman-node/config/staging.json.ejs +31 -0
  62. package/templates/postman-node/local.test.env.ejs +3 -0
  63. package/templates/postman-node/mocks/external.js +14 -0
  64. package/templates/postman-node/package.json.ejs +39 -0
  65. package/templates/postman-node/requirements.txt +1 -0
  66. package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
  67. package/templates/postman-node/scripts/database/run-migrations.js +29 -0
  68. package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
  69. package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
  70. package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
  71. package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
  72. package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
  73. package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
  74. package/templates/postman-node/scripts/lib/start-app.sh +48 -0
  75. package/templates/postman-node/scripts/lib/utils.sh +114 -0
  76. package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
  77. package/templates/postman-node/scripts/run-all.sh +303 -0
  78. package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
  79. package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
  80. package/templates/postman-node/stryker.config.js.ejs +51 -0
  81. package/templates/rules/local-test-setup.mdc +420 -0
  82. package/templates/rules/testing-node.mdc +66 -0
  83. package/templates/rules/testing.mdc +248 -0
  84. package/templates/skills/_shared/postman-standards.md +380 -0
  85. package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
  86. package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
  87. package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
  88. package/templates/skills/review-test-suite/SKILL-java.md +137 -0
  89. package/templates/skills/review-test-suite/SKILL-node.md +78 -0
  90. package/templates/skills/review-test-suite/SKILL.md +9 -0
  91. package/templates/skills/run-test-suite/SKILL-java.md +186 -0
  92. package/templates/skills/run-test-suite/SKILL-node.md +191 -0
  93. package/templates/skills/run-test-suite/SKILL.md +9 -0
  94. package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
  95. package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
  96. package/templates/skills/setup-api-tests/SKILL.md +9 -0
  97. package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
  98. package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
  99. package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
  100. package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
  101. package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
  102. package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
  103. package/templates/skills/write-api-tests/SKILL-java.md +115 -0
  104. package/templates/skills/write-api-tests/SKILL-node.md +83 -0
  105. package/templates/skills/write-api-tests/SKILL.md +9 -0
  106. package/templates/stryker.config.js +50 -0
@@ -0,0 +1,318 @@
1
+ # Setup Test Pipeline — Node.js / Express
2
+
3
+ Set up a complete test pipeline from scratch (or near-scratch) for a Node.js/Express repo. This skill orchestrates the full pipeline: unit tests, nyc/Istanbul coverage, Stryker mutation tests, Postman API tests, API coverage matrix, combined quality report, and Jenkins integration.
4
+
5
+ Use this skill when a repo has NOTHING (or only bare unit tests). For repos that already have partial pipeline setup, use `/enhance-test-pipeline` instead.
6
+
7
+ ## When to Use
8
+
9
+ Invoke when:
10
+ - "set up the full test pipeline"
11
+ - "add complete test infrastructure to this Node.js repo"
12
+ - "set up unit tests, mutation tests, and postman tests"
13
+ - "I want everything: unit tests, coverage, mutation, API tests, quality report"
14
+
15
+ ---
16
+
17
+ ## Phase 1: Inspect — Audit What Exists
18
+
19
+ Run each check and record the result (present/missing/partial).
20
+
21
+ ### 1.1 Unit tests
22
+
23
+ ```bash
24
+ cat package.json | grep -E '"test"|"mocha"|"jest"'
25
+ ls test/ test/unit/ 2>/dev/null | head -20
26
+ yarn test 2>&1 | tail -5
27
+ ```
28
+
29
+ - Present and passing: unit tests exist and pass
30
+ - Present but failing: tests exist but have failures (must fix before mutation tests)
31
+ - Missing: no test directory or test script
32
+
33
+ ### 1.2 nyc / Istanbul coverage
34
+
35
+ ```bash
36
+ cat package.json | grep -E '"nyc"|"istanbul"|"c8"'
37
+ grep -r "nyc\|istanbul\|c8" package.json
38
+ ```
39
+
40
+ - Present: coverage already configured
41
+ - Missing: needs to be added
42
+
43
+ ### 1.3 Postman infrastructure
44
+
45
+ ```bash
46
+ ls postman/ 2>/dev/null
47
+ ls postman/collections/ 2>/dev/null
48
+ ls postman/scripts/ 2>/dev/null
49
+ ls postman/scripts/run-all.sh 2>/dev/null
50
+ ```
51
+
52
+ - Present: full postman/ directory with collections and scripts
53
+ - Partial: directory exists but scripts or collections missing
54
+ - Missing: no postman/ directory
55
+
56
+ ### 1.4 Stryker mutation testing
57
+
58
+ ```bash
59
+ cat package.json | grep stryker
60
+ ls stryker.config.js 2>/dev/null
61
+ ```
62
+
63
+ - Present: Stryker configured (check mutate scope — should target business logic only)
64
+ - Missing: needs to be added
65
+
66
+ ### 1.5 API coverage matrix
67
+
68
+ ```bash
69
+ ls postman/scripts/report-generators/node-api-coverage-matrix.sh 2>/dev/null
70
+ ```
71
+
72
+ ### 1.6 Quality report
73
+
74
+ ```bash
75
+ ls postman/scripts/run-all.sh 2>/dev/null
76
+ grep "skip-report\|skip-unit\|skip-mutation" postman/scripts/run-all.sh 2>/dev/null | head -5
77
+ ```
78
+
79
+ - Present and modern: run-all.sh exists and has --skip-* flags
80
+ - Present but stale: run-all.sh exists but is an old version without flags
81
+ - Missing
82
+
83
+ ### 1.7 Jenkinsfile
84
+
85
+ ```bash
86
+ ls Jenkinsfile
87
+ grep -E "Mutation|ShiftLeft|Quality|quality-report|stryker" Jenkinsfile 2>/dev/null
88
+ ```
89
+
90
+ - Complete: has Unit Tests, Mutation Tests, ShiftLeft stages with quality report generation
91
+ - Partial: has some stages but missing mutation or quality report
92
+ - Missing: no Jenkinsfile
93
+
94
+ ---
95
+
96
+ ## Phase 2: Report Gaps
97
+
98
+ Present a clear status table to the user:
99
+
100
+ ```
101
+ Pipeline Audit Results
102
+ ======================
103
+ Component Status
104
+ -----------------------------------------------
105
+ Unit Tests [PRESENT / MISSING / FAILING]
106
+ nyc Coverage [PRESENT / MISSING]
107
+ Postman Infrastructure [PRESENT / PARTIAL / MISSING]
108
+ Stryker Mutation Tests [PRESENT / MISSING]
109
+ API Coverage Matrix [PRESENT / MISSING]
110
+ run-all.sh (modern) [PRESENT / STALE / MISSING]
111
+ Jenkinsfile [COMPLETE / PARTIAL / MISSING]
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Phase 3: Confirm
117
+
118
+ Tell the user exactly what will be set up:
119
+
120
+ ```
121
+ I will set up the following components in order:
122
+ 1. [if missing] Postman infrastructure (collections, scripts, config)
123
+ 2. [if missing] nyc coverage in package.json
124
+ 3. [if missing] Stryker mutation testing (discover actual src structure first)
125
+ 4. Stage library scripts from the shiftleft-tools package (`shiftleft stage-scripts`):
126
+ run-all.sh, runners/run-mutation-tests.sh,
127
+ report-generators/node-api-coverage-matrix.sh, generate-consolidated-report.sh,
128
+ report-generators/stage-report-artifacts.sh,
129
+ lib/report_generator.py (entry point), lib/report_utils.py, lib/report_consolidated.py,
130
+ lib/report_migration.py, lib/report_mutation.py, lib/report_unit.py, lib/report_combined.py,
131
+ lib/api_coverage_node.py
132
+ 5. [if partial] Update Jenkinsfile with mutation + ShiftLeft + quality report stages
133
+
134
+ This will take approximately 5-10 minutes.
135
+ Proceed? [Y/n]
136
+ ```
137
+
138
+ Wait for confirmation before making any changes.
139
+
140
+ ---
141
+
142
+ ## Phase 4: Execute in Order
143
+
144
+ ### Step A: Postman infrastructure (if missing)
145
+
146
+ If no `postman/` directory exists, invoke `/setup-api-tests` skill for the full Postman setup.
147
+
148
+ ### Step B: nyc coverage (if missing)
149
+
150
+ Add nyc configuration to `package.json`:
151
+
152
+ ```json
153
+ {
154
+ "scripts": {
155
+ "test:coverage": "nyc mocha test/unit/**/*.test.js"
156
+ },
157
+ "nyc": {
158
+ "reporter": ["lcov", "text", "html"],
159
+ "report-dir": "coverage/unit",
160
+ "exclude": [
161
+ "test/**",
162
+ "postman/**",
163
+ "coverage/**",
164
+ "node_modules/**"
165
+ ],
166
+ "include": [
167
+ "src/**/*.js"
168
+ ]
169
+ }
170
+ }
171
+ ```
172
+
173
+ Install if missing:
174
+ ```bash
175
+ yarn add --dev nyc
176
+ ```
177
+
178
+ ### Step C: Stryker mutation testing (if missing)
179
+
180
+ Follow the `setup-mutation-tests` SKILL-node.md skill in full:
181
+ 1. Discover source folders — **only** actions, services, serializers, middlewares (+ selective helpers)
182
+ 2. **Exclude** controllers, routes, models, config, migrations
183
+ 3. Inspect helpers file-by-file — exclude external SDK wrappers
184
+ 4. **Count files** — mutate scope must stay **under 80 files** (never `src/**`)
185
+ 5. Confirm narrow scope with user before writing config
186
+ 6. Install `@stryker-mutator/core` and appropriate runner
187
+ 7. Create `stryker.config.js` with the audited scope only
188
+ 8. Add `mutation-tests` (since mode) and `mutation-tests:full` scripts to package.json
189
+
190
+ Key requirements:
191
+ - **Never** `mutate: ['src/**/*.js']` — Stryker will run for hours
192
+ - `coverageAnalysis: 'perTest'` — fastest
193
+ - `incremental: true` — reuse previous results
194
+ - `concurrency: 4`
195
+ - `thresholds: { high: 80, low: 60, break: 0 }` — break:0 means CI never hard-fails on score
196
+ - `htmlReporter: { fileName: 'coverage/mutation/index.html' }`
197
+ - `run-mutation-tests.sh` for the two-mode approach (since vs full)
198
+
199
+ ### Step D: Stage scripts from the shiftleft-tools package
200
+
201
+ Run `shiftleft stage-scripts` to pull the library scripts from the installed
202
+ package into `postman/scripts/` — do not copy or write them by hand. They are
203
+ gitignored and refreshed on every `shiftleft test` run. The staged set includes:
204
+
205
+ **Core pipeline scripts (required):**
206
+ - `run-all.sh` — master pipeline runner with `--skip-*` and `--env` flags
207
+ - `runners/run-mutation-tests.sh` — Stryker two-mode runner (since vs full)
208
+ - `report-generators/node-api-coverage-matrix.sh` — Express route coverage matrix
209
+ - `report-generators/generate-consolidated-report.sh` — aggregates Newman JSON results
210
+ - `report-generators/stage-report-artifacts.sh` — copies nyc/Stryker HTML for Jenkins linking
211
+
212
+ **Support scripts:**
213
+ - `run-tests.sh` (or `run-all.sh`) — runs Postman tests locally and against staging
214
+ - `get-issuer-secret.sh` / `auth/get-issuer-secret.sh` — fetches JWT secret from AWS
215
+
216
+ **Lib folder (required):**
217
+ - `lib/report_generator.py` — CLI entry point, dispatches to report modules
218
+ - `lib/report_utils.py` — shared CSS, helpers, UI component builders
219
+ - `lib/report_consolidated.py` — consolidated Newman test results report
220
+ - `lib/report_migration.py` — migration comparison report
221
+ - `lib/report_mutation.py` — PIT/Stryker mutation testing report
222
+ - `lib/report_unit.py` — unit test parsers and report
223
+ - `lib/report_combined.py` — combined quality report (unit + API tabs)
224
+ - `lib/api_coverage_node.py` — generates API coverage matrix from Express routes + Postman
225
+ - `lib/cleanup-stryker.sh` — kills Stryker processes and cleans temp files
226
+
227
+ Make all `.sh` files executable:
228
+ ```bash
229
+ chmod +x postman/scripts/*.sh postman/scripts/lib/*.sh
230
+ ```
231
+
232
+ ### Step E: Update Jenkinsfile (if missing stages)
233
+
234
+ If the Jenkinsfile is missing mutation or quality report stages, update it to match the `templates/jenkins/Jenkinsfile-node.groovy` pattern:
235
+
236
+ Required stages:
237
+ 1. `Unit Tests` — `yarn test`
238
+ 2. `Mutation Tests` — `yarn mutation-tests:full` (full mode for CI), publish Stryker HTML report
239
+ 3. `Staging Postman, API Coverage & Quality Report` — ShiftLeft isolation, Postman, API coverage matrix, quality report
240
+
241
+ Key quality report pattern:
242
+ ```groovy
243
+ // API coverage (after ShiftLeft Postman):
244
+ sh "./postman/scripts/report-generators/node-api-coverage-matrix.sh ./src/controllers ./postman"
245
+ publishHTML([reportDir: 'postman/reports', reportFiles: 'api-coverage-matrix-latest.html', reportName: 'API Coverage Matrix'])
246
+
247
+ // Quality report:
248
+ sh "./postman/scripts/run-all.sh --skip-unit --skip-mutation --skip-postman --skip-coverage --no-delay"
249
+ publishHTML([reportDir: 'postman/reports', reportFiles: 'quality-report-*.html', reportName: 'QualityReport'])
250
+ archiveArtifacts artifacts: 'postman/reports/**', allowEmptyArchive: true
251
+ ```
252
+
253
+ Replace placeholders:
254
+ - `SERVICE_NAME` → your actual service name (e.g. `freshapps_api_node`)
255
+ - `NAMESPACE` → your Kubernetes namespace
256
+ - `ISO_HEADER` → isoforge routing header
257
+ - `ISO_HEADER_VALUE` → the account ID or regex value
258
+
259
+ ---
260
+
261
+ ## Phase 5: Verify
262
+
263
+ ### Verify Phase A: Unit + Mutation + Coverage (no Postman needed)
264
+
265
+ ```bash
266
+ yarn test # Unit tests
267
+ yarn mutation-tests # Stryker since-mode (only changed files)
268
+ ```
269
+
270
+ ### Verify Phase B: Postman + API Coverage + Quality Report
271
+
272
+ ```bash
273
+ cd postman/scripts
274
+ ./run-all.sh --skip-mutation --no-delay
275
+ ```
276
+
277
+ Expected: Postman tests run locally, API coverage matrix generates, quality report generates.
278
+
279
+ ### Verify Phase C: Full pipeline
280
+
281
+ ```bash
282
+ cd postman/scripts
283
+ ./run-all.sh --no-delay
284
+ ```
285
+
286
+ ### Report to user
287
+
288
+ ```
289
+ Pipeline setup complete!
290
+
291
+ Verification results:
292
+ Unit Tests: [PASS/FAIL] — N tests, M% line coverage
293
+ Mutation Tests: [PASS/FAIL] — X% mutation score (since mode)
294
+ Postman Tests: [PASS/FAIL] — N collections, M assertions
295
+ API Coverage: [PASS/FAIL] — X% endpoints covered
296
+ Quality Report: [GENERATED] — postman/reports/quality-report-*.html
297
+
298
+ Next steps:
299
+ - Local run-all: cd postman/scripts && ./run-all.sh
300
+ - Fast mutation check: yarn mutation-tests (only changed files)
301
+ - Full mutation check: yarn mutation-tests:full (all scoped files)
302
+ - Staging run: cd postman/scripts && ./run-all.sh --env staging
303
+ - Jenkins: push a PR and comment "shiftleft" to trigger integration tests
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Verification Checklist
309
+
310
+ - [ ] `yarn test` passes
311
+ - [ ] `yarn test:coverage` generates coverage report
312
+ - [ ] `yarn mutation-tests` works in since mode
313
+ - [ ] `yarn mutation-tests:full` runs full Stryker scan
314
+ - [ ] `./run-all.sh --skip-mutation --no-delay` completes successfully
315
+ - [ ] `postman/reports/quality-report-*.html` is generated
316
+ - [ ] All `.sh` files are executable
317
+ - [ ] Jenkinsfile has Mutation Tests stage (full mode) and Quality Report generation
318
+ - [ ] `node-api-coverage-matrix.sh` is configured with correct routes dir
@@ -0,0 +1,9 @@
1
+ # Setup Test Pipeline Skill
2
+
3
+ ## Detect Project Type First
4
+
5
+ Before doing anything, detect the stack:
6
+
7
+ 1. `pom.xml` in project root → **Java Spring Boot** → read `SKILL-java.md` in this folder and follow it completely
8
+ 2. `package.json` (no `pom.xml`) → **Node.js** → read `SKILL-node.md` in this folder and follow it completely
9
+ 3. If unsure → ask the user: "Is this a Java or Node.js project?"
@@ -0,0 +1,115 @@
1
+ # Write API Tests Skill — Java Spring Boot
2
+
3
+ Write and manage Postman/Newman integration tests for a Java Spring Boot API.
4
+
5
+ ## When to Use
6
+
7
+ Invoke this skill when the user mentions:
8
+ - "write api tests", "add api test", "add postman test"
9
+ - "add test for endpoint", "write tests for [endpoint]", "test coverage"
10
+ - "API test", "integration test", "newman"
11
+
12
+ **Note:** If the project doesn't have a `postman/` folder yet, use the **setup-api-tests** skill first to create the infrastructure.
13
+
14
+ ## Arguments
15
+
16
+ Arguments are passed after the skill invocation. Parse them before deciding what to write.
17
+
18
+ | Argument form | Behaviour |
19
+ |---|---|
20
+ | `/write-api-tests GET /apps` | Write tests for that specific endpoint only |
21
+ | `/write-api-tests POST /apps PUT /apps/{id}` | Write tests for each listed endpoint |
22
+ | `/write-api-tests` (no argument) | Ask the user which endpoint(s) to target, OR run `java-api-coverage-matrix.sh` to find untested endpoints and offer to write tests for those |
23
+
24
+ ### Argument Parsing Rules
25
+
26
+ 1. Check if the user passed an HTTP method + path after the skill name (e.g. `GET /apps`, `POST /apps/{id}`)
27
+ 2. **If a specific endpoint is given** — scope all work to that endpoint only. Do not touch other collections or endpoints.
28
+ 3. **If multiple endpoints are given** — handle each one in sequence, same collection if they belong together, separate if not.
29
+ 4. **If no argument** — do one of the following (ask the user which they prefer):
30
+ - **Option A**: Specify an endpoint now (e.g. `GET /apps`)
31
+ - **Option B**: Run `./postman/scripts/report-generators/java-api-coverage-matrix.sh` to find untested endpoints, then let the user pick
32
+
33
+ ### When Writing for a Specific Endpoint
34
+
35
+ Before writing any test:
36
+ 1. Read the controller file to confirm the exact path, method, request params, and response DTO
37
+ 2. Read the response DTO to get correct field names
38
+ 3. Check the existing collections to find the right file to add tests to
39
+ 4. Confirm the JSON naming strategy (snake_case vs camelCase) from `application.properties`
40
+ 5. Write tests, then run `./runners/run-tests-local.sh` and `./java-api-coverage-matrix.sh` to verify
41
+
42
+ ## Dual Environment Support
43
+
44
+ ### Local Environment
45
+ - **Database**: H2 in-memory (no MySQL needed)
46
+ - **External Services**: WireMock mocks
47
+ - **Authentication**: Hardcoded test JWT token
48
+ - **Command**: `cd postman/scripts && ./runners/run-tests-local.sh`
49
+
50
+ ### Staging Environment
51
+ - **Database**: Real MySQL
52
+ - **External Services**: Real services (FreshID, other Freshworks services)
53
+ - **Authentication**: JWT from AWS Secrets Manager
54
+ - **Command**: `cd postman/scripts && ./runners/run-tests-staging.sh`
55
+
56
+ ---
57
+
58
+ > **Assertion standards, skip patterns, query/include coverage, and the submission checklist are in `../_shared/postman-standards.md`. Read that file for all Postman assertion rules before writing any tests.**
59
+
60
+ ---
61
+
62
+ ## Running Tests
63
+
64
+ ```bash
65
+ # Local environment
66
+ cd postman/scripts && ./runners/run-tests-local.sh
67
+
68
+ # Staging environment
69
+ cd postman/scripts && ./runners/run-tests-staging.sh
70
+
71
+ # API coverage report (must show 100% 2xx coverage)
72
+ ./postman/scripts/report-generators/java-api-coverage-matrix.sh
73
+ ```
74
+
75
+ ## Adding a New Test
76
+
77
+ 1. **Choose the right collection** based on endpoint type
78
+ 2. **Add request** with descriptive name: `"Verb - Description"`
79
+ 3. **Add status code assertion** (exactly one per request)
80
+ 4. **Add value assertions** for response fields
81
+ 5. **Add skip logic** if environment-specific
82
+ 6. **Run locally**: `cd postman/scripts && ./runners/run-tests-local.sh`
83
+ 7. **Check coverage**: `./postman/scripts/report-generators/java-api-coverage-matrix.sh`
84
+
85
+ ## Adding a New Collection
86
+
87
+ 1. Create `postman/collections/XX-feature-name.json` (follow existing collection structure)
88
+ 2. Add collection to the arrays in `run-tests-local.sh` and `run-tests-staging.sh`
89
+ 3. Format: `cd postman && npm run format`
90
+ 4. Test: `cd postman/scripts && ./runners/run-tests-local.sh`
91
+
92
+ ## Setting Up Postman in a New Project
93
+
94
+ If the project doesn't have Postman tests yet, use the **setup-api-tests** skill which provides:
95
+ - Complete folder structure
96
+ - package.json with secure dependencies
97
+ - Environment files (local/staging)
98
+ - Config files
99
+ - Script templates
100
+ - Maven integration
101
+ - Spring integration profile
102
+
103
+ ## Coverage Report Validation
104
+
105
+ The `java-api-coverage-matrix.sh` script validates all tests. It will flag:
106
+
107
+ | Issue | What It Detects | Fix |
108
+ |-------|-----------------|-----|
109
+ | **No 2xx test** | Endpoint has no success path test | Add 200/201 test |
110
+ | **Weak assertions (oneOf)** | `oneOf([200, 201])` patterns | Split into separate tests |
111
+ | **5xx assertions** | Tests asserting 500 status | Remove - bugs aren't expected behavior |
112
+ | **Missing query params** | `@RequestParam` not tested | Add tests for each param |
113
+ | **Missing include values** | Expected include values not tested | Add tests for each value |
114
+ | **Undocumented skips** | `skipRequest()` without `[SKIP] Reason:` | Add skip reason |
115
+ | **Low body assertions** | No response field validation | Add `pm.expect(json.field)` |
@@ -0,0 +1,83 @@
1
+ # Write API Tests Skill — Node.js / Express
2
+
3
+ Write Postman/Newman tests for Express API endpoints.
4
+
5
+ Reference: `freshapps_api_node` (`postman/collections/crud/`)
6
+
7
+ ## Arguments
8
+
9
+ | Form | Behaviour |
10
+ |------|-----------|
11
+ | `/write-api-tests GET /api/v2/apps` | Tests for that endpoint only |
12
+ | `/write-api-tests` (no args) | Run coverage matrix, offer untested endpoints |
13
+
14
+ ---
15
+
16
+ ## Before Writing
17
+
18
+ 1. **Read the controller** — find exact path, method, middleware:
19
+ ```bash
20
+ grep -r "router\.\(get\|post\|patch\|put\|delete\)" src/controllers/ -l
21
+ cat src/controllers/v2/<resource>.js
22
+ ```
23
+
24
+ 2. **Read the serializer/response shape** — Node APIs often use serializers, not DTOs:
25
+ ```bash
26
+ ls src/serializers/
27
+ ```
28
+
29
+ 3. **Check JSON naming** — default Express is camelCase unless a serializer transforms keys
30
+
31
+ 4. **Check auth** — which `authorize('resource.action')` permission is required?
32
+
33
+ 5. **Find the right collection** — match domain to `postman/collections/crud/NN-*.json`
34
+
35
+ ---
36
+
37
+ ## Express route patterns
38
+
39
+ ```javascript
40
+ appsRouter.get('/', [authorize('apps.read'), ...], handler);
41
+ appsRouter.get(`/:app_id(${numberRegex})`, [...], handler);
42
+ ```
43
+
44
+ Full path = mount prefix from `controllers/index.js` + route path.
45
+ Example: `/api/v2` + `/apps` → `GET /api/v2/apps`
46
+
47
+ ---
48
+
49
+ ## Writing tests
50
+
51
+ Follow `../_shared/postman-standards.md`:
52
+ - One status code assertion per request
53
+ - Specific value assertions (not just `pm.expect(json).to.be.an('object')`)
54
+ - Document skips: `[SKIP] Reason: ... | Env: staging`
55
+
56
+ ### Collection item naming
57
+ `"Verb - Description"` e.g. `"GET - List apps returns 200"`
58
+
59
+ ### Environment variables
60
+ Use `{{base_url}}`, `{{auth_token}}` from Postman environment files.
61
+ Multi-role: `auth_token_developer`, etc. (set by JWT scripts from `config/local.json` users map)
62
+
63
+ ---
64
+
65
+ ## Run and verify
66
+
67
+ ```bash
68
+ cd postman/scripts
69
+ ./runners/run-tests.sh local
70
+ ./report-generators/node-api-coverage-matrix.sh ../../src/controllers ..
71
+ ```
72
+
73
+ Target: **100% 2xx coverage** on all controller endpoints.
74
+
75
+ ---
76
+
77
+ ## Adding a new collection
78
+
79
+ 1. Create `postman/collections/crud/NN-feature-name.json` (numbered for order)
80
+ 2. Run `cd postman && npm run format`
81
+ 3. Verify with `./runners/run-tests.sh local`
82
+
83
+ Bootstrap (`01-*`) must run first; cleanup (`99-*`) must run last.
@@ -0,0 +1,9 @@
1
+ # Write API Tests Skill
2
+
3
+ ## Detect Project Type First
4
+
5
+ Before doing anything, detect the stack:
6
+
7
+ 1. `pom.xml` in project root → **Java Spring Boot** → read `SKILL-java.md` in this folder and follow it completely
8
+ 2. `package.json` (no `pom.xml`) → **Node.js** → read `SKILL-node.md` in this folder and follow it completely
9
+ 3. If unsure → ask the user: "Is this a Java or Node.js project?"
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ /** @type {import('@stryker-mutator/api/core').PartialStrykerOptions} */
4
+ module.exports = {
5
+ packageManager: 'yarn',
6
+ testRunner: 'mocha',
7
+ reporters: ['html', 'json', 'clear-text', 'progress'],
8
+ htmlReporter: {
9
+ fileName: 'coverage/mutation/index.html'
10
+ },
11
+ jsonReporter: {
12
+ fileName: 'coverage/mutation/mutation-report.json'
13
+ },
14
+ mutate: [
15
+ 'src/actions/**/*.js',
16
+ 'src/helpers/**/*.js',
17
+ 'src/serializers/**/*.js',
18
+ 'src/middlewares/**/*.js',
19
+ '!src/helpers/validator/schema/**/*.js',
20
+ '!src/helpers/aws.js',
21
+ '!src/helpers/chargebee.js',
22
+ '!src/helpers/freshid.js',
23
+ '!src/helpers/launchdarkly.js',
24
+ '!src/helpers/emailNotifications.js',
25
+ '!src/helpers/analytics.js',
26
+ '!src/helpers/observability.js',
27
+ '!src/helpers/mcp-gateway.js',
28
+ '!src/helpers/mcp-gateway-util.js',
29
+ '!src/helpers/mp-listings.js',
30
+ '!src/helpers/mp-apps.js',
31
+ '!src/helpers/constants.js',
32
+ '!src/helpers/config.js'
33
+ ],
34
+ coverageAnalysis: 'perTest',
35
+ concurrency: 4,
36
+ incremental: true,
37
+ incrementalFile: 'coverage/mutation/stryker-incremental.json',
38
+ ignorePatterns: ['postman/**', 'coverage/**'],
39
+ mochaOpts: {
40
+ files: 'test/unit/**/*.test.js',
41
+ require: ['test/unit/setup.js'],
42
+ timeout: 10000
43
+ },
44
+ thresholds: {
45
+ high: 80,
46
+ low: 60,
47
+ break: 0
48
+ },
49
+ tempDirName: 'coverage/mutation/.stryker-tmp'
50
+ };