@torus-engineering/tas-kit 1.13.0 → 2.1.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.
- package/.tas/_platform/claude-code/settings.json +58 -46
- package/.tas/_platform/hooks/code-quality.js +127 -127
- package/.tas/_platform/hooks/session-end.js +111 -111
- package/.tas/agents/architect.md +53 -53
- package/.tas/agents/aws-reviewer.md +71 -71
- package/.tas/agents/build-resolver.md +89 -59
- package/.tas/agents/code-explorer.md +63 -63
- package/.tas/agents/csharp-reviewer.md +62 -62
- package/.tas/agents/database-reviewer.md +73 -73
- package/.tas/agents/doc-updater.md +68 -66
- package/.tas/agents/python-reviewer.md +67 -67
- package/.tas/agents/security-reviewer.md +79 -79
- package/.tas/agents/software-engineer.md +53 -0
- package/.tas/agents/typescript-reviewer.md +65 -65
- package/.tas/commands/ado-create.md +33 -28
- package/.tas/commands/ado-delete.md +26 -22
- package/.tas/commands/ado-get.md +24 -20
- package/.tas/commands/ado-status.md +22 -18
- package/.tas/commands/ado-update.md +31 -27
- package/.tas/commands/tas-adr.md +37 -33
- package/.tas/commands/tas-apitest-plan.md +177 -173
- package/.tas/commands/tas-apitest.md +147 -143
- package/.tas/commands/tas-brainstorm.md +23 -19
- package/.tas/commands/tas-brd.md +50 -0
- package/.tas/commands/tas-bug.md +127 -113
- package/.tas/commands/tas-checklist.md +180 -0
- package/.tas/commands/tas-debug.md +103 -0
- package/.tas/commands/tas-design.md +41 -37
- package/.tas/commands/tas-dev.md +225 -125
- package/.tas/commands/tas-e2e-mobile.md +146 -155
- package/.tas/commands/tas-e2e-web.md +150 -163
- package/.tas/commands/tas-e2e.md +289 -102
- package/.tas/commands/tas-feature.md +181 -47
- package/.tas/commands/tas-fix.md +72 -51
- package/.tas/commands/tas-functest-mobile.md +138 -144
- package/.tas/commands/tas-functest-web.md +176 -192
- package/.tas/commands/tas-functest.md +225 -76
- package/.tas/commands/tas-init.md +22 -17
- package/.tas/commands/tas-master-plan.md +300 -0
- package/.tas/commands/tas-orchestrate.md +159 -0
- package/.tas/commands/tas-plan.md +152 -117
- package/.tas/commands/tas-prd.md +57 -37
- package/.tas/commands/tas-review-pr.md +174 -0
- package/.tas/commands/tas-review.md +115 -113
- package/.tas/commands/tas-sad.md +47 -43
- package/.tas/commands/tas-security.md +91 -87
- package/.tas/commands/tas-spec.md +54 -50
- package/.tas/commands/tas-status.md +25 -16
- package/.tas/project-status-example.yaml +3 -1
- package/.tas/rules/ado-integration.md +67 -65
- package/.tas/rules/common/api-design.md +517 -517
- package/.tas/rules/common/build-debug-loop.md +233 -0
- package/.tas/rules/common/code-review.md +4 -0
- package/.tas/rules/common/feature-done.md +42 -0
- package/.tas/rules/common/post-implementation-review.md +4 -0
- package/.tas/rules/common/project-status.md +33 -16
- package/.tas/rules/common/sad-impact.md +81 -0
- package/.tas/rules/common/tdd.md +104 -89
- package/.tas/rules/csharp/api-testing.md +2 -2
- package/.tas/rules/csharp/torus-core-framework.md +128 -0
- package/.tas/tas-example.yaml +9 -32
- package/.tas/templates/AGENTS.md +13 -0
- package/.tas/templates/API-Test-Spec.md +5 -4
- package/.tas/templates/BRD.md +133 -0
- package/.tas/templates/Bug.md +15 -0
- package/.tas/templates/E2E-Execution-Report.md +8 -8
- package/.tas/templates/E2E-Mobile-Spec.md +6 -8
- package/.tas/templates/E2E-Report.md +2 -2
- package/.tas/templates/E2E-Scenario.md +22 -22
- package/.tas/templates/E2E-Test-Spec.md +274 -0
- package/.tas/templates/E2E-Web-Spec.md +4 -4
- package/.tas/templates/Feature-Technical-Part.md +69 -0
- package/.tas/templates/Feature-Technical-Stack.md +74 -0
- package/.tas/templates/Feature-Technical.md +329 -0
- package/.tas/templates/Feature.md +50 -26
- package/.tas/templates/Func-Test-Script.md +29 -56
- package/.tas/templates/Func-Test-Spec.md +144 -142
- package/.tas/templates/PRD.md +173 -142
- package/.tas/templates/TestChecklist.md +96 -0
- package/.tas/templates/torus-dotnet-bootstrap.md +223 -0
- package/.tas/tools/tas-ado-readme.md +24 -27
- package/.tas/tools/tas-ado.py +328 -25
- package/.tas/tools/tas-github.py +339 -0
- package/README.md +142 -57
- package/bin/cli.js +90 -90
- package/lib/adapters/antigravity.js +131 -131
- package/lib/adapters/claude-code.js +71 -35
- package/lib/adapters/codex.js +157 -157
- package/lib/adapters/cursor.js +80 -80
- package/lib/adapters/index.js +20 -20
- package/lib/adapters/utils.js +81 -81
- package/lib/deleted-files.json +7 -0
- package/lib/install.js +546 -543
- package/package.json +2 -2
- package/.tas/README.md +0 -334
- package/.tas/commands/tas-epic.md +0 -35
- package/.tas/commands/tas-story.md +0 -91
- package/.tas/rules/common/story-done.md +0 -30
- package/.tas/templates/Epic.md +0 -46
- package/.tas/templates/Story.md +0 -90
|
@@ -1,155 +1,146 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Scenario
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Step 5: Update package.json Script
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
├── {scenario-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
│
|
|
124
|
-
│ -
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
│
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
## Principles
|
|
149
|
-
- MUST reuse helpers from Layer 2 when possible, DO NOT rewrite existing logic
|
|
150
|
-
- Each step in E2E flow should correspond to 1 functional test helper
|
|
151
|
-
- Steps without FT reference → write new logic in flow file
|
|
152
|
-
- Scripts MUST be runnable from CLI, WITHOUT Claude window
|
|
153
|
-
- If apps/mobile/ doesn't exist → graceful error
|
|
154
|
-
- describe block uses full E2E ID for grep-ability
|
|
155
|
-
- import paths: relative from flows/ up to features/
|
|
1
|
+
---
|
|
2
|
+
model: sonnet
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /tas-e2e-mobile $ARGUMENTS
|
|
6
|
+
|
|
7
|
+
Role: SE / QA
|
|
8
|
+
Generate Detox E2E test scripts from an E2E Scenario markdown file.
|
|
9
|
+
|
|
10
|
+
## IMPORTANT — Layer 3: Mobile E2E Scripts
|
|
11
|
+
- Create Detox test scripts from E2E-Scenario (markdown)
|
|
12
|
+
- Scripts located in `apps/mobile/e2e/flows/`
|
|
13
|
+
- REUSE helpers from Layer 2 functional tests (`features/`)
|
|
14
|
+
- Chain functional test steps into end-to-end flows
|
|
15
|
+
|
|
16
|
+
## Actions
|
|
17
|
+
|
|
18
|
+
### Step 1: Identify Scenario
|
|
19
|
+
1. `$ARGUMENTS` is path to `E2E-Scenario-*.md`
|
|
20
|
+
2. If not provided: scan `docs/e2e-scenarios/E2E-Scenario-*.md`
|
|
21
|
+
3. List scenarios and ask user to pick
|
|
22
|
+
|
|
23
|
+
### Step 2: Check Prerequisites
|
|
24
|
+
1. Check `apps/mobile/` exists. If not → graceful error.
|
|
25
|
+
2. Read scenario file to get:
|
|
26
|
+
- Scenario steps and flow
|
|
27
|
+
- FT ID references ("Builds on FT IDs" column)
|
|
28
|
+
- FT Reuse Map (section at end)
|
|
29
|
+
- Test data per environment
|
|
30
|
+
- Scenario type (single-stack / cross-stack)
|
|
31
|
+
|
|
32
|
+
### Step 3: Find Functional Test Helpers
|
|
33
|
+
From FT Reuse Map:
|
|
34
|
+
1. Find each source file in `apps/mobile/e2e/features/`
|
|
35
|
+
2. Verify helper functions exist
|
|
36
|
+
3. If helper missing → create stub with `// TODO: implement helper`
|
|
37
|
+
4. Build import map: FT ID → file path → function name
|
|
38
|
+
|
|
39
|
+
### Step 4: Generate E2E Script
|
|
40
|
+
|
|
41
|
+
**File output**: `apps/mobile/e2e/flows/{scenario-slug}.e2e.ts`
|
|
42
|
+
|
|
43
|
+
**Structure**:
|
|
44
|
+
```typescript
|
|
45
|
+
/**
|
|
46
|
+
* E2E Flow: {Scenario Name}
|
|
47
|
+
* Scenario: {Scenario_ID}
|
|
48
|
+
* Features: {Feature_IDs comma-separated}
|
|
49
|
+
* Type: {single-stack | cross-stack}
|
|
50
|
+
*
|
|
51
|
+
* Generated by /tas-e2e-mobile
|
|
52
|
+
* Spec: {path to E2E-Scenario-*.md}
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import { device, element, expect, by, waitFor } from 'detox';
|
|
56
|
+
import { TEST_IDS } from '../test-ids';
|
|
57
|
+
import { loadTestData, getCredentials } from '../helpers/data-loader';
|
|
58
|
+
import { login, logout, navigateToTab } from '../helpers/test-utils';
|
|
59
|
+
|
|
60
|
+
// Layer 2 helpers (reuse from functional tests)
|
|
61
|
+
import { fillLoginForm, verifyLoginSuccess } from '../features/{feature-slug}/helpers';
|
|
62
|
+
import { viewList } from '../features/{feature-slug-2}/helpers';
|
|
63
|
+
|
|
64
|
+
const testData = loadTestData();
|
|
65
|
+
|
|
66
|
+
describe('E2E Flow: {Scenario Name}', () => {
|
|
67
|
+
beforeAll(async () => {
|
|
68
|
+
await device.launchApp({ newInstance: true });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Main Flow
|
|
72
|
+
describe('{PROJECT}_E2E_001_H: {Flow Title}', () => {
|
|
73
|
+
it('Step 1: {Action}', async () => {
|
|
74
|
+
// Reuses: AL_F002_AC1_FT_001_H
|
|
75
|
+
const creds = getCredentials();
|
|
76
|
+
await fillLoginForm(creds.email, creds.password);
|
|
77
|
+
await verifyLoginSuccess();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('Step 2: {Action}', async () => {
|
|
81
|
+
// Reuses: AL_F003_AC1_FT_001_H
|
|
82
|
+
await viewList();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('Step 3: {New logic - no FT reference}', async () => {
|
|
86
|
+
await element(by.id(TEST_IDS.SCAN.SCREEN.CAMERA)).tap();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Alternate Flow
|
|
91
|
+
describe('{PROJECT}_E2E_002_N: {Alternate Flow}', () => {
|
|
92
|
+
it('should handle {error condition}', async () => {});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Step 5: Update package.json Script
|
|
98
|
+
```json
|
|
99
|
+
"e2e:flow:{scenario-slug}": "detox test --configuration ios.sim.debug --testPathPattern='e2e/flows/{scenario-slug}'"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Step 6: Generate Execution Report (Optional)
|
|
103
|
+
After running, generate from `.tas/templates/E2E-Execution-Report.md`:
|
|
104
|
+
- Summary metrics
|
|
105
|
+
- Results by test ID
|
|
106
|
+
- Failed test details
|
|
107
|
+
- Performance metrics
|
|
108
|
+
- AC coverage analysis
|
|
109
|
+
|
|
110
|
+
## File Structure Output
|
|
111
|
+
```
|
|
112
|
+
apps/mobile/e2e/flows/
|
|
113
|
+
├── {scenario-1-slug}.e2e.ts
|
|
114
|
+
├── {scenario-2-slug}.e2e.ts
|
|
115
|
+
└── ...
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Reuse Strategy
|
|
119
|
+
```
|
|
120
|
+
Layer 2 (features/) Layer 3 (flows/)
|
|
121
|
+
┌───────────────────┐ ┌──────────────────────┐
|
|
122
|
+
│ helpers.ts │──────>│ {scenario}.e2e.ts │
|
|
123
|
+
│ - fillLoginForm()│ │ import { fillLogin }│
|
|
124
|
+
│ - verifyLogin() │ │ import { viewList } │
|
|
125
|
+
└───────────────────┘ │ │
|
|
126
|
+
┌───────────────────┐ │ Step 1: fillLogin() │
|
|
127
|
+
│ helpers.ts │──────>│ Step 2: viewList() │
|
|
128
|
+
│ - viewList() │ │ Step 3: new logic │
|
|
129
|
+
└───────────────────┘ └──────────────────────┘
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Run Tests
|
|
133
|
+
```bash
|
|
134
|
+
yarn e2e:flow:{scenario-slug}
|
|
135
|
+
npx detox test --configuration ios.sim.debug --testPathPattern='e2e/flows/'
|
|
136
|
+
npx detox test --configuration android.emu.debug --testPathPattern='e2e/flows/{scenario}'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Principles
|
|
140
|
+
- MUST reuse helpers from Layer 2 when possible
|
|
141
|
+
- Each step in E2E flow should correspond to 1 functional test helper
|
|
142
|
+
- Steps without FT reference → write new logic in flow file
|
|
143
|
+
- Scripts MUST be runnable from CLI
|
|
144
|
+
- If `apps/mobile/` doesn't exist → graceful error
|
|
145
|
+
- describe block uses full E2E ID for grep-ability
|
|
146
|
+
- Import paths: relative from `flows/` up to `features/`
|
|
@@ -1,163 +1,150 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
3. Read `apps/web/playwright.config.ts` (if exists)
|
|
30
|
-
|
|
31
|
-
### Step 3: Find Functional Test Helpers
|
|
32
|
-
From FT Reuse Map
|
|
33
|
-
1. Find source files in `apps/web/e2e/features/`
|
|
34
|
-
2. Verify helper functions and page objects exist
|
|
35
|
-
3. If helper
|
|
36
|
-
4.
|
|
37
|
-
|
|
38
|
-
### Step 4: Generate E2E Script
|
|
39
|
-
|
|
40
|
-
**File output**: `apps/web/e2e/flows/{scenario-slug}.spec.ts`
|
|
41
|
-
|
|
42
|
-
**Structure**:
|
|
43
|
-
```typescript
|
|
44
|
-
/**
|
|
45
|
-
* E2E Flow: {Scenario Name}
|
|
46
|
-
* Scenario: {Scenario_ID}
|
|
47
|
-
*
|
|
48
|
-
* Type: {single-
|
|
49
|
-
*
|
|
50
|
-
* Generated by /tas-e2e-web
|
|
51
|
-
* Spec: {path to E2E-Scenario-*.md}
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
import { test, expect, Page } from '@playwright/test';
|
|
55
|
-
import { loadTestData, getCredentials } from '../helpers/data-loader';
|
|
56
|
-
|
|
57
|
-
// Layer 2 helpers (reuse from functional tests)
|
|
58
|
-
import { fillLoginForm, verifyLoginSuccess } from '../features/{
|
|
59
|
-
import {
|
|
60
|
-
|
|
61
|
-
const testData = loadTestData();
|
|
62
|
-
|
|
63
|
-
test.describe('E2E Flow: {Scenario Name}', () => {
|
|
64
|
-
test.beforeEach(async ({ page }) => {
|
|
65
|
-
await page.goto(testData.baseUrl);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Main Flow
|
|
69
|
-
test.describe('{PROJECT}
|
|
70
|
-
test('Complete flow', async ({ page }) => {
|
|
71
|
-
// Step 1: Login (reuses
|
|
72
|
-
const creds = getCredentials();
|
|
73
|
-
await fillLoginForm(page, creds.email, creds.password);
|
|
74
|
-
await verifyLoginSuccess(page);
|
|
75
|
-
|
|
76
|
-
// Step 2: View
|
|
77
|
-
await
|
|
78
|
-
|
|
79
|
-
// Step 3: New logic (no FT reference)
|
|
80
|
-
await page.getByTestId('scan-button').click();
|
|
81
|
-
await expect(page.getByTestId('scan-result')).toBeVisible();
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Cross-browser validation
|
|
86
|
-
test.describe('{PROJECT}
|
|
87
|
-
test('should complete flow on all browsers', async ({ page, browserName }) => {
|
|
88
|
-
test.info().annotations.push({ type: 'browser', description: browserName });
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
│
|
|
127
|
-
│
|
|
128
|
-
│ -
|
|
129
|
-
└───────────────────┘
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# Run and generate HTML report
|
|
153
|
-
npx playwright test e2e/flows/{scenario} --reporter=html
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Principles
|
|
157
|
-
- MUST reuse helpers from Layer 2 when possible
|
|
158
|
-
- Web helpers MUST receive `page: Page` parameter (dependency injection)
|
|
159
|
-
- Scripts MUST be runnable from CLI
|
|
160
|
-
- If apps/web/ doesn't exist → graceful error, DO NOT create
|
|
161
|
-
- Cross-browser: Chromium, Firefox, WebKit (from playwright.config.ts)
|
|
162
|
-
- describe block uses full E2E ID
|
|
163
|
-
- import paths: relative from flows/ up to features/
|
|
1
|
+
---
|
|
2
|
+
model: sonnet
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /tas-e2e-web $ARGUMENTS
|
|
6
|
+
|
|
7
|
+
Role: SE / QA
|
|
8
|
+
Generate Playwright E2E test scripts from an E2E Scenario markdown file.
|
|
9
|
+
|
|
10
|
+
## IMPORTANT — Layer 3: Web E2E Scripts
|
|
11
|
+
- Create Playwright test scripts from E2E-Scenario (markdown)
|
|
12
|
+
- Scripts located in `apps/web/e2e/flows/`
|
|
13
|
+
- REUSE helpers from Layer 2 functional tests (`features/`)
|
|
14
|
+
- Cross-browser testing (Chromium, Firefox, WebKit)
|
|
15
|
+
- Chain functional test steps into end-to-end flows
|
|
16
|
+
|
|
17
|
+
## Actions
|
|
18
|
+
|
|
19
|
+
### Step 1: Identify Scenario
|
|
20
|
+
1. `$ARGUMENTS` is path to `E2E-Scenario-*.md`
|
|
21
|
+
2. If not provided: scan `docs/e2e-scenarios/E2E-Scenario-*.md`
|
|
22
|
+
3. List scenarios and ask user to pick
|
|
23
|
+
|
|
24
|
+
### Step 2: Check Prerequisites
|
|
25
|
+
1. Check `apps/web/` exists. If not → report:
|
|
26
|
+
> "Web app doesn't exist. If project only has mobile, use `/tas-e2e-mobile`."
|
|
27
|
+
> STOP, DO NOT create file.
|
|
28
|
+
2. Read scenario file to get steps, FT references, FT Reuse Map, test data, scenario type.
|
|
29
|
+
3. Read `apps/web/playwright.config.ts` (if exists)
|
|
30
|
+
|
|
31
|
+
### Step 3: Find Functional Test Helpers
|
|
32
|
+
From FT Reuse Map:
|
|
33
|
+
1. Find source files in `apps/web/e2e/features/`
|
|
34
|
+
2. Verify helper functions and page objects exist
|
|
35
|
+
3. If helper missing → create stub with `// TODO: implement helper`
|
|
36
|
+
4. Build import map: FT ID → file path → function name
|
|
37
|
+
|
|
38
|
+
### Step 4: Generate E2E Script
|
|
39
|
+
|
|
40
|
+
**File output**: `apps/web/e2e/flows/{scenario-slug}.spec.ts`
|
|
41
|
+
|
|
42
|
+
**Structure**:
|
|
43
|
+
```typescript
|
|
44
|
+
/**
|
|
45
|
+
* E2E Flow: {Scenario Name}
|
|
46
|
+
* Scenario: {Scenario_ID}
|
|
47
|
+
* Features: {Feature_IDs comma-separated}
|
|
48
|
+
* Type: {single-stack | cross-stack}
|
|
49
|
+
*
|
|
50
|
+
* Generated by /tas-e2e-web
|
|
51
|
+
* Spec: {path to E2E-Scenario-*.md}
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
import { test, expect, Page } from '@playwright/test';
|
|
55
|
+
import { loadTestData, getCredentials } from '../helpers/data-loader';
|
|
56
|
+
|
|
57
|
+
// Layer 2 helpers (reuse from functional tests)
|
|
58
|
+
import { fillLoginForm, verifyLoginSuccess } from '../features/{feature-slug}/helpers';
|
|
59
|
+
import { viewList } from '../features/{feature-slug-2}/helpers';
|
|
60
|
+
|
|
61
|
+
const testData = loadTestData();
|
|
62
|
+
|
|
63
|
+
test.describe('E2E Flow: {Scenario Name}', () => {
|
|
64
|
+
test.beforeEach(async ({ page }) => {
|
|
65
|
+
await page.goto(testData.baseUrl);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Main Flow
|
|
69
|
+
test.describe('{PROJECT}_E2E_001_H: {Flow Title}', () => {
|
|
70
|
+
test('Complete flow', async ({ page }) => {
|
|
71
|
+
// Step 1: Login (reuses AL_F002_AC1_FT_001_H)
|
|
72
|
+
const creds = getCredentials();
|
|
73
|
+
await fillLoginForm(page, creds.email, creds.password);
|
|
74
|
+
await verifyLoginSuccess(page);
|
|
75
|
+
|
|
76
|
+
// Step 2: View list (reuses AL_F003_AC1_FT_001_H)
|
|
77
|
+
await viewList(page);
|
|
78
|
+
|
|
79
|
+
// Step 3: New logic (no FT reference)
|
|
80
|
+
await page.getByTestId('scan-button').click();
|
|
81
|
+
await expect(page.getByTestId('scan-result')).toBeVisible();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Cross-browser validation
|
|
86
|
+
test.describe('{PROJECT}_E2E_001_H - Cross-browser', () => {
|
|
87
|
+
test('should complete flow on all browsers', async ({ page, browserName }) => {
|
|
88
|
+
test.info().annotations.push({ type: 'browser', description: browserName });
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Alternate / Error flows
|
|
93
|
+
test.describe('{PROJECT}_E2E_002_N: {Error Flow}', () => {
|
|
94
|
+
test('should handle {error condition}', async ({ page }) => {});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Step 5: Update package.json Script
|
|
100
|
+
```json
|
|
101
|
+
"e2e:flow:{scenario-slug}": "npx playwright test e2e/flows/{scenario-slug}"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Step 6: Generate Execution Report (Optional)
|
|
105
|
+
From `.tas/templates/E2E-Execution-Report.md`:
|
|
106
|
+
- Browser-specific results
|
|
107
|
+
- Viewport testing results
|
|
108
|
+
- Performance metrics (LCP, INP, CLS)
|
|
109
|
+
|
|
110
|
+
## File Structure Output
|
|
111
|
+
```
|
|
112
|
+
apps/web/e2e/flows/
|
|
113
|
+
├── {scenario-1-slug}.spec.ts
|
|
114
|
+
├── {scenario-2-slug}.spec.ts
|
|
115
|
+
└── ...
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Reuse Strategy
|
|
119
|
+
```
|
|
120
|
+
Layer 2 (features/) Layer 3 (flows/)
|
|
121
|
+
┌───────────────────┐ ┌──────────────────────────┐
|
|
122
|
+
│ helpers.ts │──────>│ {scenario}.spec.ts │
|
|
123
|
+
│ - fillLogin(page)│ │ import { fillLogin } │
|
|
124
|
+
│ - verify(page) │ │ import { viewList } │
|
|
125
|
+
└───────────────────┘ │ │
|
|
126
|
+
┌───────────────────┐ │ Step 1: fillLogin(page) │
|
|
127
|
+
│ helpers.ts │──────>│ Step 2: viewList(page) │
|
|
128
|
+
│ - viewList(page) │ │ Step 3: new logic │
|
|
129
|
+
└───────────────────┘ └──────────────────────────┘
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Note: Web helpers receive `page: Page` parameter (unlike mobile using global Detox API).
|
|
133
|
+
|
|
134
|
+
## Run Tests
|
|
135
|
+
```bash
|
|
136
|
+
yarn e2e:flow:{scenario-slug}
|
|
137
|
+
npx playwright test e2e/flows/
|
|
138
|
+
npx playwright test --project=firefox e2e/flows/{scenario}
|
|
139
|
+
npx playwright test --ui e2e/flows/{scenario}
|
|
140
|
+
npx playwright test e2e/flows/{scenario} --reporter=html
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Principles
|
|
144
|
+
- MUST reuse helpers from Layer 2 when possible
|
|
145
|
+
- Web helpers MUST receive `page: Page` parameter (dependency injection)
|
|
146
|
+
- Scripts MUST be runnable from CLI
|
|
147
|
+
- If `apps/web/` doesn't exist → graceful error
|
|
148
|
+
- Cross-browser: Chromium, Firefox, WebKit
|
|
149
|
+
- describe block uses full E2E ID
|
|
150
|
+
- Import paths: relative from `flows/` up to `features/`
|