@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.
@@ -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 |