From 1eb282d139adb2ae42adfdf76e08f423bdb20662 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 14 Sep 2020 15:04:44 -0700 Subject: [PATCH] test(screencast): save video in test-results (#3876) --- test/screencast.spec.ts | 93 ++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/test/screencast.spec.ts b/test/screencast.spec.ts index 0306d4786d..f275316c1f 100644 --- a/test/screencast.spec.ts +++ b/test/screencast.spec.ts @@ -20,12 +20,31 @@ import type { Page } from '..'; import fs from 'fs'; import path from 'path'; import { TestServer } from '../utils/testserver'; +import { mkdirIfNeeded } from '../lib/utils/utils'; +type WorkerState = { + videoDir: string; +}; type TestState = { videoPlayer: VideoPlayer; + videoFile: string; }; -const fixtures = playwrightFixtures.declareTestFixtures(); -const { it, expect, describe, defineTestFixture } = fixtures; +const fixtures = playwrightFixtures.declareWorkerFixtures().declareTestFixtures(); +const { it, expect, describe, defineTestFixture, defineWorkerFixture, overrideWorkerFixture } = fixtures; + +defineWorkerFixture('videoDir', async ({}, test, config) => { + await test(path.join((config as any).config.outputDir, 'screencast')); +}); + +overrideWorkerFixture('browser', async ({browserType, defaultBrowserOptions, videoDir}, test) => { + const browser = await browserType.launch({ + ...defaultBrowserOptions, + // Make sure videos are stored on the same volume as the test output dir. + _videosPath: videoDir, + }); + await test(browser); + await browser.close(); +}); defineTestFixture('videoPlayer', async ({playwright, context, server}, test) => { // WebKit on Mac & Windows cannot replay webm/vp8 video, is unrelyable @@ -43,6 +62,14 @@ defineTestFixture('videoPlayer', async ({playwright, context, server}, test) => await page.close(); }); +defineTestFixture('videoFile', async ({browserType, videoDir}, runTest, info) => { + const { test } = info; + const sanitizedTitle = test.title.replace(/[^\w\d]+/g, '_'); + const videoFile = path.join(videoDir, `${browserType.name()}-${sanitizedTitle}-${test.results.length}_v.webm`); + await mkdirIfNeeded(videoFile); + await runTest(videoFile); +}); + function almostRed(r, g, b, alpha) { expect(r).toBeGreaterThan(240); expect(g).toBeLessThan(50); @@ -162,7 +189,7 @@ class VideoPlayer { describe('screencast', suite => { suite.slow(); }, () => { - it('should capture static page', async ({browser, videoPlayer}) => { + it('should capture static page', async ({browser, videoPlayer, videoFile}) => { const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } }); const page = await context.newPage(); const video = await page.waitForEvent('_videostarted') as any; @@ -171,8 +198,9 @@ describe('screencast', suite => { await new Promise(r => setTimeout(r, 1000)); await page.close(); - const videoFile = await video.path(); - expect(fs.existsSync(videoFile)).toBe(true); + const tmpPath = await video.path(); + expect(fs.existsSync(tmpPath)).toBe(true); + fs.renameSync(tmpPath, videoFile); await videoPlayer.load(videoFile); const duration = await videoPlayer.duration(); @@ -188,7 +216,7 @@ describe('screencast', suite => { it('should capture navigation', (test, parameters) => { test.flaky(); - }, async ({browser, server, videoPlayer}) => { + }, async ({browser, server, videoPlayer, videoFile}) => { const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 1280, height: 720 } }); const page = await context.newPage(); const video = await page.waitForEvent('_videostarted') as any; @@ -199,8 +227,9 @@ describe('screencast', suite => { await new Promise(r => setTimeout(r, 1000)); await page.close(); - const videoFile = await video.path(); - expect(fs.existsSync(videoFile)).toBe(true); + const tmpPath = await video.path(); + expect(fs.existsSync(tmpPath)).toBe(true); + fs.renameSync(tmpPath, videoFile); await videoPlayer.load(videoFile); const duration = await videoPlayer.duration(); @@ -221,7 +250,7 @@ describe('screencast', suite => { it('should capture css transformation', (test, parameters) => { test.fail(options.WEBKIT(parameters) && WIN, 'Does not work on WebKit Windows'); - }, async ({browser, server, videoPlayer}) => { + }, async ({browser, server, videoPlayer, videoFile}) => { const size = {width: 320, height: 240}; // Set viewport equal to screencast frame size to avoid scaling. const context = await browser.newContext({ _recordVideos: true, _videoSize: size, viewport: size }); @@ -232,8 +261,9 @@ describe('screencast', suite => { await new Promise(r => setTimeout(r, 1000)); await page.close(); - const videoFile = await video.path(); - expect(fs.existsSync(videoFile)).toBe(true); + const tmpPath = await video.path(); + expect(fs.existsSync(tmpPath)).toBe(true); + fs.renameSync(tmpPath, videoFile); await videoPlayer.load(videoFile); const duration = await videoPlayer.duration(); @@ -246,8 +276,7 @@ describe('screencast', suite => { } }); - it('should automatically start/finish when new page is created/closed', async ({browserType, defaultBrowserOptions, tmpDir}) => { - const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir }); + it('should automatically start/finish when new page is created/closed', async ({browser, videoDir}) => { const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 }}); const [screencast, newPage] = await Promise.all([ new Promise(r => context.on('page', page => page.on('_videostarted', r))), @@ -258,13 +287,11 @@ describe('screencast', suite => { screencast.path(), newPage.close(), ]); - expect(path.dirname(videoFile)).toBe(tmpDir); + expect(path.dirname(videoFile)).toBe(videoDir); await context.close(); - await browser.close(); }); - it('should finish when contex closes', async ({browserType, defaultBrowserOptions, tmpDir}) => { - const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir }); + it('should finish when contex closes', async ({browser, videoDir}) => { const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } }); const [video] = await Promise.all([ @@ -276,9 +303,7 @@ describe('screencast', suite => { video.path(), context.close(), ]); - expect(path.dirname(videoFile)).toBe(tmpDir); - - await browser.close(); + expect(path.dirname(videoFile)).toBe(videoDir); }); it('should fire striclty after context.newPage', async ({browser}) => { @@ -289,8 +314,7 @@ describe('screencast', suite => { await context.close(); }); - it('should fire start event for popups', async ({browserType, defaultBrowserOptions, tmpDir, server}) => { - const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir }); + it('should fire start event for popups', async ({browser, videoDir, server}) => { const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } }); const [page] = await Promise.all([ @@ -307,12 +331,10 @@ describe('screencast', suite => { video.path(), popup.close() ]); - expect(path.dirname(videoFile)).toBe(tmpDir); - - await browser.close(); + expect(path.dirname(videoFile)).toBe(videoDir); }); - it('should scale frames down to the requested size ', async ({browser, videoPlayer, server}) => { + it('should scale frames down to the requested size ', async ({browser, videoPlayer, videoFile, server}) => { const context = await browser.newContext({ viewport: {width: 640, height: 480}, // Set size to 1/2 of the viewport. @@ -334,8 +356,9 @@ describe('screencast', suite => { await new Promise(r => setTimeout(r, 1000)); await page.close(); - const videoFile = await video.path(); - expect(fs.existsSync(videoFile)).toBe(true); + const tmp = await video.path(); + expect(fs.existsSync(tmp)).toBe(true); + fs.renameSync(tmp, videoFile); await videoPlayer.load(videoFile); const duration = await videoPlayer.duration(); @@ -360,7 +383,7 @@ describe('screencast', suite => { } }); - it('should use viewport as default size', async ({browser, page, tmpDir, videoPlayer, toImpl}) => { + it('should use viewport as default size', async ({browser, videoPlayer, videoFile}) => { const size = {width: 800, height: 600}; const context = await browser.newContext({_recordVideos: true, viewport: size}); @@ -369,18 +392,19 @@ describe('screencast', suite => { context.newPage(), ]); await new Promise(r => setTimeout(r, 1000)); - const [videoFile] = await Promise.all([ + const [tmpPath] = await Promise.all([ video.path(), context.close(), ]); - expect(fs.existsSync(videoFile)).toBe(true); + expect(fs.existsSync(tmpPath)).toBe(true); + fs.renameSync(tmpPath, videoFile); await videoPlayer.load(videoFile); expect(await videoPlayer.videoWidth()).toBe(size.width); expect(await videoPlayer.videoHeight()).toBe(size.height); }); - it('should be 1280x720 by default', async ({browser, page, tmpDir, videoPlayer, toImpl}) => { + it('should be 1280x720 by default', async ({browser, videoPlayer, videoFile}) => { const context = await browser.newContext({_recordVideos: true}); const [video] = await Promise.all([ @@ -388,12 +412,13 @@ describe('screencast', suite => { context.newPage(), ]); await new Promise(r => setTimeout(r, 1000)); - const [videoFile] = await Promise.all([ + const [tmpPath] = await Promise.all([ video.path(), context.close(), ]); - expect(fs.existsSync(videoFile)).toBe(true); + expect(fs.existsSync(tmpPath)).toBe(true); + fs.renameSync(tmpPath, videoFile); await videoPlayer.load(videoFile); expect(await videoPlayer.videoWidth()).toBe(1280); expect(await videoPlayer.videoHeight()).toBe(720);