Add test suite with 132 unit tests across all modules
Covers DesignState (40 tests), HouseRenderer (19), InteractionManager (24), ThemeManager (8), ExportManager (11), and CatalogPanel (30). Uses vitest with THREE.js mocks for browser-free testing.
This commit is contained in:
117
tests/themes.test.js
Normal file
117
tests/themes.test.js
Normal file
@@ -0,0 +1,117 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { COLORS } from '../src/renderer.js';
|
||||
import { ThemeManager } from '../src/themes.js';
|
||||
import { Scene, Color } from '../tests/__mocks__/three.js';
|
||||
|
||||
// Snapshot of original COLORS to restore between tests (shared mutable state)
|
||||
const ORIGINAL_COLORS = {
|
||||
wall: { ...COLORS.wall },
|
||||
floor: { ...COLORS.floor },
|
||||
ceiling: COLORS.ceiling,
|
||||
door: COLORS.door,
|
||||
window: COLORS.window,
|
||||
windowFrame: COLORS.windowFrame,
|
||||
grid: COLORS.grid,
|
||||
selected: COLORS.selected
|
||||
};
|
||||
|
||||
function restoreColors() {
|
||||
Object.assign(COLORS.wall, ORIGINAL_COLORS.wall);
|
||||
Object.assign(COLORS.floor, ORIGINAL_COLORS.floor);
|
||||
COLORS.ceiling = ORIGINAL_COLORS.ceiling;
|
||||
COLORS.door = ORIGINAL_COLORS.door;
|
||||
COLORS.window = ORIGINAL_COLORS.window;
|
||||
COLORS.windowFrame = ORIGINAL_COLORS.windowFrame;
|
||||
COLORS.grid = ORIGINAL_COLORS.grid;
|
||||
COLORS.selected = ORIGINAL_COLORS.selected;
|
||||
}
|
||||
|
||||
function makeMockRenderer() {
|
||||
const scene = new Scene();
|
||||
// Add mock lights to the scene
|
||||
scene.add({ isAmbientLight: true, intensity: 0.6, traverse: (fn) => fn({ isAmbientLight: true, intensity: 0.6 }) });
|
||||
scene.add({ isDirectionalLight: true, intensity: 0.8, traverse: (fn) => fn({ isDirectionalLight: true, intensity: 0.8 }) });
|
||||
|
||||
return {
|
||||
scene,
|
||||
currentFloor: 0,
|
||||
_clearFloor: vi.fn(),
|
||||
showFloor: vi.fn()
|
||||
};
|
||||
}
|
||||
|
||||
describe('ThemeManager', () => {
|
||||
let tm, mockRenderer;
|
||||
|
||||
beforeEach(() => {
|
||||
restoreColors();
|
||||
mockRenderer = makeMockRenderer();
|
||||
tm = new ThemeManager(mockRenderer);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreColors();
|
||||
});
|
||||
|
||||
describe('getThemes', () => {
|
||||
it('returns array of theme descriptors', () => {
|
||||
const themes = tm.getThemes();
|
||||
expect(themes.length).toBeGreaterThanOrEqual(4);
|
||||
for (const theme of themes) {
|
||||
expect(theme).toHaveProperty('id');
|
||||
expect(theme).toHaveProperty('name');
|
||||
expect(theme).toHaveProperty('swatch');
|
||||
expect(typeof theme.id).toBe('string');
|
||||
expect(typeof theme.name).toBe('string');
|
||||
expect(theme.swatch).toMatch(/^#[0-9a-f]{6}$/i);
|
||||
}
|
||||
});
|
||||
|
||||
it('includes expected theme ids', () => {
|
||||
const ids = tm.getThemes().map(t => t.id);
|
||||
expect(ids).toContain('default');
|
||||
expect(ids).toContain('modern');
|
||||
expect(ids).toContain('warm');
|
||||
expect(ids).toContain('dark');
|
||||
expect(ids).toContain('scandinavian');
|
||||
});
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('starts with default theme', () => {
|
||||
expect(tm.currentTheme).toBe('default');
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyTheme', () => {
|
||||
it('updates currentTheme property', () => {
|
||||
tm.applyTheme('dark');
|
||||
expect(tm.currentTheme).toBe('dark');
|
||||
});
|
||||
|
||||
it('does nothing for invalid theme id', () => {
|
||||
tm.applyTheme('nonexistent');
|
||||
expect(tm.currentTheme).toBe('default');
|
||||
});
|
||||
|
||||
it('mutates the shared COLORS object', () => {
|
||||
const origExterior = COLORS.wall.exterior;
|
||||
tm.applyTheme('dark');
|
||||
expect(COLORS.wall.exterior).toBe(0x3a3a3a);
|
||||
// Restore for other tests
|
||||
tm.applyTheme('default');
|
||||
expect(COLORS.wall.exterior).toBe(origExterior);
|
||||
});
|
||||
|
||||
it('calls _clearFloor and showFloor on renderer', () => {
|
||||
tm.applyTheme('modern');
|
||||
expect(mockRenderer._clearFloor).toHaveBeenCalled();
|
||||
expect(mockRenderer.showFloor).toHaveBeenCalledWith(0);
|
||||
});
|
||||
|
||||
it('updates scene background', () => {
|
||||
tm.applyTheme('dark');
|
||||
expect(mockRenderer.scene.background._hex).toBe(0x222222);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user