@torus-engineering/tas-kit 1.9.0 → 1.11.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/.claude/commands/ado-create.md +17 -17
- package/.claude/commands/ado-delete.md +11 -11
- package/.claude/commands/ado-get.md +12 -12
- package/.claude/commands/ado-status.md +12 -12
- package/.claude/commands/ado-update.md +15 -15
- package/.claude/commands/tas-adr.md +33 -33
- package/.claude/commands/tas-apitest-plan.md +173 -173
- package/.claude/commands/tas-apitest.md +143 -143
- package/.claude/commands/tas-brainstorm.md +14 -14
- package/.claude/commands/tas-bug.md +113 -113
- package/.claude/commands/tas-design.md +37 -37
- package/.claude/commands/tas-dev.md +128 -128
- package/.claude/commands/tas-e2e-mobile.md +155 -155
- package/.claude/commands/tas-e2e-web.md +163 -163
- package/.claude/commands/tas-e2e.md +102 -102
- package/.claude/commands/tas-epic.md +35 -35
- package/.claude/commands/tas-feature.md +47 -47
- package/.claude/commands/tas-fix.md +51 -51
- package/.claude/commands/tas-functest-mobile.md +144 -144
- package/.claude/commands/tas-functest-web.md +192 -192
- package/.claude/commands/tas-functest.md +76 -76
- package/.claude/commands/tas-init.md +14 -14
- package/.claude/commands/tas-plan.md +198 -200
- package/.claude/commands/tas-prd.md +37 -37
- package/.claude/commands/tas-review.md +111 -111
- package/.claude/commands/tas-sad.md +43 -43
- package/.claude/commands/tas-security.md +87 -81
- package/.claude/commands/tas-spec.md +20 -20
- package/.claude/commands/tas-status.md +13 -13
- package/.claude/commands/tas-story.md +91 -91
- package/.claude/commands/tas-verify.md +51 -51
- package/.claude/rules/common/post-review-agent.md +49 -49
- package/.claude/rules/common/project-status.md +14 -14
- package/.claude/rules/common/stack-detection.md +6 -6
- package/.claude/rules/common/token-logging.md +27 -27
- package/.claude/rules/csharp/api-testing.md +171 -171
- package/.claude/skills/ado-integration/SKILL.md +36 -36
- package/.claude/skills/tas-conventions/SKILL.md +32 -32
- package/.claude/skills/tas-implementation-complete/SKILL.md +100 -99
- package/.claude/skills/tas-tdd/SKILL.md +123 -123
- package/.claude/skills/token-logger/SKILL.md +19 -19
- package/.tas/README.md +266 -1520
- package/.tas/checklists/code-review.md +13 -13
- package/.tas/checklists/security.md +3 -3
- package/.tas/checklists/story-done.md +11 -11
- package/.tas/hooks/README.md +138 -0
- package/.tas/hooks/pre-commit +26 -0
- package/.tas/hooks/security-scan.js +599 -0
- package/.tas/project-status-example.yaml +3 -3
- package/.tas/tas-example.yaml +25 -8
- package/.tas/templates/ADR.md +16 -16
- package/.tas/templates/API-Test-Spec.md +3 -3
- package/.tas/templates/Bug.md +12 -12
- package/.tas/templates/Design-Spec.md +8 -8
- package/.tas/templates/E2E-Execution-Report.md +1 -1
- package/.tas/templates/Epic.md +1 -1
- package/.tas/templates/Feature.md +10 -10
- package/.tas/templates/Func-Test-Spec.md +3 -3
- package/.tas/templates/SAD.md +106 -106
- package/.tas/templates/Security-Report.md +3 -3
- package/.tas/templates/Story.md +9 -9
- package/.tas/tools/tas-ado-readme.md +169 -169
- package/.tas/tools/tas-ado.py +1 -1
- package/CLAUDE-Example.md +37 -58
- package/README.md +294 -42
- package/bin/cli.js +24 -7
- package/lib/install.js +161 -47
- package/package.json +1 -1
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
# /tas-functest-web $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Generate
|
|
5
|
-
|
|
6
|
-
##
|
|
7
|
-
-
|
|
8
|
-
- Scripts
|
|
9
|
-
- Reusable helpers
|
|
10
|
-
-
|
|
11
|
-
- Cross-viewport testing (mobile, tablet, desktop)
|
|
12
|
-
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
###
|
|
16
|
-
1. $ARGUMENTS
|
|
17
|
-
2.
|
|
18
|
-
3.
|
|
19
|
-
|
|
20
|
-
###
|
|
21
|
-
1.
|
|
22
|
-
> "Web app
|
|
23
|
-
>
|
|
24
|
-
2.
|
|
25
|
-
```
|
|
26
|
-
docs/epics/{epic-dir}/{feature-dir}/Func-Test-*.md
|
|
27
|
-
```
|
|
28
|
-
3.
|
|
29
|
-
> "
|
|
30
|
-
4.
|
|
31
|
-
5.
|
|
32
|
-
|
|
33
|
-
###
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
###
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
**File output**: `apps/web/e2e/features/{epic-slug}/{feature-slug}/{story-slug}.func.spec.ts`
|
|
42
|
-
|
|
43
|
-
**Structure**:
|
|
44
|
-
```typescript
|
|
45
|
-
/**
|
|
46
|
-
* Functional Tests: {Story Name}
|
|
47
|
-
* Story: {Story_ID}
|
|
48
|
-
* Feature: {Feature_ID}
|
|
49
|
-
* Epic: {Epic_ID}
|
|
50
|
-
*
|
|
51
|
-
* Generated by /tas-functest-web
|
|
52
|
-
* Spec: docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
|
-
import { test, expect } from '@playwright/test';
|
|
56
|
-
import { loadTestData, getCredentials } from '../../../helpers/data-loader';
|
|
57
|
-
|
|
58
|
-
const testData = loadTestData();
|
|
59
|
-
|
|
60
|
-
test.describe('{Feature Name} - {Story Name}', () => {
|
|
61
|
-
test.beforeEach(async ({ page }) => {
|
|
62
|
-
await page.goto('/target-page');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// AC Reference: AC-1
|
|
66
|
-
test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => {
|
|
67
|
-
test('should {description from spec}', async ({ page }) => {
|
|
68
|
-
// Given: {precondition}
|
|
69
|
-
// When: {action}
|
|
70
|
-
await page.getByTestId('element-id').click();
|
|
71
|
-
// Then: {expected}
|
|
72
|
-
await expect(page.getByTestId('result')).toBeVisible();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// Viewport testing for responsive features
|
|
77
|
-
test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H - Viewports', () => {
|
|
78
|
-
const viewports = [
|
|
79
|
-
{ width: 375, height: 812, name: 'mobile' },
|
|
80
|
-
{ width: 768, height: 1024, name: 'tablet' },
|
|
81
|
-
{ width: 1280, height: 720, name: 'desktop' },
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
for (const vp of viewports) {
|
|
85
|
-
test(`should work on ${vp.name} (${vp.width}x${vp.height})`, async ({ page }) => {
|
|
86
|
-
await page.setViewportSize({ width: vp.width, height: vp.height });
|
|
87
|
-
// Test responsive behavior
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
###
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { Page, expect } from '@playwright/test';
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Reusable helpers
|
|
101
|
-
*
|
|
102
|
-
*/
|
|
103
|
-
|
|
104
|
-
export async function {featureSpecificHelper}(page: Page) {
|
|
105
|
-
// Helper logic extracted from functional tests
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
###
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
type TestEnv = 'dev' | 'staging' | 'prod';
|
|
113
|
-
|
|
114
|
-
export function loadTestData(env?: TestEnv) {
|
|
115
|
-
const targetEnv = env || (process.env.TEST_ENV as TestEnv) || 'dev';
|
|
116
|
-
return require(`../data/test-data.${targetEnv}.json`);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function getCredentials(userType = 'default') {
|
|
120
|
-
const data = loadTestData();
|
|
121
|
-
const user = data.users[userType] || data.users.default;
|
|
122
|
-
return {
|
|
123
|
-
email: user.email,
|
|
124
|
-
password: process.env.TEST_USER_PASSWORD || '',
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
###
|
|
130
|
-
|
|
131
|
-
```json
|
|
132
|
-
"functest:web:{feature-slug}": "npx playwright test e2e/features/{epic-slug}/{feature-slug}"
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
###
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
export * from './helpers';
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## File Structure Output
|
|
142
|
-
```
|
|
143
|
-
apps/web/e2e/features/
|
|
144
|
-
└── {epic-slug}/
|
|
145
|
-
└── {feature-slug}/
|
|
146
|
-
├── {story-1-slug}.func.spec.ts
|
|
147
|
-
├── {story-2-slug}.func.spec.ts
|
|
148
|
-
├── helpers.ts
|
|
149
|
-
└── index.ts
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Selector Strategy (Playwright)
|
|
153
|
-
- **
|
|
154
|
-
- **Text content**: `page.getByText('Welcome')`
|
|
155
|
-
- **Role**: `page.getByRole('button', { name: 'Submit' })`
|
|
156
|
-
- **Label**: `page.getByLabel('Email')`
|
|
157
|
-
-
|
|
158
|
-
|
|
159
|
-
## Cross-Browser Testing
|
|
160
|
-
- Chromium (
|
|
161
|
-
- Firefox (
|
|
162
|
-
- WebKit (
|
|
163
|
-
- Config
|
|
164
|
-
|
|
165
|
-
## Test Data Convention
|
|
166
|
-
- **Hardcoded values**:
|
|
167
|
-
- **Credentials**: `getCredentials()` → password
|
|
168
|
-
- **Environment data**: `loadTestData()` →
|
|
169
|
-
- **
|
|
170
|
-
|
|
171
|
-
##
|
|
172
|
-
```bash
|
|
173
|
-
#
|
|
174
|
-
yarn functest:web:{feature-slug}
|
|
175
|
-
|
|
176
|
-
#
|
|
177
|
-
npx playwright test e2e/features/{epic}/{feature}/{story}
|
|
178
|
-
|
|
179
|
-
#
|
|
180
|
-
npx playwright test --project=firefox e2e/features/{epic}/{feature}
|
|
181
|
-
|
|
182
|
-
#
|
|
183
|
-
npx playwright test --ui e2e/features/{epic}/{feature}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
##
|
|
187
|
-
- Script
|
|
188
|
-
-
|
|
189
|
-
- Helpers
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
1
|
+
# /tas-functest-web $ARGUMENTS
|
|
2
|
+
|
|
3
|
+
Role: SE / QA
|
|
4
|
+
Generate all Playwright automation test scripts for a web Feature.
|
|
5
|
+
|
|
6
|
+
## IMPORTANT - Layer 2: Web Functional Test Scripts
|
|
7
|
+
- Create Playwright test scripts from Func-Test-Spec (markdown)
|
|
8
|
+
- Scripts located in `apps/web/e2e/features/`
|
|
9
|
+
- Reusable helpers exported for Layer 3 (E2E) reuse
|
|
10
|
+
- Hardcoded data in tests, credentials from .env
|
|
11
|
+
- Cross-viewport testing (mobile, tablet, desktop)
|
|
12
|
+
|
|
13
|
+
## Actions
|
|
14
|
+
|
|
15
|
+
### Step 1: Identify Feature
|
|
16
|
+
1. $ARGUMENTS is Feature ID or file path
|
|
17
|
+
2. If not provided: scan `docs/epics/**/Feature-*.md` for features with status In Progress
|
|
18
|
+
3. Read Feature file to get Epic/Feature numbers and list of Stories
|
|
19
|
+
|
|
20
|
+
### Step 2: Check Prerequisites
|
|
21
|
+
1. Check `apps/web/` exists. If not → report:
|
|
22
|
+
> "Web app doesn't exist in this project. If project only has mobile, use /tas-functest-mobile."
|
|
23
|
+
> STOP, DO NOT create file.
|
|
24
|
+
2. Find all `Func-Test-*.md` files in Feature directory:
|
|
25
|
+
```
|
|
26
|
+
docs/epics/{epic-dir}/{feature-dir}/Func-Test-*.md
|
|
27
|
+
```
|
|
28
|
+
3. If no Func-Test-Spec exists → report:
|
|
29
|
+
> "No Func-Test-Spec for this Feature yet. Run /tas-functest {story-ID} first."
|
|
30
|
+
4. Read `apps/web/playwright.config.ts` (if exists) to understand current config
|
|
31
|
+
5. Read `apps/web/e2e/helpers/` (if exists) to understand patterns
|
|
32
|
+
|
|
33
|
+
### Step 3: Aggregate FT Test Cases
|
|
34
|
+
- From all Func-Test-Spec files, aggregate list of FT test cases
|
|
35
|
+
- Group by Story
|
|
36
|
+
- Get test data requirements from each spec
|
|
37
|
+
|
|
38
|
+
### Step 4: Generate Test Scripts
|
|
39
|
+
For EACH Story with Func-Test-Spec:
|
|
40
|
+
|
|
41
|
+
**File output**: `apps/web/e2e/features/{epic-slug}/{feature-slug}/{story-slug}.func.spec.ts`
|
|
42
|
+
|
|
43
|
+
**Structure**:
|
|
44
|
+
```typescript
|
|
45
|
+
/**
|
|
46
|
+
* Functional Tests: {Story Name}
|
|
47
|
+
* Story: {Story_ID}
|
|
48
|
+
* Feature: {Feature_ID}
|
|
49
|
+
* Epic: {Epic_ID}
|
|
50
|
+
*
|
|
51
|
+
* Generated by /tas-functest-web
|
|
52
|
+
* Spec: docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import { test, expect } from '@playwright/test';
|
|
56
|
+
import { loadTestData, getCredentials } from '../../../helpers/data-loader';
|
|
57
|
+
|
|
58
|
+
const testData = loadTestData();
|
|
59
|
+
|
|
60
|
+
test.describe('{Feature Name} - {Story Name}', () => {
|
|
61
|
+
test.beforeEach(async ({ page }) => {
|
|
62
|
+
await page.goto('/target-page');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// AC Reference: AC-1
|
|
66
|
+
test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H', () => {
|
|
67
|
+
test('should {description from spec}', async ({ page }) => {
|
|
68
|
+
// Given: {precondition}
|
|
69
|
+
// When: {action}
|
|
70
|
+
await page.getByTestId('element-id').click();
|
|
71
|
+
// Then: {expected}
|
|
72
|
+
await expect(page.getByTestId('result')).toBeVisible();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Viewport testing for responsive features
|
|
77
|
+
test.describe('{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_001_H - Viewports', () => {
|
|
78
|
+
const viewports = [
|
|
79
|
+
{ width: 375, height: 812, name: 'mobile' },
|
|
80
|
+
{ width: 768, height: 1024, name: 'tablet' },
|
|
81
|
+
{ width: 1280, height: 720, name: 'desktop' },
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
for (const vp of viewports) {
|
|
85
|
+
test(`should work on ${vp.name} (${vp.width}x${vp.height})`, async ({ page }) => {
|
|
86
|
+
await page.setViewportSize({ width: vp.width, height: vp.height });
|
|
87
|
+
// Test responsive behavior
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Step 5: Generate Feature Helpers
|
|
95
|
+
Create file `apps/web/e2e/features/{epic-slug}/{feature-slug}/helpers.ts`:
|
|
96
|
+
```typescript
|
|
97
|
+
import { Page, expect } from '@playwright/test';
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reusable helpers for {Feature Name}
|
|
101
|
+
* Exported for Layer 3 E2E scripts reuse
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
export async function {featureSpecificHelper}(page: Page) {
|
|
105
|
+
// Helper logic extracted from functional tests
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Step 6: Generate/Update Data Loader (if not exists)
|
|
110
|
+
If `apps/web/e2e/helpers/data-loader.ts` doesn't exist, create:
|
|
111
|
+
```typescript
|
|
112
|
+
type TestEnv = 'dev' | 'staging' | 'prod';
|
|
113
|
+
|
|
114
|
+
export function loadTestData(env?: TestEnv) {
|
|
115
|
+
const targetEnv = env || (process.env.TEST_ENV as TestEnv) || 'dev';
|
|
116
|
+
return require(`../data/test-data.${targetEnv}.json`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function getCredentials(userType = 'default') {
|
|
120
|
+
const data = loadTestData();
|
|
121
|
+
const user = data.users[userType] || data.users.default;
|
|
122
|
+
return {
|
|
123
|
+
email: user.email,
|
|
124
|
+
password: process.env.TEST_USER_PASSWORD || '',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Step 7: Update package.json Script
|
|
130
|
+
Add or update script in `apps/web/package.json`:
|
|
131
|
+
```json
|
|
132
|
+
"functest:web:{feature-slug}": "npx playwright test e2e/features/{epic-slug}/{feature-slug}"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Step 8: Generate Index
|
|
136
|
+
Create `apps/web/e2e/features/{epic-slug}/{feature-slug}/index.ts`:
|
|
137
|
+
```typescript
|
|
138
|
+
export * from './helpers';
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## File Structure Output
|
|
142
|
+
```
|
|
143
|
+
apps/web/e2e/features/
|
|
144
|
+
└── {epic-slug}/
|
|
145
|
+
└── {feature-slug}/
|
|
146
|
+
├── {story-1-slug}.func.spec.ts
|
|
147
|
+
├── {story-2-slug}.func.spec.ts
|
|
148
|
+
├── helpers.ts
|
|
149
|
+
└── index.ts
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Selector Strategy (Playwright)
|
|
153
|
+
- **Priority**: `data-testid` → `page.getByTestId('login-submit')`
|
|
154
|
+
- **Text content**: `page.getByText('Welcome')`
|
|
155
|
+
- **Role**: `page.getByRole('button', { name: 'Submit' })`
|
|
156
|
+
- **Label**: `page.getByLabel('Email')`
|
|
157
|
+
- DO NOT use traditional CSS selectors (`.class`, `#id`) unless required
|
|
158
|
+
|
|
159
|
+
## Cross-Browser Testing
|
|
160
|
+
- Chromium (required)
|
|
161
|
+
- Firefox (required)
|
|
162
|
+
- WebKit (required)
|
|
163
|
+
- Config in `playwright.config.ts` projects section
|
|
164
|
+
|
|
165
|
+
## Test Data Convention
|
|
166
|
+
- **Hardcoded values**: Directly in test
|
|
167
|
+
- **Credentials**: `getCredentials()` → password from process.env
|
|
168
|
+
- **Environment data**: `loadTestData()` → from test-data.{env}.json
|
|
169
|
+
- **NEVER** hardcode passwords/tokens
|
|
170
|
+
|
|
171
|
+
## Run Tests
|
|
172
|
+
```bash
|
|
173
|
+
# Run all func tests for feature
|
|
174
|
+
yarn functest:web:{feature-slug}
|
|
175
|
+
|
|
176
|
+
# Run only one story
|
|
177
|
+
npx playwright test e2e/features/{epic}/{feature}/{story}
|
|
178
|
+
|
|
179
|
+
# Run with specific browser
|
|
180
|
+
npx playwright test --project=firefox e2e/features/{epic}/{feature}
|
|
181
|
+
|
|
182
|
+
# Run with debug UI
|
|
183
|
+
npx playwright test --ui e2e/features/{epic}/{feature}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Principles
|
|
187
|
+
- Script MUST be runnable directly from CLI
|
|
188
|
+
- Each describe block uses full FT ID
|
|
189
|
+
- Helpers MUST export for Layer 3 reuse
|
|
190
|
+
- DO NOT import from Layer 3 (flows/)
|
|
191
|
+
- If apps/web/ doesn't exist → graceful error, DO NOT create
|
|
192
|
+
- Tests must work on all viewports (mobile, tablet, desktop)
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
# /tas-functest $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Generate Functional Test Specification
|
|
5
|
-
|
|
6
|
-
##
|
|
7
|
-
- Functional tests (FT)
|
|
8
|
-
- FT
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
###
|
|
14
|
-
1. $ARGUMENTS
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
17
|
-
-
|
|
18
|
-
- Epic/Feature/Story numbers (
|
|
19
|
-
- Platform context (mobile/web/backend)
|
|
20
|
-
4.
|
|
21
|
-
|
|
22
|
-
###
|
|
23
|
-
|
|
24
|
-
- **Mobile**: Keywords "screen", "navigation", "React Native", "Detox"; paths `apps/mobile/src/features/*`
|
|
25
|
-
- **Web**: Keywords "browser", "page", "Playwright", "React"; paths `apps/web/*`
|
|
26
|
-
- **Backend**: Keywords "API endpoint", "service", "controller"; paths `src/Torus.*`, `tests/`
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
###
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Naming format:
|
|
33
|
-
```
|
|
34
|
-
{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_{NNN}_{MODIFIER}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
- **
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
###
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
- Credentials:
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
###
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
###
|
|
57
|
-
|
|
58
|
-
- "
|
|
59
|
-
- "
|
|
60
|
-
- "
|
|
61
|
-
- "
|
|
62
|
-
|
|
63
|
-
## Traceability Feature
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
## Status Flow
|
|
69
|
-
Draft → Ready → Implemented → Verified
|
|
70
|
-
|
|
71
|
-
##
|
|
72
|
-
-
|
|
73
|
-
- Test code
|
|
74
|
-
- Func-Test-Spec
|
|
75
|
-
-
|
|
76
|
-
- FT
|
|
1
|
+
# /tas-functest $ARGUMENTS
|
|
2
|
+
|
|
3
|
+
Role: SE / QA
|
|
4
|
+
Generate Functional Test Specification from a User Story, linking test cases to Acceptance Criteria (AC).
|
|
5
|
+
|
|
6
|
+
## IMPORTANT - Layer 2: Functional Testing
|
|
7
|
+
- Functional tests (FT) sit between Unit tests (Layer 1) and E2E tests (Layer 3)
|
|
8
|
+
- FT tests individual function/story in isolation, DOESN'T test linked flows between multiple features
|
|
9
|
+
- Each FT case MUST reference AC-ID for traceability
|
|
10
|
+
|
|
11
|
+
## Actions
|
|
12
|
+
|
|
13
|
+
### Step 1: Identify Story
|
|
14
|
+
1. $ARGUMENTS is Story ID or file path
|
|
15
|
+
2. If no $ARGUMENTS: scan `docs/epics/**/Story-*.md` for stories with status In Progress or Committed
|
|
16
|
+
3. Read Story file to get:
|
|
17
|
+
- All Acceptance Criteria (AC-1, AC-2, ...)
|
|
18
|
+
- Epic/Feature/Story numbers (from frontmatter or file path)
|
|
19
|
+
- Platform context (mobile/web/backend)
|
|
20
|
+
4. Read `root/tas.yaml` to get project code (e.g., "AL")
|
|
21
|
+
|
|
22
|
+
### Step 2: Auto-detect Platform
|
|
23
|
+
From Story context, determine platform:
|
|
24
|
+
- **Mobile**: Keywords "screen", "navigation", "React Native", "Detox"; paths `apps/mobile/src/features/*`
|
|
25
|
+
- **Web**: Keywords "browser", "page", "Playwright", "React"; paths `apps/web/*`
|
|
26
|
+
- **Backend**: Keywords "API endpoint", "service", "controller"; paths `src/Torus.*`, `tests/`
|
|
27
|
+
- If cannot determine: ask user
|
|
28
|
+
|
|
29
|
+
### Step 3: Generate FT Test Cases
|
|
30
|
+
Read template from `.tas/templates/Func-Test-Spec.md`
|
|
31
|
+
|
|
32
|
+
Naming format:
|
|
33
|
+
```
|
|
34
|
+
{PROJECT}_E{EPIC}_F{FEATURE}_S{STORY}_FT_{NNN}_{MODIFIER}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For each AC, generate:
|
|
38
|
+
- **REQUIRED**: 1 Happy path test (H)
|
|
39
|
+
- **SHOULD HAVE**: 1 Negative test (N) if error scenarios exist
|
|
40
|
+
- **OPTIONAL**: 1 Edge case test (E) if boundary conditions exist
|
|
41
|
+
|
|
42
|
+
Each test case MUST have AC-ID column in mapping table.
|
|
43
|
+
|
|
44
|
+
### Step 4: Generate Test Data Requirements
|
|
45
|
+
- Identify data needed for each test case
|
|
46
|
+
- Hardcoded data: write directly in scenario
|
|
47
|
+
- Credentials: only reference `process.env.TEST_USER_PASSWORD`, DO NOT hardcode
|
|
48
|
+
- Environment-specific data: reference `test-data.{env}.json`
|
|
49
|
+
|
|
50
|
+
### Step 5: Output File
|
|
51
|
+
Save file at:
|
|
52
|
+
```
|
|
53
|
+
docs/epics/{epic-dir}/{feature-dir}/Func-Test-{story-slug}.md
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 6: Prompting
|
|
57
|
+
After generating, ask user:
|
|
58
|
+
- "Any edge cases to add?"
|
|
59
|
+
- "Any negative test scenarios missed?"
|
|
60
|
+
- "Any test cases to mark as P0 Critical?"
|
|
61
|
+
- "What additional test data and fixtures needed?"
|
|
62
|
+
|
|
63
|
+
## Traceability Feature
|
|
64
|
+
- Each FT case links AC-ID in mapping column
|
|
65
|
+
- When AC changes: grep AC-ID in Func-Test-*.md to know which FTs need update
|
|
66
|
+
- In test script, each describe block has comment `// AC Reference: AC-{N}`
|
|
67
|
+
|
|
68
|
+
## Status Flow
|
|
69
|
+
Draft → Ready → Implemented → Verified
|
|
70
|
+
|
|
71
|
+
## Principles
|
|
72
|
+
- DO NOT create test code, only create specification (markdown)
|
|
73
|
+
- Test code created by `/tas-functest-mobile` or `/tas-functest-web`
|
|
74
|
+
- Func-Test-Spec is input for Layer 2 script generation
|
|
75
|
+
- Each AC must have at least 1 FT case
|
|
76
|
+
- FT uses type code `FT`, NOT `E2E` or `UT`
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# /tas-init
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Initialize TAS kit for the current project.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
1.
|
|
7
|
-
2.
|
|
8
|
-
3.
|
|
9
|
-
4. Copy
|
|
10
|
-
5.
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
6.
|
|
5
|
+
## Actions
|
|
6
|
+
1. Need context from root/tas.yaml. If not exists, copy from .tas/tas-example.yaml to root and ask user to fill required information.
|
|
7
|
+
2. Create directory structure: .tas/templates/, .tas/checklists/, docs/, docs/adr/, docs/epics/, docs/bugs/
|
|
8
|
+
3. Create root/project-status.yaml file with initial state (artifacts, epics, adrs all empty).
|
|
9
|
+
4. Copy default templates to .tas/templates/ if not exist.
|
|
10
|
+
5. If project type is brownfield and codebase_scan_on_init = true:
|
|
11
|
+
- Scan existing codebase
|
|
12
|
+
- Create docs/codebase-overview.md summarizing current architecture
|
|
13
|
+
6. Display status: project type, team roles, enabled workflow phases.
|
|
14
14
|
|
|
15
|
-
##
|
|
16
|
-
-
|
|
17
|
-
-
|
|
15
|
+
## Notes
|
|
16
|
+
- DO NOT recreate files if already exist
|
|
17
|
+
- Ask for confirmation before executing
|