* fix release script * fix svgcanvas edge cases * Update path-actions.js * add modern js * update deps * Update CHANGES.md
614 lines
19 KiB
JavaScript
614 lines
19 KiB
JavaScript
import 'pathseg'
|
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
import { init as pathActionsInit, pathActionsMethod } from '../../packages/svgcanvas/core/path-actions.js'
|
|
import { init as utilitiesInit } from '../../packages/svgcanvas/core/utilities.js'
|
|
import { init as unitsInit } from '../../packages/svgcanvas/core/units.js'
|
|
import { NS } from '../../packages/svgcanvas/core/namespaces.js'
|
|
|
|
describe('PathActions', () => {
|
|
let svgRoot
|
|
let pathElement
|
|
let svgCanvas
|
|
let mockPath
|
|
|
|
beforeEach(() => {
|
|
// Create mock SVG elements
|
|
svgRoot = document.createElementNS(NS.SVG, 'svg')
|
|
svgRoot.setAttribute('width', '640')
|
|
svgRoot.setAttribute('height', '480')
|
|
document.body.append(svgRoot)
|
|
|
|
pathElement = document.createElementNS(NS.SVG, 'path')
|
|
pathElement.setAttribute('id', 'path1')
|
|
pathElement.setAttribute('d', 'M10,10 L50,50 L90,10 z')
|
|
svgRoot.append(pathElement)
|
|
|
|
// Create mock path object (simulating the path module's internal Path class)
|
|
mockPath = {
|
|
elem: pathElement,
|
|
segs: [
|
|
{ index: 0, item: { x: 10, y: 10 }, type: 2, selected: false, move: vi.fn() },
|
|
{ index: 1, item: { x: 50, y: 50 }, type: 4, selected: false, move: vi.fn() },
|
|
{ index: 2, item: { x: 90, y: 10 }, type: 4, selected: false, move: vi.fn() }
|
|
],
|
|
selected_pts: [],
|
|
matrix: null,
|
|
show: vi.fn(() => mockPath),
|
|
update: vi.fn(() => mockPath),
|
|
init: vi.fn(() => mockPath),
|
|
setPathContext: vi.fn(),
|
|
storeD: vi.fn(),
|
|
selectPt: vi.fn(),
|
|
addPtsToSelection: vi.fn(),
|
|
removePtFromSelection: vi.fn(),
|
|
clearSelection: vi.fn(),
|
|
setSegType: vi.fn(),
|
|
movePts: vi.fn(),
|
|
moveCtrl: vi.fn(),
|
|
addSeg: vi.fn(),
|
|
deleteSeg: vi.fn(),
|
|
endChanges: vi.fn(),
|
|
dragctrl: false,
|
|
dragging: null,
|
|
cur_pt: null,
|
|
oldbbox: { x: 0, y: 0, width: 100, height: 100 }
|
|
}
|
|
|
|
// Mock svgCanvas
|
|
svgCanvas = {
|
|
getSvgRoot: () => svgRoot,
|
|
getZoom: () => 1,
|
|
setCurrentMode: vi.fn(),
|
|
getCurrentMode: vi.fn(() => 'select'),
|
|
clearSelection: vi.fn(),
|
|
addToSelection: vi.fn(),
|
|
deleteSelectedElements: vi.fn(),
|
|
call: vi.fn(),
|
|
getSelectedElements: vi.fn(() => [pathElement]),
|
|
getDrawnPath: vi.fn(() => null),
|
|
setDrawnPath: vi.fn(),
|
|
getPath_: vi.fn(() => mockPath),
|
|
getId: vi.fn(() => 'svg_1'),
|
|
getNextId: vi.fn(() => 'svg_2'),
|
|
setStarted: vi.fn(),
|
|
addPointGrip: vi.fn(),
|
|
addCtrlGrip: vi.fn(() => {
|
|
const grip = document.createElementNS(NS.SVG, 'circle')
|
|
grip.setAttribute('cx', '0')
|
|
grip.setAttribute('cy', '0')
|
|
grip.setAttribute('r', '4')
|
|
return grip
|
|
}),
|
|
getCtrlLine: vi.fn(() => {
|
|
const line = document.createElementNS(NS.SVG, 'line')
|
|
return line
|
|
}),
|
|
replacePathSeg: vi.fn(),
|
|
getGridSnapping: vi.fn(() => false),
|
|
getOpacity: vi.fn(() => 1),
|
|
round: (val) => Math.round(val),
|
|
getRoundDigits: vi.fn(() => 2),
|
|
addSVGElementsFromJson: vi.fn((json) => {
|
|
const elem = document.createElementNS(NS.SVG, json.element)
|
|
if (json.attr) {
|
|
Object.entries(json.attr).forEach(([key, value]) => {
|
|
elem.setAttribute(key, value)
|
|
})
|
|
}
|
|
return elem
|
|
}),
|
|
createSVGElement: vi.fn((config) => {
|
|
const elem = document.createElementNS(NS.SVG, config.element)
|
|
if (config.attr) {
|
|
Object.entries(config.attr).forEach(([key, value]) => {
|
|
elem.setAttribute(key, value)
|
|
})
|
|
}
|
|
return elem
|
|
}),
|
|
selectorManager: {
|
|
getRubberBandBox: vi.fn(() => {
|
|
const rect = document.createElementNS(NS.SVG, 'rect')
|
|
rect.setAttribute('id', 'selectorRubberBand')
|
|
return rect
|
|
}),
|
|
requestSelector: vi.fn(() => ({
|
|
showGrips: vi.fn()
|
|
}))
|
|
},
|
|
getRubberBox: vi.fn(() => null),
|
|
setRubberBox: vi.fn((box) => box),
|
|
getPointFromGrip: vi.fn((point) => point),
|
|
getGripPt: vi.fn((seg) => ({ x: seg.item.x, y: seg.item.y })),
|
|
getContainer: vi.fn(() => svgRoot),
|
|
getMouseTarget: vi.fn(() => pathElement),
|
|
smoothControlPoints: vi.fn(),
|
|
removePath_: vi.fn(),
|
|
recalcRotatedPath: vi.fn(),
|
|
remapElement: vi.fn(),
|
|
addCommandToHistory: vi.fn(),
|
|
reorientGrads: vi.fn(),
|
|
setLinkControlPoints: vi.fn(),
|
|
contentW: 640
|
|
}
|
|
|
|
// Create selector parent group
|
|
const selectorParentGroup = document.createElementNS(NS.SVG, 'g')
|
|
selectorParentGroup.id = 'selectorParentGroup'
|
|
svgRoot.append(selectorParentGroup)
|
|
|
|
// Create pathpointgrip container
|
|
const pathpointgripContainer = document.createElementNS(NS.SVG, 'g')
|
|
pathpointgripContainer.id = 'pathpointgrip_container'
|
|
svgRoot.append(pathpointgripContainer)
|
|
|
|
// Initialize modules
|
|
utilitiesInit(svgCanvas)
|
|
unitsInit(svgCanvas)
|
|
pathActionsInit(svgCanvas)
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.body.textContent = ''
|
|
})
|
|
|
|
describe('Class instantiation', () => {
|
|
it('should export pathActionsMethod as singleton instance', () => {
|
|
expect(pathActionsMethod).toBeDefined()
|
|
expect(typeof pathActionsMethod.mouseDown).toBe('function')
|
|
expect(typeof pathActionsMethod.mouseMove).toBe('function')
|
|
expect(typeof pathActionsMethod.mouseUp).toBe('function')
|
|
})
|
|
|
|
it('should have all public methods', () => {
|
|
const publicMethods = [
|
|
'mouseDown',
|
|
'mouseMove',
|
|
'mouseUp',
|
|
'toEditMode',
|
|
'toSelectMode',
|
|
'addSubPath',
|
|
'select',
|
|
'reorient',
|
|
'clear',
|
|
'resetOrientation',
|
|
'zoomChange',
|
|
'getNodePoint',
|
|
'linkControlPoints',
|
|
'clonePathNode',
|
|
'opencloseSubPath',
|
|
'deletePathNode',
|
|
'smoothPolylineIntoPath',
|
|
'setSegType',
|
|
'moveNode',
|
|
'fixEnd',
|
|
'convertPath'
|
|
]
|
|
|
|
publicMethods.forEach(method => {
|
|
expect(typeof pathActionsMethod[method]).toBe('function')
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('mouseDown', () => {
|
|
it('should handle mouse down in path mode', () => {
|
|
svgCanvas.getCurrentMode.mockReturnValue('path')
|
|
svgCanvas.getDrawnPath.mockReturnValue(null)
|
|
|
|
const mockEvent = { target: pathElement, shiftKey: false }
|
|
const result = pathActionsMethod.mouseDown(mockEvent, pathElement, 100, 100)
|
|
|
|
expect(svgCanvas.addPointGrip).toHaveBeenCalled()
|
|
expect(result).toBeUndefined()
|
|
})
|
|
|
|
it('should handle mouse down on existing path point', () => {
|
|
// First enter edit mode to initialize path
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
svgCanvas.getCurrentMode.mockReturnValue('pathedit')
|
|
|
|
const grip = document.createElementNS(NS.SVG, 'circle')
|
|
grip.id = 'pathpointgrip_0'
|
|
const mockEvent = { target: grip, shiftKey: false }
|
|
|
|
pathActionsMethod.mouseDown(mockEvent, grip, 100, 100)
|
|
|
|
expect(mockPath.clearSelection).toHaveBeenCalled()
|
|
expect(mockPath.addPtsToSelection).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('mouseMove', () => {
|
|
it('should handle mouse move in path mode', () => {
|
|
svgCanvas.getCurrentMode.mockReturnValue('path')
|
|
const drawnPath = document.createElementNS(NS.SVG, 'path')
|
|
drawnPath.setAttribute('d', 'M10,10 L50,50')
|
|
svgCanvas.getDrawnPath.mockReturnValue(drawnPath)
|
|
|
|
pathActionsMethod.mouseMove(120, 120)
|
|
|
|
// Should update path stretchy line
|
|
expect(svgCanvas.replacePathSeg).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should handle dragging path points', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
svgCanvas.getCurrentMode.mockReturnValue('pathedit')
|
|
mockPath.dragging = [100, 100]
|
|
|
|
pathActionsMethod.mouseMove(110, 110)
|
|
|
|
expect(mockPath.movePts).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('mouseUp', () => {
|
|
it('should handle mouse up in path mode', () => {
|
|
svgCanvas.getCurrentMode.mockReturnValue('path')
|
|
const drawnPath = document.createElementNS(NS.SVG, 'path')
|
|
svgCanvas.getDrawnPath.mockReturnValue(drawnPath)
|
|
|
|
const mockEvent = { target: pathElement }
|
|
const result = pathActionsMethod.mouseUp(mockEvent, drawnPath, 100, 100)
|
|
|
|
expect(result).toEqual({ keep: true, element: drawnPath })
|
|
})
|
|
|
|
it('should finalize path point dragging', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
svgCanvas.getCurrentMode.mockReturnValue('pathedit')
|
|
mockPath.dragging = [100, 100]
|
|
mockPath.cur_pt = 1
|
|
|
|
const mockEvent = { target: pathElement, shiftKey: false }
|
|
pathActionsMethod.mouseUp(mockEvent, pathElement, 105, 105)
|
|
|
|
expect(mockPath.update).toHaveBeenCalled()
|
|
expect(mockPath.endChanges).toHaveBeenCalledWith('Move path point(s)')
|
|
})
|
|
})
|
|
|
|
describe('toEditMode', () => {
|
|
it('should switch to path edit mode', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
|
|
expect(svgCanvas.setCurrentMode).toHaveBeenCalledWith('pathedit')
|
|
expect(svgCanvas.clearSelection).toHaveBeenCalled()
|
|
expect(mockPath.show).toHaveBeenCalledWith(true)
|
|
expect(mockPath.update).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('toSelectMode', () => {
|
|
it('should switch to select mode', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
pathActionsMethod.toSelectMode(pathElement)
|
|
|
|
expect(svgCanvas.setCurrentMode).toHaveBeenCalledWith('select')
|
|
expect(mockPath.show).toHaveBeenCalledWith(false)
|
|
expect(svgCanvas.clearSelection).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should select element if it was the path element', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
pathActionsMethod.toSelectMode(pathElement)
|
|
|
|
expect(svgCanvas.call).toHaveBeenCalledWith('selected', [pathElement])
|
|
expect(svgCanvas.addToSelection).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('addSubPath', () => {
|
|
it('should enable subpath mode', () => {
|
|
pathActionsMethod.addSubPath(true)
|
|
|
|
expect(svgCanvas.setCurrentMode).toHaveBeenCalledWith('path')
|
|
})
|
|
|
|
it('should disable subpath mode', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
pathActionsMethod.addSubPath(false)
|
|
|
|
expect(mockPath.init).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('select', () => {
|
|
it('should select a path and enter edit mode if already current', () => {
|
|
pathActionsMethod.select(pathElement)
|
|
pathActionsMethod.select(pathElement)
|
|
|
|
expect(svgCanvas.setCurrentMode).toHaveBeenCalledWith('pathedit')
|
|
})
|
|
})
|
|
|
|
describe('reorient', () => {
|
|
it('should reorient a rotated path', () => {
|
|
pathElement.setAttribute('transform', 'rotate(45 50 50)')
|
|
svgCanvas.getSelectedElements.mockReturnValue([pathElement])
|
|
|
|
pathActionsMethod.reorient()
|
|
|
|
expect(svgCanvas.addCommandToHistory).toHaveBeenCalled()
|
|
expect(svgCanvas.call).toHaveBeenCalledWith('changed', [pathElement])
|
|
})
|
|
|
|
it('should do nothing if no element selected', () => {
|
|
svgCanvas.getSelectedElements.mockReturnValue([])
|
|
|
|
pathActionsMethod.reorient()
|
|
|
|
expect(svgCanvas.addCommandToHistory).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('clear', () => {
|
|
it('should clear drawn path', () => {
|
|
const drawnPath = document.createElementNS(NS.SVG, 'path')
|
|
drawnPath.id = 'svg_1'
|
|
const stretchy = document.createElementNS(NS.SVG, 'path')
|
|
stretchy.id = 'path_stretch_line'
|
|
svgRoot.append(drawnPath)
|
|
svgRoot.append(stretchy)
|
|
|
|
svgCanvas.getDrawnPath.mockReturnValue(drawnPath)
|
|
|
|
pathActionsMethod.clear()
|
|
|
|
expect(svgCanvas.setDrawnPath).toHaveBeenCalledWith(null)
|
|
expect(svgCanvas.setStarted).toHaveBeenCalledWith(false)
|
|
})
|
|
|
|
it('should switch to select mode if in pathedit mode', () => {
|
|
svgCanvas.getCurrentMode.mockReturnValue('pathedit')
|
|
svgCanvas.getDrawnPath.mockReturnValue(null)
|
|
|
|
pathActionsMethod.clear()
|
|
|
|
expect(svgCanvas.setCurrentMode).toHaveBeenCalledWith('select')
|
|
})
|
|
})
|
|
|
|
describe('resetOrientation', () => {
|
|
it('should reset path orientation', () => {
|
|
pathElement.setAttribute('transform', 'rotate(45 50 50)')
|
|
|
|
const result = pathActionsMethod.resetOrientation(pathElement)
|
|
|
|
expect(svgCanvas.reorientGrads).toHaveBeenCalled()
|
|
expect(result).toBeUndefined()
|
|
})
|
|
|
|
it('should return false for non-path elements', () => {
|
|
const rect = document.createElementNS(NS.SVG, 'rect')
|
|
|
|
const result = pathActionsMethod.resetOrientation(rect)
|
|
|
|
expect(result).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('zoomChange', () => {
|
|
it('should update path on zoom change in pathedit mode', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
svgCanvas.getCurrentMode.mockReturnValue('pathedit')
|
|
|
|
pathActionsMethod.zoomChange()
|
|
|
|
expect(mockPath.update).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should do nothing if not in pathedit mode', () => {
|
|
svgCanvas.getCurrentMode.mockReturnValue('select')
|
|
|
|
pathActionsMethod.zoomChange()
|
|
|
|
expect(mockPath.update).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('getNodePoint', () => {
|
|
it('should return selected node point', () => {
|
|
mockPath.selected_pts = [1]
|
|
svgCanvas.getPath_.mockReturnValue(mockPath)
|
|
|
|
const result = pathActionsMethod.getNodePoint()
|
|
|
|
expect(result).toEqual({
|
|
x: 50,
|
|
y: 50,
|
|
type: 4
|
|
})
|
|
})
|
|
|
|
it('should return first point if no selection', () => {
|
|
mockPath.selected_pts = []
|
|
svgCanvas.getPath_.mockReturnValue(mockPath)
|
|
|
|
const result = pathActionsMethod.getNodePoint()
|
|
|
|
expect(result.x).toBeDefined()
|
|
expect(result.y).toBeDefined()
|
|
})
|
|
})
|
|
|
|
describe('linkControlPoints', () => {
|
|
it('should set link control points flag', () => {
|
|
pathActionsMethod.linkControlPoints(true)
|
|
|
|
expect(svgCanvas.setLinkControlPoints).toHaveBeenCalledWith(true)
|
|
})
|
|
})
|
|
|
|
describe('clonePathNode', () => {
|
|
it('should clone selected path nodes', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
mockPath.selected_pts = [1]
|
|
|
|
pathActionsMethod.clonePathNode()
|
|
|
|
expect(mockPath.storeD).toHaveBeenCalled()
|
|
expect(mockPath.addSeg).toHaveBeenCalled()
|
|
expect(mockPath.init).toHaveBeenCalled()
|
|
expect(mockPath.endChanges).toHaveBeenCalledWith('Clone path node(s)')
|
|
})
|
|
})
|
|
|
|
describe('deletePathNode', () => {
|
|
it('should delete selected path nodes', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
mockPath.selected_pts = [1]
|
|
|
|
// Mock canDeleteNodes property
|
|
Object.defineProperty(pathActionsMethod, 'canDeleteNodes', {
|
|
get: () => true,
|
|
configurable: true
|
|
})
|
|
|
|
// Mock pathSegList on the element
|
|
Object.defineProperty(pathElement, 'pathSegList', {
|
|
value: {
|
|
numberOfItems: 3,
|
|
getItem: vi.fn((i) => ({
|
|
pathSegType: i === 0 ? 2 : 4 // M then L segments
|
|
})),
|
|
removeItem: vi.fn()
|
|
},
|
|
configurable: true
|
|
})
|
|
|
|
pathActionsMethod.deletePathNode()
|
|
|
|
expect(mockPath.storeD).toHaveBeenCalled()
|
|
expect(mockPath.deleteSeg).toHaveBeenCalled()
|
|
expect(mockPath.init).toHaveBeenCalled()
|
|
expect(mockPath.clearSelection).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('smoothPolylineIntoPath', () => {
|
|
it('should convert polyline to smooth path', () => {
|
|
const polyline = document.createElementNS(NS.SVG, 'polyline')
|
|
polyline.setAttribute('points', '10,10 50,50 90,10 130,50')
|
|
|
|
const mockPoints = {
|
|
numberOfItems: 4,
|
|
getItem: vi.fn((i) => {
|
|
const points = [[10, 10], [50, 50], [90, 10], [130, 50]]
|
|
return { x: points[i][0], y: points[i][1] }
|
|
})
|
|
}
|
|
Object.defineProperty(polyline, 'points', {
|
|
get: () => mockPoints,
|
|
configurable: true
|
|
})
|
|
|
|
const result = pathActionsMethod.smoothPolylineIntoPath(polyline)
|
|
|
|
expect(svgCanvas.addSVGElementsFromJson).toHaveBeenCalled()
|
|
expect(result).toBeDefined()
|
|
})
|
|
})
|
|
|
|
describe('setSegType', () => {
|
|
it('should set path segment type', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
|
|
pathActionsMethod.setSegType(6)
|
|
|
|
expect(mockPath.setSegType).toHaveBeenCalledWith(6)
|
|
})
|
|
})
|
|
|
|
describe('moveNode', () => {
|
|
it('should move selected path node', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
mockPath.selected_pts = [1]
|
|
|
|
pathActionsMethod.moveNode('x', 60)
|
|
|
|
expect(mockPath.segs[1].move).toHaveBeenCalled()
|
|
expect(mockPath.endChanges).toHaveBeenCalledWith('Move path point')
|
|
})
|
|
|
|
it('should do nothing if no points selected', () => {
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
mockPath.selected_pts = []
|
|
|
|
// When no points selected, should return early
|
|
pathActionsMethod.moveNode('x', 60)
|
|
|
|
// Verify no seg.move was called
|
|
mockPath.segs.forEach(seg => {
|
|
expect(seg.move).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('convertPath', () => {
|
|
it('should convert path to relative coordinates', () => {
|
|
const path = document.createElementNS(NS.SVG, 'path')
|
|
path.setAttribute('d', 'M10,10 L50,50 L90,10 z')
|
|
|
|
const result = pathActionsMethod.convertPath(path, true)
|
|
|
|
expect(result).toBeDefined()
|
|
expect(typeof result).toBe('string')
|
|
expect(result).toContain('m') // Should have relative move command
|
|
})
|
|
|
|
it('should convert path to absolute coordinates', () => {
|
|
const path = document.createElementNS(NS.SVG, 'path')
|
|
path.setAttribute('d', 'm10,10 l40,40 l40,-40 z')
|
|
|
|
const result = pathActionsMethod.convertPath(path, false)
|
|
|
|
expect(result).toBeDefined()
|
|
expect(typeof result).toBe('string')
|
|
expect(result).toContain('M') // Should have absolute move command
|
|
})
|
|
})
|
|
|
|
describe('Private field encapsulation', () => {
|
|
it('should not expose private fields', () => {
|
|
const privateFields = ['subpath', 'newPoint', 'firstCtrl', 'currentPath', 'hasMoved']
|
|
|
|
privateFields.forEach(field => {
|
|
expect(pathActionsMethod[field]).toBeUndefined()
|
|
expect(pathActionsMethod[`#${field}`]).toBeUndefined()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Integration scenarios', () => {
|
|
it('should handle complete path drawing workflow', () => {
|
|
// Start drawing
|
|
svgCanvas.getCurrentMode.mockReturnValue('path')
|
|
svgCanvas.getDrawnPath.mockReturnValue(null)
|
|
|
|
// First point
|
|
pathActionsMethod.mouseDown({ target: svgRoot }, svgRoot, 10, 10)
|
|
expect(svgCanvas.addPointGrip).toHaveBeenCalled()
|
|
|
|
// Add more points
|
|
const drawnPath = document.createElementNS(NS.SVG, 'path')
|
|
drawnPath.setAttribute('d', 'M10,10 L50,50')
|
|
svgCanvas.getDrawnPath.mockReturnValue(drawnPath)
|
|
|
|
pathActionsMethod.mouseMove(50, 50)
|
|
expect(svgCanvas.replacePathSeg).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should handle path editing with transform', () => {
|
|
pathElement.setAttribute('transform', 'translate(10,10) rotate(45)')
|
|
mockPath.matrix = { a: 0.707, b: 0.707, c: -0.707, d: 0.707, e: 10, f: 10 }
|
|
|
|
pathActionsMethod.toEditMode(pathElement)
|
|
|
|
expect(mockPath.show).toHaveBeenCalledWith(true)
|
|
expect(mockPath.update).toHaveBeenCalled()
|
|
})
|
|
})
|
|
})
|