claude-code-kit 0.7.0__py3-none-any.whl
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.
- claude_code_kit-0.7.0.dist-info/METADATA +384 -0
- claude_code_kit-0.7.0.dist-info/RECORD +209 -0
- claude_code_kit-0.7.0.dist-info/WHEEL +4 -0
- claude_code_kit-0.7.0.dist-info/entry_points.txt +4 -0
- claude_code_kit-0.7.0.dist-info/licenses/LICENSE +21 -0
- claude_kit/__init__.py +10 -0
- claude_kit/__main__.py +8 -0
- claude_kit/_payload/agents/acceptance-reviewer.md +60 -0
- claude_kit/_payload/agents/auditor.md +76 -0
- claude_kit/_payload/agents/dependency-scanner.md +84 -0
- claude_kit/_payload/agents/developer.md +187 -0
- claude_kit/_payload/agents/devils-advocate.md +62 -0
- claude_kit/_payload/agents/devops-engineer.md +134 -0
- claude_kit/_payload/agents/e2e-tester.md +152 -0
- claude_kit/_payload/agents/em-reviewer.md +105 -0
- claude_kit/_payload/agents/incident-responder.md +64 -0
- claude_kit/_payload/agents/merge-reviewer.md +194 -0
- claude_kit/_payload/agents/observability-engineer.md +94 -0
- claude_kit/_payload/agents/orchestrator.md +551 -0
- claude_kit/_payload/agents/owasp-reviewer.md +76 -0
- claude_kit/_payload/agents/policy-validator.md +63 -0
- claude_kit/_payload/agents/pr-raiser.md +138 -0
- claude_kit/_payload/agents/risk-classifier.md +50 -0
- claude_kit/_payload/agents/sdlc-code-reviewer.md +196 -0
- claude_kit/_payload/agents/secret-scanner.md +70 -0
- claude_kit/_payload/agents/security-reviewer.md +80 -0
- claude_kit/_payload/agents/senior-backend-dev.md +199 -0
- claude_kit/_payload/agents/senior-frontend-dev.md +181 -0
- claude_kit/_payload/agents/senior-tester.md +206 -0
- claude_kit/_payload/agents/spec-doc-writer.md +331 -0
- claude_kit/_payload/agents/story-planner.md +56 -0
- claude_kit/_payload/agents/technical-architect.md +139 -0
- claude_kit/_payload/agents/tester.md +193 -0
- claude_kit/_payload/agents/ui-designer.md +73 -0
- claude_kit/_payload/agents/unit-tester.md +119 -0
- claude_kit/_payload/catalog/mcp.yaml +54 -0
- claude_kit/_payload/catalog/org.yaml +145 -0
- claude_kit/_payload/catalog/profiles.yaml +96 -0
- claude_kit/_payload/catalog/stacks.yaml +96 -0
- claude_kit/_payload/commands/init.md +36 -0
- claude_kit/_payload/commands/sdlc.md +18 -0
- claude_kit/_payload/commands/status.md +20 -0
- claude_kit/_payload/hooks/hooks.json +58 -0
- claude_kit/_payload/hooks/scripts/audit-log.sh +18 -0
- claude_kit/_payload/hooks/scripts/guard-secrets.sh +26 -0
- claude_kit/_payload/hooks/scripts/lint-fix.sh +38 -0
- claude_kit/_payload/hooks/scripts/load-continuity.sh +32 -0
- claude_kit/_payload/hooks/scripts/load-learnings.sh +40 -0
- claude_kit/_payload/hooks/scripts/type-check.sh +23 -0
- claude_kit/_payload/hooks/scripts/validate-frontmatter.sh +34 -0
- claude_kit/_payload/hooks/scripts/validate-settings.sh +21 -0
- claude_kit/_payload/hooks/scripts/warn-large-edits.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-missing-tests.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-sensitive-files.sh +30 -0
- claude_kit/_payload/hooks/scripts/warn-shared-modules.sh +33 -0
- claude_kit/_payload/rules/agent-guardrails.md +83 -0
- claude_kit/_payload/rules/agent-memory.md +106 -0
- claude_kit/_payload/rules/agent-resilience.md +61 -0
- claude_kit/_payload/rules/autonomy-levels.md +30 -0
- claude_kit/_payload/rules/code-organization.md +312 -0
- claude_kit/_payload/rules/continuity.md +84 -0
- claude_kit/_payload/rules/design-patterns.md +422 -0
- claude_kit/_payload/rules/devops-observability.md +57 -0
- claude_kit/_payload/rules/documentation.md +326 -0
- claude_kit/_payload/rules/evals.md +62 -0
- claude_kit/_payload/rules/frontend-best-practices.md +157 -0
- claude_kit/_payload/rules/goal-setting-and-monitoring.md +72 -0
- claude_kit/_payload/rules/human-in-the-loop.md +64 -0
- claude_kit/_payload/rules/linting-and-formatting.md +220 -0
- claude_kit/_payload/rules/mandatory-workflow.md +309 -0
- claude_kit/_payload/rules/model-tiers.md +34 -0
- claude_kit/_payload/rules/quality-gates.md +107 -0
- claude_kit/_payload/rules/rarv-cycle.md +31 -0
- claude_kit/_payload/rules/reasoning-techniques.md +62 -0
- claude_kit/_payload/rules/responsive-and-accessibility.md +353 -0
- claude_kit/_payload/rules/risk-classification.md +36 -0
- claude_kit/_payload/rules/testing.md +417 -0
- claude_kit/_payload/rules/tool-design.md +66 -0
- claude_kit/_payload/skills/_references/accessibility-checklist.md +160 -0
- claude_kit/_payload/skills/_references/orchestration-patterns.md +405 -0
- claude_kit/_payload/skills/_references/performance-checklist.md +153 -0
- claude_kit/_payload/skills/_references/security-checklist.md +134 -0
- claude_kit/_payload/skills/_references/testing-patterns.md +236 -0
- claude_kit/_payload/skills/accessibility-review/SKILL.md +56 -0
- claude_kit/_payload/skills/api-and-interface-design/SKILL.md +294 -0
- claude_kit/_payload/skills/api-integration/SKILL.md +348 -0
- claude_kit/_payload/skills/archive-sprint/SKILL.md +31 -0
- claude_kit/_payload/skills/backlog/SKILL.md +41 -0
- claude_kit/_payload/skills/backlog/item-template.md +20 -0
- claude_kit/_payload/skills/browser-testing-with-devtools/SKILL.md +302 -0
- claude_kit/_payload/skills/ci-cd-and-automation/SKILL.md +402 -0
- claude_kit/_payload/skills/code-review-and-quality/SKILL.md +347 -0
- claude_kit/_payload/skills/code-simplification/SKILL.md +331 -0
- claude_kit/_payload/skills/component-design/SKILL.md +171 -0
- claude_kit/_payload/skills/consolidate-learnings/SKILL.md +55 -0
- claude_kit/_payload/skills/context-engineering/SKILL.md +321 -0
- claude_kit/_payload/skills/debugging-and-error-recovery/SKILL.md +300 -0
- claude_kit/_payload/skills/decision/SKILL.md +46 -0
- claude_kit/_payload/skills/decision/adr-template.md +36 -0
- claude_kit/_payload/skills/deprecation-and-migration/SKILL.md +207 -0
- claude_kit/_payload/skills/documentation-and-adrs/SKILL.md +299 -0
- claude_kit/_payload/skills/doubt-driven-development/SKILL.md +243 -0
- claude_kit/_payload/skills/execute/SKILL.md +27 -0
- claude_kit/_payload/skills/frontend-ui-engineering/SKILL.md +328 -0
- claude_kit/_payload/skills/git-workflow-and-versioning/SKILL.md +300 -0
- claude_kit/_payload/skills/idea-refine/SKILL.md +178 -0
- claude_kit/_payload/skills/idea-refine/examples.md +238 -0
- claude_kit/_payload/skills/idea-refine/frameworks.md +99 -0
- claude_kit/_payload/skills/idea-refine/refinement-criteria.md +113 -0
- claude_kit/_payload/skills/idea-refine/scripts/idea-refine.sh +15 -0
- claude_kit/_payload/skills/incident-postmortem/SKILL.md +74 -0
- claude_kit/_payload/skills/incremental-implementation/SKILL.md +245 -0
- claude_kit/_payload/skills/interview-me/SKILL.md +221 -0
- claude_kit/_payload/skills/load-testing/SKILL.md +83 -0
- claude_kit/_payload/skills/manual-test/SKILL.md +516 -0
- claude_kit/_payload/skills/performance-optimization/SKILL.md +277 -0
- claude_kit/_payload/skills/planning-and-task-breakdown/SKILL.md +223 -0
- claude_kit/_payload/skills/playwright-verification/SKILL.md +205 -0
- claude_kit/_payload/skills/refresh-docs/SKILL.md +63 -0
- claude_kit/_payload/skills/remember/SKILL.md +96 -0
- claude_kit/_payload/skills/scope/SKILL.md +52 -0
- claude_kit/_payload/skills/scope/scope-template.md +82 -0
- claude_kit/_payload/skills/sdlc/SKILL.md +83 -0
- claude_kit/_payload/skills/security-and-hardening/SKILL.md +368 -0
- claude_kit/_payload/skills/security-verification/SKILL.md +209 -0
- claude_kit/_payload/skills/shipping-and-launch/SKILL.md +309 -0
- claude_kit/_payload/skills/smoke-test/SKILL.md +78 -0
- claude_kit/_payload/skills/source-driven-development/SKILL.md +195 -0
- claude_kit/_payload/skills/spec-driven-development/SKILL.md +200 -0
- claude_kit/_payload/skills/sprint/SKILL.md +67 -0
- claude_kit/_payload/skills/sprint/sprint-template.md +90 -0
- claude_kit/_payload/skills/test-driven-development/SKILL.md +383 -0
- claude_kit/_payload/skills/threat-model/SKILL.md +60 -0
- claude_kit/_payload/skills/triage/SKILL.md +87 -0
- claude_kit/_payload/skills/ui-ux-design/SKILL.md +71 -0
- claude_kit/_payload/skills/unit-test/SKILL.md +237 -0
- claude_kit/_payload/skills/using-agent-skills/SKILL.md +180 -0
- claude_kit/_payload/templates/CLAUDE.md +238 -0
- claude_kit/_payload/templates/CLAUDE.stack.md.tmpl +53 -0
- claude_kit/_payload/templates/CONTINUITY.template.md +35 -0
- claude_kit/_payload/templates/README.claude-sdlc.md.tmpl +219 -0
- claude_kit/_payload/templates/agent-memory/MEMORY.md +30 -0
- claude_kit/_payload/templates/agent-memory/api/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/architecture/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/debugging/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/gotchas/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/patterns/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/performance/.gitkeep +0 -0
- claude_kit/_payload/templates/artifacts/adr.md +18 -0
- claude_kit/_payload/templates/artifacts/feature-spec.md +29 -0
- claude_kit/_payload/templates/artifacts/release-plan.md +23 -0
- claude_kit/_payload/templates/artifacts/runbook.md +24 -0
- claude_kit/_payload/templates/artifacts/security-review.md +23 -0
- claude_kit/_payload/templates/artifacts/test-plan.md +22 -0
- claude_kit/_payload/templates/org/README.md +53 -0
- claude_kit/_payload/templates/org/agents/data-workflow-agent.md +59 -0
- claude_kit/_payload/templates/org/agents/founder-prototype-agent.md +61 -0
- claude_kit/_payload/templates/org/agents/internal-tools-builder.md +63 -0
- claude_kit/_payload/templates/org/agents/pm-copilot.md +60 -0
- claude_kit/_payload/templates/org/agents/support-ticket-engineer.md +63 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/README.md +46 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/pack.yaml +32 -0
- claude_kit/_payload/templates/org/packs/engineering-core/README.md +46 -0
- claude_kit/_payload/templates/org/packs/engineering-core/pack.yaml +44 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/README.md +53 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/pack.yaml +39 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/README.md +49 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/pack.yaml +26 -0
- claude_kit/_payload/templates/org/packs/product-to-code/README.md +50 -0
- claude_kit/_payload/templates/org/packs/product-to-code/pack.yaml +34 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/README.md +53 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/pack.yaml +40 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/README.md +50 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/pack.yaml +36 -0
- claude_kit/_payload/templates/org/rules/ai-working-agreement.md +45 -0
- claude_kit/_payload/templates/org/rules/ambiguity-resolution.md +36 -0
- claude_kit/_payload/templates/org/rules/branch-and-pr-policy.md +41 -0
- claude_kit/_payload/templates/org/rules/compliance-policy.md +50 -0
- claude_kit/_payload/templates/org/rules/non-engineer-safe-coding.md +37 -0
- claude_kit/_payload/templates/org/rules/pii-policy.md +46 -0
- claude_kit/_payload/templates/org/rules/production-data-policy.md +35 -0
- claude_kit/_payload/templates/org/rules/prompt-to-task-conversion.md +30 -0
- claude_kit/_payload/templates/org/rules/prototype-boundaries.md +40 -0
- claude_kit/_payload/templates/org/rules/secrets-policy.md +34 -0
- claude_kit/_payload/templates/org/skills/customer-issue-to-fix/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/feature-from-idea/SKILL.md +56 -0
- claude_kit/_payload/templates/org/skills/prompt-to-safe-task/SKILL.md +59 -0
- claude_kit/_payload/templates/org/skills/prototype-to-production/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/repo-onboarding/SKILL.md +60 -0
- claude_kit/_payload/templates/settings.json +53 -0
- claude_kit/_payload/templates/stacks/backend/python/fastapi/rules/fastapi-patterns.md +64 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/migration-specialist.md +61 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/mongodb-specialist.md +59 -0
- claude_kit/_payload/templates/stacks/db/mongodb/rules/mongodb-patterns.md +39 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/db-performance-reviewer.md +66 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/migration-specialist.md +56 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/postgres-specialist.md +58 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/database-performance.md +64 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/postgres-patterns.md +43 -0
- claude_kit/_payload/templates/stacks/frontend/react/rules/react-patterns.md +63 -0
- claude_kit/catalog.py +476 -0
- claude_kit/cli.py +327 -0
- claude_kit/hooks.py +246 -0
- claude_kit/models.py +205 -0
- claude_kit/prompts.py +209 -0
- claude_kit/render.py +146 -0
- claude_kit/scaffold.py +492 -0
- claude_kit/upgrader.py +294 -0
- claude_kit/validator.py +197 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: manual-test
|
|
3
|
+
description: Manually test a developed feature using browser automation in headed mode. Navigates to the page, interacts with elements, and verifies behavior visually — like a QA tester sitting at the screen.
|
|
4
|
+
argument-hint: [page route or feature name, e.g. "/store-view", "dashboard filters", "exception card"]
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Manually test the feature: $ARGUMENTS.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
|
|
12
|
+
### 1. Identify what to test
|
|
13
|
+
|
|
14
|
+
Based on `$ARGUMENTS`, determine:
|
|
15
|
+
- Which page/route to navigate to
|
|
16
|
+
- Which UI elements to interact with
|
|
17
|
+
- What behavior to verify (renders, clicks, filters, navigation, edge cases)
|
|
18
|
+
|
|
19
|
+
If `$ARGUMENTS` is vague, ask the user:
|
|
20
|
+
- Which page or component should I test?
|
|
21
|
+
- What specific behavior should I verify?
|
|
22
|
+
- Any particular edge cases to check?
|
|
23
|
+
|
|
24
|
+
### 2. Set up authenticated browser session
|
|
25
|
+
|
|
26
|
+
If the app requires authentication, use the project's E2E framework to create a headed (visible) browser session with auth bypassed or configured.
|
|
27
|
+
|
|
28
|
+
The helper should support **multiple browsers** and **custom viewports** for device simulation. Example pattern (adapt to your project's E2E framework):
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Example using Playwright
|
|
32
|
+
import { test, expect } from '@playwright/test';
|
|
33
|
+
import { chromium, firefox, webkit } from '@playwright/test';
|
|
34
|
+
import type { BrowserType } from '@playwright/test';
|
|
35
|
+
|
|
36
|
+
// Supported browsers
|
|
37
|
+
const BROWSERS = {
|
|
38
|
+
chrome: chromium,
|
|
39
|
+
firefox: firefox,
|
|
40
|
+
safari: webkit,
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
// Device presets — screen sizes for testing
|
|
44
|
+
const DEVICES = {
|
|
45
|
+
// Mobile
|
|
46
|
+
'iphone-se': { width: 375, height: 667, label: 'iPhone SE', isMobile: true },
|
|
47
|
+
'iphone-14': { width: 390, height: 844, label: 'iPhone 14', isMobile: true },
|
|
48
|
+
'iphone-14-pro-max': { width: 430, height: 932, label: 'iPhone 14 Pro Max', isMobile: true },
|
|
49
|
+
'pixel-7': { width: 412, height: 915, label: 'Pixel 7', isMobile: true },
|
|
50
|
+
'samsung-s23': { width: 360, height: 780, label: 'Samsung Galaxy S23', isMobile: true },
|
|
51
|
+
// Tablet
|
|
52
|
+
'ipad': { width: 768, height: 1024, label: 'iPad', isMobile: true },
|
|
53
|
+
'ipad-pro': { width: 1024, height: 1366, label: 'iPad Pro 12.9"', isMobile: true },
|
|
54
|
+
'android-tablet': { width: 800, height: 1280, label: 'Android Tablet', isMobile: true },
|
|
55
|
+
// Desktop
|
|
56
|
+
'laptop': { width: 1366, height: 768, label: 'Laptop (1366x768)', isMobile: false },
|
|
57
|
+
'desktop': { width: 1920, height: 1080, label: 'Desktop (1080p)', isMobile: false },
|
|
58
|
+
'desktop-xl': { width: 2560, height: 1440, label: 'Desktop (1440p)', isMobile: false },
|
|
59
|
+
} as const;
|
|
60
|
+
|
|
61
|
+
type BrowserName = keyof typeof BROWSERS;
|
|
62
|
+
type DeviceName = keyof typeof DEVICES;
|
|
63
|
+
|
|
64
|
+
interface AuthPageOptions {
|
|
65
|
+
browser?: BrowserName; // default: 'chrome'
|
|
66
|
+
device?: DeviceName; // default: 'desktop'
|
|
67
|
+
viewport?: { width: number; height: number }; // custom override
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function createAuthenticatedPage(options: AuthPageOptions = {}) {
|
|
71
|
+
const browserName = options.browser ?? 'chrome';
|
|
72
|
+
const browserType = BROWSERS[browserName];
|
|
73
|
+
const device = options.device ? DEVICES[options.device] : undefined;
|
|
74
|
+
const viewport = options.viewport ?? (device ? { width: device.width, height: device.height } : { width: 1920, height: 1080 });
|
|
75
|
+
|
|
76
|
+
const browser = await browserType.launch({ headless: false });
|
|
77
|
+
const context = await browser.newContext({
|
|
78
|
+
ignoreHTTPSErrors: true,
|
|
79
|
+
viewport,
|
|
80
|
+
isMobile: device?.isMobile ?? false,
|
|
81
|
+
hasTouch: device?.isMobile ?? false,
|
|
82
|
+
userAgent: device?.isMobile
|
|
83
|
+
? 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1'
|
|
84
|
+
: undefined,
|
|
85
|
+
});
|
|
86
|
+
const page = await context.newPage();
|
|
87
|
+
|
|
88
|
+
const deviceLabel = device?.label ?? `${viewport.width}x${viewport.height}`;
|
|
89
|
+
console.log(`Browser: ${browserName} | Device: ${deviceLabel} | Viewport: ${viewport.width}x${viewport.height}`);
|
|
90
|
+
|
|
91
|
+
// Mock authentication or inject session storage
|
|
92
|
+
// Adapt this to your project's auth mechanism
|
|
93
|
+
await page.route('**/api/auth/session**', (route) => {
|
|
94
|
+
route.fulfill({
|
|
95
|
+
status: 200,
|
|
96
|
+
contentType: 'application/json',
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
success: true,
|
|
99
|
+
user: {
|
|
100
|
+
firstName: 'Test', lastName: 'User',
|
|
101
|
+
email: 'test@example.com',
|
|
102
|
+
role: 'admin',
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Navigate to login and inject session state
|
|
109
|
+
await page.goto('http://localhost:3000/login', {
|
|
110
|
+
waitUntil: 'domcontentloaded',
|
|
111
|
+
timeout: 15000,
|
|
112
|
+
});
|
|
113
|
+
await page.evaluate(() => {
|
|
114
|
+
sessionStorage.setItem('auth-state', JSON.stringify({
|
|
115
|
+
isAuthenticated: true,
|
|
116
|
+
user: {
|
|
117
|
+
firstName: 'Test', lastName: 'User',
|
|
118
|
+
email: 'test@example.com',
|
|
119
|
+
role: 'admin',
|
|
120
|
+
},
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return { browser, context, page, browserName, deviceLabel, viewport };
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 3. Write the test file
|
|
129
|
+
|
|
130
|
+
Create the test in the appropriate E2E test directory. Name it `<feature>.manual.spec.ts` or follow your project's naming convention.
|
|
131
|
+
|
|
132
|
+
**Test template:**
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { test, expect } from '@playwright/test';
|
|
136
|
+
|
|
137
|
+
// -- Auth helper with BROWSERS and DEVICES constants (from step 2) --
|
|
138
|
+
|
|
139
|
+
test.describe('<Feature Name> — Manual Test', () => {
|
|
140
|
+
|
|
141
|
+
test('<what you are testing>', async () => {
|
|
142
|
+
const { browser, page } = await createAuthenticatedPage();
|
|
143
|
+
// Or with specific browser/device:
|
|
144
|
+
// const { browser, page } = await createAuthenticatedPage({ browser: 'firefox' });
|
|
145
|
+
// const { browser, page } = await createAuthenticatedPage({ device: 'iphone-14' });
|
|
146
|
+
// const { browser, page } = await createAuthenticatedPage({ browser: 'safari', device: 'ipad' });
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
await page.goto('http://localhost:3000/<route>', {
|
|
150
|
+
waitUntil: 'networkidle',
|
|
151
|
+
timeout: 30000,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await expect(page.locator('main')).toBeVisible({ timeout: 15000 });
|
|
155
|
+
|
|
156
|
+
// ... your test steps here ...
|
|
157
|
+
|
|
158
|
+
} finally {
|
|
159
|
+
await browser.close();
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 4. Build the test based on the feature type
|
|
166
|
+
|
|
167
|
+
Pick the relevant test patterns below and combine them:
|
|
168
|
+
|
|
169
|
+
#### Page load verification
|
|
170
|
+
```typescript
|
|
171
|
+
// Verify page renders with key content
|
|
172
|
+
await page.goto('http://localhost:3000/<route>', {
|
|
173
|
+
waitUntil: 'networkidle', timeout: 30000,
|
|
174
|
+
});
|
|
175
|
+
await expect(page.locator('main')).toBeVisible({ timeout: 15000 });
|
|
176
|
+
await expect(page.getByRole('heading', { name: '<Page Title>' })).toBeVisible();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Click interactions
|
|
180
|
+
```typescript
|
|
181
|
+
// Click a button and verify result
|
|
182
|
+
const button = page.getByRole('button', { name: '<Button Text>' });
|
|
183
|
+
await expect(button).toBeVisible();
|
|
184
|
+
await button.click();
|
|
185
|
+
await expect(page.getByText('<Expected Result>')).toBeVisible();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### Filter / dropdown testing
|
|
189
|
+
```typescript
|
|
190
|
+
// Open a filter dropdown, select option, verify results update
|
|
191
|
+
const filterButton = page.getByRole('button', { name: '<Filter Name>' }).first();
|
|
192
|
+
await filterButton.click();
|
|
193
|
+
await page.waitForTimeout(500);
|
|
194
|
+
const dropdown = page.locator('.dropdown-container');
|
|
195
|
+
await expect(dropdown).toBeVisible();
|
|
196
|
+
|
|
197
|
+
// Count options
|
|
198
|
+
const optionCount = await dropdown.locator('ul li button').count();
|
|
199
|
+
console.log(`Filter options: ${optionCount}`);
|
|
200
|
+
|
|
201
|
+
// Select an option
|
|
202
|
+
const firstOption = dropdown.locator('ul li button').first();
|
|
203
|
+
const optionText = await firstOption.textContent();
|
|
204
|
+
console.log(`Selecting: "${optionText}"`);
|
|
205
|
+
await firstOption.click();
|
|
206
|
+
await page.waitForTimeout(1000);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### Tab switching
|
|
210
|
+
```typescript
|
|
211
|
+
// Click a tab and verify content changes
|
|
212
|
+
const tab = page.getByRole('tab', { name: '<Tab Name>' });
|
|
213
|
+
await tab.click();
|
|
214
|
+
await expect(page.getByRole('tabpanel')).toBeVisible();
|
|
215
|
+
await expect(page.getByText('<Expected Content>')).toBeVisible();
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### Navigation
|
|
219
|
+
```typescript
|
|
220
|
+
// Click a link/card and verify navigation
|
|
221
|
+
await page.click('a[href="/<target-route>"]');
|
|
222
|
+
await expect(page).toHaveURL('/<target-route>');
|
|
223
|
+
await expect(page.locator('main')).toBeVisible();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Table / list verification
|
|
227
|
+
```typescript
|
|
228
|
+
// Verify table renders with data
|
|
229
|
+
const table = page.locator('table');
|
|
230
|
+
await expect(table).toBeVisible();
|
|
231
|
+
const rows = table.locator('tbody tr');
|
|
232
|
+
const rowCount = await rows.count();
|
|
233
|
+
console.log(`Table rows: ${rowCount}`);
|
|
234
|
+
expect(rowCount).toBeGreaterThan(0);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Empty state
|
|
238
|
+
```typescript
|
|
239
|
+
// Verify empty state shows when no data
|
|
240
|
+
await expect(page.getByText(/no.*found/i)).toBeVisible();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### Cross-browser testing (Chrome + Firefox + Safari)
|
|
244
|
+
|
|
245
|
+
**ALWAYS run tests on multiple browsers.** Write a loop that tests the same page on Chrome, Firefox, and Safari:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// Test on all three browsers
|
|
249
|
+
for (const browserName of ['chrome', 'firefox', 'safari'] as const) {
|
|
250
|
+
test(`<Feature> works on ${browserName}`, async () => {
|
|
251
|
+
const { browser, page, deviceLabel } = await createAuthenticatedPage({ browser: browserName });
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
await page.goto('http://localhost:3000/<route>', {
|
|
255
|
+
waitUntil: 'networkidle', timeout: 30000,
|
|
256
|
+
});
|
|
257
|
+
await expect(page.locator('main')).toBeVisible({ timeout: 15000 });
|
|
258
|
+
|
|
259
|
+
// ... your test assertions here ...
|
|
260
|
+
|
|
261
|
+
await page.screenshot({
|
|
262
|
+
path: `e2e/screenshots/<feature>-${browserName}.png`,
|
|
263
|
+
fullPage: true,
|
|
264
|
+
});
|
|
265
|
+
console.log(`[${browserName}] PASSED`);
|
|
266
|
+
} finally {
|
|
267
|
+
await browser.close();
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### Multi-device responsive testing
|
|
274
|
+
|
|
275
|
+
**ALWAYS test on multiple screen sizes.** This runs the same test across mobile phones, tablets, and desktop screens:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Devices to test — covers the critical breakpoints
|
|
279
|
+
const TEST_DEVICES: DeviceName[] = [
|
|
280
|
+
'iphone-se', // 375px — smallest supported mobile
|
|
281
|
+
'iphone-14', // 390px — common iPhone
|
|
282
|
+
'pixel-7', // 412px — common Android
|
|
283
|
+
'ipad', // 768px — tablet breakpoint
|
|
284
|
+
'ipad-pro', // 1024px — large tablet / small laptop
|
|
285
|
+
'laptop', // 1366px — common laptop
|
|
286
|
+
'desktop', // 1920px — full HD desktop
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
for (const deviceName of TEST_DEVICES) {
|
|
290
|
+
test(`<Feature> renders correctly on ${DEVICES[deviceName].label}`, async () => {
|
|
291
|
+
const { browser, page, deviceLabel, viewport } = await createAuthenticatedPage({
|
|
292
|
+
device: deviceName,
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
await page.goto('http://localhost:3000/<route>', {
|
|
297
|
+
waitUntil: 'networkidle', timeout: 30000,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Verify page loads
|
|
301
|
+
await expect(page.locator('main')).toBeVisible({ timeout: 15000 });
|
|
302
|
+
|
|
303
|
+
// Check for horizontal overflow (common mobile bug)
|
|
304
|
+
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
|
|
305
|
+
const windowWidth = await page.evaluate(() => window.innerWidth);
|
|
306
|
+
const hasOverflow = bodyWidth > windowWidth + 1;
|
|
307
|
+
console.log(`[${deviceLabel}] ${viewport.width}x${viewport.height} | Overflow: ${hasOverflow ? 'YES (BUG)' : 'none'}`);
|
|
308
|
+
expect(hasOverflow, `Horizontal overflow detected on ${deviceLabel}`).toBe(false);
|
|
309
|
+
|
|
310
|
+
// Check touch targets on mobile (buttons should be at least 44px)
|
|
311
|
+
if (DEVICES[deviceName].isMobile) {
|
|
312
|
+
const buttons = page.locator('button:visible');
|
|
313
|
+
const buttonCount = await buttons.count();
|
|
314
|
+
for (let i = 0; i < Math.min(buttonCount, 10); i++) {
|
|
315
|
+
const box = await buttons.nth(i).boundingBox();
|
|
316
|
+
if (box && box.height < 44) {
|
|
317
|
+
const text = await buttons.nth(i).textContent();
|
|
318
|
+
console.log(` WARNING: Button "${text?.trim()}" is ${box.height}px tall (min 44px)`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Screenshot for visual comparison
|
|
324
|
+
await page.screenshot({
|
|
325
|
+
path: `e2e/screenshots/<feature>-${deviceName}.png`,
|
|
326
|
+
fullPage: true,
|
|
327
|
+
});
|
|
328
|
+
console.log(`[${deviceLabel}] PASSED — screenshot saved`);
|
|
329
|
+
|
|
330
|
+
} finally {
|
|
331
|
+
await browser.close();
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### Cross-browser + cross-device matrix (full coverage)
|
|
338
|
+
|
|
339
|
+
For critical features, test every browser on every device size:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// Full matrix: 3 browsers x 3 key screen sizes
|
|
343
|
+
const BROWSER_LIST: BrowserName[] = ['chrome', 'firefox', 'safari'];
|
|
344
|
+
const KEY_DEVICES: DeviceName[] = ['iphone-se', 'ipad', 'desktop'];
|
|
345
|
+
|
|
346
|
+
for (const browserName of BROWSER_LIST) {
|
|
347
|
+
for (const deviceName of KEY_DEVICES) {
|
|
348
|
+
test(`<Feature> on ${browserName} @ ${DEVICES[deviceName].label}`, async () => {
|
|
349
|
+
const { browser, page } = await createAuthenticatedPage({
|
|
350
|
+
browser: browserName,
|
|
351
|
+
device: deviceName,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
await page.goto('http://localhost:3000/<route>', {
|
|
356
|
+
waitUntil: 'networkidle', timeout: 30000,
|
|
357
|
+
});
|
|
358
|
+
await expect(page.locator('main')).toBeVisible({ timeout: 15000 });
|
|
359
|
+
|
|
360
|
+
// ... assertions ...
|
|
361
|
+
|
|
362
|
+
await page.screenshot({
|
|
363
|
+
path: `e2e/screenshots/<feature>-${browserName}-${deviceName}.png`,
|
|
364
|
+
fullPage: true,
|
|
365
|
+
});
|
|
366
|
+
console.log(`[${browserName} | ${DEVICES[deviceName].label}] PASSED`);
|
|
367
|
+
} finally {
|
|
368
|
+
await browser.close();
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### Screenshot capture
|
|
376
|
+
```typescript
|
|
377
|
+
// Take a screenshot for visual review
|
|
378
|
+
await page.screenshot({ path: `e2e/screenshots/<feature>-<state>.png`, fullPage: true });
|
|
379
|
+
console.log('Screenshot saved: e2e/screenshots/<feature>-<state>.png');
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 5. Run the test
|
|
383
|
+
|
|
384
|
+
Make sure the dev server is running first, then run the manual test using the project's E2E test runner:
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
# Ensure dev server is running (in a separate terminal or background)
|
|
388
|
+
# Use the project's dev server command (examples: npm run dev, npm start, yarn dev, pnpm dev)
|
|
389
|
+
|
|
390
|
+
# Run the specific manual test in headed mode
|
|
391
|
+
# Adjust command based on your E2E framework (Playwright, Cypress, etc.)
|
|
392
|
+
# Example with Playwright:
|
|
393
|
+
npx playwright test e2e/manual/<feature>.manual.spec.ts --headed --reporter=list
|
|
394
|
+
|
|
395
|
+
# Run all manual tests
|
|
396
|
+
npx playwright test e2e/manual/ --headed --reporter=list
|
|
397
|
+
|
|
398
|
+
# Run with longer timeout for cross-browser matrix tests
|
|
399
|
+
npx playwright test e2e/manual/<feature>.manual.spec.ts --headed --reporter=list --timeout=120000
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Important flags (Playwright example - adapt to your E2E framework):**
|
|
403
|
+
- `--headed` — opens a visible browser window so you can see the test running
|
|
404
|
+
- `--reporter=list` — shows step-by-step output in terminal
|
|
405
|
+
- `--timeout=120000` — increase timeout for multi-browser tests (2 min per test)
|
|
406
|
+
- `--debug` — opens test inspector for step-by-step debugging (optional)
|
|
407
|
+
- `--workers=1` — run tests sequentially (easier to watch headed browser)
|
|
408
|
+
|
|
409
|
+
**Note:** If using Playwright, Firefox and Safari (WebKit) require browser binaries. If not installed:
|
|
410
|
+
```bash
|
|
411
|
+
npx playwright install firefox webkit
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### 6. Report results
|
|
415
|
+
|
|
416
|
+
After running, output a report with browser and device coverage:
|
|
417
|
+
|
|
418
|
+
**If all tests pass:**
|
|
419
|
+
```
|
|
420
|
+
Manual Test Results: <Feature Name>
|
|
421
|
+
Route: /<route>
|
|
422
|
+
Status: PASSED
|
|
423
|
+
|
|
424
|
+
Browser Coverage:
|
|
425
|
+
[PASS] Chrome (Desktop 1920x1080)
|
|
426
|
+
[PASS] Firefox (Desktop 1920x1080)
|
|
427
|
+
[PASS] Safari/WebKit (Desktop 1920x1080)
|
|
428
|
+
|
|
429
|
+
Device Coverage:
|
|
430
|
+
[PASS] iPhone SE (375x667) — no overflow, touch targets OK
|
|
431
|
+
[PASS] iPhone 14 (390x844) — no overflow, touch targets OK
|
|
432
|
+
[PASS] Pixel 7 (412x915) — no overflow, touch targets OK
|
|
433
|
+
[PASS] iPad (768x1024) — no overflow
|
|
434
|
+
[PASS] Laptop (1366x768) — no overflow
|
|
435
|
+
[PASS] Desktop (1920x1080) — no overflow
|
|
436
|
+
|
|
437
|
+
Feature Tests:
|
|
438
|
+
[PASS] Page loads with expected content
|
|
439
|
+
[PASS] <Interaction> works correctly
|
|
440
|
+
[PASS] <Filter/navigation> behaves as expected
|
|
441
|
+
|
|
442
|
+
Screenshots: e2e/screenshots/<feature>-*.png (one per browser/device)
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
**If any test fails:**
|
|
446
|
+
```
|
|
447
|
+
Manual Test Results: <Feature Name>
|
|
448
|
+
Route: /<route>
|
|
449
|
+
Status: FAILED
|
|
450
|
+
|
|
451
|
+
Failures:
|
|
452
|
+
[FAIL] Firefox @ iPad (768x1024)
|
|
453
|
+
Issue: Horizontal overflow detected (body 820px > viewport 768px)
|
|
454
|
+
Screenshot: e2e/screenshots/<feature>-firefox-ipad.png
|
|
455
|
+
|
|
456
|
+
[FAIL] Chrome @ iPhone SE (375x667)
|
|
457
|
+
Issue: Button "Apply Filters" is 32px tall (minimum 44px for touch)
|
|
458
|
+
Screenshot: e2e/screenshots/<feature>-chrome-iphone-se.png
|
|
459
|
+
|
|
460
|
+
Suggested fixes:
|
|
461
|
+
1. Add overflow wrapper on the filter bar container
|
|
462
|
+
2. Increase button minimum height to 44px for touch targets
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Selector Priority
|
|
466
|
+
|
|
467
|
+
Always prefer accessible selectors:
|
|
468
|
+
|
|
469
|
+
| Priority | Selector | Example |
|
|
470
|
+
|----------|----------|---------|
|
|
471
|
+
| 1 | `getByRole` | `page.getByRole('button', { name: 'Apply' })` |
|
|
472
|
+
| 2 | `getByText` | `page.getByText('Total Revenue')` |
|
|
473
|
+
| 3 | `getByLabel` | `page.getByLabel('Search stores')` |
|
|
474
|
+
| 4 | `getByPlaceholder` | `page.getByPlaceholder('Filter by name')` |
|
|
475
|
+
| 5 | `data-testid` | `page.locator('[data-testid="metric-card"]')` |
|
|
476
|
+
| 6 | CSS selector | `page.locator('main')` (last resort) |
|
|
477
|
+
|
|
478
|
+
## Supported Browsers
|
|
479
|
+
|
|
480
|
+
| Key | Browser | Engine | Notes |
|
|
481
|
+
|-----|---------|--------|-------|
|
|
482
|
+
| `chrome` | Google Chrome | Chromium | Default. Most users. |
|
|
483
|
+
| `firefox` | Mozilla Firefox | Gecko | Second most popular. Tests CSS differences. |
|
|
484
|
+
| `safari` | Apple Safari | WebKit | Tests macOS/iOS rendering. |
|
|
485
|
+
|
|
486
|
+
Install missing browsers (Playwright): `npx playwright install firefox webkit`
|
|
487
|
+
|
|
488
|
+
## Supported Devices
|
|
489
|
+
|
|
490
|
+
| Key | Device | Size | Type |
|
|
491
|
+
|-----|--------|------|------|
|
|
492
|
+
| `iphone-se` | iPhone SE | 375x667 | Mobile (smallest supported) |
|
|
493
|
+
| `iphone-14` | iPhone 14 | 390x844 | Mobile |
|
|
494
|
+
| `iphone-14-pro-max` | iPhone 14 Pro Max | 430x932 | Mobile (largest iPhone) |
|
|
495
|
+
| `pixel-7` | Pixel 7 | 412x915 | Mobile (Android) |
|
|
496
|
+
| `samsung-s23` | Samsung Galaxy S23 | 360x780 | Mobile (Android) |
|
|
497
|
+
| `ipad` | iPad | 768x1024 | Tablet |
|
|
498
|
+
| `ipad-pro` | iPad Pro 12.9" | 1024x1366 | Tablet (large) |
|
|
499
|
+
| `android-tablet` | Android Tablet | 800x1280 | Tablet (Android) |
|
|
500
|
+
| `laptop` | Laptop | 1366x768 | Desktop (common) |
|
|
501
|
+
| `desktop` | Desktop 1080p | 1920x1080 | Desktop (default) |
|
|
502
|
+
| `desktop-xl` | Desktop 1440p | 2560x1440 | Desktop (large) |
|
|
503
|
+
|
|
504
|
+
**Minimum test coverage:** Every feature MUST be tested on at least `iphone-se` (375px), `ipad` (768px), and `desktop` (1920px).
|
|
505
|
+
|
|
506
|
+
## Tips
|
|
507
|
+
|
|
508
|
+
- Use `await page.waitForTimeout(500)` after clicks to let dropdowns/animations settle
|
|
509
|
+
- Use `await page.waitForSelector('<selector>')` instead of arbitrary timeouts when possible
|
|
510
|
+
- Use `console.log()` generously — the output shows in the terminal during test runs
|
|
511
|
+
- Use `page.pause()` to freeze the test and inspect the page manually in the browser
|
|
512
|
+
- Take screenshots at key steps for visual evidence
|
|
513
|
+
- Always close the browser in a `finally` block to prevent orphaned processes
|
|
514
|
+
- Run with `--workers=1` when using `--headed` to watch one browser at a time
|
|
515
|
+
- For cross-browser matrix tests, increase timeout appropriately
|
|
516
|
+
- Mobile tests automatically set `isMobile: true` and `hasTouch: true` for realistic simulation
|