UNPKG

svgedit

Version:

Powerful SVG-Editor for your browser

194 lines (168 loc) 6.82 kB
import { beforeEach, describe, expect, it, vi } from 'vitest' import MainMenu from '../../src/editor/MainMenu.js' vi.mock('@svgedit/svgcanvas', () => ({ default: { $id: (id) => document.getElementById(id), $click: (el, fn) => el?.addEventListener('click', fn), convertUnit: (val) => Number(val), isValidUnit: (_attr, val) => val !== 'bad' } })) vi.mock('@svgedit/svgcanvas/common/browser.js', () => ({ isChrome: () => false })) describe('MainMenu', () => { let editor let menu let prefStore beforeEach(() => { document.body.innerHTML = ` <div id="app"></div> <div id="se-export-dialog"></div> <div id="se-img-prop"></div> <div id="se-edit-prefs"></div> ` prefStore = { img_save: 'embed', lang: 'en' } const configObj = { curConfig: { baseUnit: 'px', exportWindowType: 'new', canvasName: 'svg-edit', gridSnapping: false, snappingStep: 1, gridColor: '#ccc', showRulers: false }, curPrefs: { bkgd_color: '#fff' }, preferences: false, pref: vi.fn((key, val) => { if (val !== undefined) { prefStore[key] = val } return prefStore[key] }) } const svgCanvas = { setDocumentTitle: vi.fn(), setResolution: vi.fn().mockReturnValue(true), getResolution: vi.fn(() => ({ w: 120, h: 80 })), getDocumentTitle: vi.fn(() => 'Doc'), setConfig: vi.fn(), rasterExport: vi.fn().mockResolvedValue('data-uri'), exportPDF: vi.fn() } editor = { configObj, svgCanvas, i18next: { t: (key) => key }, $svgEditor: document.getElementById('app'), docprops: false, rulers: { updateRulers: vi.fn() }, setBackground: vi.fn(), updateCanvas: vi.fn(), customExportPDF: false, customExportImage: false } globalThis.seAlert = vi.fn() menu = new MainMenu(editor) }) it('rejects invalid doc properties and shows an alert', () => { const result = menu.saveDocProperties({ detail: { title: 'Oops', w: 'bad', h: 'fit', save: 'embed' } }) expect(result).toBe(false) expect(globalThis.seAlert).toHaveBeenCalled() expect(editor.svgCanvas.setResolution).not.toHaveBeenCalled() }) it('saves document properties and hides the dialog', () => { editor.docprops = true const result = menu.saveDocProperties({ detail: { title: 'Demo', w: '200', h: '100', save: 'layer' } }) expect(result).toBe(true) expect(editor.svgCanvas.setDocumentTitle).toHaveBeenCalledWith('Demo') expect(editor.svgCanvas.setResolution).toHaveBeenCalledWith('200', '100') expect(editor.updateCanvas).toHaveBeenCalled() expect(prefStore.img_save).toBe('layer') expect(editor.docprops).toBe(false) expect(document.getElementById('se-img-prop').getAttribute('dialog')).toBe('close') }) it('saves preferences, updates config and alerts when language changes', async () => { editor.configObj.preferences = true const detail = { lang: 'fr', bgcolor: '#111', bgurl: '', gridsnappingon: true, gridsnappingstep: 2, gridcolor: '#333', showrulers: true, baseunit: 'cm' } await menu.savePreferences({ detail }) expect(editor.setBackground).toHaveBeenCalledWith('#111', '') expect(prefStore.lang).toBe('fr') expect(editor.configObj.curConfig.gridSnapping).toBe(true) expect(editor.configObj.curConfig.snappingStep).toBe(2) expect(editor.configObj.curConfig.gridColor).toBe('#333') expect(editor.configObj.curConfig.showRulers).toBe(true) expect(editor.configObj.curConfig.baseUnit).toBe('cm') expect(editor.rulers.updateRulers).toHaveBeenCalled() expect(editor.svgCanvas.setConfig).toHaveBeenCalled() expect(editor.updateCanvas).toHaveBeenCalled() expect(globalThis.seAlert).toHaveBeenCalled() expect(editor.configObj.preferences).toBe(false) }) it('opens doc properties dialog and converts units when needed', () => { editor.configObj.curConfig.baseUnit = 'cm' menu.showDocProperties() const dialog = document.getElementById('se-img-prop') expect(editor.docprops).toBe(true) expect(dialog.getAttribute('dialog')).toBe('open') expect(dialog.getAttribute('width')).toBe('120cm') expect(dialog.getAttribute('height')).toBe('80cm') expect(dialog.getAttribute('title')).toBe('Doc') editor.svgCanvas.getResolution.mockClear() menu.showDocProperties() expect(editor.svgCanvas.getResolution).not.toHaveBeenCalled() }) it('opens preferences dialog only once and populates attributes', () => { editor.configObj.curConfig.gridSnapping = true editor.configObj.curConfig.snappingStep = 4 editor.configObj.curConfig.gridColor = '#888' editor.configObj.curPrefs.bkgd_color = '#ff00ff' editor.configObj.pref = vi.fn((key) => key === 'bkgd_url' ? 'http://example.com' : prefStore[key]) menu.showPreferences() const prefs = document.getElementById('se-edit-prefs') expect(editor.configObj.preferences).toBe(true) expect(prefs.getAttribute('dialog')).toBe('open') expect(prefs.getAttribute('gridsnappingon')).toBe('true') expect(prefs.getAttribute('gridsnappingstep')).toBe('4') expect(prefs.getAttribute('gridcolor')).toBe('#888') expect(prefs.getAttribute('canvasbg')).toBe('#ff00ff') expect(prefs.getAttribute('bgurl')).toBe('http://example.com') editor.configObj.preferences = true prefs.removeAttribute('dialog') menu.showPreferences() expect(prefs.getAttribute('dialog')).toBeNull() }) it('routes export actions based on dialog detail', async () => { await menu.clickExport() expect(editor.svgCanvas.rasterExport).not.toHaveBeenCalled() await menu.clickExport({ detail: { trigger: 'ok', imgType: 'PNG', quality: 50 } }) expect(editor.svgCanvas.rasterExport).toHaveBeenCalledWith('PNG', 0.5, editor.exportWindowName) expect(editor.exportWindowCt).toBe(1) await menu.clickExport({ detail: { trigger: 'ok', imgType: 'PDF' } }) expect(editor.svgCanvas.exportPDF).toHaveBeenCalled() }) it('creates menu entries and wires click handlers in init', () => { menu.init() document.getElementById('tool_export').dispatchEvent(new Event('click', { bubbles: true })) expect(document.getElementById('se-export-dialog').getAttribute('dialog')).toBe('open') document.getElementById('tool_docprops').dispatchEvent(new Event('click', { bubbles: true })) expect(editor.docprops).toBe(true) const prefsDialog = document.getElementById('se-edit-prefs') prefsDialog.dispatchEvent(new CustomEvent('change', { detail: { dialog: 'closed' } })) expect(prefsDialog.getAttribute('dialog')).toBe('close') }) })