Mock canvas when run unit test cases with jest.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Special testing methods added to CanvasRenderingContext2D for Jest testing. These methods track canvas operations and provide utilities for snapshot testing, assertions, and debugging canvas behavior in tests. All tracking methods record operations with transformation state and relevant properties.
Methods for tracking all canvas context operations including property changes and method calls.
/**
* Get all the events associated with this CanvasRenderingContext2D object
* Records every property set and method call with transformation state
* @returns Array of all canvas context events since creation or last clear
*/
__getEvents(): CanvasRenderingContext2DEvent[];
/**
* Clear all the events associated with this CanvasRenderingContext2D object
* Resets the event tracking array to empty state
*/
__clearEvents(): void;Usage Examples:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Perform some canvas operations
ctx.fillStyle = '#ff0000';
ctx.fillRect(10, 10, 100, 100);
ctx.strokeStyle = '#00ff00';
ctx.lineWidth = 2;
ctx.strokeRect(20, 20, 80, 80);
// Get all events for snapshot testing
const events = ctx.__getEvents();
expect(events).toMatchSnapshot();
// Clear events for next test phase
ctx.__clearEvents();
expect(ctx.__getEvents()).toHaveLength(0);Methods for tracking actual drawing operations (operations that modify pixels on the canvas).
/**
* Get all the successful draw calls associated with this CanvasRenderingContext2D object
* Only includes operations that actually draw pixels: fill, stroke, fillText, strokeText, drawImage
* @returns Array of draw call events with transformation state and properties
*/
__getDrawCalls(): CanvasRenderingContext2DEvent[];
/**
* Clear all the successful draw calls associated with this CanvasRenderingContext2D object
* Resets the draw calls tracking array to empty state
*/
__clearDrawCalls(): void;Usage Examples:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Non-drawing operations (not tracked in draw calls)
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(100, 100);
ctx.fillStyle = '#ff0000';
// Drawing operations (tracked in draw calls)
ctx.fill();
ctx.fillText('Hello', 50, 50);
// Get only the actual draw operations
const drawCalls = ctx.__getDrawCalls();
expect(drawCalls).toHaveLength(2);
expect(drawCalls[0].type).toBe('fill');
expect(drawCalls[1].type).toBe('fillText');
// Clear draw calls
ctx.__clearDrawCalls();
expect(ctx.__getDrawCalls()).toHaveLength(0);Methods for tracking the current path construction and modification.
/**
* Get the current path associated with this CanvasRenderingContext2D object
* Returns all path construction commands since the last beginPath call
* @returns Array of path events representing the current path state
*/
__getPath(): CanvasRenderingContext2DEvent[];
/**
* Clears the current path associated with this CanvasRenderingContext2D object
* Resets path to a single beginPath event and updates clipping index
*/
__clearPath(): void;Usage Examples:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Build a complex path
ctx.beginPath();
ctx.arc(50, 50, 20, 0, Math.PI * 2);
ctx.moveTo(100, 50);
ctx.lineTo(150, 100);
ctx.quadraticCurveTo(175, 75, 200, 100);
ctx.closePath();
// Get the path for testing
const path = ctx.__getPath();
expect(path).toMatchSnapshot();
expect(path[0].type).toBe('beginPath');
expect(path[1].type).toBe('arc');
expect(path[2].type).toBe('moveTo');
// Clear path (resets to beginPath)
ctx.__clearPath();
const clearedPath = ctx.__getPath();
expect(clearedPath).toHaveLength(1);
expect(clearedPath[0].type).toBe('beginPath');Method for tracking clipping operations and the current clipping region.
/**
* Obtains the current clipping path
* Returns the portion of the current path that represents the clipping region
* @returns Array of path events representing the current clipping region
*/
__getClippingRegion(): CanvasRenderingContext2DEvent[];Usage Examples:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Create a clipping path
ctx.beginPath();
ctx.rect(25, 25, 100, 100);
ctx.clip();
// Add more to the path after clipping
ctx.rect(0, 0, 50, 50);
// Get only the clipping region
const clippingRegion = ctx.__getClippingRegion();
expect(clippingRegion).toMatchSnapshot();
// The clipping region cannot be cleared as it's based on stack values
// and when the clip() function is calledAll tracking methods return arrays of CanvasRenderingContext2DEvent objects:
interface CanvasRenderingContext2DEvent {
/**
* The type of canvas event that occurred (method name or property name)
*/
type: string;
/**
* Six-element array containing the current transformation matrix state
* Format: [a, b, c, d, e, f] representing the transform matrix
*/
transform: [number, number, number, number, number, number];
/**
* Relevant properties and parameters related to this canvas event
* Contains method arguments, property values, and other contextual data
*/
props: { [key: string]: any };
}Event Type Examples:
"fillRect", "arc", "drawImage", "save", "restore""fillStyle", "lineWidth", "font", "globalAlpha""beginPath", "moveTo", "lineTo", "closePath"Transform Array:
The transform array represents the current transformation matrix as [a, b, c, d, e, f] where:
a (m11): Horizontal scalingb (m12): Horizontal skewingc (m21): Vertical skewingd (m22): Vertical scalinge (m41): Horizontal translationf (m42): Vertical translationProps Object:
Contains relevant data for the operation:
{ x: 10, y: 20, width: 100, height: 50 }{ fillStyle: "#ff0000" }{ anticlockwise: false, radius: 25 }describe('Canvas drawing operations', () => {
let canvas, ctx;
beforeEach(() => {
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
});
test('complex drawing sequence', () => {
// Setup
ctx.fillStyle = '#ff0000';
ctx.strokeStyle = '#00ff00';
ctx.lineWidth = 3;
// Drawing operations
ctx.fillRect(10, 10, 100, 100);
ctx.strokeRect(15, 15, 90, 90);
// Test complete operation sequence
expect(ctx.__getEvents()).toMatchSnapshot();
// Test only actual drawing calls
expect(ctx.__getDrawCalls()).toMatchSnapshot();
});
});test('incremental canvas operations', () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Phase 1: Setup
ctx.fillStyle = '#ff0000';
ctx.beginPath();
expect(ctx.__getEvents()).toHaveLength(2);
// Phase 2: Path construction
ctx.arc(50, 50, 25, 0, Math.PI * 2);
ctx.closePath();
expect(ctx.__getPath()).toHaveLength(3); // beginPath, arc, closePath
// Phase 3: Drawing
ctx.__clearEvents(); // Clear setup events
ctx.fill();
const drawCalls = ctx.__getDrawCalls();
expect(drawCalls).toHaveLength(1);
expect(drawCalls[0].type).toBe('fill');
});test('canvas error behavior', () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Test parameter validation
expect(() => ctx.arc(0, 0, -5, 0, Math.PI)).toThrow(DOMException);
expect(() => ctx.arc(0, 0)).toThrow(TypeError);
// Verify error operations are still tracked
const events = ctx.__getEvents();
expect(events.some(e => e.type === 'arc')).toBe(true);
});