| name | test-create-fixture |
| description | Create HTML test fixture for UI components. Uses project templates to create isolated test pages for TDD validation. |
test-create-fixture - Component Test Fixture Creator
Creates HTML test fixture files for UI components. Used by dev agents during TDD to create isolated test pages before implementation.
Input Schema
{
"project_dir": "/path/to/project",
"ticket_id": "TICKET-XXX_A.1",
"component_path": "src/components/impact/MetricCard.js",
"fixture_path": "src/tests/metric-card.html",
"component_name": "MetricCard",
"component_class": "MetricCard",
"acceptance_criteria": [
{"id": "AC-001", "description": "Counter animates from 0 to target"},
{"id": "AC-002", "description": "Displays unit label correctly"}
]
}
CRITICAL: Use Absolute URL Paths (NOT Relative)
NEVER use relative paths like ../../ in fixture imports.
The server runs from src/ directory, making src/ the web root:
src/tests/*.html → served at /tests/*.html
src/components/**/*.js → served at /components/**/*.js
WHY relative paths break:
fixture_path: src/tests/metric-card.html
component_path: src/components/impact/MetricCard.js
WRONG: ../../components/impact/MetricCard.js
→ resolves to project_root/components/impact/MetricCard.js (OUTSIDE src/)
→ FILE NOT FOUND
RIGHT: /components/impact/MetricCard.js
→ resolves from server root (src/) to src/components/impact/MetricCard.js
→ FILE FOUND ✓
Instructions
1. Locate Template
2. Process Template Variables
Replace mustache-style variables in template:
| Variable | Source | Example |
|---|
{{TICKET_ID}} | input.ticket_id | TICKET-OXY-003_A.1 |
{{COMPONENT_NAME}} | input.component_name | MetricCard |
{{COMPONENT_PATH}} | Absolute URL from server root | /components/impact/MetricCard.js |
{{COMPONENT_CLASS}} | input.component_class | MetricCard |
{{COMPONENT_CSS}} | CSS absolute URL | /styles/metric-card.css |
{{COMPONENT_OPTIONS}} | Default init options | {} or from ticket |
{{COMPONENT_SELECTOR}} | data-* attribute name (kebab-case) | circular-progress |
{{#ACCEPTANCE_CRITERIA}} | Loop over ACs | Creates test sections |
{{AC_ID}} | Each AC ID | AC-001 |
{{AC_DESCRIPTION}} | Each AC description | Counter animates... |
3. Calculate Absolute URL Paths
CRITICAL: Check for import_prefix in context first!
The import_prefix context variable tells you if the server needs a path prefix (e.g., /src).
function toAbsoluteUrl(filePath, importPrefix) {
let relativePath = filePath;
if (filePath.startsWith('src/')) {
relativePath = filePath.slice(4);
}
if (importPrefix) {
return importPrefix + '/' + relativePath;
}
return '/' + relativePath;
}
Always check context for import_prefix before generating import paths!
4. Generate AC Test Sections
For each acceptance criterion, create a test section:
<div class="test-section" id="test-AC-001">
<h2>AC-001: Counter animates from 0 to target</h2>
<div data-test-scenario="ac-001"></div>
</div>
5. Write Fixture File
const fixtureDir = path.dirname(fixturePath);
await fs.mkdir(fixtureDir, { recursive: true });
await fs.writeFile(fixturePath, processedTemplate);
Output Format
{
"skill": "test-create-fixture",
"status": "success|failure",
"fixture_created": "src/tests/metric-card.html",
"template_used": "templates/project/tests/web/component-fixture.template.html",
"variables_replaced": {
"TICKET_ID": "TICKET-OXY-003_A.1",
"COMPONENT_NAME": "MetricCard",
"COMPONENT_PATH": "/components/impact/MetricCard.js",
"ACCEPTANCE_CRITERIA": 2
},
"test_sections": ["AC-001", "AC-002"],
"warnings": [],
"next_action": "validate_fixture"
}
Happy Path Only (CRITICAL)
Initial fixtures focus on happy path ONLY. Edge case testing is deferred to later phases.
What to Include (Happy Path)
- Primary data loading with valid endpoints
- Standard component initialization
- Default configurations
- Expected successful responses
What to Defer (Edge Cases)
- Missing file/endpoint tests (AC descriptions mentioning "missing", "invalid", "error handling")
- Error recovery scenarios
- Timeout/failure handling
- Malformed input validation
Handling Edge Case ACs
When an AC describes edge case behavior (missing files, errors, invalid data), do NOT test it directly. Instead:
setOutput('ac-3', JSON.stringify({
status: 'deferred',
note: 'Edge case test deferred until happy path validated'
}, null, 2));
Rationale: Early TDD phases validate that components work correctly with valid inputs. Edge case testing requires additional infrastructure (mock servers, error injection) that may not exist yet.
Fixture Requirements
The generated fixture MUST include:
- Isolated component - Only the target component, no page context
- Real imports - Import from actual src/ path, not copies
- Test sections per AC - Each acceptance criterion gets a section
- data-testid attributes - For Playwright selection
- Status indicator - Shows init success/failure (#test-status.success/.error)
- Playwright hooks - CRITICAL for test access:
Required Window Globals (CRITICAL)
window.__testModule = {
ComponentClass,
initComponentFactory,
...otherExports
};
window.__testInstances = [...];
window.__getTestInstance = () => instances[0];
window.__getTestInstances = () => instances;
window.__isInitialized = () => initComplete && !error;
window.__getInitError = () => initError;
Why __testModule is CRITICAL:
- ES6 module loading timing varies by browser (Chromium is slower)
- Tests use
page.waitForFunction(() => window.__testModule) to wait for module
- If not set synchronously, tests fail with race conditions
- Chromium especially affected (19 failures vs WebKit's 4)
Example Generated Fixture
<!DOCTYPE html>
<html lang="en">
<head>
<title>MetricCard Test - TICKET-OXY-003_A.1</title>
<link rel="stylesheet" href="/styles/impact/metric-card.css">
</head>
<body>
<div class="test-container">
<h1>MetricCard Test</h1>
<div class="test-section" id="test-AC-001">
<h2>AC-001: Counter animates from 0 to target</h2>
<div data-testid="ac-001-container"></div>
</div>
<div class="test-section" id="test-AC-002">
<h2>AC-002: Displays unit label correctly</h2>
<div data-testid="ac-002-container"></div>
</div>
<div id="test-status">Loading...</div>
</div>
<script type="module">
import { MetricCard } from '/components/impact/MetricCard.js';
</script>
</body>
</html>
Token Efficiency
- Template-based generation (no LLM needed for structure)
- ~2-5 second execution
- Returns ready-to-use HTML fixture