@roopesh.yadava/qa-pack 1.0.3
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/README.md +79 -0
- package/bin/postinstall.js +151 -0
- package/claude/commands/bug-report.md +185 -0
- package/claude/commands/qa-agent.md +12 -0
- package/claude/commands/write-acceptance-criteria.md +167 -0
- package/claude/settings.json +13 -0
- package/claude/settings.local.json.example +19 -0
- package/claude/skills/SKILLS_CONTEXT.md +194 -0
- package/claude/skills/accessibility-testing/SKILL.md +317 -0
- package/claude/skills/accessibility-testing/WCAG_CHECKS.md +478 -0
- package/claude/skills/automation/BDD_TEMPLATES.md +237 -0
- package/claude/skills/automation/LOCATOR_PATTERNS.md +169 -0
- package/claude/skills/automation/SKILL.md +364 -0
- package/claude/skills/bug-reporting/SKILL.md +257 -0
- package/claude/skills/delete-files/SKILL.md +141 -0
- package/claude/skills/manual-testing/SKILL.md +493 -0
- package/claude/skills/qa-agent/SKILL.md +391 -0
- package/claude/skills/qa-agent/product_context/CONTEXT_SCHEMA.md +58 -0
- package/claude/skills/qa-agent/product_context/README.md +19 -0
- package/claude/skills/test-charter/SKILL.md +300 -0
- package/claude/skills/ui-test-figma/COMPARISON_PATTERNS.md +300 -0
- package/claude/skills/ui-test-figma/SKILL.md +234 -0
- package/package.json +29 -0
- package/templates/CLAUDE.md +41 -0
- package/templates/cucumber.cjs +7 -0
- package/templates/mcp.json +18 -0
- package/templates/settings.local.json.example +19 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-charter
|
|
3
|
+
description: >
|
|
4
|
+
Generates a structured Test Charter in Markdown from a manual test execution report
|
|
5
|
+
(MD format) in the outputs/ folder, then publishes it to the team decision record
|
|
6
|
+
site via REST API. Triggers when the user mentions: test charter, manual test report,
|
|
7
|
+
exploratory session, session-based testing, "generate a test charter", "create a
|
|
8
|
+
charter", or "run the charter skill".
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Test Charter Skill
|
|
12
|
+
|
|
13
|
+
You are a senior QA engineer. Parse a manual test execution report, generate a Test
|
|
14
|
+
Charter document, and publish it to the decision record API.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Step 1 — Read the report
|
|
19
|
+
|
|
20
|
+
List every `.md` file in `outputs/`. If more than one is found, show the list and ask:
|
|
21
|
+
> "I found multiple reports in `outputs/`. Which one should I use?"
|
|
22
|
+
|
|
23
|
+
If only one is found, use it automatically.
|
|
24
|
+
|
|
25
|
+
If none found:
|
|
26
|
+
> "No MD file in `outputs/`. Drop your manual test execution report there and confirm,
|
|
27
|
+
> or paste it directly."
|
|
28
|
+
|
|
29
|
+
Wait for the file or pasted content before continuing.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Step 2 — Extract fields from the report
|
|
34
|
+
|
|
35
|
+
Infer the following from the report's content. Do not ask the user — derive intelligently.
|
|
36
|
+
Use `"Not provided"` only when a field truly cannot be inferred.
|
|
37
|
+
|
|
38
|
+
| Field | How to derive |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `scope` | Feature/module name — from the report title or heading |
|
|
41
|
+
| `objectives` | Purpose of the test session — from intro or summary section |
|
|
42
|
+
| `tester` | Author or tester name — from report metadata or signature |
|
|
43
|
+
| `duration` | Session length — look for time references; default `"1h"` |
|
|
44
|
+
| `duration_short` | `"30m"` / `"1h"` / `"2h"` — must match `duration`; derive from same source |
|
|
45
|
+
| `charter_vs_opportunity` | If stated; default `"90/10"` |
|
|
46
|
+
| `bug_investigation_time` | If stated; default `"30m"` |
|
|
47
|
+
| `testing_areas` | Derive from sections covered (Functional, UI/UX, Navigation, Security, Error Handling) |
|
|
48
|
+
| `environment` | QA / Staging / Prod — from report metadata |
|
|
49
|
+
| `persona` | User role being tested — from report context |
|
|
50
|
+
| `session_recording` | If mentioned; else `"Not provided"` |
|
|
51
|
+
| `bugs` | All bugs/defects listed — extract: severity, description, steps, status |
|
|
52
|
+
| `test_notes` | Key observations per area |
|
|
53
|
+
| `test_cases` | Any test case table rows present in the report |
|
|
54
|
+
| `risks` | Any risks or blockers mentioned |
|
|
55
|
+
| `issues` | Open questions or clarifications noted |
|
|
56
|
+
| `enhancements` | Improvement suggestions noted |
|
|
57
|
+
| `execution_notes` | Any notes for the next tester |
|
|
58
|
+
|
|
59
|
+
Count total bugs → `bug_count` (integer).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Step 3 — Collect charter metadata (one prompt)
|
|
64
|
+
|
|
65
|
+
Ask once:
|
|
66
|
+
> "Quick details before I generate:
|
|
67
|
+
> 1. Charter title / Jira card key (e.g. `FF-420`)
|
|
68
|
+
> 2. Your name and email (creator)
|
|
69
|
+
> 3. Reviewer name and email
|
|
70
|
+
> 4. Test environment (QA / Staging / Prod) — skip if already clear from the report"
|
|
71
|
+
|
|
72
|
+
Parse response into: `title`, `code` (card key or slugified title), `creator`, `reviewer`, `environment` (override inferred value if provided).
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Step 4 — Generate the charter
|
|
77
|
+
|
|
78
|
+
Produce the Markdown below. Only include AREAS rows for areas present in `testing_areas`.
|
|
79
|
+
For BUGS: one row per extracted bug; placeholder row if none.
|
|
80
|
+
|
|
81
|
+
**CRITICAL — TEST CASES is a mandatory section.** Always populate it from the report's test results table. If the report has no test case rows, include three blank placeholder rows. Never omit this section — it is a core feature of the Test Charter format and must appear in every charter generated or published.
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
# [title]
|
|
85
|
+
|
|
86
|
+
* Status: Proposed
|
|
87
|
+
* Reviewer: [reviewer.name]
|
|
88
|
+
* Number of Bugs: [bug_count]
|
|
89
|
+
* Duration: [duration]
|
|
90
|
+
* Date: [M/D/YYYY]
|
|
91
|
+
|
|
92
|
+
## CHARTER
|
|
93
|
+
|
|
94
|
+
**Scope:** [scope]
|
|
95
|
+
|
|
96
|
+
**Objectives:** [objectives]
|
|
97
|
+
|
|
98
|
+
## AREAS
|
|
99
|
+
|
|
100
|
+
| Testing Area | Focus |
|
|
101
|
+
|----------------|------------------------------------------------------------------|
|
|
102
|
+
[Only include rows for areas present in testing_areas. Row options:]
|
|
103
|
+
| Functional | Validate core features work as specified |
|
|
104
|
+
| UI/UX | Verify visual consistency, layout, and usability |
|
|
105
|
+
| Navigation | Confirm user flows, links, and routing behave correctly |
|
|
106
|
+
| Security | Check for common vulnerabilities and access control |
|
|
107
|
+
| Error Handling | Validate error messages, edge cases, and graceful failure states |
|
|
108
|
+
|
|
109
|
+
## TESTER
|
|
110
|
+
|
|
111
|
+
**Name:** [tester]
|
|
112
|
+
|
|
113
|
+
## TASK BREAKDOWN
|
|
114
|
+
|
|
115
|
+
1. Review application against charter objectives
|
|
116
|
+
2. Execute functional test cases
|
|
117
|
+
3. Explore UI/UX and navigation paths
|
|
118
|
+
4. Probe security touchpoints
|
|
119
|
+
5. Trigger and verify error-handling scenarios
|
|
120
|
+
6. Log bugs and observations
|
|
121
|
+
7. Summarise findings and flag risks
|
|
122
|
+
|
|
123
|
+
## DURATION
|
|
124
|
+
|
|
125
|
+
**Session Length:** [duration]
|
|
126
|
+
|
|
127
|
+
## BUG INVESTIGATION & REPORTING
|
|
128
|
+
|
|
129
|
+
**Time Allocated:** [bug_investigation_time]
|
|
130
|
+
|
|
131
|
+
## CHARTER VS. OPPORTUNITY
|
|
132
|
+
|
|
133
|
+
**Ratio:** [charter_vs_opportunity]
|
|
134
|
+
|
|
135
|
+
## TEST NOTES
|
|
136
|
+
|
|
137
|
+
[test_notes — one sub-section per testing area, bullet points only]
|
|
138
|
+
|
|
139
|
+
## TEST CASES
|
|
140
|
+
|
|
141
|
+
| Test Case ID | Steps | Expected Outcome | Actual Outcome | Status (Pass/Fail) |
|
|
142
|
+
|---|---|---|---|---|
|
|
143
|
+
[rows from report or three blank rows]
|
|
144
|
+
|
|
145
|
+
## POTENTIAL RISKS
|
|
146
|
+
|
|
147
|
+
[risks from report, or generic defaults if none found]
|
|
148
|
+
|
|
149
|
+
## BUGS
|
|
150
|
+
|
|
151
|
+
| Bug ID | Severity | Description | Steps to Reproduce | Status |
|
|
152
|
+
|---|---|---|---|---|
|
|
153
|
+
[one row per bug; placeholder row if none]
|
|
154
|
+
|
|
155
|
+
## ISSUES & CLARIFICATIONS
|
|
156
|
+
|
|
157
|
+
[issues list or single placeholder]
|
|
158
|
+
|
|
159
|
+
## ENHANCEMENTS
|
|
160
|
+
|
|
161
|
+
[enhancements list or single placeholder]
|
|
162
|
+
|
|
163
|
+
## PERSONA
|
|
164
|
+
|
|
165
|
+
[persona — describe assumed user role, goals, and technical proficiency]
|
|
166
|
+
|
|
167
|
+
## TEST EXECUTION NOTES
|
|
168
|
+
|
|
169
|
+
**Session Recording:** [session_recording]
|
|
170
|
+
|
|
171
|
+
[execution_notes]
|
|
172
|
+
|
|
173
|
+
## RESOURCES
|
|
174
|
+
|
|
175
|
+
**Test Environment:** [environment]
|
|
176
|
+
**Date:** [M/D/YYYY]
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Step 5 — Save charter locally
|
|
182
|
+
|
|
183
|
+
Save the generated Markdown to `outputs/charters/[SLUG].md` using the Write tool.
|
|
184
|
+
Create the `outputs/charters/` directory if it does not exist.
|
|
185
|
+
|
|
186
|
+
Before saving, verify the charter contains all required sections. If any are missing, regenerate before saving:
|
|
187
|
+
- `## TEST CASES` — mandatory, must contain rows (never skip)
|
|
188
|
+
- `## BUGS`
|
|
189
|
+
- `## CHARTER`
|
|
190
|
+
- `## AREAS`
|
|
191
|
+
- `## TEST NOTES`
|
|
192
|
+
|
|
193
|
+
Confirm to the user: `"Charter saved locally → outputs/charters/[SLUG].md"`
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Step 6 — Review
|
|
198
|
+
|
|
199
|
+
Show the charter and ask:
|
|
200
|
+
> "Review the charter above. Reply with edits or **'looks good'** to publish."
|
|
201
|
+
|
|
202
|
+
Apply changes if requested (re-save locally before publishing), then proceed.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Step 7 — Credentials (one prompt)
|
|
207
|
+
|
|
208
|
+
Ask once:
|
|
209
|
+
> "To publish, I need:
|
|
210
|
+
> 1. Decision record site URL
|
|
211
|
+
> 2. Login email
|
|
212
|
+
> 3. Password (not echoed or logged)"
|
|
213
|
+
|
|
214
|
+
Do not display or repeat the password back to the user at any point.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Step 8 — Login and capture token
|
|
219
|
+
|
|
220
|
+
1. `browser_navigate` → site URL
|
|
221
|
+
2. `browser_snapshot` → find login fields
|
|
222
|
+
3. `browser_fill_form` → email + password
|
|
223
|
+
4. `browser_click` → submit
|
|
224
|
+
5. `browser_wait_for` → page load
|
|
225
|
+
6. `browser_evaluate`:
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
// Only check known auth key names — avoid dumping all storage
|
|
229
|
+
const keys = ['token', 'authToken', 'access_token', 'jwt', 'id_token'];
|
|
230
|
+
for (const k of keys) {
|
|
231
|
+
const v = localStorage.getItem(k) || sessionStorage.getItem(k);
|
|
232
|
+
if (v) return v;
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
If the script returns `null`, use `browser_network_requests` to find the token in the
|
|
238
|
+
login response headers or body.
|
|
239
|
+
|
|
240
|
+
On failure:
|
|
241
|
+
> "Login failed. Fix credentials or complete MFA manually, then confirm to retry."
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Step 9 — POST to API
|
|
246
|
+
|
|
247
|
+
**Endpoint:** `POST https://hrqgymnn16.execute-api.us-east-1.amazonaws.com/dev/test-charter`
|
|
248
|
+
|
|
249
|
+
Slugify the title: lowercase, spaces/special chars → `-`, trim leading/trailing `-`.
|
|
250
|
+
The `0-` prefix in the filename is the sort-order prefix used by the decision record site.
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
254
|
+
const filename = '0-' + slug + '-' + crypto.randomUUID() + '.md';
|
|
255
|
+
|
|
256
|
+
const response = await fetch('https://hrqgymnn16.execute-api.us-east-1.amazonaws.com/dev/test-charter', {
|
|
257
|
+
method: 'POST',
|
|
258
|
+
headers: {
|
|
259
|
+
'Content-Type': 'application/json',
|
|
260
|
+
'Authorization': 'Bearer TOKEN'
|
|
261
|
+
},
|
|
262
|
+
body: JSON.stringify({
|
|
263
|
+
filename: filename,
|
|
264
|
+
adr_type: 'test',
|
|
265
|
+
title: 'TITLE',
|
|
266
|
+
date: 'M/D/YYYY',
|
|
267
|
+
status: 'Proposed',
|
|
268
|
+
// reviewer is an array of objects (same shape as creator)
|
|
269
|
+
reviewer: [{ email: 'EMAIL', name: 'NAME', status: 'Pending' }],
|
|
270
|
+
creator: { email: 'EMAIL', name: 'NAME' },
|
|
271
|
+
number_of_bugs: COUNT,
|
|
272
|
+
duration: DURATION_SHORT,
|
|
273
|
+
content: 'FULL_MARKDOWN',
|
|
274
|
+
code: 'CODE'
|
|
275
|
+
})
|
|
276
|
+
});
|
|
277
|
+
const result = await response.json();
|
|
278
|
+
return { status: response.status, body: result };
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
On non-200/201: show the full error status and response body, then ask:
|
|
282
|
+
> "Publish failed ([status]). Options: re-authenticate and retry, fix the payload field
|
|
283
|
+
> shown above, or cancel."
|
|
284
|
+
|
|
285
|
+
If the response body contains a URL, capture it as `published_url`.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Step 10 — Done
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
TEST CHARTER PUBLISHED
|
|
293
|
+
Title : [title] | Code : [code]
|
|
294
|
+
Tester : [tester] | Reviewer : [reviewer.name]
|
|
295
|
+
Duration : [duration] | Bugs : [bug_count]
|
|
296
|
+
Date : [date] | Status : Proposed
|
|
297
|
+
Local : outputs/charters/[SLUG].md
|
|
298
|
+
Published: [published_url or "URL not returned by API"]
|
|
299
|
+
✅ Uploaded to decision record
|
|
300
|
+
```
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# UI Comparison Patterns
|
|
2
|
+
|
|
3
|
+
> Load this file before Step 3 (comparison) in the ui-test-figma skill.
|
|
4
|
+
> Contains: tag classification rules, CSS extraction JS, report template, Jira comment template,
|
|
5
|
+
> MCP tool reference, and error handling table.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Tag Classification Rules (Method A — Figma MCP)
|
|
10
|
+
|
|
11
|
+
| Tag | Rule |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `STATIC` | Button labels, nav items, column headers, section titles, form labels — never changes per user |
|
|
14
|
+
| `DYNAMIC` | Currency amounts, dates, user names/emails, IDs, counts, status badges |
|
|
15
|
+
| `PATTERN` | Greeting text like "Welcome, [Name]" — verify prefix only |
|
|
16
|
+
|
|
17
|
+
**Heuristics:**
|
|
18
|
+
- Contains `$`, `€`, `₹`, `%` → `DYNAMIC`
|
|
19
|
+
- Matches date pattern (dd/mm/yyyy, Jan 01 2024, etc.) → `DYNAMIC`
|
|
20
|
+
- All-caps short string (`ACTIVE`, `PENDING`, `PAID`) → `DYNAMIC`
|
|
21
|
+
- Long alphanumeric (>8 chars, mixed case) → `DYNAMIC`
|
|
22
|
+
- Contains `@` → `DYNAMIC`
|
|
23
|
+
- Short label ending `:` or preceding an input → `STATIC`
|
|
24
|
+
|
|
25
|
+
**Comparison rules by tag:**
|
|
26
|
+
- `STATIC` → exact or case-insensitive match against `APP_DOM` required
|
|
27
|
+
- `DYNAMIC` → verify field exists and is non-empty; do not compare value
|
|
28
|
+
- `PATTERN` → verify static prefix matches
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## CSS Comparison Rules
|
|
33
|
+
|
|
34
|
+
| Property | What to check |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Font size | Figma token vs `APP_CSS[element].fontSize` |
|
|
37
|
+
| Font weight | Bold/regular from Figma vs computed `fontWeight` |
|
|
38
|
+
| Button color | Figma fill color vs `backgroundColor` |
|
|
39
|
+
| Border radius | Figma corner radius vs `borderRadius` |
|
|
40
|
+
| Padding | Figma padding values vs computed `padding` |
|
|
41
|
+
|
|
42
|
+
Flag mismatches where the Figma design token and computed style clearly differ (e.g., Figma shows `#3B82F6` but app renders `#6366F1`).
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## CSS Extraction JS (run via `browser_evaluate`)
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
browser_evaluate({
|
|
50
|
+
expression: `
|
|
51
|
+
const results = {};
|
|
52
|
+
const selectors = {
|
|
53
|
+
primaryButton: 'button[type="submit"], .btn-primary, [class*="primary"]',
|
|
54
|
+
heading: 'h1, h2, [class*="heading"], [class*="title"]',
|
|
55
|
+
navItem: 'nav a, [class*="nav-item"], [class*="sidebar-item"]',
|
|
56
|
+
tableHeader: 'th, [class*="table-header"], [class*="col-header"]',
|
|
57
|
+
badge: '[class*="badge"], [class*="chip"], [class*="tag"]',
|
|
58
|
+
inputField: 'input[type="text"], input[type="email"]'
|
|
59
|
+
};
|
|
60
|
+
for (const [name, selector] of Object.entries(selectors)) {
|
|
61
|
+
const el = document.querySelector(selector);
|
|
62
|
+
if (el) {
|
|
63
|
+
const s = window.getComputedStyle(el);
|
|
64
|
+
results[name] = {
|
|
65
|
+
fontSize: s.fontSize,
|
|
66
|
+
fontWeight: s.fontWeight,
|
|
67
|
+
color: s.color,
|
|
68
|
+
backgroundColor: s.backgroundColor,
|
|
69
|
+
padding: s.padding,
|
|
70
|
+
borderRadius: s.borderRadius,
|
|
71
|
+
border: s.border
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
`
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Visual Comparison Checklist (Method B — Screenshots)
|
|
83
|
+
|
|
84
|
+
Compare `APP_SCREENSHOT` against the Figma screenshot visually. Check:
|
|
85
|
+
|
|
86
|
+
1. Page title / heading text — exact match
|
|
87
|
+
2. Navigation structure — all sidebar/nav items present
|
|
88
|
+
3. Breadcrumb trail — matches
|
|
89
|
+
4. Table column headers — all present with same names
|
|
90
|
+
5. Button labels — primary actions, filter, export
|
|
91
|
+
6. Search bar placeholder text — matches
|
|
92
|
+
7. Form field labels — exact match
|
|
93
|
+
8. Section labels — all section headings present
|
|
94
|
+
9. Status badges / chips — present and labeled correctly
|
|
95
|
+
10. Footer row — totals, counts present
|
|
96
|
+
11. Pagination — present or absent consistently
|
|
97
|
+
12. Spacing / alignment — obvious layout gaps or misalignments
|
|
98
|
+
13. Color scheme — primary brand color consistent
|
|
99
|
+
|
|
100
|
+
For dynamic fields (amounts, names, IDs, dates): **verify presence only, not value**.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Report Template
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
╔══════════════════════════════════════════════════════════╗
|
|
108
|
+
║ UI COMPARISON REPORT ║
|
|
109
|
+
║ App URL : [APP_URL] ║
|
|
110
|
+
║ Figma : node-id [NODE_ID] ║
|
|
111
|
+
║ Method : [Figma MCP | Browser Screenshot] ║
|
|
112
|
+
║ Capture : Full-page via Playwright MCP ║
|
|
113
|
+
║ Tested : [timestamp] ║
|
|
114
|
+
╚══════════════════════════════════════════════════════════╝
|
|
115
|
+
|
|
116
|
+
SUMMARY
|
|
117
|
+
───────
|
|
118
|
+
Total checks : XX
|
|
119
|
+
✅ Passed : XX
|
|
120
|
+
❌ Failed : XX
|
|
121
|
+
⚠️ Warnings : XX
|
|
122
|
+
|
|
123
|
+
────────────────────────────────────────────────────────────
|
|
124
|
+
FAILURES (action required)
|
|
125
|
+
────────────────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
[F1] TEXT MISMATCH
|
|
128
|
+
Element : [element name]
|
|
129
|
+
Figma : "text in design"
|
|
130
|
+
Live App : "text found in DOM"
|
|
131
|
+
Severity : High
|
|
132
|
+
|
|
133
|
+
[F2] MISSING ELEMENT
|
|
134
|
+
Element : [element name]
|
|
135
|
+
Figma : Present
|
|
136
|
+
Live App : Not found in DOM
|
|
137
|
+
Severity : High
|
|
138
|
+
|
|
139
|
+
[F3] CSS MISMATCH
|
|
140
|
+
Element : [element, e.g. "Primary Button"]
|
|
141
|
+
Property : [e.g. background-color]
|
|
142
|
+
Figma : [design value, e.g. #3B82F6]
|
|
143
|
+
Live App : [computed value, e.g. rgb(99, 102, 241)]
|
|
144
|
+
Severity : Medium
|
|
145
|
+
|
|
146
|
+
[F4] EMPTY DYNAMIC FIELD
|
|
147
|
+
Element : [field name]
|
|
148
|
+
Expected : Non-empty value
|
|
149
|
+
Live App : Empty or absent
|
|
150
|
+
Severity : Medium
|
|
151
|
+
|
|
152
|
+
[F5] LAYOUT / STRUCTURAL MISSING
|
|
153
|
+
Element : [structural element]
|
|
154
|
+
Figma : Present
|
|
155
|
+
Live App : Not detected
|
|
156
|
+
Severity : High
|
|
157
|
+
|
|
158
|
+
────────────────────────────────────────────────────────────
|
|
159
|
+
WARNINGS (review recommended)
|
|
160
|
+
────────────────────────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
[W1] CASE MISMATCH
|
|
163
|
+
Element : [element]
|
|
164
|
+
Figma : "Title Case"
|
|
165
|
+
Live App : "lowercase"
|
|
166
|
+
|
|
167
|
+
[W2] EXTRA ELEMENT IN APP
|
|
168
|
+
Element : [element found in app but absent in design]
|
|
169
|
+
Note : Verify if intentional addition
|
|
170
|
+
|
|
171
|
+
[W3] CSS MINOR DIFFERENCE
|
|
172
|
+
Element : [element]
|
|
173
|
+
Property : [e.g. font-size]
|
|
174
|
+
Figma : 14px
|
|
175
|
+
Live App : 13px
|
|
176
|
+
Note : Within acceptable range — review if intentional
|
|
177
|
+
|
|
178
|
+
────────────────────────────────────────────────────────────
|
|
179
|
+
CSS SNAPSHOT (extracted via Playwright)
|
|
180
|
+
────────────────────────────────────────────────────────────
|
|
181
|
+
Primary Button : font=[fontSize], color=[color], bg=[backgroundColor], radius=[borderRadius]
|
|
182
|
+
Heading : font=[fontSize], weight=[fontWeight], color=[color]
|
|
183
|
+
Nav Item : font=[fontSize], color=[color]
|
|
184
|
+
Table Header : font=[fontSize], weight=[fontWeight]
|
|
185
|
+
Badge/Chip : bg=[backgroundColor], radius=[borderRadius]
|
|
186
|
+
|
|
187
|
+
────────────────────────────────────────────────────────────
|
|
188
|
+
PASSED
|
|
189
|
+
────────────────────────────────────────────────────────────
|
|
190
|
+
✅ [element] — matches
|
|
191
|
+
✅ [dynamic field] — value present (not compared)
|
|
192
|
+
|
|
193
|
+
────────────────────────────────────────────────────────────
|
|
194
|
+
NOTES
|
|
195
|
+
────────────────────────────────────────────────────────────
|
|
196
|
+
- Captured via: Playwright MCP (full-page, networkidle wait)
|
|
197
|
+
- CSS extracted via: window.getComputedStyle()
|
|
198
|
+
- Dynamic fields verified for presence only, not value.
|
|
199
|
+
- Source: [Figma MCP / Browser Screenshot fallback]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Jira Comment Template
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
Hi [~accountId:ACCOUNT_ID],
|
|
208
|
+
|
|
209
|
+
Please review the UI bugs below, found during automated Figma-vs-Live comparison using Playwright MCP.
|
|
210
|
+
|
|
211
|
+
------------------------------------------------------------
|
|
212
|
+
🔍 UI BUG REPORT
|
|
213
|
+
Page Tested : [APP_URL]
|
|
214
|
+
Figma Node : [NODE_ID]
|
|
215
|
+
Capture Mode : Full-page — Playwright MCP (networkidle)
|
|
216
|
+
Tested On : [timestamp]
|
|
217
|
+
Source : [Figma MCP / Browser Screenshot fallback]
|
|
218
|
+
------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
📋 SUMMARY
|
|
221
|
+
Total Failures : [N]
|
|
222
|
+
🔴 High : [count]
|
|
223
|
+
🟠 Medium : [count]
|
|
224
|
+
🟡 Low : [count]
|
|
225
|
+
|
|
226
|
+
------------------------------------------------------------
|
|
227
|
+
🐛 FAILURES (Action Required)
|
|
228
|
+
------------------------------------------------------------
|
|
229
|
+
|
|
230
|
+
[F1] 🔴 HIGH — TEXT MISMATCH
|
|
231
|
+
Element : [element name]
|
|
232
|
+
Expected : "[Figma text]"
|
|
233
|
+
Actual : "[app text]"
|
|
234
|
+
Location : [page section]
|
|
235
|
+
|
|
236
|
+
[F2] 🔴 HIGH — MISSING ELEMENT
|
|
237
|
+
Element : [element name]
|
|
238
|
+
Expected : Present (per Figma)
|
|
239
|
+
Actual : Not found
|
|
240
|
+
Location : [page section]
|
|
241
|
+
|
|
242
|
+
[F3] 🟠 MEDIUM — CSS MISMATCH
|
|
243
|
+
Element : [element]
|
|
244
|
+
Property : [CSS property]
|
|
245
|
+
Expected : [Figma value]
|
|
246
|
+
Actual : [computed value]
|
|
247
|
+
Location : [page section]
|
|
248
|
+
|
|
249
|
+
... (repeat per failure, ordered High → Medium → Low)
|
|
250
|
+
|
|
251
|
+
------------------------------------------------------------
|
|
252
|
+
ℹ️ NOTES
|
|
253
|
+
• Dynamic fields (amounts, dates, IDs) verified for presence only.
|
|
254
|
+
• CSS values extracted via Playwright getComputedStyle().
|
|
255
|
+
• Warnings excluded — reply "include warnings" to add them.
|
|
256
|
+
------------------------------------------------------------
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Do NOT assign the card. Only tag the assignee in the comment.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Playwright MCP Tool Reference
|
|
264
|
+
|
|
265
|
+
| Task | Tool |
|
|
266
|
+
|---|---|
|
|
267
|
+
| Navigate to URL | `browser_navigate(url: "...")` |
|
|
268
|
+
| Wait for page to fully load | `browser_wait_for(state: "networkidle")` |
|
|
269
|
+
| Full-page screenshot | `browser_screenshot()` |
|
|
270
|
+
| DOM + accessibility tree | `browser_snapshot()` |
|
|
271
|
+
| Extract computed CSS | `browser_evaluate(expression: "...")` |
|
|
272
|
+
| Open new tab | `browser_tab_new()` |
|
|
273
|
+
| Switch to tab by index | `browser_tab_select(index: N)` |
|
|
274
|
+
| List open tabs | `browser_tab_list()` |
|
|
275
|
+
| Fill input field | `browser_fill(selector: "...", value: "...")` |
|
|
276
|
+
| Click element | `browser_click(selector: "...")` |
|
|
277
|
+
| Wait for element | `browser_wait_for(selector: "...", state: "visible")` |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Error Handling
|
|
282
|
+
|
|
283
|
+
| Situation | Action |
|
|
284
|
+
|---|---|
|
|
285
|
+
| Figma MCP rate limited / auth error | Immediately use Method B (new browser tab). No pause, no asking user. |
|
|
286
|
+
| Figma URL has no node-id | Ask user: "Right-click the frame in Figma → Copy link to get a link with node-id." |
|
|
287
|
+
| App page redirects to login | Run Step 1 (login) first, then retry navigation. |
|
|
288
|
+
| `browser_navigate` fails | Stop. Tell user: "Playwright MCP could not reach the URL. Check that the MCP server is running and the URL is correct." |
|
|
289
|
+
| `browser_evaluate` returns null | Skip CSS comparison for that element; note it in the report as "CSS not extracted". |
|
|
290
|
+
| Figma canvas doesn't load in 25s | Ask user: "Figma canvas is slow to load. Please confirm the design is accessible, then type 'retry'." |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Severity Guide
|
|
295
|
+
|
|
296
|
+
| Severity | Meaning |
|
|
297
|
+
|---|---|
|
|
298
|
+
| **High** | User-facing text wrong, structural element missing, broken layout |
|
|
299
|
+
| **Medium** | CSS property mismatch, dynamic field empty, minor structural gap |
|
|
300
|
+
| **Low** | Casing difference, punctuation, minor label variation |
|