| 
									
										
										
										
											2020-08-10 21:22:57 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright Microsoft Corporation. All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-08-16 19:19:52 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-25 15:05:50 -08:00
										 |  |  | import { browserTest as it, expect } from '../config/browserTest'; | 
					
						
							| 
									
										
										
										
											2020-08-14 07:22:54 -07:00
										 |  |  | import fs from 'fs'; | 
					
						
							|  |  |  | import path from 'path'; | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | import { spawnSync } from 'child_process'; | 
					
						
							|  |  |  | import { PNG } from 'pngjs'; | 
					
						
							| 
									
										
										
										
											2022-03-25 15:05:50 -08:00
										 |  |  | import { registry } from '../../packages/playwright-core/lib/utils/registry'; | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 18:58:13 +02:00
										 |  |  | const ffmpeg = registry.findExecutable('ffmpeg')!.executablePath('javascript'); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class VideoPlayer { | 
					
						
							|  |  |  |   fileName: string; | 
					
						
							|  |  |  |   output: string; | 
					
						
							|  |  |  |   duration: number; | 
					
						
							|  |  |  |   frames: number; | 
					
						
							|  |  |  |   videoWidth: number; | 
					
						
							|  |  |  |   videoHeight: number; | 
					
						
							|  |  |  |   cache = new Map<number, PNG>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(fileName: string) { | 
					
						
							|  |  |  |     this.fileName = fileName; | 
					
						
							| 
									
										
										
										
											2020-10-23 10:33:58 -07:00
										 |  |  |     // Force output frame rate to 25 fps as otherwise it would produce one image per timebase unit
 | 
					
						
							|  |  |  |     // which is 1 / (25 * 1000).
 | 
					
						
							|  |  |  |     this.output = spawnSync(ffmpeg, ['-i', this.fileName, '-r', '25', `${this.fileName}-%03d.png`]).stderr.toString(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const lines = this.output.split('\n'); | 
					
						
							|  |  |  |     let framesLine = lines.find(l => l.startsWith('frame='))!; | 
					
						
							| 
									
										
										
										
											2021-02-08 10:59:48 -08:00
										 |  |  |     if (!framesLine) | 
					
						
							|  |  |  |       throw new Error(`No frame data in the output:\n${this.output}`); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     framesLine = framesLine.substring(framesLine.lastIndexOf('frame=')); | 
					
						
							|  |  |  |     const framesMatch = framesLine.match(/frame=\s+(\d+)/); | 
					
						
							|  |  |  |     const streamLine = lines.find(l => l.trim().startsWith('Stream #0:0')); | 
					
						
							|  |  |  |     const resolutionMatch = streamLine.match(/, (\d+)x(\d+),/); | 
					
						
							|  |  |  |     const durationMatch = lines.find(l => l.trim().startsWith('Duration'))!.match(/Duration: (\d+):(\d\d):(\d\d.\d\d)/); | 
					
						
							|  |  |  |     this.duration = (((parseInt(durationMatch![1], 10) * 60) + parseInt(durationMatch![2], 10)) * 60 + parseFloat(durationMatch![3])) * 1000; | 
					
						
							|  |  |  |     this.frames = parseInt(framesMatch![1], 10); | 
					
						
							|  |  |  |     this.videoWidth = parseInt(resolutionMatch![1], 10); | 
					
						
							|  |  |  |     this.videoHeight = parseInt(resolutionMatch![2], 10); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-10 21:22:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |   seekFirstNonEmptyFrame(offset?: { x: number, y: number } | undefined): PNG | undefined { | 
					
						
							|  |  |  |     for (let f = 1; f <= this.frames; ++f) { | 
					
						
							|  |  |  |       const frame = this.frame(f, { x: 0, y: 0 }); | 
					
						
							|  |  |  |       let hasColor = false; | 
					
						
							|  |  |  |       for (let i = 0; i < frame.data.length; i += 4) { | 
					
						
							|  |  |  |         if (frame.data[i + 0] < 230 || frame.data[i + 1] < 230 || frame.data[i + 2] < 230) { | 
					
						
							|  |  |  |           hasColor = true; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (hasColor) | 
					
						
							|  |  |  |         return this.frame(f, offset); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |   seekLastFrame(offset?: { x: number, y: number }): PNG { | 
					
						
							|  |  |  |     return this.frame(this.frames, offset); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |   frame(frame: number, offset = { x: 10, y: 10 }): PNG { | 
					
						
							|  |  |  |     if (!this.cache.has(frame)) { | 
					
						
							|  |  |  |       const gap = '0'.repeat(3 - String(frame).length); | 
					
						
							|  |  |  |       const buffer = fs.readFileSync(`${this.fileName}-${gap}${frame}.png`); | 
					
						
							|  |  |  |       this.cache.set(frame, PNG.sync.read(buffer)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const decoded = this.cache.get(frame); | 
					
						
							|  |  |  |     const dst = new PNG({ width: 10, height: 10 }); | 
					
						
							|  |  |  |     PNG.bitblt(decoded, dst, offset.x, offset.y, 10, 10, 0, 0); | 
					
						
							|  |  |  |     return dst; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-09-14 15:04:44 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  | function almostRed(r, g, b, alpha) { | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |   expect(r).toBeGreaterThan(185); | 
					
						
							|  |  |  |   expect(g).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(b).toBeLessThan(70); | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |   expect(alpha).toBe(255); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function almostBlack(r, g, b, alpha) { | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |   expect(r).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(g).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(b).toBeLessThan(70); | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |   expect(alpha).toBe(255); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  | function almostGray(r, g, b, alpha) { | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |   expect(r).toBeGreaterThan(70); | 
					
						
							|  |  |  |   expect(g).toBeGreaterThan(70); | 
					
						
							|  |  |  |   expect(b).toBeGreaterThan(70); | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |   expect(r).toBeLessThan(185); | 
					
						
							|  |  |  |   expect(g).toBeLessThan(185); | 
					
						
							|  |  |  |   expect(b).toBeLessThan(185); | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |   expect(alpha).toBe(255); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | function expectAll(pixels: Buffer, rgbaPredicate) { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   const checkPixel = i => { | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |     const r = pixels[i]; | 
					
						
							|  |  |  |     const g = pixels[i + 1]; | 
					
						
							|  |  |  |     const b = pixels[i + 2]; | 
					
						
							|  |  |  |     const alpha = pixels[i + 3]; | 
					
						
							|  |  |  |     rgbaPredicate(r, g, b, alpha); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |   try { | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |     for (let i = 0, n = pixels.length; i < n; i += 4) | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |       checkPixel(i); | 
					
						
							| 
									
										
										
										
											2020-08-28 04:20:29 -07:00
										 |  |  |   } catch (e) { | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |     // Log pixel values on failure.
 | 
					
						
							| 
									
										
										
										
											2020-10-23 10:33:58 -07:00
										 |  |  |     e.message += `\n\nActual pixels=[${pixels.join(',')}]`; | 
					
						
							| 
									
										
										
										
											2020-08-12 10:18:41 -07:00
										 |  |  |     throw e; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  | function findVideos(videoDir: string) { | 
					
						
							|  |  |  |   const files = fs.readdirSync(videoDir); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |   return files.filter(file => file.endsWith('webm')).map(file => path.join(videoDir, file)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  | function expectRedFrames(videoFile: string, size: { width: number, height: number }) { | 
					
						
							|  |  |  |   const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |   const duration = videoPlayer.duration; | 
					
						
							|  |  |  |   expect(duration).toBeGreaterThan(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   expect(videoPlayer.videoWidth).toBe(size.width); | 
					
						
							|  |  |  |   expect(videoPlayer.videoHeight).toBe(size.height); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const pixels = videoPlayer.seekLastFrame().data; | 
					
						
							|  |  |  |     expectAll(pixels, almostRed); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const pixels = videoPlayer.seekLastFrame({ x: size.width - 20, y: 0 }).data; | 
					
						
							|  |  |  |     expectAll(pixels, almostRed); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | it.describe('screencast', () => { | 
					
						
							| 
									
										
										
										
											2021-05-07 15:25:55 -07:00
										 |  |  |   it.slow(); | 
					
						
							| 
									
										
										
										
											2021-10-14 10:41:03 -07:00
										 |  |  |   it.skip(({ mode }) => mode === 'service', 'video.path() is not avaialble in remote mode'); | 
					
						
							| 
									
										
										
										
											2021-05-07 15:25:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('videoSize should require videosPath', async ({ browser }) => { | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |     const error = await browser.newContext({ videoSize: { width: 100, height: 100 } }).catch(e => e); | 
					
						
							|  |  |  |     expect(error.message).toContain('"videoSize" option requires "videosPath" to be specified'); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should work with old options', async ({ browser, browserName, trace }, testInfo) => { | 
					
						
							|  |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2020-10-05 17:03:24 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const size = { width: 450, height: 240 }; | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |       videosPath, | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |       videoSize: size | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-11 18:58:53 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 13:18:19 -07:00
										 |  |  |     await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							| 
									
										
										
										
											2020-09-02 15:21:58 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-08-31 13:18:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     expectRedFrames(videoFile, size); | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should throw without recordVideo.dir', async ({ browser }) => { | 
					
						
							|  |  |  |     const error = await browser.newContext({ recordVideo: {} as any }).catch(e => e); | 
					
						
							|  |  |  |     expect(error.message).toContain('recordVideo.dir: expected string, got undefined'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should capture static page', async ({ browser, browserName, trace }, testInfo) => { | 
					
						
							|  |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |     const size = { width: 450, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     expectRedFrames(videoFile, size); | 
					
						
							| 
									
										
										
										
											2020-08-31 13:18:19 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should expose video path', async ({ browser }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2020-10-13 22:15:51 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-10-13 22:15:51 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							|  |  |  |     const path = await page.video()!.path(); | 
					
						
							|  |  |  |     expect(path).toContain(videosPath); | 
					
						
							| 
									
										
										
										
											2020-10-14 14:10:35 -07:00
										 |  |  |     await context.close(); | 
					
						
							|  |  |  |     expect(fs.existsSync(path)).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2020-10-14 15:09:36 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('saveAs should throw when no video frames', async ({ browser, browserName }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-03-31 10:38:05 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.context().waitForEvent('page'), | 
					
						
							|  |  |  |       page.evaluate(() => { | 
					
						
							|  |  |  |         const win = window.open('about:blank'); | 
					
						
							|  |  |  |         win.close(); | 
					
						
							|  |  |  |       }), | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const saveAsPath = testInfo.outputPath('my-video.webm'); | 
					
						
							|  |  |  |     const error = await popup.video().saveAs(saveAsPath).catch(e => e); | 
					
						
							| 
									
										
										
										
											2021-09-24 15:05:20 -07:00
										 |  |  |     // WebKit pauses renderer before win.close() and actually writes something,
 | 
					
						
							|  |  |  |     // and other browsers are sometimes fast as well.
 | 
					
						
							|  |  |  |     if (!fs.existsSync(saveAsPath)) | 
					
						
							| 
									
										
										
										
											2021-03-31 10:38:05 -07:00
										 |  |  |       expect(error.message).toContain('Page did not produce any video frames'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should delete video', async ({ browser }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-03-31 10:38:05 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     const deletePromise = page.video().delete(); | 
					
						
							|  |  |  |     await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							|  |  |  |     await page.waitForTimeout(1000); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoPath = await page.video().path(); | 
					
						
							|  |  |  |     await deletePromise; | 
					
						
							|  |  |  |     expect(fs.existsSync(videoPath)).toBeFalsy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should expose video path blank page', async ({ browser }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2020-10-14 15:09:36 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-10-14 15:09:36 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     const path = await page.video()!.path(); | 
					
						
							|  |  |  |     expect(path).toContain(videosPath); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     expect(fs.existsSync(path)).toBeTruthy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should expose video path blank popup', async ({ browser }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2020-10-14 15:09:36 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							|  |  |  |         size | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-10-14 15:09:36 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     const [popup] = await Promise.all([ | 
					
						
							|  |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate('window.open("about:blank")') | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     const path = await popup.video()!.path(); | 
					
						
							|  |  |  |     expect(path).toContain(videosPath); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     expect(fs.existsSync(path)).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2020-10-13 22:15:51 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should capture navigation', async ({ browser, browserName, server, trace }, testInfo) => { | 
					
						
							|  |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size: { width: 1280, height: 720 } | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-11 18:58:53 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     await page.goto(server.PREFIX + '/background-color.html#rgb(0,0,0)'); | 
					
						
							| 
									
										
										
										
											2020-09-02 15:21:58 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     await page.goto(server.CROSS_PROCESS_PREFIX + '/background-color.html#rgb(100,100,100)'); | 
					
						
							| 
									
										
										
										
											2020-09-02 15:21:58 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     const duration = videoPlayer.duration; | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     expect(duration).toBeGreaterThan(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |       const pixels = videoPlayer.seekFirstNonEmptyFrame().data; | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |       expectAll(pixels, almostBlack); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-24 17:23:54 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame().data; | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |       expectAll(pixels, almostGray); | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should capture css transformation', async ({ browser, server, headless, browserName, platform, trace }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-05-13 10:22:23 -07:00
										 |  |  |     it.fixme(!headless, 'Fails on headed'); | 
					
						
							|  |  |  |     it.fixme(browserName === 'webkit' && platform === 'win32'); | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							| 
									
										
										
										
											2020-09-02 10:40:50 -07:00
										 |  |  |     // Set viewport equal to screencast frame size to avoid scaling.
 | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-11 18:58:53 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     await page.goto(server.PREFIX + '/rotate-z.html'); | 
					
						
							| 
									
										
										
										
											2020-09-02 15:21:58 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     const duration = videoPlayer.duration; | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     expect(duration).toBeGreaterThan(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame({ x: 95, y: 45 }).data; | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |       expectAll(pixels, almostRed); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should work for popups', async ({ browser, server, browserName, trace }, testInfo) => { | 
					
						
							|  |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2020-10-05 17:03:24 -07:00
										 |  |  |     const videosPath = testInfo.outputPath(''); | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     const size = { width: 450, height: 240 }; | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videosPath, | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |         size, | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |       viewport: size, | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-08-31 15:21:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 17:01:00 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							| 
									
										
										
										
											2020-09-04 22:37:38 -07:00
										 |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     const [popup] = await Promise.all([ | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |       page.waitForEvent('popup'), | 
					
						
							|  |  |  |       page.evaluate(() => { window.open('about:blank'); }), | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     await popup.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 18:21:26 -08:00
										 |  |  |     const pageVideoFile = await page.video().path(); | 
					
						
							|  |  |  |     const popupVideoFile = await popup.video().path(); | 
					
						
							|  |  |  |     expect(pageVideoFile).not.toEqual(popupVideoFile); | 
					
						
							|  |  |  |     expectRedFrames(popupVideoFile, size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |     const videoFiles = findVideos(videosPath); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     expect(videoFiles.length).toBe(2); | 
					
						
							| 
									
										
										
										
											2020-08-28 13:53:47 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |   it('should scale frames down to the requested size ', async ({ browser, browserName, server, headless, trace }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-05-13 10:22:23 -07:00
										 |  |  |     it.fixme(!headless, 'Fails on headed'); | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-11 18:58:53 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         // Set size to 1/2 of the viewport.
 | 
					
						
							|  |  |  |         size: { width: 320, height: 240 }, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       viewport: { width: 640, height: 480 }, | 
					
						
							| 
									
										
										
										
											2020-09-11 18:58:53 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |     await page.goto(server.PREFIX + '/checkerboard.html'); | 
					
						
							|  |  |  |     // Update the picture to ensure enough frames are generated.
 | 
					
						
							|  |  |  |     await page.$eval('.container', container => { | 
					
						
							|  |  |  |       container.firstElementChild.classList.remove('red'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 300)); | 
					
						
							|  |  |  |     await page.$eval('.container', container => { | 
					
						
							|  |  |  |       container.firstElementChild.classList.add('red'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-02 15:21:58 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     const duration = videoPlayer.duration; | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |     expect(duration).toBeGreaterThan(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame({ x: 0, y: 0 }).data; | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |       expectAll(pixels, almostRed); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame({ x: 300, y: 0 }).data; | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |       expectAll(pixels, almostGray); | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame({ x: 0, y: 200 }).data; | 
					
						
							| 
									
										
										
										
											2021-01-05 20:31:50 -08:00
										 |  |  |       expectAll(pixels, almostGray); | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |       const pixels = videoPlayer.seekLastFrame({ x: 300, y: 200 }).data; | 
					
						
							| 
									
										
										
										
											2020-09-02 13:59:15 -07:00
										 |  |  |       expectAll(pixels, almostRed); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |   it('should use viewport scaled down to fit into 800x800 as default size', async ({ browser }, testInfo) => { | 
					
						
							|  |  |  |     const size = { width: 1600, height: 1200 }; | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							| 
									
										
										
										
											2021-02-08 10:59:48 -08:00
										 |  |  |     expect(videoPlayer.videoWidth).toBe(800); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(600); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  |   it('should be 800x450 by default', async ({ browser }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  |     await context.close(); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-09-29 18:52:30 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							| 
									
										
										
										
											2021-02-08 10:59:48 -08:00
										 |  |  |     expect(videoPlayer.videoWidth).toBe(800); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(450); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-13 10:22:23 -07:00
										 |  |  |   it('should be 800x600 with null viewport', async ({ browser, headless, browserName }, testInfo) => { | 
					
						
							|  |  |  |     it.fixme(browserName === 'firefox' && headless, 'Fails in headless on bots'); | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-08 10:59:48 -08:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: null | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoFile = await page.video().path(); | 
					
						
							|  |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     expect(videoPlayer.videoWidth).toBe(800); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(600); | 
					
						
							| 
									
										
										
										
											2020-09-11 15:14:31 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-10 19:42:52 +01:00
										 |  |  |   it('should capture static page in persistent context @smoke', async ({ launchPersistent, browserName, trace }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2022-02-10 10:45:18 -07:00
										 |  |  |     it.fixme(browserName === 'firefox' && trace === 'on', 'https://github.com/microsoft/playwright/issues/10060'); | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |     const { context, page } = await launchPersistent({ | 
					
						
							| 
									
										
										
										
											2020-11-02 19:42:05 -08:00
										 |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 14:35:18 -07:00
										 |  |  |     const videoFile = await page.video().path(); | 
					
						
							| 
									
										
										
										
											2020-10-01 11:06:19 -07:00
										 |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     const duration = videoPlayer.duration; | 
					
						
							|  |  |  |     expect(duration).toBeGreaterThan(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(videoPlayer.videoWidth).toBe(320); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(240); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       const pixels = videoPlayer.seekLastFrame().data; | 
					
						
							|  |  |  |       expectAll(pixels, almostRed); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-02-10 13:37:27 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   it('should emulate an iphone', async ({ contextFactory, playwright, browserName }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-04-05 09:18:56 -07:00
										 |  |  |     it.skip(browserName === 'firefox', 'isMobile is not supported in Firefox'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 13:37:27 -08:00
										 |  |  |     const device = playwright.devices['iPhone 6']; | 
					
						
							|  |  |  |     const context = await contextFactory({ | 
					
						
							|  |  |  |       ...device, | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoFile = await page.video().path(); | 
					
						
							|  |  |  |     const videoPlayer = new VideoPlayer(videoFile); | 
					
						
							|  |  |  |     expect(videoPlayer.videoWidth).toBe(374); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(666); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-04-08 14:01:05 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   it('should throw on browser close', async ({ browserType }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-04-08 14:01:05 -07:00
										 |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							| 
									
										
										
										
											2021-10-27 18:00:06 -08:00
										 |  |  |     const browser = await browserType.launch(); | 
					
						
							| 
									
										
										
										
											2021-04-08 14:01:05 -07:00
										 |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await browser.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const file = testInfo.outputPath('saved-video-'); | 
					
						
							|  |  |  |     const saveResult = await page.video().saveAs(file).catch(e => e); | 
					
						
							|  |  |  |     expect(saveResult.message).toContain('browser has been closed'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-04-08 18:56:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   it('should throw if browser dies', async ({ browserType }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-04-08 18:56:09 -07:00
										 |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							| 
									
										
										
										
											2021-10-27 18:00:06 -08:00
										 |  |  |     const browser = await browserType.launch(); | 
					
						
							| 
									
										
										
										
											2021-04-08 18:56:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: testInfo.outputPath(''), | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await (browser as any)._channel.killForTests(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const file = testInfo.outputPath('saved-video-'); | 
					
						
							|  |  |  |     const saveResult = await page.video().saveAs(file).catch(e => e); | 
					
						
							|  |  |  |     expect(saveResult.message).toContain('rowser has been closed'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-05-19 05:29:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   it('should wait for video to finish if page was closed', async ({ browserType }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-05-19 05:29:39 +00:00
										 |  |  |     const size = { width: 320, height: 240 }; | 
					
						
							| 
									
										
										
										
											2021-10-27 18:00:06 -08:00
										 |  |  |     const browser = await browserType.launch(); | 
					
						
							| 
									
										
										
										
											2021-05-19 05:29:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const videoDir = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videoDir, | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     await browser.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoFiles = findVideos(videoDir); | 
					
						
							|  |  |  |     expect(videoFiles.length).toBe(1); | 
					
						
							|  |  |  |     const videoPlayer = new VideoPlayer(videoFiles[0]); | 
					
						
							|  |  |  |     expect(videoPlayer.videoWidth).toBe(320); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(240); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 07:31:30 -08:00
										 |  |  |   it('should not create video for internal pages', async ({ browser, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-05-29 01:20:49 +00:00
										 |  |  |     it.fixme(true, 'https://github.com/microsoft/playwright/issues/6743'); | 
					
						
							|  |  |  |     server.setRoute('/empty.html', (req, res) => { | 
					
						
							|  |  |  |       res.setHeader('Set-Cookie', 'name=value'); | 
					
						
							|  |  |  |       res.end(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoDir = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videoDir | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const cookies = await context.cookies(); | 
					
						
							|  |  |  |     expect(cookies.length).toBe(1); | 
					
						
							|  |  |  |     await context.storageState(); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const files = fs.readdirSync(videoDir); | 
					
						
							|  |  |  |     expect(files.length).toBe(1); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-12-08 18:13:12 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should capture full viewport on hidpi', async ({ browserType, browserName, headless }, testInfo) => { | 
					
						
							|  |  |  |     it.fail(browserName === 'firefox', 'The actual picture is smaller than video frame'); | 
					
						
							|  |  |  |     it.fail(browserName === 'chromium' && !headless, 'The square is not on the video'); | 
					
						
							|  |  |  |     const size = { width: 400, height: 400 }; | 
					
						
							|  |  |  |     const browser = await browserType.launch(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoDir = testInfo.outputPath(''); | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       viewport: size, | 
					
						
							|  |  |  |       deviceScaleFactor: 3, | 
					
						
							|  |  |  |       recordVideo: { | 
					
						
							|  |  |  |         dir: videoDir, | 
					
						
							|  |  |  |         size, | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     await page.setContent(`<div style='margin: 0; background: red; position: fixed; right:0; bottom:0; width: 30; height: 30;'></div>`); | 
					
						
							|  |  |  |     await new Promise(r => setTimeout(r, 1000)); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     await browser.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const videoFiles = findVideos(videoDir); | 
					
						
							|  |  |  |     expect(videoFiles.length).toBe(1); | 
					
						
							|  |  |  |     const videoPlayer = new VideoPlayer(videoFiles[0]); | 
					
						
							|  |  |  |     expect(videoPlayer.videoWidth).toBe(size.width); | 
					
						
							|  |  |  |     expect(videoPlayer.videoHeight).toBe(size.height); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Bottom right corner should be part of the red border.
 | 
					
						
							|  |  |  |     const pixels = videoPlayer.seekLastFrame({ x: size.width - 10, y: size.height - 10 }).data; | 
					
						
							|  |  |  |     expectAll(pixels, almostRed); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-10-14 10:41:03 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-05-29 01:20:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-14 10:41:03 -07:00
										 |  |  | it('should saveAs video', async ({ browser }, testInfo) => { | 
					
						
							|  |  |  |   it.slow(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const videosPath = testInfo.outputPath(''); | 
					
						
							|  |  |  |   const size = { width: 320, height: 240 }; | 
					
						
							|  |  |  |   const context = await browser.newContext({ | 
					
						
							|  |  |  |     recordVideo: { | 
					
						
							|  |  |  |       dir: videosPath, | 
					
						
							|  |  |  |       size | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     viewport: size, | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const page = await context.newPage(); | 
					
						
							|  |  |  |   await page.evaluate(() => document.body.style.backgroundColor = 'red'); | 
					
						
							|  |  |  |   await page.waitForTimeout(1000); | 
					
						
							|  |  |  |   await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const saveAsPath = testInfo.outputPath('my-video.webm'); | 
					
						
							|  |  |  |   await page.video().saveAs(saveAsPath); | 
					
						
							|  |  |  |   expect(fs.existsSync(saveAsPath)).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2020-09-18 17:36:43 -07:00
										 |  |  | }); |