0
# Browser API Mocks
1
2
Mock implementations of browser APIs related to canvas functionality. These classes provide complete implementations that match browser behavior including proper error handling, parameter validation, and type coercion. All methods are Jest mock functions with full spy capabilities.
3
4
## Capabilities
5
6
### Path2D Class
7
8
Mock implementation of the Path2D interface for creating and manipulating 2D paths that can be used with CanvasRenderingContext2D.
9
10
```javascript { .api }
11
/**
12
* Creates a new Path2D object, optionally copying from another path or SVG path string
13
* @param path - Optional Path2D object to copy or SVG path string to parse
14
*/
15
class Path2D {
16
constructor(path?: Path2D | string);
17
18
/**
19
* Adds the given path to the current path
20
* @param path - Path2D object to add to this path
21
* @param transform - Optional transformation matrix to apply
22
* @throws {TypeError} If path parameter is not a Path2D object
23
*/
24
addPath(path: Path2D, transform?: DOMMatrix2DInit): void;
25
26
/**
27
* Adds a straight line from current point to the start of current sub-path
28
*/
29
closePath(): void;
30
31
/**
32
* Moves the starting point of a new sub-path to specified coordinates
33
* @param x - The x-axis coordinate of the point
34
* @param y - The y-axis coordinate of the point
35
*/
36
moveTo(x: number, y: number): void;
37
38
/**
39
* Connects the last point in the sub-path to specified coordinates with a straight line
40
* @param x - The x-axis coordinate of the line's end point
41
* @param y - The y-axis coordinate of the line's end point
42
*/
43
lineTo(x: number, y: number): void;
44
45
/**
46
* Adds a circular arc to the current path
47
* @param x - The x-axis coordinate of the arc's center
48
* @param y - The y-axis coordinate of the arc's center
49
* @param radius - The arc's radius
50
* @param startAngle - The angle at which the arc starts in radians
51
* @param endAngle - The angle at which the arc ends in radians
52
* @param anticlockwise - If true, draws the arc counter-clockwise
53
*/
54
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
55
56
/**
57
* Adds an arc to the current path using control points and radius
58
* @param x1 - The x-axis coordinate of the first control point
59
* @param y1 - The y-axis coordinate of the first control point
60
* @param x2 - The x-axis coordinate of the second control point
61
* @param y2 - The y-axis coordinate of the second control point
62
* @param radius - The arc's radius
63
*/
64
arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
65
66
/**
67
* Adds a quadratic Bézier curve to the current path
68
* @param cpx - The x-axis coordinate of the control point
69
* @param cpy - The y-axis coordinate of the control point
70
* @param x - The x-axis coordinate of the end point
71
* @param y - The y-axis coordinate of the end point
72
*/
73
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
74
75
/**
76
* Adds a cubic Bézier curve to the current path
77
* @param cp1x - The x-axis coordinate of the first control point
78
* @param cp1y - The y-axis coordinate of the first control point
79
* @param cp2x - The x-axis coordinate of the second control point
80
* @param cp2y - The y-axis coordinate of the second control point
81
* @param x - The x-axis coordinate of the end point
82
* @param y - The y-axis coordinate of the end point
83
*/
84
bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
85
86
/**
87
* Adds an ellipse to the current path
88
* @param x - The x-axis coordinate of the ellipse's center
89
* @param y - The y-axis coordinate of the ellipse's center
90
* @param radiusX - The ellipse's major-axis radius
91
* @param radiusY - The ellipse's minor-axis radius
92
* @param rotation - The rotation of the ellipse in radians
93
* @param startAngle - The starting angle in radians
94
* @param endAngle - The ending angle in radians
95
* @param anticlockwise - If true, draws counter-clockwise
96
*/
97
ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
98
99
/**
100
* Adds a rectangle to the current path
101
* @param x - The x-axis coordinate of the rectangle's starting point
102
* @param y - The y-axis coordinate of the rectangle's starting point
103
* @param width - The rectangle's width
104
* @param height - The rectangle's height
105
*/
106
rect(x: number, y: number, width: number, height: number): void;
107
}
108
```
109
110
**Usage Examples:**
111
112
```javascript
113
// Create a new path
114
const path = new Path2D();
115
116
// Build the path
117
path.moveTo(10, 10);
118
path.lineTo(100, 100);
119
path.arc(50, 50, 25, 0, Math.PI * 2);
120
path.closePath();
121
122
// Use with canvas context
123
const canvas = document.createElement('canvas');
124
const ctx = canvas.getContext('2d');
125
ctx.fill(path);
126
ctx.stroke(path);
127
128
// Copy another path
129
const path2 = new Path2D(path);
130
path2.addPath(path);
131
```
132
133
### ImageData Class
134
135
Mock implementation of ImageData for representing pixel data with proper validation and error handling.
136
137
```javascript { .api }
138
/**
139
* Creates ImageData object with specified dimensions (filled with transparent black)
140
* @param width - The width of the ImageData object
141
* @param height - The height of the ImageData object
142
* @throws {RangeError} If width or height is zero or not finite
143
*/
144
class ImageData {
145
constructor(width: number, height: number);
146
147
/**
148
* Creates ImageData object from existing Uint8ClampedArray data
149
* @param data - Uint8ClampedArray containing pixel data (RGBA format)
150
* @param width - The width of the ImageData object
151
* @param height - Optional height (calculated from data length if not provided)
152
* @throws {RangeError} If data length is not a multiple of 4 or dimensions are invalid
153
* @throws {TypeError} If data is not a Uint8ClampedArray
154
*/
155
constructor(data: Uint8ClampedArray, width: number, height?: number);
156
157
/**
158
* The width of the ImageData object in pixels (read-only)
159
*/
160
readonly width: number;
161
162
/**
163
* The height of the ImageData object in pixels (read-only)
164
*/
165
readonly height: number;
166
167
/**
168
* Uint8ClampedArray containing pixel data in RGBA format (read-only)
169
* Each pixel represented by 4 consecutive values: R, G, B, A (0-255)
170
*/
171
readonly data: Uint8ClampedArray;
172
}
173
```
174
175
**Usage Examples:**
176
177
```javascript
178
// Create empty 100x100 ImageData
179
const imageData1 = new ImageData(100, 100);
180
console.log(imageData1.width); // 100
181
console.log(imageData1.height); // 100
182
console.log(imageData1.data.length); // 40000 (100 * 100 * 4)
183
184
// Create from existing data
185
const pixelData = new Uint8ClampedArray([255, 0, 0, 255, 0, 255, 0, 255]); // 2 pixels
186
const imageData2 = new ImageData(pixelData, 2, 1);
187
188
// Error cases
189
expect(() => new ImageData(0, 100)).toThrow(RangeError);
190
expect(() => new ImageData([1, 2, 3], 1)).toThrow(TypeError);
191
```
192
193
### TextMetrics Class
194
195
Mock implementation of TextMetrics containing text measurement information.
196
197
```javascript { .api }
198
/**
199
* Contains metrics information for measured text
200
* @param text - The text that was measured (used to calculate basic width)
201
*/
202
class TextMetrics {
203
constructor(text: string);
204
205
/**
206
* The width of the text in CSS pixels (calculated as text length)
207
*/
208
width: number;
209
210
/**
211
* Distance from the alignment point to the left of the bounding box
212
*/
213
actualBoundingBoxLeft: number;
214
215
/**
216
* Distance from the alignment point to the right of the bounding box
217
*/
218
actualBoundingBoxRight: number;
219
220
/**
221
* Distance from the horizontal line to the top of the font bounding box
222
*/
223
fontBoundingBoxAscent: number;
224
225
/**
226
* Distance from the horizontal line to the bottom of the font bounding box
227
*/
228
fontBoundingBoxDescent: number;
229
230
/**
231
* Distance from the horizontal line to the top of the actual bounding box
232
*/
233
actualBoundingBoxAscent: number;
234
235
/**
236
* Distance from the horizontal line to the bottom of the actual bounding box
237
*/
238
actualBoundingBoxDescent: number;
239
240
/**
241
* Distance from the horizontal line to the top of the em square
242
*/
243
emHeightAscent: number;
244
245
/**
246
* Distance from the horizontal line to the bottom of the em square
247
*/
248
emHeightDescent: number;
249
250
/**
251
* Distance from the horizontal line to the hanging baseline
252
*/
253
hangingBaseline: number;
254
255
/**
256
* Distance from the horizontal line to the alphabetic baseline
257
*/
258
alphabeticBaseline: number;
259
260
/**
261
* Distance from the horizontal line to the ideographic baseline
262
*/
263
ideographicBaseline: number;
264
}
265
```
266
267
### CanvasGradient Class
268
269
Mock implementation of CanvasGradient for creating gradient fills and strokes.
270
271
```javascript { .api }
272
/**
273
* Represents a gradient that can be used as fillStyle or strokeStyle
274
*/
275
class CanvasGradient {
276
constructor();
277
278
/**
279
* Adds a color stop to the gradient
280
* @param offset - Position of the color stop (0.0 to 1.0)
281
* @param color - CSS color value for the stop
282
* @throws {DOMException} If offset is outside the range (0.0, 1.0)
283
* @throws {SyntaxError} If color cannot be parsed as a valid CSS color
284
*/
285
addColorStop(offset: number, color: string): void;
286
}
287
```
288
289
**Usage Examples:**
290
291
```javascript
292
const canvas = document.createElement('canvas');
293
const ctx = canvas.getContext('2d');
294
295
// Create linear gradient
296
const gradient = ctx.createLinearGradient(0, 0, 100, 0);
297
gradient.addColorStop(0, '#ff0000');
298
gradient.addColorStop(0.5, '#00ff00');
299
gradient.addColorStop(1, '#0000ff');
300
301
// Use gradient
302
ctx.fillStyle = gradient;
303
ctx.fillRect(0, 0, 100, 100);
304
305
// Error cases
306
expect(() => gradient.addColorStop(-0.5, '#ff0000')).toThrow(DOMException);
307
expect(() => gradient.addColorStop(0.5, 'invalid-color')).toThrow(SyntaxError);
308
```
309
310
### CanvasPattern Class
311
312
Mock implementation of CanvasPattern for creating pattern fills and strokes.
313
314
```javascript { .api }
315
/**
316
* Represents a pattern that can be used as fillStyle or strokeStyle
317
*/
318
class CanvasPattern {
319
constructor();
320
321
/**
322
* Sets the transformation matrix for the pattern
323
* @param transform - DOMMatrix2DInit object representing the transformation
324
* @throws {TypeError} If transform is provided but is not an object
325
*/
326
setTransform(transform?: DOMMatrix2DInit): void;
327
}
328
```
329
330
### DOMMatrix Class
331
332
Mock implementation of DOMMatrix for representing 2D and 3D transformation matrices.
333
334
```javascript { .api }
335
/**
336
* Represents a 2D or 3D transformation matrix
337
* @param transform - Optional initial transformation as array or existing DOMMatrix
338
*/
339
class DOMMatrix {
340
constructor(transform?: number[] | DOMMatrix);
341
342
// Matrix elements (2D and 3D)
343
m11: number; m12: number; m13: number; m14: number;
344
m21: number; m22: number; m23: number; m24: number;
345
m31: number; m32: number; m33: number; m34: number;
346
m41: number; m42: number; m43: number; m44: number;
347
348
// 2D aliases (getters/setters)
349
a: number; // m11
350
b: number; // m12
351
c: number; // m21
352
d: number; // m22
353
e: number; // m41
354
f: number; // m42
355
356
/**
357
* Whether the matrix represents a 2D transformation (read-only)
358
*/
359
readonly is2D: boolean;
360
361
/**
362
* Whether the matrix is the identity matrix (read-only)
363
*/
364
readonly isIdentity: boolean;
365
366
/**
367
* Returns Float32Array representation of the matrix
368
* @returns 16-element Float32Array
369
*/
370
toFloat32Array(): Float32Array;
371
372
/**
373
* Returns Float64Array representation of the matrix
374
* @returns 16-element Float64Array
375
*/
376
toFloat64Array(): Float64Array;
377
378
/**
379
* Returns new matrix with translation applied
380
* @param x - Translation distance in x direction
381
* @param y - Translation distance in y direction
382
* @param z - Translation distance in z direction (optional)
383
* @returns New DOMMatrix with translation applied
384
*/
385
translate(x: number, y: number, z?: number): DOMMatrix;
386
387
/**
388
* Applies translation to this matrix (modifies in place)
389
* @param x - Translation distance in x direction
390
* @param y - Translation distance in y direction
391
* @param z - Translation distance in z direction (optional)
392
* @returns This matrix (for chaining)
393
*/
394
translateSelf(x: number, y: number, z?: number): DOMMatrix;
395
396
/**
397
* Returns new matrix with scaling applied
398
* @param scaleX - Scaling factor in x direction
399
* @param scaleY - Scaling factor in y direction (defaults to scaleX)
400
* @param scaleZ - Scaling factor in z direction (defaults to 1)
401
* @param originX - Origin x coordinate for scaling (defaults to 0)
402
* @param originY - Origin y coordinate for scaling (defaults to 0)
403
* @param originZ - Origin z coordinate for scaling (defaults to 0)
404
* @returns New DOMMatrix with scaling applied
405
*/
406
scale(scaleX: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix;
407
408
/**
409
* Applies scaling to this matrix (modifies in place)
410
* @param scaleX - Scaling factor in x direction
411
* @param scaleY - Scaling factor in y direction (defaults to scaleX)
412
* @param scaleZ - Scaling factor in z direction (defaults to 1)
413
* @param originX - Origin x coordinate for scaling (defaults to 0)
414
* @param originY - Origin y coordinate for scaling (defaults to 0)
415
* @param originZ - Origin z coordinate for scaling (defaults to 0)
416
* @returns This matrix (for chaining)
417
*/
418
scaleSelf(scaleX: number, scaleY?: number, scaleZ?: number, originX?: number, originY?: number, originZ?: number): DOMMatrix;
419
}
420
```
421
422
### ImageBitmap Class
423
424
Mock implementation of ImageBitmap for representing bitmap images.
425
426
```javascript { .api }
427
/**
428
* Represents a bitmap image that can be drawn to a canvas
429
* @param width - Width of the bitmap
430
* @param height - Height of the bitmap
431
*/
432
class ImageBitmap {
433
constructor(width: number, height: number);
434
435
/**
436
* Width of the bitmap in pixels
437
*/
438
width: number;
439
440
/**
441
* Height of the bitmap in pixels
442
*/
443
height: number;
444
445
/**
446
* Releases resources associated with the bitmap
447
* Sets width and height to 0 and marks as closed
448
*/
449
close(): void;
450
}
451
```
452
453
### createImageBitmap Function
454
455
Mock implementation of the global createImageBitmap function for creating ImageBitmap objects from various sources.
456
457
```javascript { .api }
458
/**
459
* Creates an ImageBitmap from an image source
460
* @param image - Image source (HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, Blob, ImageData, ImageBitmap)
461
* @param options - Optional configuration for the bitmap creation
462
* @returns Promise that resolves to an ImageBitmap
463
* @throws {TypeError} If image source is invalid or options parameter is not an object
464
*/
465
function createImageBitmap(
466
image: ImageBitmapSource,
467
options?: ImageBitmapOptions
468
): Promise<ImageBitmap>;
469
470
/**
471
* Creates an ImageBitmap from a cropped portion of an image source
472
* @param image - Image source
473
* @param sx - Source x coordinate
474
* @param sy - Source y coordinate
475
* @param sw - Source width
476
* @param sh - Source height
477
* @param options - Optional configuration for the bitmap creation
478
* @returns Promise that resolves to an ImageBitmap
479
* @throws {RangeError} If crop dimensions are zero or invalid
480
*/
481
function createImageBitmap(
482
image: ImageBitmapSource,
483
sx: number, sy: number, sw: number, sh: number,
484
options?: ImageBitmapOptions
485
): Promise<ImageBitmap>;
486
```
487
488
**Usage Examples:**
489
490
```javascript
491
// From canvas element
492
const canvas = document.createElement('canvas');
493
const bitmap1 = await createImageBitmap(canvas);
494
495
// From image element with cropping
496
const img = new Image();
497
const bitmap2 = await createImageBitmap(img, 10, 10, 100, 100);
498
499
// With options
500
const bitmap3 = await createImageBitmap(canvas, {
501
imageOrientation: 'flipY',
502
resizeWidth: 200,
503
resizeHeight: 200
504
});
505
506
// Error cases
507
await expect(createImageBitmap()).rejects.toThrow(TypeError);
508
await expect(createImageBitmap(canvas, 0, 0, 0, 100)).rejects.toThrow(RangeError);
509
```
510
511
## HTML Canvas Element Extensions
512
513
Extensions to HTMLCanvasElement.prototype for enhanced canvas testing capabilities.
514
515
```javascript { .api }
516
/**
517
* Enhanced getContext method that returns mock 2D contexts
518
* @param contextType - The context type to create ('2d', 'webgl', etc.)
519
* @returns Mock CanvasRenderingContext2D for '2d', null for unsupported types
520
*/
521
HTMLCanvasElement.prototype.getContext(contextType: string): CanvasRenderingContext2D | null;
522
523
/**
524
* Mock implementation of toBlob that creates mock Blob objects
525
* @param callback - Callback function to receive the blob
526
* @param type - MIME type for the blob ('image/png', 'image/jpeg', 'image/webp')
527
* @param encoderOptions - Quality setting for lossy formats
528
* @throws {TypeError} If callback is not provided or not a function
529
*/
530
HTMLCanvasElement.prototype.toBlob(callback: BlobCallback, type?: string, encoderOptions?: any): void;
531
532
/**
533
* Mock implementation of toDataURL that returns mock data URLs
534
* @param type - MIME type for the data URL ('image/png', 'image/jpeg', 'image/webp')
535
* @param encoderOptions - Quality setting for lossy formats
536
* @returns Mock data URL string
537
*/
538
HTMLCanvasElement.prototype.toDataURL(type?: string, encoderOptions?: any): string;
539
```
540
541
All browser API mocks are fully integrated with Jest's mocking system, providing complete spy functionality for testing and verification.