bmad-method-test-architecture-enterprise 1.1.0 → 1.2.1
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/docs/how-to/workflows/run-test-review.md +40 -44
- package/docs/how-to/workflows/run-trace.md +14 -6
- package/docs/reference/commands.md +6 -6
- package/package.json +1 -1
- package/release_notes.md +5 -9
- package/src/testarch/knowledge/api-request.md +121 -0
- package/src/testarch/knowledge/api-testing-patterns.md +64 -0
- package/src/testarch/knowledge/overview.md +11 -11
- package/src/testarch/tea-index.csv +1 -1
- package/src/workflows/testarch/test-review/checklist.md +3 -0
- package/src/workflows/testarch/test-review/instructions.md +2 -0
- package/src/workflows/testarch/test-review/steps-c/step-01-load-context.md +2 -0
- package/src/workflows/testarch/test-review/steps-c/step-03-quality-evaluation.md +25 -36
- package/src/workflows/testarch/test-review/steps-c/step-03f-aggregate-scores.md +19 -16
- package/src/workflows/testarch/test-review/steps-c/step-04-generate-report.md +1 -0
- package/src/workflows/testarch/test-review/test-review-template.md +4 -15
- package/src/workflows/testarch/trace/checklist.md +7 -2
- package/src/workflows/testarch/trace/steps-c/step-02-discover-tests.md +19 -1
- package/src/workflows/testarch/trace/steps-c/step-03-map-criteria.md +7 -0
- package/src/workflows/testarch/trace/steps-c/step-04-analyze-gaps.md +82 -21
- package/src/workflows/testarch/trace/steps-c/step-05-gate-decision.md +36 -16
- package/src/workflows/testarch/trace/trace-template.md +25 -0
- package/src/workflows/testarch/test-review/steps-c/step-03d-subprocess-coverage.md +0 -111
|
@@ -7,14 +7,17 @@ description: Audit test quality using TEA's comprehensive knowledge base and get
|
|
|
7
7
|
|
|
8
8
|
Use TEA's `test-review` workflow to audit test quality with objective scoring and actionable feedback. TEA reviews tests against its knowledge base of best practices.
|
|
9
9
|
|
|
10
|
+
Coverage scoring is intentionally excluded from `test-review`. Use `trace` for requirements coverage analysis and coverage gate decisions.
|
|
11
|
+
|
|
10
12
|
## When to Use This
|
|
11
13
|
|
|
12
14
|
- Want to validate test quality objectively
|
|
13
|
-
- Need quality metrics for
|
|
15
|
+
- Need quality metrics for test quality gates
|
|
14
16
|
- Preparing for production deployment
|
|
15
17
|
- Reviewing team-written tests
|
|
16
18
|
- Auditing AI-generated tests
|
|
17
19
|
- Onboarding new team members (show good patterns)
|
|
20
|
+
- Validating migration quality before coverage expansion
|
|
18
21
|
|
|
19
22
|
## Prerequisites
|
|
20
23
|
|
|
@@ -311,42 +314,34 @@ test('should show validation error for expired card', async ({ page }) => {});
|
|
|
311
314
|
|
|
312
315
|
## Quality Scores by Category
|
|
313
316
|
|
|
314
|
-
| Category
|
|
315
|
-
|
|
|
316
|
-
| **Determinism**
|
|
317
|
-
| **Isolation**
|
|
318
|
-
| **
|
|
319
|
-
| **
|
|
320
|
-
| **Performance** | 3/10 | 8/10 | ❌ Critical |
|
|
317
|
+
| Category | Score | Target | Status |
|
|
318
|
+
| ------------------- | ----- | ------ | -------------------- |
|
|
319
|
+
| **Determinism** | 72 | 80 | ⚠️ Needs Improvement |
|
|
320
|
+
| **Isolation** | 88 | 80 | ✅ Good |
|
|
321
|
+
| **Maintainability** | 70 | 80 | ⚠️ Needs Improvement |
|
|
322
|
+
| **Performance** | 60 | 80 | ❌ Critical |
|
|
321
323
|
|
|
322
324
|
### Scoring Breakdown
|
|
323
325
|
|
|
324
|
-
**Determinism (
|
|
325
|
-
|
|
326
|
-
- No hard waits: 0/10 ❌ (found 3 instances)
|
|
327
|
-
- No conditionals: 8/10 ⚠️ (found 2 instances)
|
|
328
|
-
- No try-catch flow control: 10/10 ✅
|
|
329
|
-
- Network-first patterns: 8/15 ⚠️ (some tests missing)
|
|
330
|
-
|
|
331
|
-
**Isolation (25 points max):**
|
|
326
|
+
**Determinism (30% weight):**
|
|
332
327
|
|
|
333
|
-
-
|
|
334
|
-
-
|
|
335
|
-
- Parallel-safe: 0/0 ✅ (not tested)
|
|
328
|
+
- Hard waits and race conditions penalized
|
|
329
|
+
- Unstable control flow patterns penalized
|
|
336
330
|
|
|
337
|
-
**
|
|
331
|
+
**Isolation (30% weight):**
|
|
338
332
|
|
|
339
|
-
-
|
|
340
|
-
-
|
|
333
|
+
- Shared state and order dependency penalized
|
|
334
|
+
- Cleanup and parallel-safety rewarded
|
|
341
335
|
|
|
342
|
-
**
|
|
336
|
+
**Maintainability (25% weight):**
|
|
343
337
|
|
|
344
|
-
-
|
|
345
|
-
-
|
|
338
|
+
- Overly large files and copy-paste patterns penalized
|
|
339
|
+
- Naming clarity and structure rewarded
|
|
346
340
|
|
|
347
|
-
**Performance (
|
|
341
|
+
**Performance (15% weight):**
|
|
348
342
|
|
|
349
|
-
-
|
|
343
|
+
- Serial bottlenecks and inefficient setup penalized
|
|
344
|
+
- Parallel-friendly structure rewarded
|
|
350
345
|
|
|
351
346
|
## Files Reviewed
|
|
352
347
|
|
|
@@ -402,31 +397,30 @@ TEA reviewed against these patterns:
|
|
|
402
397
|
|
|
403
398
|
### Scoring Criteria
|
|
404
399
|
|
|
405
|
-
**Determinism (
|
|
400
|
+
**Determinism (30%):**
|
|
406
401
|
- Tests produce same result every run
|
|
407
402
|
- No random failures (flakiness)
|
|
408
403
|
- No environment-dependent behavior
|
|
409
404
|
|
|
410
|
-
**Isolation (
|
|
405
|
+
**Isolation (30%):**
|
|
411
406
|
- Tests don't depend on each other
|
|
412
407
|
- Can run in any order
|
|
413
408
|
- Clean up after themselves
|
|
414
409
|
|
|
415
|
-
**
|
|
416
|
-
- Verify actual behavior
|
|
417
|
-
- Specific and meaningful
|
|
418
|
-
- Not abstracted away in helpers
|
|
419
|
-
|
|
420
|
-
**Structure (10 points):**
|
|
410
|
+
**Maintainability (25%):**
|
|
421
411
|
- Readable and maintainable
|
|
422
412
|
- Appropriate size
|
|
423
413
|
- Clear naming
|
|
424
414
|
|
|
425
|
-
**Performance (
|
|
415
|
+
**Performance (15%):**
|
|
426
416
|
- Fast execution
|
|
427
417
|
- Efficient selectors
|
|
428
418
|
- No unnecessary waits
|
|
429
419
|
|
|
420
|
+
**Coverage:**
|
|
421
|
+
- Not scored in `test-review`
|
|
422
|
+
- Use `trace` for coverage percentage, requirement mapping, and gate decisions
|
|
423
|
+
|
|
430
424
|
## What You Get
|
|
431
425
|
|
|
432
426
|
### Quality Report
|
|
@@ -457,9 +451,9 @@ TEA reviewed against these patterns:
|
|
|
457
451
|
Make test review part of release checklist:
|
|
458
452
|
|
|
459
453
|
```markdown
|
|
460
|
-
##
|
|
454
|
+
## Quality Checklist (Test-Review)
|
|
461
455
|
- [ ] All tests passing
|
|
462
|
-
- [ ] Test
|
|
456
|
+
- [ ] Test-review quality score > 80
|
|
463
457
|
- [ ] Critical issues resolved
|
|
464
458
|
- [ ] Performance within budget
|
|
465
459
|
````
|
|
@@ -483,21 +477,23 @@ Use scores as quality gates:
|
|
|
483
477
|
# .github/workflows/test.yml
|
|
484
478
|
- name: Review test quality
|
|
485
479
|
run: |
|
|
486
|
-
# Run test
|
|
487
|
-
# Parse score from report
|
|
480
|
+
# Run test-review quality gate
|
|
481
|
+
# Parse quality score from report
|
|
488
482
|
if [ $SCORE -lt 80 ]; then
|
|
489
|
-
echo "Test quality below threshold"
|
|
483
|
+
echo "Test-review quality gate below threshold"
|
|
490
484
|
exit 1
|
|
491
485
|
fi
|
|
492
486
|
```
|
|
493
487
|
|
|
488
|
+
Coverage gate checks are handled by `trace`, not `test-review`.
|
|
489
|
+
|
|
494
490
|
### Review Regularly
|
|
495
491
|
|
|
496
492
|
Schedule periodic reviews:
|
|
497
493
|
|
|
498
494
|
- **Per story:** Optional (spot check new tests)
|
|
499
495
|
- **Per epic:** Recommended (ensure consistency)
|
|
500
|
-
- **Per release:** Recommended for quality gates (
|
|
496
|
+
- **Per release:** Recommended for test quality gates (coverage gates remain in `trace`)
|
|
501
497
|
- **Quarterly:** Audit entire suite
|
|
502
498
|
|
|
503
499
|
### Focus Reviews
|
|
@@ -619,8 +615,8 @@ Don't try to fix everything at once.
|
|
|
619
615
|
## Related Guides
|
|
620
616
|
|
|
621
617
|
- [How to Run ATDD](/docs/how-to/workflows/run-atdd.md) - Generate tests to review
|
|
622
|
-
- [How to Run Automate](/docs/how-to/workflows/run-automate.md) - Expand
|
|
623
|
-
- [How to Run Trace](/docs/how-to/workflows/run-trace.md) - Coverage
|
|
618
|
+
- [How to Run Automate](/docs/how-to/workflows/run-automate.md) - Expand and improve tests before review
|
|
619
|
+
- [How to Run Trace](/docs/how-to/workflows/run-trace.md) - Coverage analysis and gate decisions
|
|
624
620
|
|
|
625
621
|
## Understanding the Concepts
|
|
626
622
|
|
|
@@ -489,7 +489,7 @@ TEA makes evidence-based gate decision and writes to separate file.
|
|
|
489
489
|
|
|
490
490
|
| Metric | Threshold | Actual | Status |
|
|
491
491
|
| ------------------ | --------- | ------ | ------ |
|
|
492
|
-
| P0/P1 Coverage |
|
|
492
|
+
| P0/P1 Coverage | P0=100%, P1>=90% | 100% / 100% | ✅ |
|
|
493
493
|
| Test Quality Score | >80 | 84 | ✅ |
|
|
494
494
|
| NFR Status | PASS | PASS | ✅ |
|
|
495
495
|
|
|
@@ -609,7 +609,7 @@ TEA uses deterministic rules when decision_mode = "deterministic":
|
|
|
609
609
|
|
|
610
610
|
**Evidence:**
|
|
611
611
|
|
|
612
|
-
- P0 coverage: 60% (below
|
|
612
|
+
- P0 coverage: 60% (below required 100%)
|
|
613
613
|
- Critical security vulnerability (CVE-2024-12345)
|
|
614
614
|
- Test quality: 55/100
|
|
615
615
|
|
|
@@ -787,8 +787,16 @@ Use traceability in CI:
|
|
|
787
787
|
run: |
|
|
788
788
|
# Run trace Phase 1
|
|
789
789
|
# Parse coverage percentages
|
|
790
|
-
if [ $P0_COVERAGE -lt
|
|
791
|
-
echo "P0 coverage below
|
|
790
|
+
if [ $P0_COVERAGE -lt 100 ]; then
|
|
791
|
+
echo "P0 coverage below required 100%"
|
|
792
|
+
exit 1
|
|
793
|
+
fi
|
|
794
|
+
if [ $P1_COVERAGE -lt 80 ]; then
|
|
795
|
+
echo "P1 coverage below minimum 80%"
|
|
796
|
+
exit 1
|
|
797
|
+
fi
|
|
798
|
+
if [ $OVERALL_COVERAGE -lt 80 ]; then
|
|
799
|
+
echo "Overall coverage below minimum 80%"
|
|
792
800
|
exit 1
|
|
793
801
|
fi
|
|
794
802
|
```
|
|
@@ -916,7 +924,7 @@ Result: PARTIAL coverage (3/4 criteria)
|
|
|
916
924
|
|
|
917
925
|
**Use CONCERNS** ⚠️ if:
|
|
918
926
|
|
|
919
|
-
- P1 coverage
|
|
927
|
+
- P1 coverage 80-89% (below PASS target, above minimum)
|
|
920
928
|
- Minor quality issues (score 70-79)
|
|
921
929
|
- NFRs have mitigation plans
|
|
922
930
|
- Team agrees risk is acceptable
|
|
@@ -924,7 +932,7 @@ Result: PARTIAL coverage (3/4 criteria)
|
|
|
924
932
|
**Use FAIL** ❌ if:
|
|
925
933
|
|
|
926
934
|
- P0 coverage <100% (critical path gaps)
|
|
927
|
-
- P1 coverage <
|
|
935
|
+
- P1 coverage <80%
|
|
928
936
|
- Critical security/performance issues
|
|
929
937
|
- No mitigation possible
|
|
930
938
|
|
|
@@ -232,15 +232,15 @@ Quick reference for all 9 TEA (Test Engineering Architect) workflows. For detail
|
|
|
232
232
|
- `test-review.md` with quality score (0-100)
|
|
233
233
|
- Critical issues with fixes
|
|
234
234
|
- Recommendations
|
|
235
|
-
- Category scores (Determinism, Isolation,
|
|
235
|
+
- Category scores (Determinism, Isolation, Maintainability, Performance)
|
|
236
|
+
- Coverage guidance is informational only; coverage scoring and gates are handled by `trace`
|
|
236
237
|
|
|
237
238
|
**Scoring Categories:**
|
|
238
239
|
|
|
239
|
-
- Determinism:
|
|
240
|
-
- Isolation:
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
- Performance: 10 points
|
|
240
|
+
- Determinism: 30%
|
|
241
|
+
- Isolation: 30%
|
|
242
|
+
- Maintainability: 25%
|
|
243
|
+
- Performance: 15%
|
|
244
244
|
|
|
245
245
|
**How-To Guide:** [Run Test Review](/docs/how-to/workflows/run-test-review.md)
|
|
246
246
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-method-test-architecture-enterprise",
|
|
4
|
-
"version": "1.1
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"description": "Master Test Architect for quality strategy, test automation, and release gates",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bmad",
|
package/release_notes.md
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
## 🚀 What's New in v1.1
|
|
2
|
-
|
|
3
|
-
### ✨ New Features
|
|
4
|
-
- feat: prereq prompts part2
|
|
1
|
+
## 🚀 What's New in v1.2.1
|
|
5
2
|
|
|
6
3
|
### 🐛 Bug Fixes
|
|
7
|
-
- fix:
|
|
4
|
+
- fix: test review vs trace for coverage
|
|
8
5
|
|
|
9
6
|
### 📦 Other Changes
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
- Merge pull request #26 from bmad-code-org/fix/issue-22-23
|
|
7
|
+
- improved trace with coverage
|
|
8
|
+
- Merge pull request #30 from bmad-code-org/fix/test-review-vs-trace-for-coverage
|
|
13
9
|
|
|
14
10
|
|
|
15
11
|
## 📦 Installation
|
|
@@ -19,4 +15,4 @@ npx bmad-method install
|
|
|
19
15
|
# Select "Test Architect" from module menu
|
|
20
16
|
```
|
|
21
17
|
|
|
22
|
-
**Full Changelog**: https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise/compare/v1.0
|
|
18
|
+
**Full Changelog**: https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise/compare/v1.2.0...v1.2.1
|
|
@@ -371,6 +371,95 @@ test.describe('GraphQL API', () => {
|
|
|
371
371
|
- Check `body.errors` for GraphQL errors (not status code)
|
|
372
372
|
- Works for queries and mutations
|
|
373
373
|
|
|
374
|
+
### Example 8: Operation-Based Overload (OpenAPI / Code Generators)
|
|
375
|
+
|
|
376
|
+
**Context**: When using a code generator (orval, openapi-generator, custom scripts) that produces typed operation definitions from an OpenAPI spec, pass the operation object directly to `apiRequest`. This eliminates manual `method`/`path` extraction and `typeof` assertions while preserving full type inference for request body, response, and query parameters. Available since v3.14.0.
|
|
377
|
+
|
|
378
|
+
**Implementation**:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// Generated operation definition — structural typing, no import from playwright-utils needed
|
|
382
|
+
// type OperationShape = { path: string; method: 'POST'|'GET'|'PUT'|'DELETE'|'PATCH'|'HEAD'; response: unknown; request: unknown; query?: unknown }
|
|
383
|
+
|
|
384
|
+
import { test, expect } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
|
385
|
+
|
|
386
|
+
// --- Basic usage: operation replaces method + path ---
|
|
387
|
+
test('should upsert person via operation overload', async ({ apiRequest }) => {
|
|
388
|
+
const { status, body } = await apiRequest({
|
|
389
|
+
operation: upsertPersonv2({ customerId }),
|
|
390
|
+
headers: getHeaders(customerId),
|
|
391
|
+
body: personInput, // compile-time typed as Schemas.PersonInput
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(status).toBe(200);
|
|
395
|
+
expect(body.id).toBeDefined(); // body typed as Schemas.Person
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// --- Typed query parameters (replaces string concatenation) ---
|
|
399
|
+
test('should list people with typed query', async ({ apiRequest }) => {
|
|
400
|
+
const { body } = await apiRequest({
|
|
401
|
+
operation: getPeoplev2({ customerId }),
|
|
402
|
+
headers: getHeaders(customerId),
|
|
403
|
+
query: { page: 0, page_size: 5 }, // typed from operation's query definition
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
expect(body.items).toHaveLength(5);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// --- Params escape hatch (pre-formatted query strings) ---
|
|
410
|
+
test('should fetch billing history with raw params', async ({ apiRequest }) => {
|
|
411
|
+
const { body } = await apiRequest({
|
|
412
|
+
operation: getBillingHistoryv2({ customerId }),
|
|
413
|
+
headers: getHeaders(customerId),
|
|
414
|
+
params: {
|
|
415
|
+
'filters[start_date]': getThisMonthTimestamp(),
|
|
416
|
+
'filters[date_type]': 'MONTH',
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
expect(body.entries.length).toBeGreaterThan(0);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// --- Works with recurse (polling) ---
|
|
424
|
+
test('should poll until person is reviewed', async ({ apiRequest, recurse }) => {
|
|
425
|
+
await recurse(
|
|
426
|
+
async () =>
|
|
427
|
+
apiRequest({
|
|
428
|
+
operation: getPersonv2({ customerId, hash }),
|
|
429
|
+
headers: getHeaders(customerId),
|
|
430
|
+
}),
|
|
431
|
+
(res) => {
|
|
432
|
+
expect(res.status).toBe(200);
|
|
433
|
+
expect(res.body.status).toBe('REVIEWED');
|
|
434
|
+
},
|
|
435
|
+
{ timeout: 30000, interval: 1000 },
|
|
436
|
+
);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// --- Schema validation chains work identically ---
|
|
440
|
+
test('should create movie with schema validation', async ({ apiRequest }) => {
|
|
441
|
+
const { body } = await apiRequest({
|
|
442
|
+
operation: createMovieOp,
|
|
443
|
+
headers: commonHeaders(authToken),
|
|
444
|
+
body: movie,
|
|
445
|
+
}).validateSchema(CreateMovieResponseSchema, {
|
|
446
|
+
shape: { status: 200, data: { name: movie.name } },
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
expect(body.data.id).toBeDefined();
|
|
450
|
+
});
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Key Points**:
|
|
454
|
+
|
|
455
|
+
- Pass `operation` instead of `method` + `path` — mutually exclusive at compile time
|
|
456
|
+
- Response body, request body, and query types inferred from operation definition
|
|
457
|
+
- Uses structural typing (duck typing) — works with any code generator producing `{ path, method, response, request, query? }`
|
|
458
|
+
- `query` field auto-serializes to bracket notation (`filters[type]=pep`, `ids[0]=10`)
|
|
459
|
+
- `params` escape hatch for pre-formatted strings — wins over `query` on conflict
|
|
460
|
+
- Fully composable with `recurse`, `validateSchema`, and all existing features
|
|
461
|
+
- `response`/`request`/`query` on the operation are type-level only — runtime never reads their values
|
|
462
|
+
|
|
374
463
|
## Comparison with Vanilla Playwright
|
|
375
464
|
|
|
376
465
|
| Vanilla Playwright | playwright-utils apiRequest |
|
|
@@ -393,6 +482,7 @@ test.describe('GraphQL API', () => {
|
|
|
393
482
|
- ✅ Tests requiring retry logic
|
|
394
483
|
- ✅ Background API calls in UI tests
|
|
395
484
|
- ✅ Contract testing support
|
|
485
|
+
- ✅ Type-safe API testing with OpenAPI-generated operations (v3.14.0+)
|
|
396
486
|
|
|
397
487
|
**Stick with vanilla Playwright for:**
|
|
398
488
|
|
|
@@ -440,3 +530,34 @@ const response: any = await apiRequest({ method: 'GET', path: '/users' });
|
|
|
440
530
|
const { body } = await apiRequest<User[]>({ method: 'GET', path: '/users' });
|
|
441
531
|
// body is typed as User[]
|
|
442
532
|
```
|
|
533
|
+
|
|
534
|
+
**❌ Mixing operation overload with explicit generics:**
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
// Don't pass a generic when using operation — types are inferred from the operation
|
|
538
|
+
const { body } = await apiRequest<MyType>({
|
|
539
|
+
operation: getPersonv2({ customerId }),
|
|
540
|
+
headers: getHeaders(customerId),
|
|
541
|
+
});
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**✅ Let the operation infer the types:**
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
const { body } = await apiRequest({
|
|
548
|
+
operation: getPersonv2({ customerId }),
|
|
549
|
+
headers: getHeaders(customerId),
|
|
550
|
+
});
|
|
551
|
+
// body type inferred from operation.response
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
**❌ Mixing operation with method/path:**
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
// Compile error — operation and method/path are mutually exclusive
|
|
558
|
+
await apiRequest({
|
|
559
|
+
operation: getPersonv2({ customerId }),
|
|
560
|
+
method: 'GET', // Error: method?: never
|
|
561
|
+
path: '/api/person', // Error: path?: never
|
|
562
|
+
});
|
|
563
|
+
```
|
|
@@ -197,6 +197,7 @@ test.describe('Orders API', () => {
|
|
|
197
197
|
- `validateSchema` throws if response doesn't match
|
|
198
198
|
- Built-in retry for transient failures
|
|
199
199
|
- Type-safe `body` access
|
|
200
|
+
- **Note**: If your project uses code-generated operations from an OpenAPI spec, see [Example 8](#example-8-operation-based-api-testing-openapi--code-generators) for the preferred `operation`-based overload (v3.14.0+)
|
|
200
201
|
|
|
201
202
|
### Example 3: Microservice-to-Microservice Testing
|
|
202
203
|
|
|
@@ -713,6 +714,69 @@ test.describe('Authenticated API Tests', () => {
|
|
|
713
714
|
- Test auth, expired tokens, and RBAC
|
|
714
715
|
- Pure API testing without UI
|
|
715
716
|
|
|
717
|
+
### Example 8: Operation-Based API Testing (OpenAPI / Code Generators)
|
|
718
|
+
|
|
719
|
+
**Context**: When your project uses code-generated operation definitions from an OpenAPI spec, leverage the operation-based overload of `apiRequest` (v3.14.0+) instead of manual `method`/`path` extraction. This eliminates `typeof` assertions and provides full type inference for request body, response, and query parameters.
|
|
720
|
+
|
|
721
|
+
**Implementation**:
|
|
722
|
+
|
|
723
|
+
```typescript
|
|
724
|
+
// tests/api/operations.spec.ts
|
|
725
|
+
import { test, expect } from '@seontechnologies/playwright-utils/api-request/fixtures';
|
|
726
|
+
|
|
727
|
+
test.describe('API Tests with Generated Operations', () => {
|
|
728
|
+
test('should create entity with full type safety', async ({ apiRequest }) => {
|
|
729
|
+
// Operation object from code generator — contains path, method, and type info
|
|
730
|
+
const { status, body } = await apiRequest({
|
|
731
|
+
operation: createEntityOp({ workspaceId }),
|
|
732
|
+
headers: getHeaders(workspaceId),
|
|
733
|
+
body: entityInput, // Compile-time typed from operation.request
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
expect(status).toBe(201);
|
|
737
|
+
expect(body.id).toBeDefined(); // body typed from operation.response
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
test('should list with typed query parameters', async ({ apiRequest }) => {
|
|
741
|
+
// query field replaces manual string concatenation
|
|
742
|
+
const { body } = await apiRequest({
|
|
743
|
+
operation: listEntitiesOp({ workspaceId }),
|
|
744
|
+
headers: getHeaders(workspaceId),
|
|
745
|
+
query: { page: 0, page_size: 10, status: 'active' },
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
expect(body.items).toHaveLength(10);
|
|
749
|
+
expect(body.total).toBeGreaterThan(10);
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
test('should poll async operation until complete', async ({ apiRequest, recurse }) => {
|
|
753
|
+
const { body: job } = await apiRequest({
|
|
754
|
+
operation: startJobOp({ workspaceId }),
|
|
755
|
+
headers: getHeaders(workspaceId),
|
|
756
|
+
body: { type: 'export' },
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
await recurse(
|
|
760
|
+
async () =>
|
|
761
|
+
apiRequest({
|
|
762
|
+
operation: getJobOp({ workspaceId, jobId: job.id }),
|
|
763
|
+
headers: getHeaders(workspaceId),
|
|
764
|
+
}),
|
|
765
|
+
(res) => res.body.status === 'completed',
|
|
766
|
+
{ timeout: 60000, interval: 2000 },
|
|
767
|
+
);
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
**Key Points**:
|
|
773
|
+
|
|
774
|
+
- `operation` replaces `method` + `path` — mutually exclusive at compile time
|
|
775
|
+
- Types for body, response, and query all inferred from the operation definition
|
|
776
|
+
- Works with any code generator using structural typing (no imports from playwright-utils needed in generator)
|
|
777
|
+
- Composable with `recurse`, `validateSchema`, and all existing `apiRequest` features
|
|
778
|
+
- Preferred approach over `typeof operation.response` for generated operations
|
|
779
|
+
|
|
716
780
|
## API Test Configuration
|
|
717
781
|
|
|
718
782
|
### Playwright Config for API-Only Tests
|
|
@@ -38,17 +38,17 @@ npm install -D @seontechnologies/playwright-utils
|
|
|
38
38
|
|
|
39
39
|
### Core Testing Utilities
|
|
40
40
|
|
|
41
|
-
| Utility | Purpose
|
|
42
|
-
| -------------------------- |
|
|
43
|
-
| **api-request** | Typed HTTP client with schema validation and
|
|
44
|
-
| **recurse** | Polling for async operations, background jobs
|
|
45
|
-
| **auth-session** | Token persistence, multi-user, service-to-service
|
|
46
|
-
| **log** | Playwright report-integrated logging
|
|
47
|
-
| **file-utils** | CSV/XLSX/PDF/ZIP reading & validation
|
|
48
|
-
| **burn-in** | Smart test selection with git diff
|
|
49
|
-
| **network-recorder** | HAR record/playback for offline testing
|
|
50
|
-
| **intercept-network-call** | Network spy/stub with auto JSON parsing
|
|
51
|
-
| **network-error-monitor** | Automatic HTTP 4xx/5xx detection
|
|
41
|
+
| Utility | Purpose | Test Context |
|
|
42
|
+
| -------------------------- | ----------------------------------------------------------------------------- | ------------------ |
|
|
43
|
+
| **api-request** | Typed HTTP client with schema validation, retry, and operation-based overload | **API/Backend** |
|
|
44
|
+
| **recurse** | Polling for async operations, background jobs | **API/Backend** |
|
|
45
|
+
| **auth-session** | Token persistence, multi-user, service-to-service | **API/Backend/UI** |
|
|
46
|
+
| **log** | Playwright report-integrated logging | **API/Backend/UI** |
|
|
47
|
+
| **file-utils** | CSV/XLSX/PDF/ZIP reading & validation | **API/Backend/UI** |
|
|
48
|
+
| **burn-in** | Smart test selection with git diff | **CI/CD** |
|
|
49
|
+
| **network-recorder** | HAR record/playback for offline testing | UI only |
|
|
50
|
+
| **intercept-network-call** | Network spy/stub with auto JSON parsing | UI only |
|
|
51
|
+
| **network-error-monitor** | Automatic HTTP 4xx/5xx detection | UI only |
|
|
52
52
|
|
|
53
53
|
**Note**: 6 of 9 utilities work without a browser. Only 3 are UI-specific (network-recorder, intercept-network-call, network-error-monitor).
|
|
54
54
|
|
|
@@ -21,7 +21,7 @@ test-healing-patterns,Test Healing Patterns,"Common failure patterns and automat
|
|
|
21
21
|
selector-resilience,Selector Resilience,"Robust selector strategies and debugging techniques","selectors,locators,debugging,ui",knowledge/selector-resilience.md
|
|
22
22
|
timing-debugging,Timing Debugging,"Race condition identification and deterministic wait fixes","timing,async,debugging",knowledge/timing-debugging.md
|
|
23
23
|
overview,Playwright Utils Overview,"Installation, design principles, fixture patterns for API and UI testing","playwright-utils,fixtures,api,backend,ui",knowledge/overview.md
|
|
24
|
-
api-request,API Request,"Typed HTTP client, schema validation, retry logic for API and service testing","api,backend,service-testing,api-testing,playwright-utils",knowledge/api-request.md
|
|
24
|
+
api-request,API Request,"Typed HTTP client, schema validation, retry logic, operation-based overload for API and service testing","api,backend,service-testing,api-testing,playwright-utils,openapi,codegen,operation",knowledge/api-request.md
|
|
25
25
|
network-recorder,Network Recorder,"HAR record/playback, CRUD detection for offline UI testing","network,playwright-utils,ui,har",knowledge/network-recorder.md
|
|
26
26
|
auth-session,Auth Session,"Token persistence, multi-user, API and browser authentication","auth,playwright-utils,api,backend,jwt,token",knowledge/auth-session.md
|
|
27
27
|
intercept-network-call,Intercept Network Call,"Network spy/stub, JSON parsing for UI tests","network,playwright-utils,ui",knowledge/intercept-network-call.md
|
|
@@ -7,6 +7,7 @@ Use this checklist to validate that the test quality review workflow completed s
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
9
9
|
Note: `test-review` is optional and only audits existing tests; it does not generate tests.
|
|
10
|
+
Coverage analysis is out of scope for this workflow. Use `trace` for coverage metrics and coverage gate decisions.
|
|
10
11
|
|
|
11
12
|
### Test File Discovery
|
|
12
13
|
|
|
@@ -72,6 +73,8 @@ Note: `test-review` is optional and only audits existing tests; it does not gene
|
|
|
72
73
|
|
|
73
74
|
### Step 3: Quality Criteria Validation
|
|
74
75
|
|
|
76
|
+
Coverage criteria are intentionally excluded from this checklist.
|
|
77
|
+
|
|
75
78
|
**For Each Enabled Criterion:**
|
|
76
79
|
|
|
77
80
|
#### BDD Format (if `check_given_when_then: true`)
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
Review test quality using TEA knowledge base and produce a 0–100 quality score with actionable findings.
|
|
11
11
|
|
|
12
|
+
Coverage assessment is intentionally out of scope for this workflow. Use `trace` for requirements coverage and coverage gate decisions.
|
|
13
|
+
|
|
12
14
|
---
|
|
13
15
|
|
|
14
16
|
## WORKFLOW ARCHITECTURE
|