generated from coulomb/repo-seed
test: improve test infrastructure and fix test assertions
- Add mockPapaParse helper to centralize CSV mocking - Fix test assertions to match actual output (German month names) - Add missing DOM elements to test setup (projectFile, csvFile, etc.) - Update vitest to v4.0.14 for improved testing capabilities - Make setupEventHandlers globally accessible for testing - Use textContent instead of innerText for better consistency - Fix autoLoadDefaultProject test to check all three fallback paths - Add proper event handler setup in integration tests - Improve error handling test assertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import { setupBasicDOM, createMockElement } from './setup.js'
|
||||
import { createSampleProject, createSampleCSV, mockFetch, expectElementToHaveText } from './testHelpers.js'
|
||||
import { createSampleProject, createSampleCSV, mockFetch, mockPapaParse, expectElementToHaveText } from './testHelpers.js'
|
||||
|
||||
// Import the engine by loading it as text and evaluating
|
||||
// This is needed because engine.js creates a global object
|
||||
@@ -56,6 +56,7 @@ describe('Timeline Engine', () => {
|
||||
|
||||
mockFetch('<svg></svg>')
|
||||
mockFetch(createSampleCSV())
|
||||
mockPapaParse()
|
||||
|
||||
await timelineEngine.loadProjectConfigObject(config)
|
||||
|
||||
@@ -76,9 +77,16 @@ describe('Timeline Engine', () => {
|
||||
timelineEngine.cssOverride = true
|
||||
const config = createSampleProject()
|
||||
|
||||
// Still need to mock SVG template and CSV fetches
|
||||
mockFetch('<svg></svg>')
|
||||
mockFetch(createSampleCSV())
|
||||
mockPapaParse()
|
||||
|
||||
await timelineEngine.loadProjectConfigObject(config)
|
||||
|
||||
expect(document.getElementById('dynamicCss').href).toBe('')
|
||||
// Should not load the stylesheet from config
|
||||
const href = document.getElementById('dynamicCss').href
|
||||
expect(href).not.toContain(config.stylesheet)
|
||||
})
|
||||
|
||||
it('should not load CSV when csvOverride is true', async () => {
|
||||
@@ -86,6 +94,9 @@ describe('Timeline Engine', () => {
|
||||
const config = createSampleProject()
|
||||
const processCsvSpy = vi.spyOn(timelineEngine, 'processCsv')
|
||||
|
||||
// Still need to mock SVG template fetch
|
||||
mockFetch('<svg></svg>')
|
||||
|
||||
await timelineEngine.loadProjectConfigObject(config)
|
||||
|
||||
expect(processCsvSpy).not.toHaveBeenCalled()
|
||||
@@ -156,10 +167,12 @@ describe('Timeline Engine', () => {
|
||||
})
|
||||
|
||||
describe('autoLoadDefaultProject', () => {
|
||||
it('should try binect/project.json first, then example/project.json', async () => {
|
||||
it('should try binect/project.json first, then my-project, then example', async () => {
|
||||
// First call (binect) fails
|
||||
global.fetch.mockResolvedValueOnce({ ok: false })
|
||||
// Second call (example) succeeds
|
||||
global.fetch.mockResolvedValueOnce({ ok: false, status: 404, statusText: 'Not Found' })
|
||||
// Second call (my-project) fails
|
||||
global.fetch.mockResolvedValueOnce({ ok: false, status: 404, statusText: 'Not Found' })
|
||||
// Third call (example) succeeds
|
||||
mockFetch(createSampleProject())
|
||||
mockFetch('<svg></svg>')
|
||||
mockFetch(createSampleCSV())
|
||||
@@ -167,6 +180,7 @@ describe('Timeline Engine', () => {
|
||||
await timelineEngine.autoLoadDefaultProject()
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledWith('binect/project.json')
|
||||
expect(global.fetch).toHaveBeenCalledWith('my-project/project.json')
|
||||
expect(global.fetch).toHaveBeenCalledWith('example/project.json')
|
||||
})
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('Timeline Generator', () => {
|
||||
const template = createSampleTemplate()
|
||||
const result = timelineGenerator.generate(items, config, template)
|
||||
|
||||
expect(result).toContain('<svg xmlns="http://www.w3.org/2000/svg">')
|
||||
expect(result).toContain('<svg xmlns="http://www.w3.org/2000/svg"')
|
||||
expect(result).toContain('<rect width="100%" height="100%" fill="#FFFFFF"/>')
|
||||
expect(result).not.toContain('{{MONTHS}}')
|
||||
expect(result).not.toContain('{{LANES}}')
|
||||
@@ -147,8 +147,8 @@ describe('Timeline Generator', () => {
|
||||
|
||||
const result = timelineGenerator.generate(itemsWithEarlyDate, config, null)
|
||||
|
||||
// Should start from June 2024 (first day of month)
|
||||
expect(result).toContain('Jun 24')
|
||||
// Should start from June 2024 (first day of month) - German month name
|
||||
expect(result).toContain('Juni 24')
|
||||
})
|
||||
|
||||
it('should clamp item positions to timeline bounds', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import { setupBasicDOM } from './setup.js'
|
||||
import { createSampleProject, createSampleCSV, createSampleTemplate, mockFetch } from './testHelpers.js'
|
||||
import { createSampleProject, createSampleCSV, createSampleTemplate, mockFetch, mockPapaParse } from './testHelpers.js'
|
||||
|
||||
// Import both engine and generator
|
||||
const fs = await import('fs/promises')
|
||||
@@ -33,21 +33,7 @@ describe('Timeline Integration', () => {
|
||||
// Mock fetch calls in order: template, CSV
|
||||
mockFetch(template)
|
||||
mockFetch(csvData)
|
||||
|
||||
// Mock Papa.parse to process the CSV
|
||||
global.Papa.parse.mockImplementation((text, options) => {
|
||||
const lines = text.trim().split('\n')
|
||||
const headers = lines[0].split(',')
|
||||
const data = lines.slice(1).map(line => {
|
||||
const values = line.split(',')
|
||||
const obj = {}
|
||||
headers.forEach((header, i) => {
|
||||
obj[header] = values[i]
|
||||
})
|
||||
return obj
|
||||
})
|
||||
options.complete({ data })
|
||||
})
|
||||
mockPapaParse()
|
||||
|
||||
await timelineEngine.loadProjectConfigObject(config)
|
||||
|
||||
@@ -124,11 +110,11 @@ describe('Timeline Integration', () => {
|
||||
// Mock fetch failures
|
||||
global.fetch.mockRejectedValue(new Error('Network error'))
|
||||
|
||||
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
|
||||
await timelineEngine.autoLoadDefaultProject()
|
||||
|
||||
// Should not crash, just log warnings
|
||||
// Should not crash, just log messages
|
||||
expect(consoleSpy).toHaveBeenCalled()
|
||||
|
||||
consoleSpy.mockRestore()
|
||||
@@ -142,6 +128,9 @@ describe('Timeline Integration', () => {
|
||||
projectInput.id = 'projectInput'
|
||||
document.body.appendChild(projectInput)
|
||||
|
||||
// Setup event handlers
|
||||
window.setupEventHandlers()
|
||||
|
||||
// Mock file reading
|
||||
const mockFile = new File([JSON.stringify(config)], 'project.json', { type: 'application/json' })
|
||||
mockFile.text = vi.fn().mockResolvedValue(JSON.stringify(config))
|
||||
@@ -149,10 +138,7 @@ describe('Timeline Integration', () => {
|
||||
// Mock the fetch calls that loadProjectConfigObject will make
|
||||
mockFetch(createSampleTemplate())
|
||||
mockFetch(createSampleCSV())
|
||||
|
||||
global.Papa.parse.mockImplementation((text, options) => {
|
||||
options.complete({ data: [] })
|
||||
})
|
||||
mockPapaParse()
|
||||
|
||||
// Simulate file selection
|
||||
Object.defineProperty(projectInput, 'files', {
|
||||
@@ -178,6 +164,9 @@ describe('Timeline Integration', () => {
|
||||
csvInput.id = 'csvInput'
|
||||
document.body.appendChild(csvInput)
|
||||
|
||||
// Setup event handlers
|
||||
window.setupEventHandlers()
|
||||
|
||||
const csvContent = createSampleCSV()
|
||||
const mockFile = new File([csvContent], 'data.csv', { type: 'text/csv' })
|
||||
mockFile.text = vi.fn().mockResolvedValue(csvContent)
|
||||
|
||||
@@ -35,5 +35,9 @@ export const setupBasicDOM = () => {
|
||||
<div id="viewer"></div>
|
||||
<link id="dynamicCss" rel="stylesheet" href="">
|
||||
<button id="downloadSvg"></button>
|
||||
<span id="projectFile"></span>
|
||||
<span id="csvFile"></span>
|
||||
<span id="svgFile"></span>
|
||||
<span id="cssFile"></span>
|
||||
`
|
||||
}
|
||||
@@ -52,11 +52,30 @@ export const createSampleTemplate = () => `<svg xmlns="http://www.w3.org/2000/sv
|
||||
export const mockFetch = (data, ok = true) => {
|
||||
global.fetch.mockResolvedValueOnce({
|
||||
ok,
|
||||
status: ok ? 200 : 404,
|
||||
statusText: ok ? 'OK' : 'Not Found',
|
||||
json: () => Promise.resolve(data),
|
||||
text: () => Promise.resolve(typeof data === 'string' ? data : JSON.stringify(data))
|
||||
})
|
||||
}
|
||||
|
||||
// Helper to mock Papa.parse with proper CSV parsing
|
||||
export const mockPapaParse = () => {
|
||||
global.Papa.parse.mockImplementation((text, options) => {
|
||||
const lines = text.trim().split('\n')
|
||||
const headers = lines[0].split(',')
|
||||
const data = lines.slice(1).map(line => {
|
||||
const values = line.split(',')
|
||||
const obj = {}
|
||||
headers.forEach((header, i) => {
|
||||
obj[header] = values[i]
|
||||
})
|
||||
return obj
|
||||
})
|
||||
options.complete({ data })
|
||||
})
|
||||
}
|
||||
|
||||
export const expectElementToHaveText = (selector, text) => {
|
||||
const element = document.querySelector(selector)
|
||||
expect(element).toBeTruthy()
|
||||
|
||||
Reference in New Issue
Block a user