@keber/qa-framework 1.0.4
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/CHANGELOG.md +53 -0
- package/README.md +233 -0
- package/agent-instructions/00-module-analysis.md +263 -0
- package/agent-instructions/01-spec-generation.md +278 -0
- package/agent-instructions/02-test-plan-generation.md +202 -0
- package/agent-instructions/03-test-case-generation.md +147 -0
- package/agent-instructions/04-automation-generation.md +310 -0
- package/agent-instructions/04b-test-stabilization.md +306 -0
- package/agent-instructions/05-ado-integration.md +244 -0
- package/agent-instructions/06-maintenance.md +125 -0
- package/docs/architecture.md +227 -0
- package/docs/comparison-matrix.md +131 -0
- package/docs/final-report.md +279 -0
- package/docs/folder-structure-guide.md +291 -0
- package/docs/generalization-decisions.md +203 -0
- package/docs/installation.md +239 -0
- package/docs/spec-driven-philosophy.md +170 -0
- package/docs/usage-with-agent.md +203 -0
- package/examples/module-example/README.md +34 -0
- package/examples/module-example/suppliers/00-inventory.md +56 -0
- package/examples/module-example/suppliers/suppliers-create.spec.ts +148 -0
- package/integrations/ado-powershell/README.md +75 -0
- package/integrations/ado-powershell/pipelines/azure-pipeline-qa.yml +133 -0
- package/integrations/ado-powershell/scripts/create-testplan-from-mapping.ps1 +114 -0
- package/integrations/ado-powershell/scripts/inject-ado-ids.ps1 +96 -0
- package/integrations/ado-powershell/scripts/sync-ado-titles.ps1 +93 -0
- package/integrations/playwright/README.md +68 -0
- package/integrations/playwright-azure-reporter/README.md +88 -0
- package/package.json +57 -0
- package/qa-framework.config.json +87 -0
- package/scripts/cli.js +74 -0
- package/scripts/generate.js +92 -0
- package/scripts/init.js +322 -0
- package/scripts/validate.js +184 -0
- package/templates/automation-scaffold/.env.example +56 -0
- package/templates/automation-scaffold/fixtures/auth.ts +77 -0
- package/templates/automation-scaffold/fixtures/test-helpers.ts +85 -0
- package/templates/automation-scaffold/global-setup.ts +106 -0
- package/templates/automation-scaffold/package.json +24 -0
- package/templates/automation-scaffold/playwright.config.ts +85 -0
- package/templates/defect-report.md +101 -0
- package/templates/execution-report.md +116 -0
- package/templates/session-summary.md +73 -0
- package/templates/specification/00-inventory.md +81 -0
- package/templates/specification/01-business-rules.md +90 -0
- package/templates/specification/02-workflows.md +114 -0
- package/templates/specification/03-roles-permissions.md +49 -0
- package/templates/specification/04-test-data.md +104 -0
- package/templates/specification/05-test-scenarios.md +226 -0
- package/templates/test-case.md +81 -0
- package/templates/test-plan.md +130 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Business Rules — {{MODULE_NAME}}: {{SUBMODULE_NAME}}
|
|
2
|
+
|
|
3
|
+
> **Module code**: {{MODULE_CODE}} | **Submodule code**: {{SUBMODULE_CODE}}
|
|
4
|
+
> **Last updated**: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
| ID | Title | Type | Trigger |
|
|
11
|
+
|----|-------|------|---------|
|
|
12
|
+
| RN-{{M}}-001 | {{rule title}} | Validation | {{trigger}} |
|
|
13
|
+
| RN-{{M}}-002 | {{rule title}} | Access Control | {{trigger}} |
|
|
14
|
+
| RN-{{M}}-003 | {{rule title}} | State Machine | {{trigger}} |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Rules
|
|
19
|
+
|
|
20
|
+
### RN-{{MODULE_CODE}}-001: {{Rule Title}}
|
|
21
|
+
|
|
22
|
+
- **Type**: Validation
|
|
23
|
+
- **Trigger**: When user attempts to {{action}}
|
|
24
|
+
- **Behavior**: {{what the system does}}
|
|
25
|
+
- **Error message**: "{{exact text shown in UI}}"
|
|
26
|
+
- **Notes**: {{any special circumstances}}
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### RN-{{MODULE_CODE}}-002: {{Rule Title}}
|
|
31
|
+
|
|
32
|
+
- **Type**: Access Control
|
|
33
|
+
- **Trigger**: When user with role {{role}} navigates to {{URL}}
|
|
34
|
+
- **Behavior**: {{redirect / error / empty page}}
|
|
35
|
+
- **Notes**: —
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### RN-{{MODULE_CODE}}-003: {{Rule Title}}
|
|
40
|
+
|
|
41
|
+
- **Type**: State Machine
|
|
42
|
+
- **Trigger**: When {{action}} is performed on a record with status {{STATUS_A}}
|
|
43
|
+
- **Behavior**: Record transitions from {{STATUS_A}} to {{STATUS_B}}
|
|
44
|
+
- **Invalid state**: Attempting this action on status {{STATUS_C}} results in {{error}}
|
|
45
|
+
- **Notes**: —
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### RN-{{MODULE_CODE}}-004: {{Rule Title}}
|
|
50
|
+
|
|
51
|
+
- **Type**: Calculation
|
|
52
|
+
- **Trigger**: When {{field}} or {{field}} changes
|
|
53
|
+
- **Behavior**: {{calculated_field}} = {{formula}}
|
|
54
|
+
- **Notes**: —
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### RN-{{MODULE_CODE}}-005: {{Rule Title}}
|
|
59
|
+
|
|
60
|
+
- **Type**: Integration
|
|
61
|
+
- **Trigger**: When {{action}} completes successfully
|
|
62
|
+
- **Behavior**: {{external system}} is notified/called — {{what happens}}
|
|
63
|
+
- **Fallback**: {{what happens if external system fails}}
|
|
64
|
+
- **Notes**: —
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## State Machine (if applicable)
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
{{STATUS_INITIAL}}
|
|
72
|
+
│
|
|
73
|
+
├─[action: approve]──► {{STATUS_APPROVED}}
|
|
74
|
+
│
|
|
75
|
+
└─[action: reject]───► {{STATUS_REJECTED}}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| State | Code | Description |
|
|
79
|
+
|-------|------|-------------|
|
|
80
|
+
| {{Pending}} | {{1}} | {{description}} |
|
|
81
|
+
| {{Approved}} | {{2}} | {{description}} |
|
|
82
|
+
| {{Rejected}} | {{3}} | {{description}} |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Changelog
|
|
87
|
+
|
|
88
|
+
| Version | Date | Description |
|
|
89
|
+
|---------|------|-------------|
|
|
90
|
+
| 1.0 | YYYY-MM-DD | Initial creation |
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Workflows — {{MODULE_NAME}}: {{SUBMODULE_NAME}}
|
|
2
|
+
|
|
3
|
+
> **Module code**: {{MODULE_CODE}} | **Submodule code**: {{SUBMODULE_CODE}}
|
|
4
|
+
> **Last updated**: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## FL-{{MODULE_CODE}}-001: {{Main Workflow Title}}
|
|
9
|
+
|
|
10
|
+
**Actor**: {{Role}}
|
|
11
|
+
**Trigger**: {{What starts this workflow}}
|
|
12
|
+
**Precondition**: {{What must be true before this starts}}
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
[Start: navigate to {{URL}}]
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
[Click 'New' button]
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
[Form opens]
|
|
22
|
+
│
|
|
23
|
+
├─[Required field empty]──► [Validation error shown] ──► [User corrects] ──► (loop back)
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
[Fill all required fields]
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
[Click 'Save']
|
|
30
|
+
│
|
|
31
|
+
├─[Duplicate detected]────► [System shows duplicate error] ──► [End: failure]
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
[Success message displayed]
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
[New record appears in list]
|
|
38
|
+
│
|
|
39
|
+
▼
|
|
40
|
+
[End: record created successfully]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Postcondition**: New record is persisted. Visible in the list view.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## FL-{{MODULE_CODE}}-002: {{Rejection / Cancellation Workflow Title}}
|
|
48
|
+
|
|
49
|
+
**Actor**: {{Role}}
|
|
50
|
+
**Trigger**: {{What starts this workflow}}
|
|
51
|
+
**Precondition**: {{What must be true before this starts}}
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
[Start: navigate to pending records list]
|
|
55
|
+
│
|
|
56
|
+
▼
|
|
57
|
+
[Select record]
|
|
58
|
+
│
|
|
59
|
+
▼
|
|
60
|
+
[Click 'Reject' / 'Cancel']
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
[Confirmation dialog appears]
|
|
64
|
+
│
|
|
65
|
+
├─[User clicks 'No' / 'Cancel']──► [Dialog closes, no change]
|
|
66
|
+
│
|
|
67
|
+
▼
|
|
68
|
+
[User confirms]
|
|
69
|
+
│
|
|
70
|
+
▼
|
|
71
|
+
[System validates preconditions]
|
|
72
|
+
│
|
|
73
|
+
├─[Precondition not met]─────────► [Error message]──► [End: rejected]
|
|
74
|
+
│
|
|
75
|
+
▼
|
|
76
|
+
[Record status changes to 'Rejected']
|
|
77
|
+
│
|
|
78
|
+
▼
|
|
79
|
+
[Notification sent (if applicable)]
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
[End: record rejected]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Postcondition**: Record status = Rejected. Notification sent to relevant parties.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## FL-{{MODULE_CODE}}-003: {{Error/Validation Workflow Title}}
|
|
90
|
+
|
|
91
|
+
**Actor**: {{Role}}
|
|
92
|
+
**Trigger**: {{What starts this workflow when things go wrong}}
|
|
93
|
+
|
|
94
|
+
```mermaid
|
|
95
|
+
flowchart TD
|
|
96
|
+
A[User submits form] --> B{Validation passes?}
|
|
97
|
+
B -- No --> C[Show validation errors]
|
|
98
|
+
C --> D[User corrects input]
|
|
99
|
+
D --> A
|
|
100
|
+
B -- Yes --> E{Business rule passes?}
|
|
101
|
+
E -- No --> F[Show business rule error]
|
|
102
|
+
F --> G[End: submission rejected]
|
|
103
|
+
E -- Yes --> H[Record saved]
|
|
104
|
+
H --> I[Success feedback]
|
|
105
|
+
I --> J[End: success]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Changelog
|
|
111
|
+
|
|
112
|
+
| Version | Date | Description |
|
|
113
|
+
|---------|------|-------------|
|
|
114
|
+
| 1.0 | YYYY-MM-DD | Initial creation |
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Roles and Permissions — {{MODULE_NAME}}: {{SUBMODULE_NAME}}
|
|
2
|
+
|
|
3
|
+
> **Module code**: {{MODULE_CODE}} | **Submodule code**: {{SUBMODULE_CODE}}
|
|
4
|
+
> **Last updated**: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Access Matrix
|
|
9
|
+
|
|
10
|
+
| Feature / Action | {{Role 1}} | {{Role 2}} | {{Role 3}} | Notes |
|
|
11
|
+
|-----------------|-----------|-----------|-----------|-------|
|
|
12
|
+
| View list | ✅ | ✅ | ❌ | |
|
|
13
|
+
| View detail | ✅ | ✅ | ❌ | |
|
|
14
|
+
| Create new record | ✅ | ❌ | ❌ | |
|
|
15
|
+
| Edit record | ✅ | ❌ | ❌ | |
|
|
16
|
+
| Delete / deactivate | ✅ | ❌ | ❌ | Only own records |
|
|
17
|
+
| Approve / reject | ❌ | ✅ | ❌ | |
|
|
18
|
+
| Export | ✅ | ✅ | ❌ | |
|
|
19
|
+
| View audit log | ✅ | ❌ | ❌ | |
|
|
20
|
+
|
|
21
|
+
**Legend**: ✅ Permitted | ❌ Not permitted | ⚠️ Conditional
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Test User Reference
|
|
26
|
+
|
|
27
|
+
| Role | Env var (email) | Env var (password) | Notes |
|
|
28
|
+
|------|----------------|-------------------|-------|
|
|
29
|
+
| {{Role 1}} | `QA_USER_{{ROLE1_UPPER}}_EMAIL` | `QA_USER_{{ROLE1_UPPER}}_PASSWORD` | {{any notes}} |
|
|
30
|
+
| {{Role 2}} | `QA_USER_{{ROLE2_UPPER}}_EMAIL` | `QA_USER_{{ROLE2_UPPER}}_PASSWORD` | {{any notes}} |
|
|
31
|
+
| {{Role 3}} | `QA_USER_{{ROLE3_UPPER}}_EMAIL` | `QA_USER_{{ROLE3_UPPER}}_PASSWORD` | {{any notes}} |
|
|
32
|
+
|
|
33
|
+
> ⚠️ **Never put actual credentials in this file.** Credentials are loaded from environment variables only.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Notes
|
|
38
|
+
|
|
39
|
+
- {{Conditional access rule 1, e.g., "Admin can only edit records created by their team"}}
|
|
40
|
+
- {{Conditional access rule 2}}
|
|
41
|
+
- {{Any role-specific UI differences, e.g., "Encargado sees additional 'Assign' button"}}
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Changelog
|
|
46
|
+
|
|
47
|
+
| Version | Date | Description |
|
|
48
|
+
|---------|------|-------------|
|
|
49
|
+
| 1.0 | YYYY-MM-DD | Initial creation |
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Test Data — {{MODULE_NAME}}: {{SUBMODULE_NAME}}
|
|
2
|
+
|
|
3
|
+
> **Module code**: {{MODULE_CODE}} | **Submodule code**: {{SUBMODULE_CODE}}
|
|
4
|
+
> **Last updated**: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
> ⚠️ **Security reminder**: Never put actual credentials, DNIs, or personal data in this file.
|
|
7
|
+
> All credentials are read from environment variables only.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
The following data must exist in the QA environment before tests run:
|
|
14
|
+
|
|
15
|
+
| Item | Description | How provided |
|
|
16
|
+
|------|-------------|-------------|
|
|
17
|
+
| {{entity type}} | At least 1 active record exists | QA seed / pre-existing in env |
|
|
18
|
+
| User: {{Role 1}} | Active user with {{Role 1}} role | `QA_USER_{{ROLE1_UPPER}}_EMAIL` env var |
|
|
19
|
+
| User: {{Role 2}} | Active user with {{Role 2}} role | `QA_USER_{{ROLE2_UPPER}}_EMAIL` env var |
|
|
20
|
+
| {{Prerequisite N}} | {{Description}} | Manual setup required / Seeder script |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Data Shapes for Key Scenarios
|
|
25
|
+
|
|
26
|
+
### Scenario: Happy path — create record
|
|
27
|
+
|
|
28
|
+
| Field | Value / Rule |
|
|
29
|
+
|-------|-------------|
|
|
30
|
+
| {{name-field}} | `Test-{EXEC_IDX}` — unique per run via EXEC_IDX pattern |
|
|
31
|
+
| {{select-field}} | Any valid option (first option is acceptable) |
|
|
32
|
+
| {{date-field}} | `${2120 + (EXEC_IDX % 10)}-01-01` — future date, collision-resistant |
|
|
33
|
+
| User | `{{Role 1}}`, credentials from `QA_USER_{{ROLE1_UPPER}}_EMAIL` |
|
|
34
|
+
|
|
35
|
+
### Scenario: Required field validation
|
|
36
|
+
|
|
37
|
+
| Field | Value |
|
|
38
|
+
|-------|-------|
|
|
39
|
+
| {{name-field}} | Empty (leave blank) |
|
|
40
|
+
| All other fields | Valid values |
|
|
41
|
+
|
|
42
|
+
**Expected**: Validation error prevents submission.
|
|
43
|
+
|
|
44
|
+
### Scenario: Duplicate rejection
|
|
45
|
+
|
|
46
|
+
| Field | Value |
|
|
47
|
+
|-------|-------|
|
|
48
|
+
| {{unique-field}} | Same value as an existing record |
|
|
49
|
+
|
|
50
|
+
**Expected**: System error message: "{{exact duplicate error text}}"
|
|
51
|
+
|
|
52
|
+
### Scenario: State transition — {{action}}
|
|
53
|
+
|
|
54
|
+
| Field | Value |
|
|
55
|
+
|-------|-------|
|
|
56
|
+
| Source record | Record in status `{{STATUS_A}}` |
|
|
57
|
+
| Action | Click '{{action button}}' |
|
|
58
|
+
|
|
59
|
+
**Expected**: Record transitions to status `{{STATUS_B}}`. {{Notification sent if applicable.}}
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Dynamic Data Generation Pattern
|
|
64
|
+
|
|
65
|
+
For tests that create records and need unique identifiers:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// Changes every 60 seconds. Provides collision-resistant keys without cleanup.
|
|
69
|
+
const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
|
|
70
|
+
|
|
71
|
+
// String key
|
|
72
|
+
const entityName = `Test-${EXEC_IDX}`;
|
|
73
|
+
|
|
74
|
+
// Date (far future avoids prod data overlap)
|
|
75
|
+
const year = 2120 + (EXEC_IDX % 10);
|
|
76
|
+
const month = String((EXEC_IDX % 12) + 1).padStart(2, '0');
|
|
77
|
+
const day = String((EXEC_IDX % 28) + 1).padStart(2, '0');
|
|
78
|
+
const testDate = `${year}-${month}-${day}`;
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Data Isolation Rules
|
|
84
|
+
|
|
85
|
+
1. Each test creates its own data — no shared mutable state between tests
|
|
86
|
+
2. `beforeAll` creates records for the entire suite — provision ≥ N records for N consuming tests
|
|
87
|
+
3. No test teardown required when EXEC_IDX-based names are used (future-dated records do not collide across runs)
|
|
88
|
+
4. If a test modifies shared data (approve/reject), it must create its own record in `beforeAll`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Retired / Deprecated Test Data
|
|
93
|
+
|
|
94
|
+
| Item | Reason for retirement | Replaced by |
|
|
95
|
+
|------|-----------------------|-------------|
|
|
96
|
+
| {{item}} | Real employee data — PII risk | EXEC_IDX-generated test record |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Changelog
|
|
101
|
+
|
|
102
|
+
| Version | Date | Description |
|
|
103
|
+
|---------|------|-------------|
|
|
104
|
+
| 1.0 | YYYY-MM-DD | Initial creation |
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Test Scenarios — {{MODULE_NAME}}: {{SUBMODULE_NAME}}
|
|
2
|
+
|
|
3
|
+
> **Module code**: {{MODULE_CODE}} | **Submodule code**: {{SUBMODULE_CODE}}
|
|
4
|
+
> **Last updated**: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
| Priority | Total | Automated | Manual | Pending |
|
|
11
|
+
|----------|-------|-----------|--------|---------|
|
|
12
|
+
| P0 | 0 | 0 | 0 | 0 |
|
|
13
|
+
| P1 | 0 | 0 | 0 | 0 |
|
|
14
|
+
| P2 | 0 | 0 | 0 | 0 |
|
|
15
|
+
| P3 | 0 | 0 | 0 | 0 |
|
|
16
|
+
| **Total** | **0** | **0** | **0** | **0** |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Test Cases
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### TC-{{M}}-{{S}}-001: Unauthenticated access redirects to login
|
|
25
|
+
|
|
26
|
+
| Field | Value |
|
|
27
|
+
|-------|-------|
|
|
28
|
+
| Priority | P0 |
|
|
29
|
+
| Type | Security |
|
|
30
|
+
| Origin | UI-OBSERVED |
|
|
31
|
+
| Automation | Yes |
|
|
32
|
+
|
|
33
|
+
**Preconditions**: User is NOT logged in.
|
|
34
|
+
|
|
35
|
+
**Steps**:
|
|
36
|
+
1. Navigate directly to `{{QA_BASE_URL}}/{{SUBMODULE_PATH}}`
|
|
37
|
+
|
|
38
|
+
**Expected result**: Redirected to login page. `{{SUBMODULE_PATH}}` URL is not accessible.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
### TC-{{M}}-{{S}}-002: Role without permission cannot access submodule
|
|
43
|
+
|
|
44
|
+
| Field | Value |
|
|
45
|
+
|-------|-------|
|
|
46
|
+
| Priority | P0 |
|
|
47
|
+
| Type | Security |
|
|
48
|
+
| Origin | UI-OBSERVED |
|
|
49
|
+
| Automation | Yes |
|
|
50
|
+
|
|
51
|
+
**Preconditions**: Logged in as `{{ROLE_WITHOUT_PERMISSION}}`.
|
|
52
|
+
|
|
53
|
+
**Steps**:
|
|
54
|
+
1. Navigate to `{{QA_BASE_URL}}/{{SUBMODULE_PATH}}`
|
|
55
|
+
|
|
56
|
+
**Expected result**: Permission error displayed OR menu item not visible OR redirect to home.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### TC-{{M}}-{{S}}-003: List loads correctly for authorized user
|
|
61
|
+
|
|
62
|
+
| Field | Value |
|
|
63
|
+
|-------|-------|
|
|
64
|
+
| Priority | P0 |
|
|
65
|
+
| Type | Functional |
|
|
66
|
+
| Origin | UI-OBSERVED |
|
|
67
|
+
| Automation | Yes |
|
|
68
|
+
|
|
69
|
+
**Preconditions**: Logged in as `{{AUTHORIZED_ROLE}}`. At least 1 record exists.
|
|
70
|
+
|
|
71
|
+
**Steps**:
|
|
72
|
+
1. Navigate to `{{QA_BASE_URL}}/{{SUBMODULE_PATH}}`
|
|
73
|
+
|
|
74
|
+
**Expected result**: Table/grid displays records. Column headers visible. Pagination controls present.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### TC-{{M}}-{{S}}-004: Create new record — happy path
|
|
79
|
+
|
|
80
|
+
| Field | Value |
|
|
81
|
+
|-------|-------|
|
|
82
|
+
| Priority | P0 |
|
|
83
|
+
| Type | Functional |
|
|
84
|
+
| Origin | UI-OBSERVED |
|
|
85
|
+
| Automation | Yes |
|
|
86
|
+
|
|
87
|
+
**Test data**:
|
|
88
|
+
- Name: `Test-{EXEC_IDX}` (unique per run)
|
|
89
|
+
- other fields: valid values per 04-test-data.md
|
|
90
|
+
|
|
91
|
+
**Steps**:
|
|
92
|
+
1. Click 'New' / 'Create' button
|
|
93
|
+
2. Fill all required fields with valid data
|
|
94
|
+
3. Click 'Save' / 'Submit'
|
|
95
|
+
|
|
96
|
+
**Expected result**: Success message appears. New record visible in the list.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### TC-{{M}}-{{S}}-005: Required field validation — name empty
|
|
101
|
+
|
|
102
|
+
| Field | Value |
|
|
103
|
+
|-------|-------|
|
|
104
|
+
| Priority | P1 |
|
|
105
|
+
| Type | Negative |
|
|
106
|
+
| Origin | UI-OBSERVED |
|
|
107
|
+
| Automation | Yes |
|
|
108
|
+
|
|
109
|
+
**Steps**:
|
|
110
|
+
1. Click 'New' / 'Create' button
|
|
111
|
+
2. Leave required field `{{FIELD_NAME}}` empty
|
|
112
|
+
3. Click 'Save' / 'Submit'
|
|
113
|
+
|
|
114
|
+
**Expected result**: Validation error shown near the field: "{{exact error message text}}"
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### TC-{{M}}-{{S}}-006: Duplicate rejection
|
|
119
|
+
|
|
120
|
+
| Field | Value |
|
|
121
|
+
|-------|-------|
|
|
122
|
+
| Priority | P1 |
|
|
123
|
+
| Type | Negative |
|
|
124
|
+
| Origin | UI-OBSERVED |
|
|
125
|
+
| Automation | Yes |
|
|
126
|
+
|
|
127
|
+
**Preconditions**: A record with name "{{duplicate-value}}" already exists.
|
|
128
|
+
|
|
129
|
+
**Steps**:
|
|
130
|
+
1. Click 'New' / 'Create' button
|
|
131
|
+
2. Enter the same name as an existing record
|
|
132
|
+
3. Click 'Save' / 'Submit'
|
|
133
|
+
|
|
134
|
+
**Expected result**: System rejects with error: "{{exact duplicate error message}}"
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### TC-{{M}}-{{S}}-007: Edit existing record
|
|
139
|
+
|
|
140
|
+
| Field | Value |
|
|
141
|
+
|-------|-------|
|
|
142
|
+
| Priority | P1 |
|
|
143
|
+
| Type | Functional |
|
|
144
|
+
| Origin | UI-OBSERVED |
|
|
145
|
+
| Automation | Yes |
|
|
146
|
+
|
|
147
|
+
**Preconditions**: At least 1 record exists.
|
|
148
|
+
|
|
149
|
+
**Steps**:
|
|
150
|
+
1. Click 'Edit' on an existing record
|
|
151
|
+
2. Modify `{{FIELD_NAME}}` to a new valid value
|
|
152
|
+
3. Click 'Save'
|
|
153
|
+
|
|
154
|
+
**Expected result**: Success message. Record in list shows updated value.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### TC-{{M}}-{{S}}-008: Delete / deactivate record
|
|
159
|
+
|
|
160
|
+
| Field | Value |
|
|
161
|
+
|-------|-------|
|
|
162
|
+
| Priority | P1 |
|
|
163
|
+
| Type | Functional |
|
|
164
|
+
| Origin | UI-OBSERVED |
|
|
165
|
+
| Automation | Partial |
|
|
166
|
+
|
|
167
|
+
**Preconditions**: At least 1 deletable record exists.
|
|
168
|
+
|
|
169
|
+
**Steps**:
|
|
170
|
+
1. Click 'Delete' / 'Deactivate' on an existing record
|
|
171
|
+
2. Confirm the action in the confirmation dialog
|
|
172
|
+
|
|
173
|
+
**Expected result**: Record is removed from active list or marked as inactive.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### TC-{{M}}-{{S}}-009: Export to Excel / CSV
|
|
178
|
+
|
|
179
|
+
| Field | Value |
|
|
180
|
+
|-------|-------|
|
|
181
|
+
| Priority | P2 |
|
|
182
|
+
| Type | Functional |
|
|
183
|
+
| Origin | UI-OBSERVED |
|
|
184
|
+
| Automation | Partial |
|
|
185
|
+
|
|
186
|
+
**Steps**:
|
|
187
|
+
1. Navigate to list view
|
|
188
|
+
2. Click 'Export' button
|
|
189
|
+
|
|
190
|
+
**Expected result**: File download initiates. File is non-empty.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### TC-{{M}}-{{S}}-010: Search / filter works
|
|
195
|
+
|
|
196
|
+
| Field | Value |
|
|
197
|
+
|-------|-------|
|
|
198
|
+
| Priority | P2 |
|
|
199
|
+
| Type | Functional |
|
|
200
|
+
| Origin | UI-OBSERVED |
|
|
201
|
+
| Automation | Yes |
|
|
202
|
+
|
|
203
|
+
**Steps**:
|
|
204
|
+
1. Navigate to list view
|
|
205
|
+
2. Type a known value in the search input
|
|
206
|
+
3. Wait for filter to apply
|
|
207
|
+
|
|
208
|
+
**Expected result**: Only records matching the search term are shown.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Traceability
|
|
213
|
+
|
|
214
|
+
| TC ID | Business Rules | Workflow |
|
|
215
|
+
|-------|---------------|---------|
|
|
216
|
+
| TC-{{M}}-{{S}}-001 | — | — |
|
|
217
|
+
| TC-{{M}}-{{S}}-004 | RN-{{M}}-001 | FL-{{M}}-001 |
|
|
218
|
+
| TC-{{M}}-{{S}}-005 | RN-{{M}}-001 | — |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Changelog
|
|
223
|
+
|
|
224
|
+
| Version | Date | Description |
|
|
225
|
+
|---------|------|-------------|
|
|
226
|
+
| 1.0 | YYYY-MM-DD | Initial creation (N TCs) |
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Test Case — TC-{{MODULE}}-{{SUB}}-{{NNN}}: {{Title}}
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| TC-ID | TC-{{MODULE}}-{{SUB}}-{{NNN}} |
|
|
6
|
+
| ADO WI | #{ADO_WORK_ITEM_ID} (after inject-ado-ids.ps1) |
|
|
7
|
+
| Title | {{Title}} |
|
|
8
|
+
| Module | {{MODULE_NAME}} |
|
|
9
|
+
| Submodule | {{SUBMODULE_NAME}} |
|
|
10
|
+
| Priority | P0 / P1 / P2 / P3 |
|
|
11
|
+
| Type | Functional / Integration / Regression / Smoke |
|
|
12
|
+
| Execution | Manual / Automated / Both |
|
|
13
|
+
| Automation file | `qa/07-automation/e2e/{{module}}/{{submodule}}.spec.ts` (if automated) |
|
|
14
|
+
| Preconditions | {{List required setup — see 04-test-data.md}} |
|
|
15
|
+
| Author | (agent output — reviewed by human) |
|
|
16
|
+
| Last updated | YYYY-MM-DD |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Test Steps
|
|
21
|
+
|
|
22
|
+
| # | Action | Expected Result |
|
|
23
|
+
|---|--------|----------------|
|
|
24
|
+
| 1 | Navigate to `{{QA_BASE_URL}}/{{path}}` | Login page loads with form visible |
|
|
25
|
+
| 2 | Log in as `{{role}}` (credentials from `.env`) | Dashboard displays; role navigation visible |
|
|
26
|
+
| 3 | Navigate to `{{module}} > {{submodule}}` | Grid/form renders without console errors |
|
|
27
|
+
| 4 | {{Action on primary element}} | {{Observable, measurable outcome}} |
|
|
28
|
+
| 5 | {{Confirm secondary state}} | {{Confirmation visible to end user}} |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Expected Final State
|
|
33
|
+
|
|
34
|
+
- **UI**: {{What the user sees after completing all steps}}
|
|
35
|
+
- **Data**: {{Observable data change (record count, field value, etc.)}}
|
|
36
|
+
- **Notifications**: {{toastr, SweetAlert, or inline message shown (exact text if known)}}
|
|
37
|
+
- **Side effects**: {{Other systems/modules affected}}
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Test Data
|
|
42
|
+
|
|
43
|
+
| Item | Value |
|
|
44
|
+
|------|-------|
|
|
45
|
+
| User | `{{QA_USER_EMAIL}}` (role: {{ROLE}}) |
|
|
46
|
+
| Input field 1 | `EXEC_IDX` or `{{static-value}}` |
|
|
47
|
+
| Input field 2 | `{{value}}` |
|
|
48
|
+
|
|
49
|
+
> Use EXEC_IDX for fields that must be unique: `Math.floor(Date.now() / 60_000) % 100_000`
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Pass / Fail Criteria
|
|
54
|
+
|
|
55
|
+
**PASS**: All step assertions met AND final state matches expected.
|
|
56
|
+
|
|
57
|
+
**FAIL**: Any step assertion failed, unexpected error appeared, or final state differs.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Linked Artifacts
|
|
62
|
+
|
|
63
|
+
- Spec source: `{{module}}/{{submodule}}/05-test-scenarios.md`
|
|
64
|
+
- Business rules: `{{module}}/{{submodule}}/01-business-rules.md §RN-{{M}}-{{NNN}}`
|
|
65
|
+
- Related defects: DEF-{{NNN}} (if any)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Execution History
|
|
70
|
+
|
|
71
|
+
| Date | Executor | Environment | Result | Notes |
|
|
72
|
+
|------|----------|-------------|--------|-------|
|
|
73
|
+
| YYYY-MM-DD | | QA | Pass / Fail / Skip | |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Changelog
|
|
78
|
+
|
|
79
|
+
| Version | Date | Description |
|
|
80
|
+
|---------|------|-------------|
|
|
81
|
+
| 1.0 | YYYY-MM-DD | TC created |
|