@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
292 lines (225 loc) • 9.05 kB
JavaScript
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)
})
})
})
})