@torus-engineering/tas-kit 1.7.0 → 1.9.0

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 (73) hide show
  1. package/.claude/commands/tas-adr.md +33 -29
  2. package/.claude/commands/tas-apitest-plan.md +173 -0
  3. package/.claude/commands/tas-apitest.md +143 -0
  4. package/.claude/commands/tas-bug.md +113 -109
  5. package/.claude/commands/tas-design.md +37 -33
  6. package/.claude/commands/tas-dev.md +128 -115
  7. package/.claude/commands/tas-e2e-mobile.md +155 -0
  8. package/.claude/commands/tas-e2e-web.md +163 -0
  9. package/.claude/commands/tas-e2e.md +102 -0
  10. package/.claude/commands/tas-epic.md +35 -31
  11. package/.claude/commands/tas-feature.md +47 -43
  12. package/.claude/commands/tas-fix.md +51 -47
  13. package/.claude/commands/tas-functest-mobile.md +144 -0
  14. package/.claude/commands/tas-functest-web.md +192 -0
  15. package/.claude/commands/tas-functest.md +76 -0
  16. package/.claude/commands/tas-plan.md +200 -184
  17. package/.claude/commands/tas-prd.md +37 -33
  18. package/.claude/commands/tas-review.md +111 -104
  19. package/.claude/commands/tas-sad.md +43 -39
  20. package/.claude/commands/tas-security.md +81 -80
  21. package/.claude/commands/tas-story.md +91 -87
  22. package/.claude/commands/tas-verify.md +51 -41
  23. package/.claude/rules/common/post-review-agent.md +49 -39
  24. package/.claude/rules/common/testing.md +24 -0
  25. package/.claude/rules/common/token-logging.md +27 -0
  26. package/.claude/rules/csharp/api-testing.md +171 -0
  27. package/.claude/rules/csharp/patterns.md +10 -0
  28. package/.claude/rules/python/patterns.md +10 -0
  29. package/.claude/rules/typescript/patterns.md +10 -0
  30. package/.claude/rules/web/performance.md +9 -0
  31. package/.claude/skills/api-design/SKILL.md +3 -1
  32. package/.claude/skills/{backend-patterns → js-backend-patterns}/SKILL.md +2 -1
  33. package/.claude/skills/tas-implementation-complete/SKILL.md +99 -97
  34. package/.claude/skills/tas-tdd/SKILL.md +123 -82
  35. package/.claude/skills/token-logger/SKILL.md +19 -0
  36. package/.tas/templates/API-Test-Spec.md +400 -0
  37. package/.tas/templates/E2E-Execution-Report.md +198 -0
  38. package/.tas/templates/E2E-Mobile-Spec.md +130 -0
  39. package/.tas/templates/E2E-Report.md +174 -0
  40. package/.tas/templates/E2E-Scenario.md +180 -0
  41. package/.tas/templates/E2E-Web-Spec.md +164 -0
  42. package/.tas/templates/Feature.md +55 -55
  43. package/.tas/templates/Func-Test-Script.md +254 -0
  44. package/.tas/templates/Func-Test-Spec.md +187 -0
  45. package/.tas/templates/SAD.md +274 -274
  46. package/.tas/templates/Story.md +90 -88
  47. package/bin/cli.js +56 -56
  48. package/lib/deleted-files.json +36 -0
  49. package/lib/install.js +213 -176
  50. package/package.json +34 -34
  51. package/.claude/agents/README.md +0 -83
  52. package/.claude/agents/ado-agent.md +0 -39
  53. package/.claude/agents/code-architect.md +0 -62
  54. package/.claude/agents/code-simplifier.md +0 -53
  55. package/.claude/agents/comment-analyzer.md +0 -59
  56. package/.claude/agents/conversation-analyzer.md +0 -57
  57. package/.claude/agents/docs-lookup.md +0 -55
  58. package/.claude/agents/harness-optimizer.md +0 -62
  59. package/.claude/agents/loop-operator.md +0 -56
  60. package/.claude/agents/performance-optimizer.md +0 -78
  61. package/.claude/agents/pr-test-analyzer.md +0 -68
  62. package/.claude/agents/pytorch-build-resolver.md +0 -76
  63. package/.claude/agents/refactor-cleaner.md +0 -70
  64. package/.claude/agents/seo-specialist.md +0 -75
  65. package/.claude/agents/silent-failure-hunter.md +0 -69
  66. package/.claude/agents/type-design-analyzer.md +0 -75
  67. package/.claude/rules/common/agents.md +0 -65
  68. package/.claude/rules/common/coding-style.md +0 -90
  69. package/.claude/rules/common/development-workflow.md +0 -44
  70. package/.claude/rules/common/git-workflow.md +0 -24
  71. package/.claude/rules/common/performance.md +0 -55
  72. package/.claude/skills/agent-harness-construction/SKILL.md +0 -77
  73. package/.claude/skills/agent-introspection-debugging/SKILL.md +0 -157
@@ -1,55 +1,55 @@
1
- ---
2
- ado_id:
3
- ado_type: Feature
4
- ado_title: "{Title}"
5
- ado_state: New
6
- ado_assigned_to:
7
- ado_created:
8
- last_ado_sync:
9
- parent_ado_id:
10
- ---
11
- # Feature-{NNN}: {Title}
12
-
13
- > **Status:** New | Pending | In Design | In Progress | Ready for Dev | In Development | Ready To Verify | Verified | Done | Removed
14
- > **Epic:** Epic-{NNN}
15
- > **Owner:** {PE name}
16
- > **Created:** {Date}
17
- > **Verified Date:** {Date khi status = Verified}
18
-
19
- ## Description
20
- {Mô tả chức năng}
21
-
22
- ## User Stories
23
- | ID | Story | Priority | Estimate | Status |
24
- |----|-------|----------|----------|--------|
25
- | Story-001 | {name} | Must | S | New |
26
-
27
- ## Acceptance Criteria
28
- - [ ] AC-1: {criteria}
29
- - [ ] AC-2: {criteria}
30
-
31
- ## UI/UX Notes
32
- {Nếu có, reference đến design-spec.md}
33
-
34
- ## Technical Notes
35
- {Nếu có, reference đến SAD/ADR}
36
-
37
- ## Integration Test Cases
38
- PE thiết kế khi tạo Feature. SE implement trong code.
39
-
40
- | ID | Scenario | Expected Result | Status |
41
- |----|----------|-----------------|--------|
42
- | IT-1 | {Mô tả flow liên kết} | {Kết quả mong đợi} | - |
43
- | IT-2 | {Mô tả flow liên kết} | {Kết quả mong đợi} | - |
44
-
45
- ## E2E / Acceptance Test Cases
46
- PE thiết kế khi tạo Feature. PE verify trên Staging ở Phase 2 bằng /tas-verify.
47
-
48
- | ID | User Scenario | Steps | Expected Result | Status | Verified Date |
49
- |----|---------------|-------|-----------------|--------|---------------|
50
- | E2E-1 | {Scenario} | {Bước thực hiện} | {Kết quả mong đợi} | - | - |
51
- | E2E-2 | {Scenario} | {Bước thực hiện} | {Kết quả mong đợi} | - | - |
52
-
53
- ## Changelog
54
- | Date | Changes | Author |
55
- |------|---------|--------|
1
+ ---
2
+ ado_id:
3
+ ado_type: Feature
4
+ ado_title: "{Title}"
5
+ ado_state: New
6
+ ado_assigned_to:
7
+ ado_created:
8
+ last_ado_sync:
9
+ parent_ado_id:
10
+ ---
11
+ # Feature-{NNN}: {Title}
12
+
13
+ > **Status:** New | Pending | In Design | In Progress | Ready for Dev | In Development | Ready To Verify | Verified | Done | Removed
14
+ > **Epic:** Epic-{NNN}
15
+ > **Owner:** {PE name}
16
+ > **Created:** {Date}
17
+ > **Verified Date:** {Date khi status = Verified}
18
+
19
+ ## Description
20
+ {Mô tả chức năng}
21
+
22
+ ## User Stories
23
+ | ID | Story | Priority | Estimate | Status |
24
+ |----|-------|----------|----------|--------|
25
+ | Story-001 | {name} | Must | S | New |
26
+
27
+ ## Acceptance Criteria
28
+ - [ ] AC-1: {criteria}
29
+ - [ ] AC-2: {criteria}
30
+
31
+ ## UI/UX Notes
32
+ {Nếu có, reference đến design-spec.md}
33
+
34
+ ## Technical Notes
35
+ {Nếu có, reference đến SAD/ADR}
36
+
37
+ ## Integration Test Cases
38
+ PE thiết kế khi tạo Feature. SE implement trong code.
39
+
40
+ | ID | AC Ref | Scenario | Expected Result | Status |
41
+ |----|--------|----------|-----------------|--------|
42
+ | IT-1 | AC-1 | {Mô tả flow liên kết} | {Kết quả mong đợi} | - |
43
+ | IT-2 | AC-2 | {Mô tả flow liên kết} | {Kết quả mong đợi} | - |
44
+
45
+ ## E2E / Acceptance Test Cases
46
+ PE thiết kế khi tạo Feature. PE verify trên Staging ở Phase 2 bằng /tas-verify.
47
+
48
+ | ID | AC Ref | User Scenario | Steps | Expected Result | Status | Verified Date |
49
+ |----|--------|---------------|-------|-----------------|--------|---------------|
50
+ | E2E-1 | AC-1 | {Scenario} | {Bước thực hiện} | {Kết quả mong đợi} | - | - |
51
+ | E2E-2 | AC-2 | {Scenario} | {Bước thực hiện} | {Kết quả mong đợi} | - | - |
52
+
53
+ ## Changelog
54
+ | Date | Changes | Author |
55
+ |------|---------|--------|
@@ -0,0 +1,254 @@
1
+ # Functional Test Script Guide
2
+
3
+ > This document defines the conventions for generated functional test scripts.
4
+ > Used by `/tas-functest-mobile` and `/tas-functest-web` commands.
5
+
6
+ ---
7
+
8
+ ## File Structure Convention
9
+
10
+ ### Mobile (Detox)
11
+ ```
12
+ apps/mobile/e2e/
13
+ ├── features/ # Layer 2: Functional test scripts
14
+ │ ├── {epic-slug}/
15
+ │ │ ├── {feature-slug}/
16
+ │ │ │ ├── {story-slug}.func.e2e.ts # One file per story
17
+ │ │ │ ├── helpers.ts # Feature-specific helpers (reusable by E2E)
18
+ │ │ │ └── index.ts # Barrel export
19
+ │ │ └── ...
20
+ │ └── ...
21
+ ├── flows/ # Layer 3: E2E scripts (separate)
22
+ ├── data/ # Test data per environment
23
+ │ ├── test-data.dev.json
24
+ │ ├── test-data.staging.json
25
+ │ └── test-data.prod.json
26
+ ├── helpers/ # Shared helpers
27
+ │ ├── data-loader.ts
28
+ │ └── test-utils.ts
29
+ └── test-ids.ts # Centralized test ID registry
30
+ ```
31
+
32
+ ### Web (Playwright)
33
+ ```
34
+ apps/web/e2e/
35
+ ├── features/ # Layer 2: Functional test scripts
36
+ │ ├── {epic-slug}/
37
+ │ │ ├── {feature-slug}/
38
+ │ │ │ ├── {story-slug}.func.spec.ts # One file per story
39
+ │ │ │ ├── helpers.ts
40
+ │ │ │ └── index.ts
41
+ │ │ └── ...
42
+ │ └── ...
43
+ ├── flows/ # Layer 3: E2E scripts
44
+ ├── data/
45
+ │ ├── test-data.dev.json
46
+ │ ├── test-data.staging.json
47
+ │ └── test-data.prod.json
48
+ ├── helpers/
49
+ │ ├── data-loader.ts
50
+ │ └── test-utils.ts
51
+ └── page-objects/ # Playwright page objects
52
+ ```
53
+
54
+ ---
55
+
56
+ ## File Naming Convention
57
+
58
+ | Layer | Platform | Suffix | Example |
59
+ |-------|----------|--------|---------|
60
+ | Functional | Mobile | `.func.e2e.ts` | `login-form.func.e2e.ts` |
61
+ | Functional | Web | `.func.spec.ts` | `login-form.func.spec.ts` |
62
+ | E2E Flow | Mobile | `.e2e.ts` | `auth-complete-flow.e2e.ts` |
63
+ | E2E Flow | Web | `.spec.ts` | `auth-complete-flow.spec.ts` |
64
+
65
+ ---
66
+
67
+ ## Script Template: Mobile (Detox)
68
+
69
+ ```typescript
70
+ /**
71
+ * Functional Tests: {Story Name}
72
+ * Story: {Story_ID}
73
+ * Feature: {Feature_ID}
74
+ * Epic: {Epic_ID}
75
+ *
76
+ * Generated by /tas-functest-mobile
77
+ * Spec: docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
78
+ */
79
+
80
+ import { device, element, expect, by, waitFor } from 'detox';
81
+ import { TEST_IDS } from '../../test-ids';
82
+ import { loadTestData, getCredentials } from '../../helpers/data-loader';
83
+ import { login, navigateTo } from '../../helpers/test-utils';
84
+
85
+ const testData = loadTestData();
86
+
87
+ describe('{Feature Name} - {Story Name}', () => {
88
+ beforeAll(async () => {
89
+ await device.launchApp({ newInstance: true });
90
+ // Setup: login, navigate to target screen, etc.
91
+ });
92
+
93
+ beforeEach(async () => {
94
+ await device.reloadReactNative();
95
+ });
96
+
97
+ // AC Reference: AC-1
98
+ describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => {
99
+ it('should {happy path description}', async () => {
100
+ // Given: {precondition}
101
+ // When: {action}
102
+ await element(by.id(TEST_IDS.FEATURE.ELEMENT)).tap();
103
+ // Then: {expected}
104
+ await expect(element(by.id(TEST_IDS.FEATURE.RESULT))).toBeVisible();
105
+ });
106
+ });
107
+
108
+ // AC Reference: AC-1
109
+ describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_002_N', () => {
110
+ it('should {negative scenario description}', async () => {
111
+ // Given: {precondition}
112
+ // When: {invalid action}
113
+ await element(by.id(TEST_IDS.FEATURE.INPUT)).typeText('invalid');
114
+ await element(by.id(TEST_IDS.FEATURE.SUBMIT)).tap();
115
+ // Then: {error handling}
116
+ await expect(element(by.id(TEST_IDS.FEATURE.ERROR))).toBeVisible();
117
+ });
118
+ });
119
+ });
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Script Template: Web (Playwright)
125
+
126
+ ```typescript
127
+ /**
128
+ * Functional Tests: {Story Name}
129
+ * Story: {Story_ID}
130
+ * Feature: {Feature_ID}
131
+ * Epic: {Epic_ID}
132
+ *
133
+ * Generated by /tas-functest-web
134
+ * Spec: docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
135
+ */
136
+
137
+ import { test, expect } from '@playwright/test';
138
+ import { loadTestData, getCredentials } from '../../helpers/data-loader';
139
+
140
+ const testData = loadTestData();
141
+
142
+ test.describe('{Feature Name} - {Story Name}', () => {
143
+ test.beforeEach(async ({ page }) => {
144
+ // Setup: login, navigate to target page, etc.
145
+ await page.goto('/target-page');
146
+ });
147
+
148
+ // AC Reference: AC-1
149
+ test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => {
150
+ test('should {happy path description}', async ({ page }) => {
151
+ // Given: {precondition}
152
+ // When: {action}
153
+ await page.getByTestId('feature-element').click();
154
+ // Then: {expected}
155
+ await expect(page.getByTestId('feature-result')).toBeVisible();
156
+ });
157
+
158
+ // Cross-viewport test
159
+ for (const viewport of [
160
+ { width: 375, height: 812, name: 'mobile' },
161
+ { width: 768, height: 1024, name: 'tablet' },
162
+ { width: 1280, height: 720, name: 'desktop' },
163
+ ]) {
164
+ test(`should work on ${viewport.name}`, async ({ page }) => {
165
+ await page.setViewportSize({ width: viewport.width, height: viewport.height });
166
+ // Test responsive behavior
167
+ });
168
+ }
169
+ });
170
+
171
+ // AC Reference: AC-1
172
+ test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_002_N', () => {
173
+ test('should {negative scenario description}', async ({ page }) => {
174
+ // Given: {precondition}
175
+ // When: {invalid action}
176
+ await page.getByTestId('feature-input').fill('invalid');
177
+ await page.getByTestId('feature-submit').click();
178
+ // Then: {error handling}
179
+ await expect(page.getByTestId('feature-error')).toBeVisible();
180
+ });
181
+ });
182
+ });
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Data Loading Pattern
188
+
189
+ ```typescript
190
+ // Import data loader
191
+ import { loadTestData, getCredentials } from '../../helpers/data-loader';
192
+
193
+ // Load environment-specific data (reads TEST_ENV env var)
194
+ const testData = loadTestData();
195
+ // testData.users.default.email -> "e2e-user@yopmail.com" (from JSON)
196
+
197
+ // Load credentials (passwords from .env, never from JSON)
198
+ const creds = getCredentials();
199
+ // creds.email -> from JSON
200
+ // creds.password -> from process.env.TEST_USER_PASSWORD
201
+ ```
202
+
203
+ ---
204
+
205
+ ## describe/it Block Naming Convention
206
+
207
+ ```typescript
208
+ // Top-level: Feature + Story name
209
+ describe('{Feature Name} - {Story Name}', () => {
210
+ // Mid-level: Full FT ID (enables grep by test ID)
211
+ describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => {
212
+ // Leaf: Human-readable description
213
+ it('should {action} when {condition}', async () => { ... });
214
+ });
215
+ });
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Reusable Helpers
221
+
222
+ Feature-specific helpers should be exported for Layer 3 (E2E) reuse:
223
+
224
+ ```typescript
225
+ // features/{epic}/{feature}/helpers.ts
226
+ export async function fillLoginForm(email: string, password: string) {
227
+ await element(by.id(TEST_IDS.AUTH.LOGIN.EMAIL_INPUT)).typeText(email);
228
+ await element(by.id(TEST_IDS.AUTH.LOGIN.PASSWORD_INPUT)).typeText(password);
229
+ await element(by.id(TEST_IDS.AUTH.LOGIN.SUBMIT_BUTTON)).tap();
230
+ }
231
+
232
+ export async function verifyLoginSuccess() {
233
+ await waitFor(element(by.id(TEST_IDS.HOME.SCREEN)))
234
+ .toBeVisible()
235
+ .withTimeout(5000);
236
+ }
237
+ ```
238
+
239
+ These helpers are imported by E2E flow scripts in `flows/` to avoid duplication.
240
+
241
+ ---
242
+
243
+ ## package.json Script Convention
244
+
245
+ ```json
246
+ {
247
+ "scripts": {
248
+ "functest:mobile:{feature-slug}": "detox test --configuration ios.sim.debug --testPathPattern='features/{epic}/{feature}'",
249
+ "functest:web:{feature-slug}": "npx playwright test --grep '@{feature-slug}' e2e/features/{epic}/{feature}",
250
+ "functest:mobile:all": "detox test --configuration ios.sim.debug --testPathPattern='features/'",
251
+ "functest:web:all": "npx playwright test e2e/features/"
252
+ }
253
+ }
254
+ ```
@@ -0,0 +1,187 @@
1
+ ---
2
+ created_date:
3
+ updated_date:
4
+ executor:
5
+ status: Draft
6
+ story_id:
7
+ feature_id:
8
+ epic_id:
9
+ platform: # mobile | web | backend
10
+ ---
11
+
12
+ # Functional Test Specification: {Story Name}
13
+
14
+ **Epic**: [{Epic_ID}]({Epic_LINK})
15
+ **Feature**: [{Feature_ID}]({FEATURE_LINK})
16
+ **Story**: [{Story_ID}]({STORY_LINK})
17
+ **Platform**: {{platform}}
18
+ **Author**: @[executor]
19
+ **Created**: [created_date]
20
+ **Status**: [status] (Draft | Ready | Implemented | Verified)
21
+
22
+ ---
23
+
24
+ ## Test Case Naming Convention
25
+
26
+ > Functional Tests dung type code **FT** theo format chuẩn TAS
27
+
28
+ ### Format
29
+ ```
30
+ {PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_{NUMBER}_{MODIFIER}
31
+ ```
32
+
33
+ ### Example
34
+ ```
35
+ AL_E002_F002_S001_FT_001_H - Functional Test Happy path
36
+ AL_E002_F002_S001_FT_002_N - Functional Test Negative
37
+ AL_E002_F002_S001_FT_003_E - Functional Test Edge case
38
+ ```
39
+
40
+ ### Modifier Codes
41
+
42
+ | Code | Modifier | Description |
43
+ |------|----------|-------------|
44
+ | H | Happy | Positive test - success scenario |
45
+ | N | Negative | Negative test - failure scenario |
46
+ | E | Edge | Edge case - boundary conditions |
47
+ | S | Security | Security test |
48
+ | P | Performance | Performance test |
49
+
50
+ ---
51
+
52
+ ## Overview
53
+
54
+ > Brief description of what this functional test suite validates for the Story
55
+
56
+ **Scope**: {What user functionality is being tested}
57
+ **Target Users**: {Clinical / Organic / Both}
58
+
59
+ ---
60
+
61
+ ## AC to Functional Test Mapping
62
+
63
+ > QUAN TRONG: Moi FT case PHAI reference AC-ID de dam bao traceability.
64
+ > Khi AC thay doi, grep theo AC-ID de biet FT nao can update.
65
+
66
+ | AC ID | AC Description (Given/When/Then) | FT Test ID | Test Scenario | Modifier | Priority | Status |
67
+ |-------|----------------------------------|------------|---------------|----------|----------|--------|
68
+ | AC-1 | {Given...When...Then...} | {PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H | {Happy path description} | Happy | P0 | Draft |
69
+ | AC-1 | {Given...When...Then...} | {PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_002_N | {Negative scenario} | Negative | P0 | Draft |
70
+ | AC-1 | {Given...When...Then...} | {PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_003_E | {Edge case} | Edge | P1 | Draft |
71
+ | AC-2 | {Given...When...Then...} | {PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_004_H | {Happy path description} | Happy | P0 | Draft |
72
+
73
+ ### Coverage Requirements
74
+ - Each AC MUST have at minimum **1 Happy path (H)** test
75
+ - Each AC SHOULD have **1 Negative (N)** test if error scenarios exist
76
+ - Each AC MAY have **1 Edge case (E)** test if boundary conditions apply
77
+
78
+ ---
79
+
80
+ ## Test Scenarios
81
+
82
+ ### FT_001_H: {Title - Happy Path}
83
+ - **AC Reference**: AC-1
84
+ - **Preconditions**:
85
+ - {List preconditions}
86
+ - **Test Data**:
87
+ - {Hardcoded values used in test}
88
+ - {Env-specific: from test-data.{env}.json}
89
+ - {Credentials: from .env via process.env}
90
+ - **Steps**:
91
+ 1. **Given** {initial state}
92
+ 2. **When** {user action}
93
+ 3. **Then** {expected outcome}
94
+ - **Expected Result**: {Detailed expected behavior}
95
+
96
+ ### FT_002_N: {Title - Negative Scenario}
97
+ - **AC Reference**: AC-1
98
+ - **Preconditions**:
99
+ - {List preconditions}
100
+ - **Test Data**:
101
+ - {Invalid/error data}
102
+ - **Steps**:
103
+ 1. **Given** {initial state}
104
+ 2. **When** {user performs invalid action}
105
+ 3. **Then** {expected error handling}
106
+ - **Expected Result**: {Error message, recovery option}
107
+
108
+ ### FT_003_E: {Title - Edge Case}
109
+ - **AC Reference**: AC-1
110
+ - **Preconditions**:
111
+ - {Boundary condition setup}
112
+ - **Test Data**:
113
+ - {Boundary values}
114
+ - **Steps**:
115
+ 1. **Given** {boundary state}
116
+ 2. **When** {boundary action}
117
+ 3. **Then** {graceful handling}
118
+ - **Expected Result**: {Handled gracefully without crash}
119
+
120
+ ---
121
+
122
+ ## Test Data Requirements
123
+
124
+ | Data Item | Value | Source | Environment-Specific | Notes |
125
+ |-----------|-------|--------|---------------------|-------|
126
+ | User Email | test@example.com | test-data.{env}.json | Yes | Different per env |
127
+ | User Password | (from .env) | process.env.TEST_USER_PASSWORD | Yes | NEVER hardcode |
128
+ | {Entity} ID | {value} | test-data.{env}.json | Yes | Pre-seeded |
129
+ | {Static Data} | {value} | Hardcoded in test | No | Same all envs |
130
+
131
+ ### Environment Data Files
132
+ - **Dev**: `apps/{platform}/e2e/data/test-data.dev.json`
133
+ - **Staging**: `apps/{platform}/e2e/data/test-data.staging.json`
134
+ - **Prod**: `apps/{platform}/e2e/data/test-data.prod.json` (smoke tests only)
135
+
136
+ ### Credentials
137
+ > NEVER put passwords/tokens in JSON files or test code.
138
+ > Always use `.env` via `process.env`.
139
+
140
+ ---
141
+
142
+ ## Platform-Specific Implementation
143
+
144
+ {{#if platform === "mobile"}}
145
+ ### Mobile (Detox)
146
+ - **Script Location**: `apps/mobile/e2e/features/{epic-slug}/{feature-slug}/{story-slug}.func.e2e.ts`
147
+ - **Test IDs**: Import from `apps/mobile/e2e/test-ids.ts`
148
+ - **Data Loader**: Import from `apps/mobile/e2e/helpers/data-loader.ts`
149
+ - **Test Helpers**: Import from `apps/mobile/e2e/helpers/test-utils.ts`
150
+ - **Run Command**: `yarn functest:mobile:{feature-slug}`
151
+ {{/if}}
152
+ {{#if platform === "web"}}
153
+ ### Web (Playwright)
154
+ - **Script Location**: `apps/web/e2e/features/{epic-slug}/{feature-slug}/{story-slug}.func.spec.ts`
155
+ - **Selectors**: Use `data-testid` attributes
156
+ - **Data Loader**: Import from `apps/web/e2e/helpers/data-loader.ts`
157
+ - **Test Helpers**: Import from `apps/web/e2e/helpers/test-utils.ts`
158
+ - **Run Command**: `yarn functest:web:{feature-slug}`
159
+ - **Viewports**: Test mobile (375px), tablet (768px), desktop (1280px)
160
+ {{/if}}
161
+
162
+ ---
163
+
164
+ ## Traceability
165
+
166
+ > This section enables impact analysis when requirements change.
167
+
168
+ ### How to find impacted tests when AC changes:
169
+ 1. Note the AC-ID that changed (e.g., AC-1)
170
+ 2. Search this document's "AC to Functional Test Mapping" table
171
+ 3. All FT Test IDs in rows matching that AC-ID need review
172
+ 4. Find corresponding script files using the FT Test ID as describe block name
173
+
174
+ ### Reverse traceability (test to requirement):
175
+ Each test script `describe` block includes the AC-ID in comments:
176
+ ```typescript
177
+ // AC Reference: AC-1
178
+ describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => { ... });
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Changelog
184
+
185
+ | Date | Changes | Author |
186
+ |------|---------|--------|
187
+ | [created_date] | Initial functional test spec created | @[executor] |