generated from coulomb/repo-seed
refactor: complete migration to template-v2 architecture
- Remove legacy template.svg files from example/ and my-project/ - Simplify generator.js by removing generateHardcoded method (326→210 lines, -36%) - Add strict template validation with clear error messages - Remove all fallback mechanisms - template-v2.svg format now required - Clean up tests: remove hardcoded generation tests, keep template-based tests - Add comprehensive e2e tests (large datasets, edge cases, error handling) - Update documentation: mark REFACTORING_PLAN.md complete, add TEMPLATE_V2_GUIDE.md - All 56 tests passing (16 engine + 25 generator + 15 integration) BREAKING CHANGE: Old template.svg format no longer supported. Must use template-v2.svg with <g id="*-template"> elements in defs section. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -43,12 +43,100 @@ T-1,First Task,Development,2025-01-15
|
||||
T-2,Second Task,Testing,2025-02-20
|
||||
T-3,Third Task,Development,2025-03-10`
|
||||
|
||||
// Create a proper template-v2.svg format with template elements in defs
|
||||
export const createSampleTemplate = () => `<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<!-- Month template -->
|
||||
<g id="month-template" style="display:none">
|
||||
<line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}" stroke="#E0E0E0" stroke-width="1"/>
|
||||
<rect x="{{MONTH_X_OFFSET}}" y="{{MONTH_LABEL_Y_OFFSET}}" width="60" height="24" fill="#F5F5F5" rx="4"/>
|
||||
<text x="{{MONTH_TEXT_X}}" y="{{MONTH_LABEL_Y}}" font-family="Arial" font-size="12" fill="#424242">{{MONTH_LABEL}}</text>
|
||||
<line x1="{{MONTH_SEP_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_SEP_X}}" y2="{{GRID_BOTTOM}}" stroke="#BDBDBD" stroke-width="2"/>
|
||||
</g>
|
||||
|
||||
<!-- Lane template -->
|
||||
<g id="lane-template" style="display:none">
|
||||
<rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}" fill="#FAFAFA" stroke="#E0E0E0" rx="8"/>
|
||||
<text x="{{LABEL_X}}" y="{{LABEL_Y}}" font-family="Arial" font-size="14" font-weight="bold" fill="#212121">{{LANE_NAME}}</text>
|
||||
</g>
|
||||
|
||||
<!-- Task template -->
|
||||
<g id="task-template" style="display:none">
|
||||
<circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6" fill="#1976D2"/>
|
||||
<text x="{{TEXT_X}}" y="{{TEXT_Y}}" font-family="Arial" font-size="11" fill="#424242">{{TASK_ID}} {{TASK_TITLE}}</text>
|
||||
</g>
|
||||
</defs>
|
||||
|
||||
<rect width="100%" height="100%" fill="#FFFFFF"/>
|
||||
{{MONTHS}}
|
||||
{{LANES}}
|
||||
</svg>`
|
||||
|
||||
// Create a malformed template missing required elements (for error testing)
|
||||
export const createMalformedTemplate = (missingElement = 'month-template') => {
|
||||
const templates = {
|
||||
'month-template': `<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<g id="lane-template" style="display:none">
|
||||
<rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}" fill="#FAFAFA"/>
|
||||
</g>
|
||||
<g id="task-template" style="display:none">
|
||||
<circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6" fill="#1976D2"/>
|
||||
</g>
|
||||
</defs>
|
||||
{{MONTHS}}
|
||||
{{LANES}}
|
||||
</svg>`,
|
||||
'lane-template': `<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<g id="month-template" style="display:none">
|
||||
<line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}" stroke="#E0E0E0"/>
|
||||
</g>
|
||||
<g id="task-template" style="display:none">
|
||||
<circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6" fill="#1976D2"/>
|
||||
</g>
|
||||
</defs>
|
||||
{{MONTHS}}
|
||||
{{LANES}}
|
||||
</svg>`,
|
||||
'task-template': `<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<g id="month-template" style="display:none">
|
||||
<line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}" stroke="#E0E0E0"/>
|
||||
</g>
|
||||
<g id="lane-template" style="display:none">
|
||||
<rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}" fill="#FAFAFA"/>
|
||||
</g>
|
||||
</defs>
|
||||
{{MONTHS}}
|
||||
{{LANES}}
|
||||
</svg>`
|
||||
}
|
||||
return templates[missingElement] || templates['month-template']
|
||||
}
|
||||
|
||||
// Create a large dataset for stress testing (50+ items)
|
||||
export const createLargeDataset = (itemCount = 60) => {
|
||||
const lanes = ['Development', 'Testing', 'Design', 'DevOps', 'Documentation']
|
||||
const startDate = new Date('2025-01-01')
|
||||
const items = []
|
||||
|
||||
for (let i = 1; i <= itemCount; i++) {
|
||||
const daysOffset = Math.floor(i * 8) // Spread items across ~480 days (16 months)
|
||||
const dueDate = new Date(startDate)
|
||||
dueDate.setDate(dueDate.getDate() + daysOffset)
|
||||
|
||||
items.push({
|
||||
id: `TASK-${i}`,
|
||||
title: `Task ${i}: Implementation Item`,
|
||||
lane: lanes[i % lanes.length],
|
||||
due: dueDate
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
export const mockFetch = (data, ok = true) => {
|
||||
global.fetch.mockResolvedValueOnce({
|
||||
ok,
|
||||
|
||||
Reference in New Issue
Block a user