UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

292 lines (225 loc) • 9.05 kB
import React from 'react' import {vi} from 'vitest' import {render} from '@testing-library/react' import {assertImageData} from '../../Canvas/__tests__/CanvasTestHelpers' import Square from '../index' const handleSetCoordinatesStub = vi.fn() const onSetStateStub = vi.fn() const props = { coordinates: [ {x: 10, y: 10}, {x: 20, y: 20}, ], height: 500, width: 700, handleSetCoordinates: handleSetCoordinatesStub, } describe('Square', () => { afterEach(() => { handleSetCoordinatesStub.mockClear() onSetStateStub.mockClear() }) describe('#__getSquareCoordinates', () => { it('returns square coordinates given a click event', () => { const ref = React.createRef() render(<Square {...props} coordinates={[{x: 15, y: 20}]} ref={ref} />) const instance = ref.current const e = { nativeEvent: { offsetX: 30, offsetY: 50, }, } const squareCoordinates = instance.__getSquareCoordinates(e) expect(squareCoordinates.length).toBe(2) expect(squareCoordinates[0].x).toBe(15) expect(squareCoordinates[0].y).toBe(20) // width and the height expect(squareCoordinates[1].x).toBe(30) expect(squareCoordinates[1].y).toBe(50) }) }) // vitest-canvas-mock does not render actual pixels, so getImageData returns zeros. // Tests that assert positive pixel rendering are skipped. // TODO: QUIZ-17438 - Investigate alternative canvas testing approach describe('#drawShape', () => { it.skip('draws a square on canvas based on the given coordinates', () => { const ref = React.createRef() render(<Square {...props} ref={ref} />) const instance = ref.current instance.canvas.clearCanvas() const squareCoordinates = props.coordinates instance.canvas.drawShape(squareCoordinates) const ctx = instance.canvas.canvasElement.getContext('2d') const imageData = ctx.getImageData( squareCoordinates[0].x, squareCoordinates[0].y, squareCoordinates[1].x, squareCoordinates[1].y, ) assertImageData(imageData, true) }) it("does not draw a square if there's not the expected number of coordinates", () => { const ref = React.createRef() render(<Square {...props} ref={ref} />) const instance = ref.current instance.canvas.clearCanvas() const squareCoordinates = props.coordinates instance.canvas.drawShape([squareCoordinates[1]]) const ctx = instance.canvas.canvasElement.getContext('2d') // return the pixels from the range const imageData = ctx.getImageData( squareCoordinates[0].x, squareCoordinates[0].y, squareCoordinates[1].x, squareCoordinates[1].y, ) assertImageData(imageData, false) }) }) describe('events', () => { describe('onMouseDown', () => { it('sets a new initial coordinate and updates the drawing state', () => { const ref = React.createRef() render(<Square {...props} ref={ref} />) const instance = ref.current instance.canvas.setState = onSetStateStub instance.onMouseDown({ nativeEvent: {offsetX: 1, offsetY: 2}, }) const newCoordinates = handleSetCoordinatesStub.mock.calls[0][0] const newState = onSetStateStub.mock.calls[0][0] expect(newCoordinates.length).toBe(1) expect(newCoordinates[0].x).toBe(1) expect(newCoordinates[0].y).toBe(2) expect(newState.isDrawing).toBe(true) }) }) describe('onMouseUp', () => { it(`updates the coordinates and the state if the event is triggered at diferent position of the first coordinate`, () => { const ref = React.createRef() render(<Square {...props} coordinates={[{x: 1, y: 2}]} ref={ref} />) const instance = ref.current instance.canvas.state.isDrawing = true instance.canvas.setState = onSetStateStub instance.onMouseUp({ nativeEvent: {offsetX: 5, offsetY: 6}, }) const newCoordinates = handleSetCoordinatesStub.mock.calls[0][0] const newState = onSetStateStub.mock.calls[0][0] expect(newCoordinates.length).toBe(2) expect(newCoordinates[0].x).toBe(1) expect(newCoordinates[0].y).toBe(2) // width and the height expect(newCoordinates[1].x).toBe(5) expect(newCoordinates[1].y).toBe(6) expect(newState.isDrawing).toBe(false) }) it(`does not update the coordinates and the state if the event is triggered at the same position of the first coordinate`, () => { const ref = React.createRef() render(<Square {...props} coordinates={[{x: 1, y: 1}]} ref={ref} />) const instance = ref.current instance.canvas.state.isDrawing = true instance.canvas.setState = onSetStateStub instance.onMouseUp({ nativeEvent: {offsetX: 1, offsetY: 1}, }) const newCoordinates = handleSetCoordinatesStub.mock.calls[0] const newState = onSetStateStub.mock.calls[0] expect(newCoordinates).toBeUndefined() expect(newState).toBeUndefined() }) }) describe('onMouseMove', () => { it.skip('draws a square from the intial coordinate to the current coordinate', () => { const ref = React.createRef() render(<Square {...props} coordinates={[{x: 1, y: 1}]} ref={ref} />) const instance = ref.current instance.canvas.clearCanvas() instance.canvas.state.isDrawing = true instance.onMouseMove({ nativeEvent: {offsetX: 3, offsetY: 3}, }) const ctx = instance.canvas.canvasElement.getContext('2d') // return the pixels from the range const imageData = ctx.getImageData(1, 1, 3, 3) assertImageData(imageData, true) }) }) describe('onTouchMove', () => { it.skip('draws a square from the intial coordinate to the current coordinate', () => { const ref = React.createRef() render(<Square {...props} coordinates={[{x: 1, y: 1}]} ref={ref} />) const instance = ref.current instance.canvas.clearCanvas() instance.canvas.state.isDrawing = true const touchX = 300 const touchY = 300 instance.onTouchMove({ changedTouches: [{pageX: touchX, pageY: touchY}], }) const rect = instance.canvas.canvasElement.getBoundingClientRect() const x = touchX - rect.left const y = touchY - rect.top const ctx = instance.canvas.canvasElement.getContext('2d') const width = Math.max(1, x - 1) const height = Math.max(1, y - 1) // return the pixels from the range const imageData = ctx.getImageData(1, 1, width, height) assertImageData(imageData, true) }) }) describe('onTouchStart', () => { it('sets a new initial coordinate and updates the drawing state', () => { const ref = React.createRef() render(<Square {...props} ref={ref} />) const instance = ref.current instance.canvas.setState = onSetStateStub instance.onTouchStart({ preventDefault: () => {}, changedTouches: [{pageX: 10, pageY: 20}], }) const newCoordinates = handleSetCoordinatesStub.mock.calls[0][0] const newState = onSetStateStub.mock.calls[0][0] const rect = instance.canvas.canvasElement.getBoundingClientRect() const newX = 10 - rect.left const newY = 20 - rect.top expect(newCoordinates.length).toBe(1) expect(newCoordinates[0].x).toBe(newX) expect(newCoordinates[0].y).toBe(newY) expect(newState.isDrawing).toBe(true) }) }) describe('onTouchEnd', () => { it('updates the coordinates and the state', () => { const initialX = 1 const initialY = 2 const endX = 300 const endY = 250 const ref = React.createRef() render(<Square {...props} coordinates={[{x: initialX, y: initialY}]} ref={ref} />) const instance = ref.current instance.canvas.state.isDrawing = true instance.canvas.setState = onSetStateStub instance.onTouchEnd({ preventDefault: () => {}, changedTouches: [{pageX: endX, pageY: endY}], }) const rect = instance.canvas.canvasElement.getBoundingClientRect() const newX = endX - rect.left const newY = endY - rect.top const newCoordinates = handleSetCoordinatesStub.mock.calls[0][0] const newState = onSetStateStub.mock.calls[0][0] expect(newCoordinates.length).toBe(2) expect(newCoordinates[0].x).toBe(1) expect(newCoordinates[0].y).toBe(2) // width and the height expect(newCoordinates[1].x).toBe(newX) expect(newCoordinates[1].y).toBe(newY) expect(newState.isDrawing).toBe(false) }) }) }) })