@balazsbarta/mp-skills 0.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/.agents/skills/brainstorming/SKILL.md +201 -0
- package/.agents/skills/brainstorming/references/option-evaluation.md +64 -0
- package/.agents/skills/brainstorming/references/questioning-playbook.md +57 -0
- package/.agents/skills/brainstorming/references/repo-analysis.md +60 -0
- package/.agents/skills/conventional-commits/SKILL.md +124 -0
- package/.agents/skills/conventional-commits/references/commit-types-scopes.md +75 -0
- package/.agents/skills/conventional-commits/references/semantic-release.md +71 -0
- package/.agents/skills/jest/SKILL.md +219 -0
- package/.agents/skills/jest/references/common-errors.md +274 -0
- package/.agents/skills/jest/references/configuration.md +175 -0
- package/.agents/skills/jest/references/embedded-docs.md +44 -0
- package/.agents/skills/jest/references/mocking.md +206 -0
- package/.agents/skills/jest/references/remote-docs.md +19 -0
- package/.agents/skills/jest/references/snapshot-testing.md +181 -0
- package/.agents/skills/jest/references/transforms.md +216 -0
- package/.agents/skills/maestro/SKILL.md +230 -0
- package/.agents/skills/maestro/references/assertions-commands.md +259 -0
- package/.agents/skills/maestro/references/common-errors.md +273 -0
- package/.agents/skills/maestro/references/eas-ci-integration.md +219 -0
- package/.agents/skills/maestro/references/flow-authoring.md +224 -0
- package/.agents/skills/maestro/references/remote-docs.md +23 -0
- package/.agents/skills/mastra/SKILL.md +159 -0
- package/.agents/skills/mastra/references/common-errors.md +535 -0
- package/.agents/skills/mastra/references/create-mastra.md +220 -0
- package/.agents/skills/mastra/references/embedded-docs.md +123 -0
- package/.agents/skills/mastra/references/migration-guide.md +180 -0
- package/.agents/skills/mastra/references/remote-docs.md +193 -0
- package/.agents/skills/next-js/SKILL.md +209 -0
- package/.agents/skills/next-js/references/api-routes.md +213 -0
- package/.agents/skills/next-js/references/app-router.md +206 -0
- package/.agents/skills/next-js/references/caching-revalidation.md +211 -0
- package/.agents/skills/next-js/references/common-errors.md +251 -0
- package/.agents/skills/next-js/references/embedded-docs.md +43 -0
- package/.agents/skills/next-js/references/metadata-seo.md +257 -0
- package/.agents/skills/next-js/references/remote-docs.md +22 -0
- package/.agents/skills/playwright/SKILL.md +218 -0
- package/.agents/skills/playwright/references/ci-configuration.md +208 -0
- package/.agents/skills/playwright/references/common-errors.md +258 -0
- package/.agents/skills/playwright/references/embedded-docs.md +41 -0
- package/.agents/skills/playwright/references/fixtures-assertions.md +208 -0
- package/.agents/skills/playwright/references/page-objects.md +167 -0
- package/.agents/skills/playwright/references/remote-docs.md +23 -0
- package/.agents/skills/playwright/references/visual-regression.md +206 -0
- package/.agents/skills/pull-request-lifecycle/SKILL.md +116 -0
- package/.agents/skills/pull-request-lifecycle/references/changelog-versioning.md +72 -0
- package/.agents/skills/pull-request-lifecycle/references/merge-strategies.md +33 -0
- package/.agents/skills/pull-request-lifecycle/references/pr-description-template.md +72 -0
- package/.agents/skills/pull-request-lifecycle/references/review-process.md +54 -0
- package/.agents/skills/pull-request-lifecycle/scripts/code_review.py +220 -0
- package/.agents/skills/react-native-expo/SKILL.md +212 -0
- package/.agents/skills/react-native-expo/references/common-errors.md +251 -0
- package/.agents/skills/react-native-expo/references/eas-build-submit.md +238 -0
- package/.agents/skills/react-native-expo/references/embedded-docs.md +42 -0
- package/.agents/skills/react-native-expo/references/native-modules.md +181 -0
- package/.agents/skills/react-native-expo/references/navigation-setup.md +229 -0
- package/.agents/skills/react-native-expo/references/remote-docs.md +23 -0
- package/.agents/skills/supabase/SKILL.md +216 -0
- package/.agents/skills/supabase/references/auth-setup.md +206 -0
- package/.agents/skills/supabase/references/common-errors.md +285 -0
- package/.agents/skills/supabase/references/edge-functions.md +178 -0
- package/.agents/skills/supabase/references/embedded-docs.md +43 -0
- package/.agents/skills/supabase/references/migrations.md +193 -0
- package/.agents/skills/supabase/references/remote-docs.md +24 -0
- package/.agents/skills/supabase/references/rls-policies.md +187 -0
- package/.agents/skills/supabase/references/storage.md +182 -0
- package/.agents/skills/task-breakdown/SKILL.md +179 -0
- package/.agents/skills/task-breakdown/references/acceptance-criteria.md +165 -0
- package/.agents/skills/task-breakdown/references/epic-story-format.md +209 -0
- package/.agents/skills/task-breakdown/references/estimation-guide.md +140 -0
- package/.agents/skills/vitest/SKILL.md +219 -0
- package/.agents/skills/vitest/references/common-errors.md +271 -0
- package/.agents/skills/vitest/references/component-testing.md +182 -0
- package/.agents/skills/vitest/references/configuration.md +184 -0
- package/.agents/skills/vitest/references/coverage.md +179 -0
- package/.agents/skills/vitest/references/embedded-docs.md +43 -0
- package/.agents/skills/vitest/references/mocking.md +182 -0
- package/.agents/skills/vitest/references/remote-docs.md +22 -0
- package/README.md +235 -0
- package/package.json +20 -0
- package/scripts/skills.mjs +849 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Supabase Storage
|
|
2
|
+
|
|
3
|
+
Configure and use Supabase Storage for file uploads and downloads.
|
|
4
|
+
|
|
5
|
+
## When to use this reference
|
|
6
|
+
|
|
7
|
+
- Setting up file storage buckets
|
|
8
|
+
- Uploading and downloading files
|
|
9
|
+
- Configuring storage policies (public/private)
|
|
10
|
+
- Generating signed URLs
|
|
11
|
+
|
|
12
|
+
## Creating buckets
|
|
13
|
+
|
|
14
|
+
### Via SQL migration
|
|
15
|
+
|
|
16
|
+
```sql
|
|
17
|
+
-- supabase/migrations/20250101000000_create_storage_buckets.sql
|
|
18
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
19
|
+
VALUES ('avatars', 'avatars', true);
|
|
20
|
+
|
|
21
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
22
|
+
VALUES ('documents', 'documents', false);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Via client
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
const { data, error } = await supabase.storage.createBucket('avatars', {
|
|
29
|
+
public: true,
|
|
30
|
+
fileSizeLimit: 5242880, // 5MB
|
|
31
|
+
allowedMimeTypes: ['image/png', 'image/jpeg', 'image/webp'],
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Storage policies
|
|
36
|
+
|
|
37
|
+
### Public bucket — anyone can read
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
CREATE POLICY "Public read access" ON storage.objects
|
|
41
|
+
FOR SELECT
|
|
42
|
+
USING (bucket_id = 'avatars');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Authenticated upload to own folder
|
|
46
|
+
|
|
47
|
+
```sql
|
|
48
|
+
CREATE POLICY "Users can upload own avatar" ON storage.objects
|
|
49
|
+
FOR INSERT
|
|
50
|
+
TO authenticated
|
|
51
|
+
WITH CHECK (
|
|
52
|
+
bucket_id = 'avatars'
|
|
53
|
+
AND (storage.foldername(name))[1] = auth.uid()::text
|
|
54
|
+
);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Users can manage own files
|
|
58
|
+
|
|
59
|
+
```sql
|
|
60
|
+
CREATE POLICY "Users can manage own files" ON storage.objects
|
|
61
|
+
FOR ALL
|
|
62
|
+
TO authenticated
|
|
63
|
+
USING (
|
|
64
|
+
bucket_id = 'documents'
|
|
65
|
+
AND auth.uid()::text = (storage.foldername(name))[1]
|
|
66
|
+
)
|
|
67
|
+
WITH CHECK (
|
|
68
|
+
bucket_id = 'documents'
|
|
69
|
+
AND auth.uid()::text = (storage.foldername(name))[1]
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Uploading files
|
|
74
|
+
|
|
75
|
+
### From client (browser)
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const file = event.target.files[0];
|
|
79
|
+
const filePath = `${user.id}/${file.name}`;
|
|
80
|
+
|
|
81
|
+
const { data, error } = await supabase.storage
|
|
82
|
+
.from('avatars')
|
|
83
|
+
.upload(filePath, file, {
|
|
84
|
+
cacheControl: '3600',
|
|
85
|
+
upsert: true,
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### From server
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const { data, error } = await supabase.storage
|
|
93
|
+
.from('documents')
|
|
94
|
+
.upload('reports/annual.pdf', fileBuffer, {
|
|
95
|
+
contentType: 'application/pdf',
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Downloading files
|
|
100
|
+
|
|
101
|
+
### Public URL (public buckets)
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const { data } = supabase.storage
|
|
105
|
+
.from('avatars')
|
|
106
|
+
.getPublicUrl('user-123/avatar.png');
|
|
107
|
+
|
|
108
|
+
// data.publicUrl = https://project.supabase.co/storage/v1/object/public/avatars/user-123/avatar.png
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Signed URL (private buckets)
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const { data, error } = await supabase.storage
|
|
115
|
+
.from('documents')
|
|
116
|
+
.createSignedUrl('reports/annual.pdf', 3600); // 1 hour expiry
|
|
117
|
+
|
|
118
|
+
// data.signedUrl = https://project.supabase.co/storage/v1/object/sign/documents/reports/annual.pdf?token=...
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Download file
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const { data, error } = await supabase.storage
|
|
125
|
+
.from('documents')
|
|
126
|
+
.download('reports/annual.pdf');
|
|
127
|
+
|
|
128
|
+
// data is a Blob
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Listing files
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const { data, error } = await supabase.storage
|
|
135
|
+
.from('avatars')
|
|
136
|
+
.list('user-123/', {
|
|
137
|
+
limit: 100,
|
|
138
|
+
offset: 0,
|
|
139
|
+
sortBy: { column: 'created_at', order: 'desc' },
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Deleting files
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const { data, error } = await supabase.storage
|
|
147
|
+
.from('avatars')
|
|
148
|
+
.remove(['user-123/old-avatar.png']);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Image transformations
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const { data } = supabase.storage
|
|
155
|
+
.from('avatars')
|
|
156
|
+
.getPublicUrl('user-123/avatar.png', {
|
|
157
|
+
transform: {
|
|
158
|
+
width: 200,
|
|
159
|
+
height: 200,
|
|
160
|
+
resize: 'cover',
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Troubleshooting
|
|
166
|
+
|
|
167
|
+
### "Bucket not found"
|
|
168
|
+
|
|
169
|
+
- Verify bucket exists: check Supabase dashboard > Storage
|
|
170
|
+
- Bucket names are case-sensitive
|
|
171
|
+
|
|
172
|
+
### "Permission denied" on upload
|
|
173
|
+
|
|
174
|
+
- Check storage policies exist for the bucket
|
|
175
|
+
- Verify the file path matches policy conditions
|
|
176
|
+
- Ensure user is authenticated
|
|
177
|
+
|
|
178
|
+
### File uploaded but can't access
|
|
179
|
+
|
|
180
|
+
- For public buckets: use `getPublicUrl()`
|
|
181
|
+
- For private buckets: use `createSignedUrl()`
|
|
182
|
+
- Check the bucket's `public` setting matches your intent
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-breakdown
|
|
3
|
+
description: "Task breakdown and estimation guide. Covers epic/story/task hierarchy, acceptance criteria writing, estimation techniques, and work decomposition. Use this skill when planning sprints, writing user stories, breaking down features into tasks, or estimating effort."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Balazs Barta
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
repository: https://github.com/balazsbarta/mp-skills
|
|
9
|
+
tags:
|
|
10
|
+
- planning
|
|
11
|
+
- user-stories
|
|
12
|
+
- estimation
|
|
13
|
+
- agile
|
|
14
|
+
- task-management
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Task Breakdown Guide
|
|
18
|
+
|
|
19
|
+
Use this skill to decompose feature requests into actionable, estimable tasks. Audience: another coding agent producing implementation-ready planning artifacts.
|
|
20
|
+
|
|
21
|
+
## When to use this skill
|
|
22
|
+
|
|
23
|
+
- Breaking a feature into implementable tasks
|
|
24
|
+
- Writing user stories with acceptance criteria
|
|
25
|
+
- Estimating effort for stories and tasks
|
|
26
|
+
- Planning sprint scope
|
|
27
|
+
- Converting brainstorming outputs into a backlog
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
**Before decomposing work, extract and confirm:**
|
|
32
|
+
|
|
33
|
+
- **Feature goal**: What user problem does this solve?
|
|
34
|
+
- **Scope boundaries**: What is explicitly out of scope?
|
|
35
|
+
- **Technical context**: Existing architecture and constraints
|
|
36
|
+
|
|
37
|
+
## Quick reference
|
|
38
|
+
|
|
39
|
+
| Request Pattern | First Check | How To |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| "Break this feature into tasks" | [`references/epic-story-format.md`](references/epic-story-format.md) | Epic/story/task hierarchy and templates |
|
|
42
|
+
| "Write acceptance criteria" | [`references/acceptance-criteria.md`](references/acceptance-criteria.md) | Given/When/Then and checklist formats |
|
|
43
|
+
| "How long will this take?" | [`references/estimation-guide.md`](references/estimation-guide.md) | T-shirt sizing, story points, time-based |
|
|
44
|
+
|
|
45
|
+
## Core concepts
|
|
46
|
+
|
|
47
|
+
### Work hierarchy
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Epic (large feature, multiple sprints)
|
|
51
|
+
├── Story (user-facing value, fits in 1 sprint)
|
|
52
|
+
│ ├── Task (technical work, fits in 1 day)
|
|
53
|
+
│ └── Task
|
|
54
|
+
├── Story
|
|
55
|
+
│ ├── Task
|
|
56
|
+
│ └── Task
|
|
57
|
+
└── Story
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Story format
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
As a [user role],
|
|
64
|
+
I want to [action],
|
|
65
|
+
So that [benefit].
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Task characteristics
|
|
69
|
+
|
|
70
|
+
A well-defined task is:
|
|
71
|
+
- **Small** — Completable in 1 day or less
|
|
72
|
+
- **Specific** — Clear start and end state
|
|
73
|
+
- **Testable** — Has verification criteria
|
|
74
|
+
- **Independent** — Minimal dependencies on other tasks
|
|
75
|
+
|
|
76
|
+
## Critical requirements
|
|
77
|
+
|
|
78
|
+
### Every story must have
|
|
79
|
+
|
|
80
|
+
- **Title** — Short, descriptive (imperative mood)
|
|
81
|
+
- **Description** — User story format or clear problem statement
|
|
82
|
+
- **Acceptance criteria** — Testable conditions for "done"
|
|
83
|
+
- **Estimate** — Relative size or time estimate
|
|
84
|
+
|
|
85
|
+
### Task decomposition rules
|
|
86
|
+
|
|
87
|
+
- No task larger than 1 day of work
|
|
88
|
+
- Each task produces a testable output
|
|
89
|
+
- Tasks are ordered by dependency (what blocks what)
|
|
90
|
+
- Infrastructure tasks come before feature tasks
|
|
91
|
+
|
|
92
|
+
## Execution workflow
|
|
93
|
+
|
|
94
|
+
### 1. Identify the epic
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Epic: User Authentication
|
|
98
|
+
Goal: Users can sign up, log in, and manage their accounts.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. Break into stories
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Story 1: User can sign up with email and password
|
|
105
|
+
Story 2: User can log in with existing credentials
|
|
106
|
+
Story 3: User can reset forgotten password
|
|
107
|
+
Story 4: User can update profile information
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Write acceptance criteria for each story
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Story 1: User can sign up with email and password
|
|
114
|
+
|
|
115
|
+
Acceptance Criteria:
|
|
116
|
+
- [ ] Sign-up form validates email format
|
|
117
|
+
- [ ] Password meets minimum requirements (8+ chars, 1 uppercase, 1 number)
|
|
118
|
+
- [ ] Duplicate email shows clear error message
|
|
119
|
+
- [ ] Successful sign-up sends verification email
|
|
120
|
+
- [ ] User is redirected to onboarding after verification
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 4. Break stories into tasks
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Story 1 Tasks:
|
|
127
|
+
1. Create sign-up API endpoint (POST /auth/signup)
|
|
128
|
+
2. Add email validation and password hashing
|
|
129
|
+
3. Create sign-up form component
|
|
130
|
+
4. Add form validation (client-side)
|
|
131
|
+
5. Implement email verification flow
|
|
132
|
+
6. Add error handling and user feedback
|
|
133
|
+
7. Write integration tests for sign-up flow
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 5. Estimate tasks
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
1. Create sign-up API endpoint — S (2-3 hours)
|
|
140
|
+
2. Add email validation and password hashing — S (2 hours)
|
|
141
|
+
3. Create sign-up form component — M (4 hours)
|
|
142
|
+
4. Add form validation — S (2 hours)
|
|
143
|
+
5. Implement email verification flow — M (4-5 hours)
|
|
144
|
+
6. Add error handling and user feedback — S (2 hours)
|
|
145
|
+
7. Write integration tests — M (3-4 hours)
|
|
146
|
+
|
|
147
|
+
Story total: ~20-22 hours (M t-shirt size)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Error handling
|
|
151
|
+
|
|
152
|
+
### Failure modes
|
|
153
|
+
|
|
154
|
+
| Mistake | Symptom | Fix |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| Stories too large | Can't finish in 1 sprint | Split by workflow step or user action |
|
|
157
|
+
| Vague acceptance criteria | "Works correctly" | Use Given/When/Then format |
|
|
158
|
+
| Missing edge cases | Bugs in production | Add negative test criteria |
|
|
159
|
+
| No dependency order | Tasks blocked constantly | Map dependencies before starting |
|
|
160
|
+
| Underestimation | Sprint overflow | Add buffer, use historical data |
|
|
161
|
+
|
|
162
|
+
## Output contract
|
|
163
|
+
|
|
164
|
+
Produce markdown that includes:
|
|
165
|
+
- Epic with goal, scope boundaries, and non-goals
|
|
166
|
+
- Stories with user-story statements and explicit acceptance criteria
|
|
167
|
+
- Tasks with estimates, dependency order, and verification criteria
|
|
168
|
+
- Sprint allocation summary tied to team capacity assumptions
|
|
169
|
+
|
|
170
|
+
## Cross-references
|
|
171
|
+
|
|
172
|
+
- **Brainstorming**: [../brainstorming/SKILL.md](../brainstorming/SKILL.md) — Generate and evaluate feature ideas before breaking down
|
|
173
|
+
- **Pull Request Lifecycle**: [../pull-request-lifecycle/SKILL.md](../pull-request-lifecycle/SKILL.md) — Each story/task becomes a PR
|
|
174
|
+
|
|
175
|
+
## Resources
|
|
176
|
+
|
|
177
|
+
- **Epic and story format**: [`references/epic-story-format.md`](references/epic-story-format.md)
|
|
178
|
+
- **Acceptance criteria**: [`references/acceptance-criteria.md`](references/acceptance-criteria.md)
|
|
179
|
+
- **Estimation guide**: [`references/estimation-guide.md`](references/estimation-guide.md)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Acceptance Criteria
|
|
2
|
+
|
|
3
|
+
Patterns for writing clear, testable acceptance criteria for user stories.
|
|
4
|
+
|
|
5
|
+
## When to use this reference
|
|
6
|
+
|
|
7
|
+
- Writing acceptance criteria for a user story
|
|
8
|
+
- Defining "done" for a task or feature
|
|
9
|
+
- Translating requirements into testable conditions
|
|
10
|
+
|
|
11
|
+
## Formats
|
|
12
|
+
|
|
13
|
+
### Checklist format (simple)
|
|
14
|
+
|
|
15
|
+
Best for straightforward requirements:
|
|
16
|
+
|
|
17
|
+
```markdown
|
|
18
|
+
### Acceptance criteria
|
|
19
|
+
- [ ] Email field validates format before submission
|
|
20
|
+
- [ ] Password requires minimum 8 characters
|
|
21
|
+
- [ ] Success message displays after submission
|
|
22
|
+
- [ ] Form data persists if page is refreshed (draft state)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Given/When/Then format (BDD)
|
|
26
|
+
|
|
27
|
+
Best for complex behavior with multiple scenarios:
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
### Acceptance criteria
|
|
31
|
+
|
|
32
|
+
**Scenario: Successful login**
|
|
33
|
+
Given the user is on the login page
|
|
34
|
+
And they have a registered account
|
|
35
|
+
When they enter valid email and password
|
|
36
|
+
And click "Log in"
|
|
37
|
+
Then they are redirected to the dashboard
|
|
38
|
+
And a success toast is shown
|
|
39
|
+
|
|
40
|
+
**Scenario: Invalid credentials**
|
|
41
|
+
Given the user is on the login page
|
|
42
|
+
When they enter an incorrect password
|
|
43
|
+
And click "Log in"
|
|
44
|
+
Then an error message "Invalid email or password" is shown
|
|
45
|
+
And the password field is cleared
|
|
46
|
+
And the form remains on the login page
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Rule-based format
|
|
50
|
+
|
|
51
|
+
Best for business rules and constraints:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
### Acceptance criteria
|
|
55
|
+
|
|
56
|
+
**Rules:**
|
|
57
|
+
1. Discount code must be alphanumeric, 6-12 characters
|
|
58
|
+
2. Only one discount code per order
|
|
59
|
+
3. Expired codes show "This code has expired"
|
|
60
|
+
4. Codes are case-insensitive
|
|
61
|
+
5. Valid code shows discount amount before checkout
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Writing good acceptance criteria
|
|
65
|
+
|
|
66
|
+
### Characteristics
|
|
67
|
+
|
|
68
|
+
| Good Criteria | Bad Criteria |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| Specific and testable | Vague ("works correctly") |
|
|
71
|
+
| Focused on behavior | Focused on implementation |
|
|
72
|
+
| Independent | Dependent on other criteria |
|
|
73
|
+
| Written in user language | Written in technical jargon |
|
|
74
|
+
|
|
75
|
+
### Examples
|
|
76
|
+
|
|
77
|
+
#### Good
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
- [ ] Search results appear within 2 seconds
|
|
81
|
+
- [ ] Empty search shows "No results found" message
|
|
82
|
+
- [ ] Search highlights matching terms in results
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### Bad
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
- [ ] Search works
|
|
89
|
+
- [ ] Fast response time
|
|
90
|
+
- [ ] Good UX for empty state
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Coverage checklist
|
|
94
|
+
|
|
95
|
+
For each story, ensure criteria cover:
|
|
96
|
+
|
|
97
|
+
### Functional
|
|
98
|
+
|
|
99
|
+
- [ ] **Happy path** — The main success scenario
|
|
100
|
+
- [ ] **Validation** — Input validation and error messages
|
|
101
|
+
- [ ] **Edge cases** — Empty states, max values, special characters
|
|
102
|
+
- [ ] **Error handling** — Network errors, server errors, timeouts
|
|
103
|
+
|
|
104
|
+
### Non-functional
|
|
105
|
+
|
|
106
|
+
- [ ] **Performance** — Response time, load handling
|
|
107
|
+
- [ ] **Accessibility** — Keyboard navigation, screen reader support
|
|
108
|
+
- [ ] **Security** — Authentication, authorization, input sanitization
|
|
109
|
+
- [ ] **Responsiveness** — Mobile, tablet, desktop behavior
|
|
110
|
+
|
|
111
|
+
## Mapping to tests
|
|
112
|
+
|
|
113
|
+
Each acceptance criterion should map to at least one test:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
### Acceptance criteria → Test mapping
|
|
117
|
+
|
|
118
|
+
| Criterion | Test Type | Test File |
|
|
119
|
+
| --- | --- | --- |
|
|
120
|
+
| Email validates format | Unit test | `auth.test.ts` |
|
|
121
|
+
| Success redirects to dashboard | Integration test | `login.test.ts` |
|
|
122
|
+
| Error shows message | Component test | `LoginForm.test.tsx` |
|
|
123
|
+
| Rate limit after 5 attempts | API test | `auth-api.test.ts` |
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Templates by story type
|
|
127
|
+
|
|
128
|
+
### API endpoint story
|
|
129
|
+
|
|
130
|
+
```markdown
|
|
131
|
+
- [ ] Endpoint returns correct status code (200/201/204)
|
|
132
|
+
- [ ] Response body matches schema
|
|
133
|
+
- [ ] Invalid input returns 400 with error details
|
|
134
|
+
- [ ] Unauthorized request returns 401
|
|
135
|
+
- [ ] Rate limiting returns 429 after threshold
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### UI component story
|
|
139
|
+
|
|
140
|
+
```markdown
|
|
141
|
+
- [ ] Component renders in default state
|
|
142
|
+
- [ ] Component handles loading state
|
|
143
|
+
- [ ] Component handles error state
|
|
144
|
+
- [ ] Component handles empty state
|
|
145
|
+
- [ ] Component is keyboard accessible
|
|
146
|
+
- [ ] Component works on mobile viewport (375px)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Data migration story
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
- [ ] Migration runs without errors on staging data
|
|
153
|
+
- [ ] All existing records are transformed correctly
|
|
154
|
+
- [ ] Rollback script restores original state
|
|
155
|
+
- [ ] Migration completes within acceptable time window
|
|
156
|
+
- [ ] No data loss verified by row count comparison
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Tips
|
|
160
|
+
|
|
161
|
+
- Write criteria before starting implementation
|
|
162
|
+
- If you can't write criteria, the story needs more definition
|
|
163
|
+
- Review criteria with stakeholders before starting
|
|
164
|
+
- Each criterion should be independently verifiable
|
|
165
|
+
- Aim for 3-8 criteria per story (fewer = too vague, more = split the story)
|