0
# Test Utilities
1
2
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.
3
4
## Capabilities
5
6
### Event Tracking
7
8
Methods for tracking all canvas context operations including property changes and method calls.
9
10
```javascript { .api }
11
/**
12
* Get all the events associated with this CanvasRenderingContext2D object
13
* Records every property set and method call with transformation state
14
* @returns Array of all canvas context events since creation or last clear
15
*/
16
__getEvents(): CanvasRenderingContext2DEvent[];
17
18
/**
19
* Clear all the events associated with this CanvasRenderingContext2D object
20
* Resets the event tracking array to empty state
21
*/
22
__clearEvents(): void;
23
```
24
25
**Usage Examples:**
26
27
```javascript
28
const canvas = document.createElement('canvas');
29
const ctx = canvas.getContext('2d');
30
31
// Perform some canvas operations
32
ctx.fillStyle = '#ff0000';
33
ctx.fillRect(10, 10, 100, 100);
34
ctx.strokeStyle = '#00ff00';
35
ctx.lineWidth = 2;
36
ctx.strokeRect(20, 20, 80, 80);
37
38
// Get all events for snapshot testing
39
const events = ctx.__getEvents();
40
expect(events).toMatchSnapshot();
41
42
// Clear events for next test phase
43
ctx.__clearEvents();
44
expect(ctx.__getEvents()).toHaveLength(0);
45
```
46
47
### Draw Call Tracking
48
49
Methods for tracking actual drawing operations (operations that modify pixels on the canvas).
50
51
```javascript { .api }
52
/**
53
* Get all the successful draw calls associated with this CanvasRenderingContext2D object
54
* Only includes operations that actually draw pixels: fill, stroke, fillText, strokeText, drawImage
55
* @returns Array of draw call events with transformation state and properties
56
*/
57
__getDrawCalls(): CanvasRenderingContext2DEvent[];
58
59
/**
60
* Clear all the successful draw calls associated with this CanvasRenderingContext2D object
61
* Resets the draw calls tracking array to empty state
62
*/
63
__clearDrawCalls(): void;
64
```
65
66
**Usage Examples:**
67
68
```javascript
69
const canvas = document.createElement('canvas');
70
const ctx = canvas.getContext('2d');
71
72
// Non-drawing operations (not tracked in draw calls)
73
ctx.beginPath();
74
ctx.moveTo(10, 10);
75
ctx.lineTo(100, 100);
76
ctx.fillStyle = '#ff0000';
77
78
// Drawing operations (tracked in draw calls)
79
ctx.fill();
80
ctx.fillText('Hello', 50, 50);
81
82
// Get only the actual draw operations
83
const drawCalls = ctx.__getDrawCalls();
84
expect(drawCalls).toHaveLength(2);
85
expect(drawCalls[0].type).toBe('fill');
86
expect(drawCalls[1].type).toBe('fillText');
87
88
// Clear draw calls
89
ctx.__clearDrawCalls();
90
expect(ctx.__getDrawCalls()).toHaveLength(0);
91
```
92
93
### Path Tracking
94
95
Methods for tracking the current path construction and modification.
96
97
```javascript { .api }
98
/**
99
* Get the current path associated with this CanvasRenderingContext2D object
100
* Returns all path construction commands since the last beginPath call
101
* @returns Array of path events representing the current path state
102
*/
103
__getPath(): CanvasRenderingContext2DEvent[];
104
105
/**
106
* Clears the current path associated with this CanvasRenderingContext2D object
107
* Resets path to a single beginPath event and updates clipping index
108
*/
109
__clearPath(): void;
110
```
111
112
**Usage Examples:**
113
114
```javascript
115
const canvas = document.createElement('canvas');
116
const ctx = canvas.getContext('2d');
117
118
// Build a complex path
119
ctx.beginPath();
120
ctx.arc(50, 50, 20, 0, Math.PI * 2);
121
ctx.moveTo(100, 50);
122
ctx.lineTo(150, 100);
123
ctx.quadraticCurveTo(175, 75, 200, 100);
124
ctx.closePath();
125
126
// Get the path for testing
127
const path = ctx.__getPath();
128
expect(path).toMatchSnapshot();
129
expect(path[0].type).toBe('beginPath');
130
expect(path[1].type).toBe('arc');
131
expect(path[2].type).toBe('moveTo');
132
133
// Clear path (resets to beginPath)
134
ctx.__clearPath();
135
const clearedPath = ctx.__getPath();
136
expect(clearedPath).toHaveLength(1);
137
expect(clearedPath[0].type).toBe('beginPath');
138
```
139
140
### Clipping Region Tracking
141
142
Method for tracking clipping operations and the current clipping region.
143
144
```javascript { .api }
145
/**
146
* Obtains the current clipping path
147
* Returns the portion of the current path that represents the clipping region
148
* @returns Array of path events representing the current clipping region
149
*/
150
__getClippingRegion(): CanvasRenderingContext2DEvent[];
151
```
152
153
**Usage Examples:**
154
155
```javascript
156
const canvas = document.createElement('canvas');
157
const ctx = canvas.getContext('2d');
158
159
// Create a clipping path
160
ctx.beginPath();
161
ctx.rect(25, 25, 100, 100);
162
ctx.clip();
163
164
// Add more to the path after clipping
165
ctx.rect(0, 0, 50, 50);
166
167
// Get only the clipping region
168
const clippingRegion = ctx.__getClippingRegion();
169
expect(clippingRegion).toMatchSnapshot();
170
171
// The clipping region cannot be cleared as it's based on stack values
172
// and when the clip() function is called
173
```
174
175
## Event Object Structure
176
177
All tracking methods return arrays of `CanvasRenderingContext2DEvent` objects:
178
179
```javascript { .api }
180
interface CanvasRenderingContext2DEvent {
181
/**
182
* The type of canvas event that occurred (method name or property name)
183
*/
184
type: string;
185
186
/**
187
* Six-element array containing the current transformation matrix state
188
* Format: [a, b, c, d, e, f] representing the transform matrix
189
*/
190
transform: [number, number, number, number, number, number];
191
192
/**
193
* Relevant properties and parameters related to this canvas event
194
* Contains method arguments, property values, and other contextual data
195
*/
196
props: { [key: string]: any };
197
}
198
```
199
200
**Event Type Examples:**
201
202
- Method calls: `"fillRect"`, `"arc"`, `"drawImage"`, `"save"`, `"restore"`
203
- Property sets: `"fillStyle"`, `"lineWidth"`, `"font"`, `"globalAlpha"`
204
- Path operations: `"beginPath"`, `"moveTo"`, `"lineTo"`, `"closePath"`
205
206
**Transform Array:**
207
208
The transform array represents the current transformation matrix as `[a, b, c, d, e, f]` where:
209
- `a` (m11): Horizontal scaling
210
- `b` (m12): Horizontal skewing
211
- `c` (m21): Vertical skewing
212
- `d` (m22): Vertical scaling
213
- `e` (m41): Horizontal translation
214
- `f` (m42): Vertical translation
215
216
**Props Object:**
217
218
Contains relevant data for the operation:
219
- Method arguments: `{ x: 10, y: 20, width: 100, height: 50 }`
220
- Property values: `{ fillStyle: "#ff0000" }`
221
- Additional context: `{ anticlockwise: false, radius: 25 }`
222
223
## Advanced Testing Patterns
224
225
### Snapshot Testing Workflow
226
227
```javascript
228
describe('Canvas drawing operations', () => {
229
let canvas, ctx;
230
231
beforeEach(() => {
232
canvas = document.createElement('canvas');
233
ctx = canvas.getContext('2d');
234
});
235
236
test('complex drawing sequence', () => {
237
// Setup
238
ctx.fillStyle = '#ff0000';
239
ctx.strokeStyle = '#00ff00';
240
ctx.lineWidth = 3;
241
242
// Drawing operations
243
ctx.fillRect(10, 10, 100, 100);
244
ctx.strokeRect(15, 15, 90, 90);
245
246
// Test complete operation sequence
247
expect(ctx.__getEvents()).toMatchSnapshot();
248
249
// Test only actual drawing calls
250
expect(ctx.__getDrawCalls()).toMatchSnapshot();
251
});
252
});
253
```
254
255
### Incremental Testing
256
257
```javascript
258
test('incremental canvas operations', () => {
259
const canvas = document.createElement('canvas');
260
const ctx = canvas.getContext('2d');
261
262
// Phase 1: Setup
263
ctx.fillStyle = '#ff0000';
264
ctx.beginPath();
265
expect(ctx.__getEvents()).toHaveLength(2);
266
267
// Phase 2: Path construction
268
ctx.arc(50, 50, 25, 0, Math.PI * 2);
269
ctx.closePath();
270
expect(ctx.__getPath()).toHaveLength(3); // beginPath, arc, closePath
271
272
// Phase 3: Drawing
273
ctx.__clearEvents(); // Clear setup events
274
ctx.fill();
275
276
const drawCalls = ctx.__getDrawCalls();
277
expect(drawCalls).toHaveLength(1);
278
expect(drawCalls[0].type).toBe('fill');
279
});
280
```
281
282
### Error Validation Testing
283
284
```javascript
285
test('canvas error behavior', () => {
286
const canvas = document.createElement('canvas');
287
const ctx = canvas.getContext('2d');
288
289
// Test parameter validation
290
expect(() => ctx.arc(0, 0, -5, 0, Math.PI)).toThrow(DOMException);
291
expect(() => ctx.arc(0, 0)).toThrow(TypeError);
292
293
// Verify error operations are still tracked
294
const events = ctx.__getEvents();
295
expect(events.some(e => e.type === 'arc')).toBe(true);
296
});
297
```