4 <script src="../../http/tests/inspector/resources/inspector-test.js"></script>
5 <script src="resources/recording-utilities.js"></script>
10 let image = document.createElement("img");
11 image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=";
14 let video = document.createElement("video");
17 let canvas = document.createElement("canvas");
21 let linearGradient = null;
23 let radialGradient = null;
27 let path12 = new Path2D("M 1 2");
28 let path34 = new Path2D("M 3 4");
30 let imageData14 = new ImageData(1, 4);
31 let imageData23 = new ImageData(2, 3);
34 ctx = canvas.getContext("2d");
35 linearGradient = ctx.createLinearGradient(1, 2, 3, 4);
36 radialGradient = ctx.createRadialGradient(1, 2, 3, 4, 5, 6);
37 pattern = ctx.createPattern(image, "no-repeat");
39 document.body.appendChild(canvas);
42 ctx.save(); // This matches the `restore` call in `performActions`.
47 function ignoreException(func){
54 let restoreCalled = false;
56 function cancelActions() {
57 if (!isNaN(timeoutID)) {
63 clearTimeout(timeoutID);
70 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
72 restoreCalled = false;
75 function performActions() {
78 ignoreException(() => ctx.arc(1, 2, 3, 4, 5));
79 ignoreException(() => ctx.arc(6, 7, 8, 9, 10, true));
82 ignoreException(() => ctx.arcTo(1, 2, 3, 4, 5));
88 ctx.bezierCurveTo(1, 2, 3, 4, 5, 6);
91 ctx.clearRect(1, 2, 3, 4);
100 ctx.clip(path34, "evenodd");
106 ignoreException(() => ctx.createImageData(imageData14));
107 ignoreException(() => ctx.createImageData(2, 3));
110 ignoreException(() => ctx.createLinearGradient(1, 2, 3, 4));
113 ignoreException(() => ctx.createPattern(image, "testA"));
114 ignoreException(() => ctx.createPattern(video, "testB"));
115 ignoreException(() => ctx.createPattern(canvas, "testC"));
118 ignoreException(() => ctx.createRadialGradient(1, 2, 3, 4, 5, 6));
122 ctx.direction = "test";
125 ctx.drawFocusIfNeeded(document.body);
126 ctx.drawFocusIfNeeded(path12, document.body);
129 ignoreException(() => ctx.drawImage(image, 1, 2));
130 ignoreException(() => ctx.drawImage(video, 3, 4));
131 ignoreException(() => ctx.drawImage(canvas, 5, 6));
132 ignoreException(() => ctx.drawImage(image, 7, 8, 9, 10));
133 ignoreException(() => ctx.drawImage(video, 11, 12, 13, 14));
134 ignoreException(() => ctx.drawImage(canvas, 15, 16, 17, 18));
135 ignoreException(() => ctx.drawImage(image, 19, 20, 21, 22, 23, 24, 25, 26));
136 ignoreException(() => ctx.drawImage(video, 27, 28, 29, 30, 31, 32, 33, 34));
137 ignoreException(() => ctx.drawImage(canvas, 35, 36, 37, 38, 39, 40, 41 ,42));
140 ctx.drawImageFromRect(image, 1, 2, 3, 4, 5, 6, 7, 8)
141 ctx.drawImageFromRect(image, 9, 10, 11, 12, 13, 14, 15, 16, "test");
144 ignoreException(() => ctx.ellipse(1, 2, 3, 4, 5, 6, 7));
145 ignoreException(() => ctx.ellipse(8, 9, 10, 11, 12, 13, 14, true));
151 ctx.fill(path34, "evenodd");
154 ctx.fillRect(1, 2, 3, 4);
158 ctx.fillStyle = "test";
159 ctx.fillStyle = linearGradient;
160 ctx.fillStyle = radialGradient;
161 ctx.fillStyle = pattern;
164 ctx.fillText("testA", 1, 2);
165 ctx.fillText("testB", 3, 4, 5);
172 ignoreException(() => ctx.getImageData(1, 2, 3, 4));
185 ctx.globalCompositeOperation;
186 ctx.globalCompositeOperation = "test";
189 ctx.imageSmoothingEnabled;
190 ctx.imageSmoothingEnabled = true;
193 ctx.imageSmoothingQuality;
194 ctx.imageSmoothingQuality = "low";
197 ctx.isPointInPath(path12, 5, 6);
198 ctx.isPointInPath(path34, 7, 8, "evenodd");
199 ctx.isPointInPath(9, 10);
200 ctx.isPointInPath(11, 12, "evenodd");
203 ctx.isPointInStroke(path12, 3, 4);
204 ctx.isPointInStroke(5, 6);
208 ctx.lineCap = "test";
212 ctx.lineDashOffset = 1;
216 ctx.lineJoin = "test";
226 ctx.measureText("test");
236 ctx.putImageData(imageData14, 5, 6);
237 ctx.putImageData(imageData23, 7, 8, 9, 10, 11, 12);
240 ctx.quadraticCurveTo(1, 2, 3, 4);
243 ctx.rect(1, 2, 3, 4);
246 ctx.resetTransform();
251 restoreCalled = true;
267 ctx.setCompositeOperation();
268 ctx.setCompositeOperation("test");
271 ctx.setFillColor("testA");
272 ctx.setFillColor("testB", 1);
274 ctx.setFillColor(3, 4);
275 ctx.setFillColor(5, 6, 7, 8);
276 ctx.setFillColor(9, 10, 11, 12, 13);
280 ctx.setLineCap("test");
283 ctx.setLineDash([1, 2]);
287 ctx.setLineJoin("test");
295 ctx.setMiterLimit(1);
298 ctx.setShadow(1, 2, 3);
299 ctx.setShadow(4, 5, 6, "test", 7);
300 ctx.setShadow(8, 9, 10, 11);
301 ctx.setShadow(12, 13, 14, 15, 16);
302 ctx.setShadow(17, 18, 19, 20, 21, 22, 23);
303 ctx.setShadow(24, 25, 26, 27, 28, 29, 30, 31);
306 ctx.setStrokeColor("testA");
307 ctx.setStrokeColor("testB", 1);
308 ctx.setStrokeColor(2);
309 ctx.setStrokeColor(3, 4);
310 ctx.setStrokeColor(5, 6, 7, 8);
311 ctx.setStrokeColor(9, 10, 11, 12, 13);
314 ctx.setTransform(1, 2, 3, 4, 5, 6);
315 ignoreException(() => ctx.setTransform());
316 ignoreException(() => ctx.setTransform(new DOMMatrix([7, 8, 9, 10, 11, 12])));
324 ctx.shadowColor = "test";
328 ctx.shadowOffsetX = 1;
332 ctx.shadowOffsetY = 1;
339 ctx.strokeRect(1, 2, 3, 4);
343 ctx.strokeStyle = "test";
344 ctx.strokeStyle = linearGradient;
345 ctx.strokeStyle = radialGradient;
346 ctx.strokeStyle = pattern;
349 ctx.strokeText("testA", 1, 2);
350 ctx.strokeText("testB", 3, 4, 5);
354 ctx.textAlign = "test";
358 ctx.textBaseline = "test";
361 ctx.transform(1, 2, 3, 4, 5, 6);
367 ignoreException(() => ctx.webkitGetImageDataHD(1, 2, 3, 4));
370 ctx.webkitImageSmoothingEnabled;
371 ctx.webkitImageSmoothingEnabled = true;
375 ctx.webkitLineDash = [1, 2];
378 ctx.webkitLineDashOffset;
379 ctx.webkitLineDashOffset = 1;
382 ctx.webkitPutImageDataHD(imageData14, 5, 6);
383 ctx.webkitPutImageDataHD(imageData23, 7, 8, 9, 10, 11, 12);
386 TestPage.dispatchEventToFrontend("LastFrame");
390 function executeFrameFunction() {
392 if (index < frames.length)
393 timeoutID = setTimeout(executeFrameFunction, 0);
395 executeFrameFunction();
398 function performNaNActions() {
399 ctx.globalAlpha = NaN;
403 let suite = InspectorTest.createAsyncSuite("Canvas.recording2D");
406 name: "Canvas.recording2D.singleFrame",
407 description: "Check that the recording is stopped after a single frame.",
408 test(resolve, reject) {
409 startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {singleFrame: true});
414 name: "Canvas.recording2D.multipleFrames",
415 description: "Check that recording data is serialized correctly for multiple frames.",
416 test(resolve, reject) {
417 let canvas = startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {singleFrame: false});
419 InspectorTest.singleFireEventListener("LastFrame", () => {
420 CanvasAgent.stopRecording(canvas.identifier, (error) => {
431 name: "Canvas.recording2D.memoryLimit",
432 description: "Check that the recording is stopped when it reaches the memory limit.",
433 test(resolve, reject) {
434 startRecording(WI.Canvas.ContextType.Canvas2D, resolve, reject, {memoryLimit: 10});
439 name: "Canvas.recording2D.ActionParameterNaN",
440 description: "Check that NaN is converted into the proper value for serialization.",
441 test(resolve, reject) {
442 let canvas = getCanvas(WI.Canvas.ContextType.Canvas2D);
444 reject("Missing 2D canvas.");
448 WI.canvasManager.awaitEvent(WI.CanvasManager.Event.RecordingStopped)
450 let recording = event.data.recording.toJSON();
452 let frames = recording.frames;
453 InspectorTest.expectEqual(frames.length, 1, "The recording should have 1 frame.");
455 let actions = frames[0].actions;
456 InspectorTest.expectEqual(actions.length, 1, "The first frame should have 1 action.");
457 InspectorTest.expectEqual(actions[0][1].length, 1, "The action should have 1 parameter.");
458 InspectorTest.expectEqual(actions[0][1][0], null, "The parameter should be null.");
460 .then(resolve, reject);
462 const singleFrame = true;
463 CanvasAgent.startRecording(canvas.identifier, singleFrame, (error) => {
469 InspectorTest.evaluateInPage(`performNaNActions()`);
475 name: "Canvas.recording2D.NoActions",
476 description: "Check that a canvas is still able to be recorded after stopping a recording with no actions.",
477 test(resolve, reject) {
478 let canvas = getCanvas(WI.Canvas.ContextType.Canvas2D);
480 throw "Missing 2D canvas.";
483 function handleRecordingStopped(event) {
484 InspectorTest.assert(event.data.canvas === canvas, "We should have stopped recording the selected canvas.");
488 InspectorTest.pass("A recording should have been started and stopped once.");
490 if (eventCount >= 2) {
491 InspectorTest.pass("A recording should have been started and stopped twice.");
493 WI.canvasManager.removeEventListener(handleRecordingStopped);
497 WI.canvasManager.addEventListener(WI.CanvasManager.Event.RecordingStopped, handleRecordingStopped);
499 WI.canvasManager.startRecording(canvas);
500 WI.canvasManager.stopRecording();
502 WI.canvasManager.startRecording(canvas);
503 WI.canvasManager.stopRecording();
507 suite.runTestCasesAndFinish();
511 <body onload="load()">
512 <p>Test that CanvasManager is able to record actions made to 2D canvas contexts.</p>