2026-08-29 02:55:53 +02:00
|
|
|
|
/**
|
|
|
|
|
|
* Task H1 – simple/pro Mode.
|
|
|
|
|
|
*
|
|
|
|
|
|
* uiModeService: persistierter UI-Modus ('simple' | 'pro', Default 'pro'),
|
|
|
|
|
|
* localStorage-Persistenz, Subscribe für Live-Updates.
|
|
|
|
|
|
* RibbonBar filtert im simple-Modus auf tools mit tags 'basic'.
|
|
|
|
|
|
* CommandLine ist pro-only (im simple-Modus versteckt).
|
|
|
|
|
|
*/
|
|
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
|
|
|
|
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
getUIMode, setUIMode, subscribeUIMode, UIMode,
|
|
|
|
|
|
} from '../src/services/uiModeService';
|
|
|
|
|
|
|
|
|
|
|
|
afterEach(cleanup);
|
|
|
|
|
|
|
|
|
|
|
|
// ─── uiModeService ────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
describe('H1: uiModeService', () => {
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
|
localStorage.clear();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('Default ist pro (Vollständige Werkzeugpalette)', () => {
|
|
|
|
|
|
expect(getUIMode()).toBe('pro');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('setUIMode simple persistiert in localStorage', () => {
|
|
|
|
|
|
setUIMode('simple');
|
|
|
|
|
|
expect(getUIMode()).toBe('simple');
|
|
|
|
|
|
expect(localStorage.getItem('webcad.uiMode')).toBe('simple');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('Persistiert über Reload hinweg (localStorage gesetzt vor erstem get)', () => {
|
|
|
|
|
|
localStorage.setItem('webcad.uiMode', 'simple');
|
|
|
|
|
|
expect(getUIMode()).toBe('simple');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('subscribeUIMode feuert bei Wechsel und unsubscribed korrekt', () => {
|
|
|
|
|
|
const cb = vi.fn();
|
|
|
|
|
|
const off = subscribeUIMode(cb);
|
|
|
|
|
|
setUIMode('simple');
|
|
|
|
|
|
expect(cb).toHaveBeenCalledWith('simple');
|
|
|
|
|
|
setUIMode('pro');
|
|
|
|
|
|
expect(cb).toHaveBeenCalledWith('pro');
|
|
|
|
|
|
off();
|
|
|
|
|
|
cb.mockClear();
|
|
|
|
|
|
setUIMode('simple');
|
|
|
|
|
|
expect(cb).not.toHaveBeenCalled();
|
|
|
|
|
|
// Aufräumen für weitere Tests
|
|
|
|
|
|
setUIMode('pro');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('ungültiger localStorage-Wert fällt auf pro zurück', () => {
|
|
|
|
|
|
localStorage.setItem('webcad.uiMode', 'gibts-nicht');
|
|
|
|
|
|
expect(getUIMode()).toBe('pro');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-09-16 10:22:36 +02:00
|
|
|
|
// ─── simple/pro-Filter (Registry-Logik) ─────────────────
|
2026-08-29 02:55:53 +02:00
|
|
|
|
|
2026-09-16 10:22:36 +02:00
|
|
|
|
describe('H1: simple/pro-Werkzeug-Filter', () => {
|
2026-08-29 02:55:53 +02:00
|
|
|
|
beforeEach(() => {
|
|
|
|
|
|
localStorage.clear();
|
|
|
|
|
|
setUIMode('pro');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-09-16 10:22:36 +02:00
|
|
|
|
it('pro-Modus: alle V2-Tools registriert (basic + pro-Tags)', async () => {
|
2026-08-29 02:55:53 +02:00
|
|
|
|
const { registerBuiltinPlugins, pluginRegistry } = await import('../src/plugins');
|
|
|
|
|
|
registerBuiltinPlugins();
|
|
|
|
|
|
pluginRegistry.initDefaults();
|
2026-09-16 10:22:36 +02:00
|
|
|
|
const all = pluginRegistry.getToolsV2();
|
|
|
|
|
|
expect(all.length).toBeGreaterThan(10);
|
|
|
|
|
|
const basics = all.filter((t) => (t.manifest.tags ?? []).includes('basic'));
|
|
|
|
|
|
expect(basics.length).toBeGreaterThan(0);
|
|
|
|
|
|
expect(basics.length).toBeLessThan(all.length);
|
2026-08-29 02:55:53 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-09-16 10:22:36 +02:00
|
|
|
|
it('simple-Modus: nur basic-Tools (rotate/scale/mirror gefiltert, line bleibt)', async () => {
|
2026-08-29 02:55:53 +02:00
|
|
|
|
localStorage.clear();
|
|
|
|
|
|
setUIMode('simple');
|
|
|
|
|
|
const { registerBuiltinPlugins, pluginRegistry } = await import('../src/plugins');
|
|
|
|
|
|
registerBuiltinPlugins();
|
|
|
|
|
|
pluginRegistry.initDefaults();
|
2026-09-16 10:22:36 +02:00
|
|
|
|
const visible = pluginRegistry.getToolsV2()
|
|
|
|
|
|
.filter((t) => (t.manifest.tags ?? []).includes('basic'))
|
|
|
|
|
|
.map((t) => t.manifest.id);
|
|
|
|
|
|
expect(visible).toContain('line');
|
|
|
|
|
|
expect(visible).not.toContain('rotate');
|
|
|
|
|
|
expect(visible).not.toContain('mirror');
|
2026-08-29 02:55:53 +02:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('CommandLine-Komponente: pro-only rendering via useUIMode', async () => {
|
|
|
|
|
|
const { useUIMode } = await import('../src/services/uiModeService');
|
|
|
|
|
|
const CommandLine = (await import('../src/components/CommandLine')).default;
|
|
|
|
|
|
setUIMode('pro');
|
|
|
|
|
|
const { container: proContainer } = render(<CommandLine history={[]} onCommand={() => {}} />);
|
|
|
|
|
|
expect(proContainer.querySelector('.cmdline')).toBeTruthy();
|
|
|
|
|
|
cleanup();
|
|
|
|
|
|
setUIMode('simple');
|
|
|
|
|
|
const { container: simpleContainer } = render(<CommandLine history={[]} onCommand={() => {}} />);
|
|
|
|
|
|
expect(simpleContainer.querySelector('.cmdline')).toBeFalsy();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('Topbar-Toggle wechselt Mode', async () => {
|
|
|
|
|
|
const Topbar = (await import('../src/components/Topbar')).default;
|
|
|
|
|
|
setUIMode('pro');
|
|
|
|
|
|
render(<Topbar projectName="Testprojekt" savedStatus="Gespeichert" onUndo={() => {}} onRedo={() => {}} onThemeToggle={() => {}} theme="dark" />);
|
|
|
|
|
|
const btn = screen.getByTitle(/Modus.*wechseln|Einfach.*Modus|Profi-Modus/i);
|
|
|
|
|
|
fireEvent.click(btn);
|
|
|
|
|
|
expect(getUIMode()).toBe('simple');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|