claude-mpm 5.4.55__py3-none-any.whl → 5.4.85__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_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +63 -241
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +36 -9
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/skills.py +166 -14
- claude_mpm/cli/executor.py +1 -0
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +5 -0
- claude_mpm/cli/startup.py +223 -388
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/output_style_manager.py +21 -13
- claude_mpm/core/unified_config.py +50 -8
- claude_mpm/core/unified_paths.py +30 -13
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +7 -4
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/pm_skills_deployer.py +4 -0
- claude_mpm/services/skills/git_skill_source_manager.py +24 -8
- claude_mpm/services/skills/selective_skill_deployer.py +82 -83
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/METADATA +47 -23
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/RECORD +159 -47
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.55.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: webapp-testing
|
|
3
|
+
version: 2.0.0
|
|
4
|
+
category: testing
|
|
5
|
+
description: Automated webapp testing with Playwright. Server management, UI testing, visual debugging, and reconnaissance-first approach.
|
|
6
|
+
license: Complete terms in LICENSE.txt
|
|
7
|
+
progressive_disclosure:
|
|
8
|
+
entry_point:
|
|
9
|
+
summary: "Reconnaissance before action: verify server state and page load before testing"
|
|
10
|
+
when_to_use: "When testing web applications with Playwright. Server verification, UI testing, frontend debugging."
|
|
11
|
+
quick_start: "1. Check server with lsof 2. Start with with_server.py 3. Wait for networkidle 4. Screenshot and verify"
|
|
12
|
+
references:
|
|
13
|
+
- playwright-patterns.md
|
|
14
|
+
- server-management.md
|
|
15
|
+
- reconnaissance-pattern.md
|
|
16
|
+
- decision-tree.md
|
|
17
|
+
- troubleshooting.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Webapp Testing
|
|
21
|
+
|
|
22
|
+
## Overview
|
|
23
|
+
|
|
24
|
+
**Core Principle: Reconnaissance Before Action**
|
|
25
|
+
|
|
26
|
+
Automated webapp testing using Playwright with a focus on verifying system state (server status, page load, element presence) before taking any action. This ensures reliable, debuggable tests that fail for clear reasons.
|
|
27
|
+
|
|
28
|
+
**Key capabilities:**
|
|
29
|
+
- Automated browser testing with Playwright
|
|
30
|
+
- Server lifecycle management
|
|
31
|
+
- Visual reconnaissance (screenshots, DOM inspection)
|
|
32
|
+
- Network monitoring and debugging
|
|
33
|
+
|
|
34
|
+
## When to Use This Skill
|
|
35
|
+
|
|
36
|
+
- **Web application testing** - UI behavior, forms, navigation, integration testing
|
|
37
|
+
- **Frontend debugging** - Screenshots, DOM inspection, console monitoring
|
|
38
|
+
- **Regression testing** - Ensure changes don't break existing functionality
|
|
39
|
+
- **Server verification** - Check servers are running and responding
|
|
40
|
+
|
|
41
|
+
**Not suitable for:** Unit testing (use Jest/pytest), load testing, or API-only testing.
|
|
42
|
+
|
|
43
|
+
## The Iron Law
|
|
44
|
+
|
|
45
|
+
**RECONNAISSANCE BEFORE ACTION**
|
|
46
|
+
|
|
47
|
+
Never execute test actions without first:
|
|
48
|
+
1. **Verify server state** - `lsof -i :PORT` and `curl` checks
|
|
49
|
+
2. **Wait for page ready** - `page.wait_for_load_state('networkidle')`
|
|
50
|
+
3. **Visual confirmation** - Screenshot before actions
|
|
51
|
+
4. **Read complete output** - Examine full results before claiming success
|
|
52
|
+
|
|
53
|
+
**Why:** Tests fail mysteriously when servers aren't ready, selectors break when DOM is still building, and 5 seconds of reconnaissance saves 30 minutes of debugging.
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
### Step 1: Verify Server State
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
lsof -i :3000 -sTCP:LISTEN # Check server listening
|
|
61
|
+
curl -f http://localhost:3000/health # Test response
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 2: Start Server (If Needed)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Single server
|
|
68
|
+
python scripts/with_server.py --server "npm run dev" --port 5173 -- python test.py
|
|
69
|
+
|
|
70
|
+
# Multiple servers (backend + frontend)
|
|
71
|
+
python scripts/with_server.py \
|
|
72
|
+
--server "cd backend && python server.py" --port 3000 \
|
|
73
|
+
--server "cd frontend && npm run dev" --port 5173 \
|
|
74
|
+
-- python test.py
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Step 3: Write Test with Reconnaissance
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from playwright.sync_api import sync_playwright
|
|
81
|
+
|
|
82
|
+
with sync_playwright() as p:
|
|
83
|
+
browser = p.chromium.launch(headless=True)
|
|
84
|
+
page = browser.new_page()
|
|
85
|
+
|
|
86
|
+
# 1. Navigate and wait
|
|
87
|
+
page.goto('http://localhost:5173')
|
|
88
|
+
page.wait_for_load_state('networkidle') # CRITICAL
|
|
89
|
+
|
|
90
|
+
# 2. Reconnaissance
|
|
91
|
+
page.screenshot(path='/tmp/before.png', full_page=True)
|
|
92
|
+
buttons = page.locator('button').all()
|
|
93
|
+
print(f"Found {len(buttons)} buttons")
|
|
94
|
+
|
|
95
|
+
# 3. Execute
|
|
96
|
+
page.click('button.submit')
|
|
97
|
+
|
|
98
|
+
# 4. Verify
|
|
99
|
+
page.wait_for_selector('.success-message')
|
|
100
|
+
page.screenshot(path='/tmp/after.png', full_page=True)
|
|
101
|
+
|
|
102
|
+
browser.close()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Step 4: Verify Results
|
|
106
|
+
|
|
107
|
+
Review console output, check for errors, verify state changes, examine screenshots.
|
|
108
|
+
|
|
109
|
+
## Key Patterns
|
|
110
|
+
|
|
111
|
+
**Server Management** - Check → Start → Wait → Test → Cleanup
|
|
112
|
+
- Use `with_server.py` for automatic lifecycle management
|
|
113
|
+
- Check status with `lsof`, test with `curl`
|
|
114
|
+
- Automatic cleanup on exit
|
|
115
|
+
|
|
116
|
+
**Reconnaissance** - Inspect → Understand → Act → Verify
|
|
117
|
+
- Screenshot current state
|
|
118
|
+
- Inspect DOM for elements
|
|
119
|
+
- Act on discovered selectors
|
|
120
|
+
- Verify results visually
|
|
121
|
+
|
|
122
|
+
**Wait Strategy** - Load → Idle → Element → Action
|
|
123
|
+
- Always wait for `networkidle` on dynamic apps
|
|
124
|
+
- Wait for specific elements before interaction
|
|
125
|
+
- Playwright auto-waits but explicit waits prevent race conditions
|
|
126
|
+
|
|
127
|
+
**Selector Priority** - data-testid > role > text > CSS > XPath
|
|
128
|
+
- `[data-testid="submit"]` - most stable
|
|
129
|
+
- `role=button[name="Submit"]` - semantic
|
|
130
|
+
- `text=Submit` - readable
|
|
131
|
+
- `button.submit` - acceptable
|
|
132
|
+
- XPath - last resort
|
|
133
|
+
|
|
134
|
+
## Common Pitfalls
|
|
135
|
+
|
|
136
|
+
❌ **Testing without server verification** - Always check `lsof` and `curl` first
|
|
137
|
+
❌ **Ignoring timeout errors** - TimeoutError means something is wrong, investigate
|
|
138
|
+
❌ **Not waiting for networkidle** - Dynamic apps need full page load
|
|
139
|
+
❌ **Poor selector strategies** - Use data-testid for stability
|
|
140
|
+
❌ **Missing network verification** - Check API responses complete
|
|
141
|
+
❌ **Incomplete cleanup** - Close browsers, stop servers properly
|
|
142
|
+
|
|
143
|
+
## Reference Documentation
|
|
144
|
+
|
|
145
|
+
**[playwright-patterns.md](playwright-patterns.md)** - Complete Playwright reference
|
|
146
|
+
Selectors, waits, interactions, assertions, test organization, network interception, screenshots, debugging
|
|
147
|
+
|
|
148
|
+
**[server-management.md](server-management.md)** - Server lifecycle and operations
|
|
149
|
+
with_server.py usage, manual management, port management, process control, environment config, health checks
|
|
150
|
+
|
|
151
|
+
**[reconnaissance-pattern.md](reconnaissance-pattern.md)** - Philosophy and practice
|
|
152
|
+
Why reconnaissance first, complete process, server checks, network diagnostics, DOM inspection, log analysis
|
|
153
|
+
|
|
154
|
+
**[decision-tree.md](decision-tree.md)** - Flowcharts for every scenario
|
|
155
|
+
New test decisions, server state paths, test failure diagnosis, debugging flows, selector/wait strategies
|
|
156
|
+
|
|
157
|
+
**[troubleshooting.md](troubleshooting.md)** - Solutions to common problems
|
|
158
|
+
Timeout issues, selector problems, server crashes, network errors, environment config, debugging workflow
|
|
159
|
+
|
|
160
|
+
## Examples and Scripts
|
|
161
|
+
|
|
162
|
+
**Examples** (`examples/` directory):
|
|
163
|
+
- `element_discovery.py` - Discovering page elements
|
|
164
|
+
- `static_html_automation.py` - Testing local HTML files
|
|
165
|
+
- `console_logging.py` - Capturing console output
|
|
166
|
+
|
|
167
|
+
**Scripts** (`scripts/` directory):
|
|
168
|
+
- `with_server.py` - Server lifecycle management (run with `--help` first)
|
|
169
|
+
|
|
170
|
+
## Integration with Other Skills
|
|
171
|
+
|
|
172
|
+
**Mandatory:** verification-before-completion
|
|
173
|
+
**Recommended:** systematic-debugging, test-driven-development
|
|
174
|
+
**Related:** playwright-testing, selenium-automation
|
|
175
|
+
|
|
176
|
+
## Bottom Line
|
|
177
|
+
|
|
178
|
+
1. **Reconnaissance always comes first** - Verify before acting
|
|
179
|
+
2. **Never skip server checks** - 5 seconds saves 30 minutes
|
|
180
|
+
3. **Wait for networkidle** - Dynamic apps need time
|
|
181
|
+
4. **Read complete output** - Verify before claiming success
|
|
182
|
+
5. **Screenshot everything** - Visual evidence is invaluable
|
|
183
|
+
|
|
184
|
+
The reconnaissance-then-action pattern is not optional - it's the foundation of reliable webapp testing.
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
# Decision Tree Reference
|
|
2
|
+
|
|
3
|
+
Complete flowcharts and decision guides for webapp testing scenarios.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Start Here: New Test Decision Tree](#start-here-new-test-decision-tree)
|
|
8
|
+
- [Server State Decision Tree](#server-state-decision-tree)
|
|
9
|
+
- [Test Failure Decision Tree](#test-failure-decision-tree)
|
|
10
|
+
- [Debugging Decision Tree](#debugging-decision-tree)
|
|
11
|
+
- [Selector Strategy Decision Tree](#selector-strategy-decision-tree)
|
|
12
|
+
- [Wait Strategy Decision Tree](#wait-strategy-decision-tree)
|
|
13
|
+
- [Environment Selection Decision Tree](#environment-selection-decision-tree)
|
|
14
|
+
- [Testing Approach Decision Tree](#testing-approach-decision-tree)
|
|
15
|
+
|
|
16
|
+
## Start Here: New Test Decision Tree
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
User requests webapp testing
|
|
20
|
+
↓
|
|
21
|
+
Is it a local webapp?
|
|
22
|
+
├─ No → Ask for deployment URL
|
|
23
|
+
│ ├─ Public URL → Test directly with Playwright
|
|
24
|
+
│ └─ Private URL → Configure authentication first
|
|
25
|
+
│
|
|
26
|
+
└─ Yes → What type of webapp?
|
|
27
|
+
├─ Static HTML file
|
|
28
|
+
│ ├─ Read HTML source directly
|
|
29
|
+
│ │ ├─ Can identify selectors? → Write test
|
|
30
|
+
│ │ └─ Need to see rendered? → Use file:// URL
|
|
31
|
+
│ └─ Write Playwright script with file:// URL
|
|
32
|
+
│
|
|
33
|
+
├─ Dynamic webapp (React, Vue, Angular, etc.)
|
|
34
|
+
│ └─ Is server already running?
|
|
35
|
+
│ ├─ Yes → Check server status
|
|
36
|
+
│ │ ├─ lsof -i :PORT shows LISTEN
|
|
37
|
+
│ │ │ └─ curl http://localhost:PORT succeeds
|
|
38
|
+
│ │ │ └─ Write Playwright test
|
|
39
|
+
│ │ └─ Server not responding
|
|
40
|
+
│ │ └─ Restart server
|
|
41
|
+
│ │
|
|
42
|
+
│ └─ No → Need to start server
|
|
43
|
+
│ ├─ Single server
|
|
44
|
+
│ │ └─ Use with_server.py:
|
|
45
|
+
│ │ python scripts/with_server.py \
|
|
46
|
+
│ │ --server "npm start" --port 3000 \
|
|
47
|
+
│ │ -- python test.py
|
|
48
|
+
│ │
|
|
49
|
+
│ └─ Multiple servers (backend + frontend)
|
|
50
|
+
│ └─ Use with_server.py with multiple --server flags:
|
|
51
|
+
│ python scripts/with_server.py \
|
|
52
|
+
│ --server "cd backend && npm start" --port 4000 \
|
|
53
|
+
│ --server "cd frontend && npm start" --port 3000 \
|
|
54
|
+
│ -- python test.py
|
|
55
|
+
│
|
|
56
|
+
└─ Server-side rendered (Django, Flask, Rails, etc.)
|
|
57
|
+
└─ Follow dynamic webapp path above
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Server State Decision Tree
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
Need to test webapp
|
|
64
|
+
↓
|
|
65
|
+
Check if server is running
|
|
66
|
+
└─ lsof -i :PORT -sTCP:LISTEN
|
|
67
|
+
├─ No output (server not running)
|
|
68
|
+
│ └─ Need to start server
|
|
69
|
+
│ ├─ Know server command?
|
|
70
|
+
│ │ ├─ Yes → Use with_server.py
|
|
71
|
+
│ │ └─ No → Check package.json or README
|
|
72
|
+
│ │ ├─ Found start command
|
|
73
|
+
│ │ │ └─ Use with_server.py
|
|
74
|
+
│ │ └─ Can't find command
|
|
75
|
+
│ │ └─ Ask user for startup instructions
|
|
76
|
+
│ │
|
|
77
|
+
│ └─ Port conflict?
|
|
78
|
+
│ ├─ Check: lsof -i :PORT (without LISTEN filter)
|
|
79
|
+
│ │ └─ Shows process using port
|
|
80
|
+
│ │ ├─ Different app using port
|
|
81
|
+
│ │ │ └─ Kill: lsof -t -i :PORT | xargs kill
|
|
82
|
+
│ │ └─ Old instance of same app
|
|
83
|
+
│ │ └─ Kill and restart
|
|
84
|
+
│ └─ Port available
|
|
85
|
+
│ └─ Start server on this port
|
|
86
|
+
│
|
|
87
|
+
└─ Shows server (server running)
|
|
88
|
+
└─ Test HTTP response
|
|
89
|
+
└─ curl -f http://localhost:PORT/health
|
|
90
|
+
├─ Success (200 OK)
|
|
91
|
+
│ └─ Server is healthy
|
|
92
|
+
│ └─ Proceed with testing
|
|
93
|
+
│
|
|
94
|
+
├─ Connection refused
|
|
95
|
+
│ └─ Process running but not accepting connections
|
|
96
|
+
│ ├─ Check logs: tail -f server.log
|
|
97
|
+
│ ├─ Check if still starting up
|
|
98
|
+
│ │ └─ Wait 10-30 seconds and retry
|
|
99
|
+
│ └─ Server may have crashed during startup
|
|
100
|
+
│ └─ Restart server
|
|
101
|
+
│
|
|
102
|
+
├─ Timeout
|
|
103
|
+
│ └─ Server responding slowly
|
|
104
|
+
│ ├─ Check server resource usage
|
|
105
|
+
│ │ └─ ps -p PID -o %cpu,%mem
|
|
106
|
+
│ ├─ High CPU/memory?
|
|
107
|
+
│ │ └─ Server may be overloaded
|
|
108
|
+
│ └─ Increase timeout or wait longer
|
|
109
|
+
│
|
|
110
|
+
└─ 404 or other error
|
|
111
|
+
└─ Server running but endpoint doesn't exist
|
|
112
|
+
├─ Try root: curl http://localhost:PORT/
|
|
113
|
+
└─ Check server routes/endpoints
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Test Failure Decision Tree
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Playwright test failed
|
|
120
|
+
↓
|
|
121
|
+
What type of error?
|
|
122
|
+
├─ TimeoutError: Timeout 30000ms exceeded
|
|
123
|
+
│ └─ What was timing out?
|
|
124
|
+
│ ├─ page.goto() timeout
|
|
125
|
+
│ │ └─ Server issues
|
|
126
|
+
│ │ ├─ Check server is running
|
|
127
|
+
│ │ ├─ Check server response time: curl -w "Time: %{time_total}s\n"
|
|
128
|
+
│ │ ├─ Increase timeout: goto(url, timeout=60000)
|
|
129
|
+
│ │ └─ Check network connectivity
|
|
130
|
+
│ │
|
|
131
|
+
│ ├─ wait_for_selector() timeout
|
|
132
|
+
│ │ └─ Element not appearing
|
|
133
|
+
│ │ ├─ Did you wait for networkidle first?
|
|
134
|
+
│ │ │ └─ No → Add page.wait_for_load_state('networkidle')
|
|
135
|
+
│ │ ├─ Take screenshot to see actual state
|
|
136
|
+
│ │ │ └─ page.screenshot(path='/tmp/debug.png', full_page=True)
|
|
137
|
+
│ │ ├─ Is selector correct?
|
|
138
|
+
│ │ │ └─ Inspect DOM: page.content()
|
|
139
|
+
│ │ └─ Is element conditionally rendered?
|
|
140
|
+
│ │ └─ Check application state
|
|
141
|
+
│ │
|
|
142
|
+
│ ├─ page.click() timeout
|
|
143
|
+
│ │ └─ Element not clickable
|
|
144
|
+
│ │ ├─ Element not visible?
|
|
145
|
+
│ │ │ └─ Check: page.locator(selector).is_visible()
|
|
146
|
+
│ │ ├─ Element disabled?
|
|
147
|
+
│ │ │ └─ Check: page.locator(selector).is_enabled()
|
|
148
|
+
│ │ ├─ Element obscured by another element?
|
|
149
|
+
│ │ │ └─ Try: page.click(selector, force=True)
|
|
150
|
+
│ │ └─ Selector matches multiple elements?
|
|
151
|
+
│ │ └─ Make selector more specific
|
|
152
|
+
│ │
|
|
153
|
+
│ └─ wait_for_load_state() timeout
|
|
154
|
+
│ └─ Page never reaches networkidle
|
|
155
|
+
│ ├─ Polling API?
|
|
156
|
+
│ │ └─ Use 'load' instead of 'networkidle'
|
|
157
|
+
│ ├─ WebSocket connection?
|
|
158
|
+
│ │ └─ Use 'load' instead of 'networkidle'
|
|
159
|
+
│ └─ Long-running requests?
|
|
160
|
+
│ └─ Wait for specific element instead
|
|
161
|
+
│
|
|
162
|
+
├─ Error: Element not found
|
|
163
|
+
│ └─ Selector doesn't match
|
|
164
|
+
│ ├─ Wrong selector syntax?
|
|
165
|
+
│ │ ├─ text= for text content
|
|
166
|
+
│ │ ├─ role= for ARIA roles
|
|
167
|
+
│ │ ├─ CSS selector for classes/IDs
|
|
168
|
+
│ │ └─ xpath= for XPath
|
|
169
|
+
│ ├─ Element doesn't exist?
|
|
170
|
+
│ │ └─ Inspect DOM: page.content()
|
|
171
|
+
│ ├─ Element inside iframe?
|
|
172
|
+
│ │ └─ Use: page.frame_locator('iframe').locator(selector)
|
|
173
|
+
│ └─ Element created dynamically?
|
|
174
|
+
│ └─ Wait for element first: page.wait_for_selector(selector)
|
|
175
|
+
│
|
|
176
|
+
├─ Error: Element is not visible
|
|
177
|
+
│ └─ Element exists but not visible
|
|
178
|
+
│ ├─ Display: none or visibility: hidden?
|
|
179
|
+
│ │ └─ Check CSS properties
|
|
180
|
+
│ ├─ Outside viewport?
|
|
181
|
+
│ │ └─ Scroll to element: page.locator(selector).scroll_into_view_if_needed()
|
|
182
|
+
│ ├─ Hidden by parent?
|
|
183
|
+
│ │ └─ Check parent visibility
|
|
184
|
+
│ └─ Animation in progress?
|
|
185
|
+
│ └─ Wait for animation: page.wait_for_timeout(500)
|
|
186
|
+
│
|
|
187
|
+
├─ Error: Element is not enabled
|
|
188
|
+
│ └─ Button/input disabled
|
|
189
|
+
│ ├─ Check application state
|
|
190
|
+
│ │ └─ What conditions enable this element?
|
|
191
|
+
│ ├─ Need to fill other fields first?
|
|
192
|
+
│ │ └─ Complete prerequisite steps
|
|
193
|
+
│ └─ Network request must complete first?
|
|
194
|
+
│ └─ Wait for API response
|
|
195
|
+
│
|
|
196
|
+
├─ Error: Connection refused / ECONNREFUSED
|
|
197
|
+
│ └─ Server not accessible
|
|
198
|
+
│ └─ Follow Server State Decision Tree above
|
|
199
|
+
│
|
|
200
|
+
├─ JavaScript error in console
|
|
201
|
+
│ └─ Application error
|
|
202
|
+
│ ├─ Capture console logs
|
|
203
|
+
│ │ └─ page.on("console", lambda msg: print(msg.text))
|
|
204
|
+
│ ├─ Check browser console in headed mode
|
|
205
|
+
│ │ └─ launch(headless=False)
|
|
206
|
+
│ └─ Review application code
|
|
207
|
+
│
|
|
208
|
+
└─ Test assertion failed
|
|
209
|
+
└─ Unexpected state
|
|
210
|
+
├─ Take screenshot: page.screenshot(path='/tmp/actual.png')
|
|
211
|
+
├─ Compare with expected state
|
|
212
|
+
├─ Check console for errors
|
|
213
|
+
└─ Review test logic
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Debugging Decision Tree
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Test is failing, need to debug
|
|
220
|
+
↓
|
|
221
|
+
Start with reconnaissance
|
|
222
|
+
├─ Server reconnaissance
|
|
223
|
+
│ ├─ lsof -i :PORT -sTCP:LISTEN
|
|
224
|
+
│ ├─ curl http://localhost:PORT/health
|
|
225
|
+
│ └─ tail -f server.log
|
|
226
|
+
│
|
|
227
|
+
├─ Visual reconnaissance
|
|
228
|
+
│ ├─ page.screenshot(path='/tmp/debug.png', full_page=True)
|
|
229
|
+
│ └─ Open screenshot to see actual state
|
|
230
|
+
│
|
|
231
|
+
├─ DOM reconnaissance
|
|
232
|
+
│ ├─ content = page.content()
|
|
233
|
+
│ ├─ print(content[:500])
|
|
234
|
+
│ └─ Search for expected elements
|
|
235
|
+
│
|
|
236
|
+
└─ Console reconnaissance
|
|
237
|
+
├─ page.on("console", handler)
|
|
238
|
+
└─ Check for JavaScript errors
|
|
239
|
+
↓
|
|
240
|
+
Analyze reconnaissance data
|
|
241
|
+
├─ Server not running?
|
|
242
|
+
│ └─ Follow Server State Decision Tree
|
|
243
|
+
│
|
|
244
|
+
├─ Page not loaded correctly?
|
|
245
|
+
│ ├─ Screenshot shows blank page
|
|
246
|
+
│ │ ├─ Network issue?
|
|
247
|
+
│ │ ├─ Server returned error?
|
|
248
|
+
│ │ └─ Wrong URL?
|
|
249
|
+
│ ├─ Screenshot shows loading spinner
|
|
250
|
+
│ │ ├─ Wait longer: wait_for_load_state('networkidle')
|
|
251
|
+
│ │ └─ Check for blocking requests
|
|
252
|
+
│ └─ Screenshot shows error page
|
|
253
|
+
│ └─ Check server logs for errors
|
|
254
|
+
│
|
|
255
|
+
├─ Element not found?
|
|
256
|
+
│ ├─ Search DOM content for element
|
|
257
|
+
│ │ ├─ Not in DOM → Wait longer or check conditions
|
|
258
|
+
│ │ └─ In DOM → Selector is wrong
|
|
259
|
+
│ └─ Highlight element to verify
|
|
260
|
+
│ └─ page.locator(selector).evaluate('el => el.style.border = "3px solid red"')
|
|
261
|
+
│
|
|
262
|
+
├─ Console errors?
|
|
263
|
+
│ ├─ JavaScript syntax error
|
|
264
|
+
│ │ └─ Application bug
|
|
265
|
+
│ ├─ Network request failed
|
|
266
|
+
│ │ └─ API server issue
|
|
267
|
+
│ └─ React/Vue error
|
|
268
|
+
│ └─ Component issue
|
|
269
|
+
│
|
|
270
|
+
└─ Still unclear?
|
|
271
|
+
└─ Progressive debugging
|
|
272
|
+
├─ Run in headed mode: launch(headless=False)
|
|
273
|
+
├─ Add slow motion: launch(slow_mo=1000)
|
|
274
|
+
├─ Add pause: page.pause()
|
|
275
|
+
└─ Enable verbose logging: DEBUG=pw:api python test.py
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Selector Strategy Decision Tree
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
Need to select an element
|
|
282
|
+
↓
|
|
283
|
+
What do you know about the element?
|
|
284
|
+
├─ Has data-testid attribute?
|
|
285
|
+
│ └─ USE: page.click('[data-testid="submit"]')
|
|
286
|
+
│ → Most stable, won't break with UI changes
|
|
287
|
+
│
|
|
288
|
+
├─ Has unique text content?
|
|
289
|
+
│ └─ USE: page.click('text=Submit Form')
|
|
290
|
+
│ → Readable, but text may change
|
|
291
|
+
│ ├─ Exact match: 'text="Submit"'
|
|
292
|
+
│ └─ Regex: 'text=/submit/i'
|
|
293
|
+
│
|
|
294
|
+
├─ Has semantic role?
|
|
295
|
+
│ └─ USE: page.click('role=button[name="Submit"]')
|
|
296
|
+
│ → Accessible, semantic, stable
|
|
297
|
+
│ ├─ Common roles: button, link, textbox, checkbox
|
|
298
|
+
│ └─ With name: role=button[name="Submit"]
|
|
299
|
+
│
|
|
300
|
+
├─ Has unique ID?
|
|
301
|
+
│ └─ USE: page.click('#submit-button')
|
|
302
|
+
│ → Fast, stable if ID doesn't change
|
|
303
|
+
│ └─ Avoid dynamically generated IDs
|
|
304
|
+
│
|
|
305
|
+
├─ Has unique class?
|
|
306
|
+
│ └─ USE: page.click('.submit-button')
|
|
307
|
+
│ → May break with CSS refactoring
|
|
308
|
+
│ └─ Combine with tag: 'button.submit'
|
|
309
|
+
│
|
|
310
|
+
├─ Need complex selection?
|
|
311
|
+
│ └─ USE: CSS combinators
|
|
312
|
+
│ ├─ Child: 'form > button'
|
|
313
|
+
│ ├─ Descendant: 'form button'
|
|
314
|
+
│ ├─ Sibling: '.label + input'
|
|
315
|
+
│ └─ Nth child: 'button:nth-child(2)'
|
|
316
|
+
│
|
|
317
|
+
├─ Nothing else works?
|
|
318
|
+
│ └─ USE: XPath (last resort)
|
|
319
|
+
│ └─ 'xpath=//button[contains(text(), "Submit")]'
|
|
320
|
+
│
|
|
321
|
+
└─ Multiple matches?
|
|
322
|
+
└─ Make selector more specific
|
|
323
|
+
├─ Chain: page.locator('form').locator('button.submit')
|
|
324
|
+
├─ Combine: 'button.submit[type="submit"]'
|
|
325
|
+
└─ Use parent context: 'div.modal >> button.submit'
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Wait Strategy Decision Tree
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
Need to wait for something
|
|
332
|
+
↓
|
|
333
|
+
What are you waiting for?
|
|
334
|
+
├─ Page to load
|
|
335
|
+
│ └─ What type of page?
|
|
336
|
+
│ ├─ Dynamic (React, Vue, Angular)
|
|
337
|
+
│ │ └─ USE: page.wait_for_load_state('networkidle')
|
|
338
|
+
│ │ → Waits for network requests to finish
|
|
339
|
+
│ ├─ Static with images
|
|
340
|
+
│ │ └─ USE: page.wait_for_load_state('load')
|
|
341
|
+
│ │ → Waits for all resources
|
|
342
|
+
│ └─ Server-side rendered
|
|
343
|
+
│ └─ USE: page.wait_for_load_state('domcontentloaded')
|
|
344
|
+
│ → Waits for HTML to parse
|
|
345
|
+
│
|
|
346
|
+
├─ Specific element
|
|
347
|
+
│ └─ What state?
|
|
348
|
+
│ ├─ Element to appear
|
|
349
|
+
│ │ └─ USE: page.wait_for_selector('.modal', state='visible')
|
|
350
|
+
│ ├─ Element to disappear
|
|
351
|
+
│ │ └─ USE: page.wait_for_selector('.loading', state='hidden')
|
|
352
|
+
│ ├─ Element to exist in DOM
|
|
353
|
+
│ │ └─ USE: page.wait_for_selector('.data', state='attached')
|
|
354
|
+
│ └─ Element to be removed from DOM
|
|
355
|
+
│ └─ USE: page.wait_for_selector('.temp', state='detached')
|
|
356
|
+
│
|
|
357
|
+
├─ Network request
|
|
358
|
+
│ └─ Specific API call
|
|
359
|
+
│ ├─ Wait for response
|
|
360
|
+
│ │ └─ USE: with page.expect_response('**/api/data'):
|
|
361
|
+
│ ├─ Wait for request
|
|
362
|
+
│ │ └─ USE: with page.expect_request('**/api/data'):
|
|
363
|
+
│ └─ All network idle
|
|
364
|
+
│ └─ USE: page.wait_for_load_state('networkidle')
|
|
365
|
+
│
|
|
366
|
+
├─ JavaScript condition
|
|
367
|
+
│ └─ Custom condition
|
|
368
|
+
│ ├─ Variable set
|
|
369
|
+
│ │ └─ USE: page.wait_for_function('() => window.appReady')
|
|
370
|
+
│ ├─ Element content
|
|
371
|
+
│ │ └─ USE: page.wait_for_function('() => document.body.innerText.includes("Ready")')
|
|
372
|
+
│ └─ Animation complete
|
|
373
|
+
│ └─ USE: page.wait_for_function('() => !document.querySelector(".animated")')
|
|
374
|
+
│
|
|
375
|
+
├─ Fixed time (avoid if possible)
|
|
376
|
+
│ └─ Known delay
|
|
377
|
+
│ └─ USE: page.wait_for_timeout(1000)
|
|
378
|
+
│ → Only use when no other option works
|
|
379
|
+
│
|
|
380
|
+
└─ Multiple conditions
|
|
381
|
+
└─ Combine waits
|
|
382
|
+
├─ Sequential: wait_for_selector() then wait_for_function()
|
|
383
|
+
└─ Parallel: Use Promise.all() in async context
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Environment Selection Decision Tree
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
Setting up test environment
|
|
390
|
+
↓
|
|
391
|
+
What environment do you need?
|
|
392
|
+
├─ Local development
|
|
393
|
+
│ ├─ Testing during development
|
|
394
|
+
│ │ ├─ Server: npm run dev (hot reload)
|
|
395
|
+
│ │ ├─ Port: 3000 (dev port)
|
|
396
|
+
│ │ └─ Database: Local SQLite/Postgres
|
|
397
|
+
│ └─ Quick iteration cycle
|
|
398
|
+
│
|
|
399
|
+
├─ CI/CD pipeline
|
|
400
|
+
│ ├─ Automated testing
|
|
401
|
+
│ │ ├─ Server: npm run build && npm start
|
|
402
|
+
│ │ ├─ Port: Any available port
|
|
403
|
+
│ │ ├─ Database: Test database / fixtures
|
|
404
|
+
│ │ └─ Headless: Always true
|
|
405
|
+
│ └─ Environment variables from CI secrets
|
|
406
|
+
│
|
|
407
|
+
├─ Staging
|
|
408
|
+
│ ├─ Pre-production testing
|
|
409
|
+
│ │ ├─ Server: Remote staging URL
|
|
410
|
+
│ │ ├─ Database: Staging database
|
|
411
|
+
│ │ └─ Real API keys (staging)
|
|
412
|
+
│ └─ Similar to production
|
|
413
|
+
│
|
|
414
|
+
└─ Production (careful!)
|
|
415
|
+
├─ Read-only tests only
|
|
416
|
+
├─ No data modification
|
|
417
|
+
└─ Minimal load generation
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
## Testing Approach Decision Tree
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
What kind of test do you need?
|
|
424
|
+
↓
|
|
425
|
+
├─ Unit test (single function/component)
|
|
426
|
+
│ └─ NOT this skill
|
|
427
|
+
│ → Use testing framework (Jest, pytest)
|
|
428
|
+
│
|
|
429
|
+
├─ Integration test (multiple components)
|
|
430
|
+
│ └─ Do components interact via UI?
|
|
431
|
+
│ ├─ Yes → Use this skill (Playwright)
|
|
432
|
+
│ └─ No → Use API testing or unit tests
|
|
433
|
+
│
|
|
434
|
+
├─ End-to-end test (full user flow)
|
|
435
|
+
│ └─ USE THIS SKILL
|
|
436
|
+
│ ├─ Start server(s) with with_server.py
|
|
437
|
+
│ ├─ Write Playwright script for user journey
|
|
438
|
+
│ └─ Test complete workflow
|
|
439
|
+
│
|
|
440
|
+
├─ Visual regression test
|
|
441
|
+
│ └─ USE THIS SKILL + Screenshot comparison
|
|
442
|
+
│ ├─ Capture baseline: page.screenshot()
|
|
443
|
+
│ ├─ Capture current: page.screenshot()
|
|
444
|
+
│ └─ Compare images (external tool)
|
|
445
|
+
│
|
|
446
|
+
├─ Performance test
|
|
447
|
+
│ └─ What metrics?
|
|
448
|
+
│ ├─ Page load time
|
|
449
|
+
│ │ └─ Measure: page.goto() timing
|
|
450
|
+
│ ├─ API response time
|
|
451
|
+
│ │ └─ Monitor: page.on("response")
|
|
452
|
+
│ └─ Heavy load
|
|
453
|
+
│ → Not this skill, use load testing tool
|
|
454
|
+
│
|
|
455
|
+
└─ Accessibility test
|
|
456
|
+
└─ USE THIS SKILL + axe-core
|
|
457
|
+
├─ Inject axe: page.evaluate()
|
|
458
|
+
└─ Run audit: Check ARIA, contrast, etc.
|
|
459
|
+
```
|