* feat(tracker): add support for multi tab sessions
* feat(backend): added support of multitabs
* fix(backend): added support of deprecated batch meta message to pre-decoder
* fix(backend): fixed nil meta issue for TabData messages in sink
* feat(player): add tabmanager
* feat(player): basic tabchange event support
* feat(player): pick tabstate for console panel and timeline
* fix(player): only display tabs that are created
* feat(player): connect performance, xray and events to tab state
* feat(player): merge all tabs data for overview
* feat(backend/tracker): extract tabdata into separate message from batchmeta
* fix(tracker): fix new session check
* fix(backend): remove batchmetadeprecated
* fix(backend): fix switch case
* fix(player): fix for tab message size
* feat(tracker): check for active tabs with broadcast channel
* feat(tracker): prevent multiple messages
* fix(tracker): ignore beacons from same tab, only ask if token isnt present yet, add small delay before start to wait for answer
* feat(player): support new msg struct in assist player
* fix(player): fix some livepl components for multi tab states
* feat(tracker): add option to disable multitab
* feat(tracker): add multitab to assist plugin
* feat(player): back compat for tab id
* fix(ui): fix missing list in controls
* fix(ui): optional list update
* feat(ui): fix visuals for multitab; use window focus event for tabs
* fix(tracker): fix for dying tests (added tabid to writer, refactored other tests)
* feat(ui): update LivePlayerSubHeader.tsx to support tabs
* feat(backend): added tabs support to devtools mob files
* feat(ui): connect state to current tab properly
* feat(backend): added multitab support to assits
* feat(backend): removed data check in agent message
* feat(backend): debug on
* fix(backend): fixed typo in message broadcast
* feat(backend): fixed issue in connect method
* fix(assist): fixed typo
* feat(assist): added more debug logs
* feat(assist): removed one log
* feat(assist): more logs
* feat(assist): use query.peerId
* feat(assist): more logs
* feat(assist): fixed session update
* fix(assist): fixed getSessions
* fix(assist): fixed request_control broadcast
* fix(assist): fixed typo
* fix(assist): added missed line
* fix(assist): fix typo
* feat(tracker): multitab support for assist sessions
* fix(tracker): fix dead tests (tabid prop)
* fix(tracker): fix yaml
* fix(tracker): timers issue
* fix(ui): fix ui E2E tests with magic?
* feat(assist): multitabs support for ee version
* fix(assist): added missed method import
* fix(tracker): fix fix events in assist
* feat(assist): added back compatibility for sessions without tabId
* fix(assist): apply message's top layer structure before broadcast call
* fix(assist): added random tabID for prev version
* fix(assist): added random tabID for prev version (ee)
* feat(assist): added debug logs
* fix(assist): fix typo in sessions_agents_count method
* fix(assist): fixed more typos in copy-pastes
* fix(tracker): fix restart timings
* feat(backend): added tabIDs for some events
* feat(ui): add tab change event to the user steps bar
* Revert "feat(backend): added tabIDs for some events"
This reverts commit 1467ad7f9f.
* feat(ui): revert timeline and xray to grab events from all tabs
* fix(ui): fix typo
---------
Co-authored-by: Alexander Zavorotynskiy <zavorotynskiy@pm.me>
148 lines
No EOL
5 KiB
TypeScript
148 lines
No EOL
5 KiB
TypeScript
import AnnotationCanvas from '../src/AnnotationCanvas'
|
|
import { describe, expect, test, it, jest, beforeEach, afterEach, } from '@jest/globals'
|
|
|
|
|
|
describe('AnnotationCanvas', () => {
|
|
let annotationCanvas
|
|
let documentBody
|
|
let canvasMock
|
|
let contextMock
|
|
|
|
beforeEach(() => {
|
|
canvasMock = {
|
|
width: 0,
|
|
height: 0,
|
|
style: {},
|
|
getContext: jest.fn(() => contextMock as unknown as HTMLCanvasElement),
|
|
parentNode: document,
|
|
}
|
|
|
|
contextMock = {
|
|
globalAlpha: 1.0,
|
|
beginPath: jest.fn(),
|
|
moveTo: jest.fn(),
|
|
lineTo: jest.fn(),
|
|
lineWidth: 8,
|
|
lineCap: 'round',
|
|
lineJoin: 'round',
|
|
strokeStyle: 'red',
|
|
stroke: jest.fn(),
|
|
globalCompositeOperation: '',
|
|
fillStyle: '',
|
|
fillRect: jest.fn(),
|
|
clearRect: jest.fn(),
|
|
}
|
|
|
|
documentBody = document.body
|
|
// @ts-ignore
|
|
document['removeChild'] = (el) => jest.fn(el)
|
|
// @ts-ignore
|
|
document['createElement'] = () => canvasMock
|
|
|
|
jest.spyOn(documentBody, 'appendChild').mockImplementation(jest.fn())
|
|
jest.spyOn(documentBody, 'removeChild').mockImplementation(jest.fn())
|
|
jest.spyOn(window, 'addEventListener').mockImplementation(jest.fn())
|
|
jest.spyOn(window, 'removeEventListener').mockImplementation(jest.fn())
|
|
annotationCanvas = new AnnotationCanvas()
|
|
})
|
|
|
|
afterEach(() => {
|
|
jest.restoreAllMocks()
|
|
})
|
|
|
|
it('should create a canvas element with correct styles when initialized', () => {
|
|
const createElSpy = jest.spyOn(document, 'createElement')
|
|
annotationCanvas = new AnnotationCanvas()
|
|
expect(createElSpy).toHaveBeenCalledWith('canvas')
|
|
expect(canvasMock.style.position).toBe('fixed')
|
|
expect(canvasMock.style.left).toBe(0)
|
|
expect(canvasMock.style.top).toBe(0)
|
|
expect(canvasMock.style.pointerEvents).toBe('none')
|
|
expect(canvasMock.style.zIndex).toBe(2147483647 - 2)
|
|
})
|
|
|
|
it('should resize the canvas when calling resizeCanvas method', () => {
|
|
annotationCanvas.resizeCanvas()
|
|
|
|
expect(canvasMock.width).toBe(window.innerWidth)
|
|
expect(canvasMock.height).toBe(window.innerHeight)
|
|
})
|
|
|
|
it('should start painting and set the last position when calling start method', () => {
|
|
const position = [10, 20,]
|
|
|
|
annotationCanvas.start(position)
|
|
|
|
expect(annotationCanvas.painting).toBe(true)
|
|
expect(annotationCanvas.clrTmID).toBeNull()
|
|
expect(annotationCanvas.lastPosition).toEqual(position)
|
|
})
|
|
|
|
it('should stop painting and call fadeOut method when calling stop method', () => {
|
|
annotationCanvas.painting = true
|
|
const fadeOutSpy = jest.spyOn(annotationCanvas, 'fadeOut')
|
|
|
|
annotationCanvas.stop()
|
|
|
|
expect(annotationCanvas.painting).toBe(false)
|
|
expect(fadeOutSpy).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should not stop painting or call fadeOut method when calling stop method while not painting', () => {
|
|
annotationCanvas.painting = false
|
|
const fadeOutSpy = jest.spyOn(annotationCanvas, 'fadeOut')
|
|
annotationCanvas.stop()
|
|
|
|
expect(fadeOutSpy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should draw a line on the canvas when calling move method', () => {
|
|
annotationCanvas.painting = true
|
|
annotationCanvas.ctx = contextMock
|
|
const initialLastPosition = [0, 0,]
|
|
const position = [10, 20,]
|
|
|
|
annotationCanvas.move(position)
|
|
|
|
expect(contextMock.globalAlpha).toBe(1.0)
|
|
expect(contextMock.beginPath).toHaveBeenCalled()
|
|
expect(contextMock.moveTo).toHaveBeenCalledWith(initialLastPosition[0], initialLastPosition[1])
|
|
expect(contextMock.lineTo).toHaveBeenCalledWith(position[0], position[1])
|
|
expect(contextMock.stroke).toHaveBeenCalled()
|
|
expect(annotationCanvas.lastPosition).toEqual(position)
|
|
})
|
|
|
|
it('should not draw a line on the canvas when calling move method while not painting', () => {
|
|
annotationCanvas.painting = false
|
|
annotationCanvas.ctx = contextMock
|
|
const position = [10, 20,]
|
|
|
|
annotationCanvas.move(position)
|
|
|
|
expect(contextMock.beginPath).not.toHaveBeenCalled()
|
|
expect(contextMock.stroke).not.toHaveBeenCalled()
|
|
expect(annotationCanvas.lastPosition).toEqual([0, 0,])
|
|
})
|
|
|
|
it('should fade out the canvas when calling fadeOut method', () => {
|
|
annotationCanvas.ctx = contextMock
|
|
jest.useFakeTimers()
|
|
const timerSpy = jest.spyOn(window, 'setTimeout')
|
|
annotationCanvas.fadeOut()
|
|
|
|
expect(timerSpy).toHaveBeenCalledTimes(2)
|
|
expect(contextMock.globalCompositeOperation).toBe('source-over')
|
|
expect(contextMock.fillStyle).toBe('rgba(255, 255, 255, 0.1)')
|
|
expect(contextMock.fillRect).toHaveBeenCalledWith(0, 0, canvasMock.width, canvasMock.height)
|
|
jest.runOnlyPendingTimers()
|
|
expect(contextMock.clearRect).toHaveBeenCalledWith(0, 0, canvasMock.width, canvasMock.height)
|
|
})
|
|
|
|
it('should remove the canvas element when calling remove method', () => {
|
|
const spyOnRemove = jest.spyOn(document, 'removeChild')
|
|
annotationCanvas.remove()
|
|
|
|
expect(spyOnRemove).toHaveBeenCalledWith(canvasMock)
|
|
expect(window.removeEventListener).toHaveBeenCalledWith('resize', annotationCanvas.resizeCanvas)
|
|
})
|
|
}) |