Adds right, left, bottom, and bottom-left-corner resize handles alongside the existing bottom-right corner, and raises resize handle z-index above Handsontable's frozen header clones so clicks reach the handle instead of the table underneath it.
622 lines
20 KiB
TypeScript
622 lines
20 KiB
TypeScript
import { ViewboxesComponent } from './viewboxes.component'
|
|
|
|
/**
|
|
* resize()'s debounced callback (run synchronously here, see helperService
|
|
* below) also calls viewboxChanged() -> router.navigate() and
|
|
* prepareFilterCache() -> this.viewboxes - these stubs cover exactly that
|
|
* surface, not the full real services (no TestBed/DI needed, same
|
|
* plain-instantiation-with-stubs precedent as app.service.spec.ts).
|
|
*/
|
|
const buildComponent = () => {
|
|
const helperService: any = {
|
|
debounceCall: (_time: number, callback: () => void) => callback()
|
|
}
|
|
|
|
const component = new ViewboxesComponent(
|
|
{
|
|
runOutsideAngular: (fn: () => void) => fn(),
|
|
run: (fn: () => void) => fn()
|
|
} as any, // NgZone
|
|
{ licenceState: { value: {} } } as any, // LicenceService
|
|
{} as any, // SasService
|
|
{ dispatchEvent: () => {} } as any, // EventService
|
|
{} as any, // SasStoreService
|
|
{} as any, // LoggerService
|
|
helperService,
|
|
{ navigate: () => {} } as any, // Router
|
|
{} as any, // ActivatedRoute
|
|
{} as any // ChangeDetectorRef
|
|
)
|
|
|
|
// setAllHandleTransform() (called synchronously by resize()) iterates
|
|
// these two @ViewChildren query lists - empty arrays keep it a no-op
|
|
// without needing a real view to populate them.
|
|
component.resizeBoxQuery = [] as any
|
|
component.dragHandleCornerQuery = [] as any
|
|
component.viewboxes = []
|
|
|
|
return component
|
|
}
|
|
|
|
// Real DOM elements, positioned absolutely with known coordinates - Karma
|
|
// runs in an actual browser (ChromeHeadlessCI), so getBoundingClientRect()
|
|
// returns genuine, accurate values with no need to mock it.
|
|
const positionedDiv = (
|
|
left: number,
|
|
top: number,
|
|
width: number,
|
|
height: number
|
|
): HTMLDivElement => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
return el
|
|
}
|
|
|
|
describe('ViewboxesComponent - resize', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = positionedDiv(left, top, width, height)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('computes width/height as the distance from the target corner to the drag handle', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
// Positioned so the handle's own bottom-right corner (280+20, 230+20)
|
|
// exactly coincides with target's current bottom-right corner
|
|
// (100+200, 100+150) - the handle "hasn't moved" from a fresh render,
|
|
// so the computed size should match the target's current size exactly.
|
|
const dragHandle = addDiv(280, 230, 20, 20)
|
|
|
|
const result = component.resize(dragHandle, target)
|
|
|
|
expect(result).toEqual({ width: 200, height: 150 })
|
|
})
|
|
|
|
it('grows the target element when the handle is dragged further from the corner', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
// Dragged 100px right and down from the exact-corner position used
|
|
// above.
|
|
const dragHandle = addDiv(400, 350, 20, 20)
|
|
|
|
const result = component.resize(dragHandle, target)
|
|
|
|
expect(result).toEqual({ width: 320, height: 270 })
|
|
expect(target.style.width).toBe('320px')
|
|
expect(target.style.height).toBe('270px')
|
|
})
|
|
|
|
it('shrinks the target element when the handle is dragged toward the corner', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
const dragHandle = addDiv(220, 180, 20, 20)
|
|
|
|
const result = component.resize(dragHandle, target)
|
|
|
|
expect(result).toEqual({ width: 140, height: 100 })
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - setHandleTransform', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('translates the handle to the target rect bottom-right corner, plus a 5px fine-tune, for position "both"', () => {
|
|
const component = buildComponent()
|
|
const dragHandle = addDiv(20, 20)
|
|
const targetRect = { width: 200, height: 150 } as DOMRect
|
|
|
|
component.setHandleTransform(dragHandle, targetRect, 'both')
|
|
|
|
// translateX = 200 - 20 + 5 = 185, translateY = 150 - 20 + 5 = 135
|
|
expect(dragHandle.style.transform).toBe('translate(185px, 135px)')
|
|
})
|
|
|
|
it('only translates along x for position "x"', () => {
|
|
const component = buildComponent()
|
|
const dragHandle = addDiv(20, 20)
|
|
const targetRect = { width: 200, height: 150 } as DOMRect
|
|
|
|
component.setHandleTransform(dragHandle, targetRect, 'x')
|
|
|
|
// The browser normalizes the unitless '0' the source writes back to
|
|
// '0px' when the style is read back.
|
|
expect(dragHandle.style.transform).toBe('translate(185px, 0px)')
|
|
})
|
|
|
|
it('only translates along y for position "y"', () => {
|
|
const component = buildComponent()
|
|
const dragHandle = addDiv(20, 20)
|
|
const targetRect = { width: 200, height: 150 } as DOMRect
|
|
|
|
component.setHandleTransform(dragHandle, targetRect, 'y')
|
|
|
|
expect(dragHandle.style.transform).toBe('translate(0px, 135px)')
|
|
})
|
|
|
|
it('translates to a small fixed left-edge offset for position "left", independent of target size', () => {
|
|
const component = buildComponent()
|
|
const dragHandle = addDiv(20, 20)
|
|
const targetRect = { width: 200, height: 150 } as DOMRect
|
|
|
|
component.setHandleTransform(dragHandle, targetRect, 'left')
|
|
|
|
expect(dragHandle.style.transform).toBe('translate(-5px, 0px)')
|
|
})
|
|
|
|
it('combines the left-edge x offset with the bottom-edge y calculation for position "bottomLeft"', () => {
|
|
const component = buildComponent()
|
|
const dragHandle = addDiv(20, 20)
|
|
const targetRect = { width: 200, height: 150 } as DOMRect
|
|
|
|
component.setHandleTransform(dragHandle, targetRect, 'bottomLeft')
|
|
|
|
// translateY = 150 - 20 + 5 = 135, same calculation as position "y"
|
|
expect(dragHandle.style.transform).toBe('translate(-5px, 135px)')
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - parseHandleTranslate', () => {
|
|
it('returns {x: 0, y: 0} for an empty/unset transform', () => {
|
|
const component: any = buildComponent()
|
|
|
|
expect(component.parseHandleTranslate('')).toEqual({ x: 0, y: 0 })
|
|
})
|
|
|
|
it('parses an existing translate(...) transform, including negative values', () => {
|
|
const component: any = buildComponent()
|
|
|
|
expect(component.parseHandleTranslate('translate(12px, -34px)')).toEqual({
|
|
x: 12,
|
|
y: -34
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - startResize', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('grows the target as the pointer moves after pointerdown on the handle', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
// Positioned exactly at target's current bottom-right corner - see the
|
|
// identical setup in the "resize" describe block above.
|
|
const dragHandle = addDiv(280, 230, 20, 20)
|
|
const viewbox: any = { width: 200, height: 150 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 300,
|
|
clientY: 250
|
|
})
|
|
component.startResize(pointerDown, dragHandle, target, viewbox)
|
|
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 400, clientY: 350 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(300)
|
|
expect(viewbox.height).toBe(250)
|
|
})
|
|
|
|
it('stops tracking the pointer once pointerup fires', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
const dragHandle = addDiv(280, 230, 20, 20)
|
|
const viewbox: any = { width: 200, height: 150 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 300,
|
|
clientY: 250
|
|
})
|
|
component.startResize(pointerDown, dragHandle, target, viewbox)
|
|
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
|
|
const widthAfterPointerUp = viewbox.width
|
|
|
|
// A move after pointerup must not still be tracked - the listener was
|
|
// meant to be removed.
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 600, clientY: 600 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(widthAfterPointerUp)
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - resizeWidth/resizeHeight (edge-only resize)', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('resizeWidth grows/shrinks width from the target left edge, leaving height untouched', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(0, 0, 200, 150)
|
|
const dragHandle = addDiv(220, 0, 10, 10)
|
|
|
|
const width = component.resizeWidth(dragHandle, target)
|
|
|
|
expect(width).toBe(230)
|
|
expect(target.style.width).toBe('230px')
|
|
expect(target.style.height).toBe('150px')
|
|
})
|
|
|
|
it('resizeHeight grows/shrinks height from the target top edge, leaving width untouched', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(0, 0, 200, 150)
|
|
const dragHandle = addDiv(0, 170, 10, 10)
|
|
|
|
const height = component.resizeHeight(dragHandle, target)
|
|
|
|
expect(height).toBe(180)
|
|
expect(target.style.height).toBe('180px')
|
|
expect(target.style.width).toBe('200px')
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - resizeFromLeftEdge', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('grows width and moves x left by the same amount when dragged left (right edge stays put)', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // right edge = 300
|
|
|
|
const result = component.resizeFromLeftEdge(
|
|
/* pointerClientX */ 50,
|
|
target,
|
|
/* startTargetRight */ 300,
|
|
/* startX */ 10,
|
|
/* startWidth */ 200
|
|
)
|
|
|
|
// intended width = 300 - 50 = 250 (grew by 50)
|
|
expect(result.width).toBe(250)
|
|
// x moves left by exactly how much width grew, so the right edge stays
|
|
// visually fixed.
|
|
expect(result.x).toBe(-40) // 10 + (200 - 250)
|
|
})
|
|
|
|
it('shrinks width and moves x right when dragged right, without exceeding min-width', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
|
|
const result = component.resizeFromLeftEdge(250, target, 300, 10, 200)
|
|
|
|
// intended width = 300 - 250 = 50
|
|
expect(result.width).toBe(50)
|
|
expect(result.x).toBe(160) // 10 + (200 - 50)
|
|
})
|
|
|
|
it("does not let x drift past what the target's CSS min-width actually allows", () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
// Simulates .viewbox's real min-width: 200px constraint, which a plain
|
|
// test div doesn't have unless set explicitly.
|
|
target.style.minWidth = '200px'
|
|
|
|
const result = component.resizeFromLeftEdge(250, target, 300, 10, 200) // would intend width 50
|
|
|
|
// The browser clamps target's rendered width to 200px (min-width) -
|
|
// resizeFromLeftEdge must read that back rather than trust its own
|
|
// unclamped math, or x would drift while the box visibly stops moving.
|
|
expect(result.width).toBe(200)
|
|
expect(result.x).toBe(10)
|
|
})
|
|
|
|
it('does not compound growth across repeated moves even if the target itself gets repositioned via a transform in between (what CDK does as viewbox.x changes)', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // right edge = 300
|
|
const startTargetRight = 300
|
|
const startX = 10
|
|
const startWidth = 200
|
|
|
|
// First pointermove: dragged 20px left from an implied drag-start of
|
|
// clientX=100.
|
|
const first = component.resizeFromLeftEdge(
|
|
80,
|
|
target,
|
|
startTargetRight,
|
|
startX,
|
|
startWidth
|
|
)
|
|
expect(first.width).toBe(220)
|
|
|
|
// Simulate CDK repositioning the box in response to first.x - a real
|
|
// transform on target, exactly like [cdkDragFreeDragPosition] applies.
|
|
// This must not feed back into the next call's width.
|
|
target.style.transform = `translate(${first.x - startX}px, 0)`
|
|
|
|
// Second pointermove: another 20px left, same speed as the first move.
|
|
const second = component.resizeFromLeftEdge(
|
|
60,
|
|
target,
|
|
startTargetRight,
|
|
startX,
|
|
startWidth
|
|
)
|
|
|
|
// Constant pointer speed must produce constant growth - not more the
|
|
// second time just because the box moved in response to the first.
|
|
expect(second.width - first.width).toBe(20)
|
|
expect(second.width).toBe(240)
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - startResizeRight/startResizeBottom (edge handles)', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('startResizeRight only changes width as the pointer moves', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // right edge = 300
|
|
// Handle's own bottom-right-ish corner (290+10) exactly at target's
|
|
// current right edge (300) - the "hasn't moved yet" baseline, same
|
|
// convention as the resize()/resizeWidth() tests above.
|
|
const dragHandle = addDiv(290, 100, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 0, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 300,
|
|
clientY: 100
|
|
})
|
|
component.startResizeRight(pointerDown, dragHandle, target, viewbox)
|
|
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 400, clientY: 100 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(300)
|
|
expect(viewbox.height).toBe(150)
|
|
expect(viewbox.x).toBe(0)
|
|
})
|
|
|
|
it('startResizeBottom only changes height as the pointer moves', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // bottom edge = 250
|
|
// Handle's own bottom edge (240+10) exactly at target's current bottom
|
|
// edge (250) - the "hasn't moved yet" baseline.
|
|
const dragHandle = addDiv(100, 240, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 0, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 100,
|
|
clientY: 250
|
|
})
|
|
component.startResizeBottom(pointerDown, dragHandle, target, viewbox)
|
|
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 100, clientY: 350 })
|
|
)
|
|
|
|
expect(viewbox.height).toBe(250)
|
|
expect(viewbox.width).toBe(200)
|
|
})
|
|
|
|
it('stops tracking the pointer for startResizeRight once pointerup fires', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
const dragHandle = addDiv(290, 100, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 0, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 300,
|
|
clientY: 100
|
|
})
|
|
component.startResizeRight(pointerDown, dragHandle, target, viewbox)
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
|
|
const widthAfterPointerUp = viewbox.width
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 600, clientY: 100 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(widthAfterPointerUp)
|
|
})
|
|
})
|
|
|
|
describe('ViewboxesComponent - startResizeLeft/startResizeBottomLeft', () => {
|
|
let toRemove: HTMLElement[]
|
|
|
|
beforeEach(() => {
|
|
toRemove = []
|
|
})
|
|
|
|
afterEach(() => {
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
toRemove.forEach((el) => el.remove())
|
|
})
|
|
|
|
const addDiv = (left: number, top: number, width: number, height: number) => {
|
|
const el = document.createElement('div')
|
|
el.style.position = 'absolute'
|
|
el.style.left = `${left}px`
|
|
el.style.top = `${top}px`
|
|
el.style.width = `${width}px`
|
|
el.style.height = `${height}px`
|
|
document.body.appendChild(el)
|
|
toRemove.push(el)
|
|
return el
|
|
}
|
|
|
|
it('startResizeLeft grows width and moves x left, leaving height untouched', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // right edge = 300
|
|
const dragHandle = addDiv(100, 100, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 10, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 100,
|
|
clientY: 100
|
|
})
|
|
component.startResizeLeft(pointerDown, dragHandle, target, viewbox)
|
|
|
|
// Dragged 50px left.
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 50, clientY: 100 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(250)
|
|
expect(viewbox.x).toBe(-40) // 10 + (200 - 250)
|
|
expect(viewbox.height).toBe(150)
|
|
})
|
|
|
|
it('startResizeBottomLeft grows width+x and height together', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150) // bottom edge = 250
|
|
// top=240 so the handle's own bottom edge (240+10) starts exactly at
|
|
// target's current bottom edge (250) - the height "hasn't moved yet"
|
|
// baseline (left=100 needs no equivalent adjustment - resizeFromLeftEdge
|
|
// only reads dragRect.left, never dragRect.width, see its own tests).
|
|
const dragHandle = addDiv(100, 240, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 10, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 100,
|
|
clientY: 250
|
|
})
|
|
component.startResizeBottomLeft(pointerDown, dragHandle, target, viewbox)
|
|
|
|
// Dragged 50px left and 50px down.
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: 50, clientY: 300 })
|
|
)
|
|
|
|
expect(viewbox.width).toBe(250)
|
|
expect(viewbox.x).toBe(-40)
|
|
expect(viewbox.height).toBe(200)
|
|
})
|
|
|
|
it('stops tracking the pointer for startResizeLeft once pointerup fires', () => {
|
|
const component = buildComponent()
|
|
const target = addDiv(100, 100, 200, 150)
|
|
const dragHandle = addDiv(100, 100, 10, 10)
|
|
const viewbox: any = { width: 200, height: 150, x: 10, y: 0 }
|
|
|
|
const pointerDown = new PointerEvent('pointerdown', {
|
|
clientX: 100,
|
|
clientY: 100
|
|
})
|
|
component.startResizeLeft(pointerDown, dragHandle, target, viewbox)
|
|
document.dispatchEvent(new PointerEvent('pointerup'))
|
|
|
|
const xAfterPointerUp = viewbox.x
|
|
document.dispatchEvent(
|
|
new PointerEvent('pointermove', { clientX: -200, clientY: 100 })
|
|
)
|
|
|
|
expect(viewbox.x).toBe(xAfterPointerUp)
|
|
})
|
|
})
|