test(screencast): save video in test-results (#3876)
This commit is contained in:
parent
0a243c6792
commit
1eb282d139
|
|
@ -20,12 +20,31 @@ import type { Page } from '..';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { TestServer } from '../utils/testserver';
|
import { TestServer } from '../utils/testserver';
|
||||||
|
import { mkdirIfNeeded } from '../lib/utils/utils';
|
||||||
|
|
||||||
|
type WorkerState = {
|
||||||
|
videoDir: string;
|
||||||
|
};
|
||||||
type TestState = {
|
type TestState = {
|
||||||
videoPlayer: VideoPlayer;
|
videoPlayer: VideoPlayer;
|
||||||
|
videoFile: string;
|
||||||
};
|
};
|
||||||
const fixtures = playwrightFixtures.declareTestFixtures<TestState>();
|
const fixtures = playwrightFixtures.declareWorkerFixtures<WorkerState>().declareTestFixtures<TestState>();
|
||||||
const { it, expect, describe, defineTestFixture } = fixtures;
|
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) => {
|
defineTestFixture('videoPlayer', async ({playwright, context, server}, test) => {
|
||||||
// WebKit on Mac & Windows cannot replay webm/vp8 video, is unrelyable
|
// 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();
|
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) {
|
function almostRed(r, g, b, alpha) {
|
||||||
expect(r).toBeGreaterThan(240);
|
expect(r).toBeGreaterThan(240);
|
||||||
expect(g).toBeLessThan(50);
|
expect(g).toBeLessThan(50);
|
||||||
|
|
@ -162,7 +189,7 @@ class VideoPlayer {
|
||||||
describe('screencast', suite => {
|
describe('screencast', suite => {
|
||||||
suite.slow();
|
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 context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } });
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
const video = await page.waitForEvent('_videostarted') as any;
|
const video = await page.waitForEvent('_videostarted') as any;
|
||||||
|
|
@ -171,8 +198,9 @@ describe('screencast', suite => {
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
await page.close();
|
await page.close();
|
||||||
|
|
||||||
const videoFile = await video.path();
|
const tmpPath = await video.path();
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmpPath)).toBe(true);
|
||||||
|
fs.renameSync(tmpPath, videoFile);
|
||||||
|
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
const duration = await videoPlayer.duration();
|
const duration = await videoPlayer.duration();
|
||||||
|
|
@ -188,7 +216,7 @@ describe('screencast', suite => {
|
||||||
|
|
||||||
it('should capture navigation', (test, parameters) => {
|
it('should capture navigation', (test, parameters) => {
|
||||||
test.flaky();
|
test.flaky();
|
||||||
}, async ({browser, server, videoPlayer}) => {
|
}, async ({browser, server, videoPlayer, videoFile}) => {
|
||||||
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 1280, height: 720 } });
|
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 1280, height: 720 } });
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
const video = await page.waitForEvent('_videostarted') as any;
|
const video = await page.waitForEvent('_videostarted') as any;
|
||||||
|
|
@ -199,8 +227,9 @@ describe('screencast', suite => {
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
await page.close();
|
await page.close();
|
||||||
|
|
||||||
const videoFile = await video.path();
|
const tmpPath = await video.path();
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmpPath)).toBe(true);
|
||||||
|
fs.renameSync(tmpPath, videoFile);
|
||||||
|
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
const duration = await videoPlayer.duration();
|
const duration = await videoPlayer.duration();
|
||||||
|
|
@ -221,7 +250,7 @@ describe('screencast', suite => {
|
||||||
|
|
||||||
it('should capture css transformation', (test, parameters) => {
|
it('should capture css transformation', (test, parameters) => {
|
||||||
test.fail(options.WEBKIT(parameters) && WIN, 'Does not work on WebKit Windows');
|
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};
|
const size = {width: 320, height: 240};
|
||||||
// Set viewport equal to screencast frame size to avoid scaling.
|
// Set viewport equal to screencast frame size to avoid scaling.
|
||||||
const context = await browser.newContext({ _recordVideos: true, _videoSize: size, viewport: size });
|
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 new Promise(r => setTimeout(r, 1000));
|
||||||
await page.close();
|
await page.close();
|
||||||
|
|
||||||
const videoFile = await video.path();
|
const tmpPath = await video.path();
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmpPath)).toBe(true);
|
||||||
|
fs.renameSync(tmpPath, videoFile);
|
||||||
|
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
const duration = await videoPlayer.duration();
|
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}) => {
|
it('should automatically start/finish when new page is created/closed', async ({browser, videoDir}) => {
|
||||||
const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir });
|
|
||||||
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 }});
|
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 }});
|
||||||
const [screencast, newPage] = await Promise.all([
|
const [screencast, newPage] = await Promise.all([
|
||||||
new Promise<any>(r => context.on('page', page => page.on('_videostarted', r))),
|
new Promise<any>(r => context.on('page', page => page.on('_videostarted', r))),
|
||||||
|
|
@ -258,13 +287,11 @@ describe('screencast', suite => {
|
||||||
screencast.path(),
|
screencast.path(),
|
||||||
newPage.close(),
|
newPage.close(),
|
||||||
]);
|
]);
|
||||||
expect(path.dirname(videoFile)).toBe(tmpDir);
|
expect(path.dirname(videoFile)).toBe(videoDir);
|
||||||
await context.close();
|
await context.close();
|
||||||
await browser.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should finish when contex closes', async ({browserType, defaultBrowserOptions, tmpDir}) => {
|
it('should finish when contex closes', async ({browser, videoDir}) => {
|
||||||
const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir });
|
|
||||||
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } });
|
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } });
|
||||||
|
|
||||||
const [video] = await Promise.all([
|
const [video] = await Promise.all([
|
||||||
|
|
@ -276,9 +303,7 @@ describe('screencast', suite => {
|
||||||
video.path(),
|
video.path(),
|
||||||
context.close(),
|
context.close(),
|
||||||
]);
|
]);
|
||||||
expect(path.dirname(videoFile)).toBe(tmpDir);
|
expect(path.dirname(videoFile)).toBe(videoDir);
|
||||||
|
|
||||||
await browser.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fire striclty after context.newPage', async ({browser}) => {
|
it('should fire striclty after context.newPage', async ({browser}) => {
|
||||||
|
|
@ -289,8 +314,7 @@ describe('screencast', suite => {
|
||||||
await context.close();
|
await context.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fire start event for popups', async ({browserType, defaultBrowserOptions, tmpDir, server}) => {
|
it('should fire start event for popups', async ({browser, videoDir, server}) => {
|
||||||
const browser = await browserType.launch({ ...defaultBrowserOptions, _videosPath: tmpDir });
|
|
||||||
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } });
|
const context = await browser.newContext({ _recordVideos: true, _videoSize: { width: 320, height: 240 } });
|
||||||
|
|
||||||
const [page] = await Promise.all([
|
const [page] = await Promise.all([
|
||||||
|
|
@ -307,12 +331,10 @@ describe('screencast', suite => {
|
||||||
video.path(),
|
video.path(),
|
||||||
popup.close()
|
popup.close()
|
||||||
]);
|
]);
|
||||||
expect(path.dirname(videoFile)).toBe(tmpDir);
|
expect(path.dirname(videoFile)).toBe(videoDir);
|
||||||
|
|
||||||
await browser.close();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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({
|
const context = await browser.newContext({
|
||||||
viewport: {width: 640, height: 480},
|
viewport: {width: 640, height: 480},
|
||||||
// Set size to 1/2 of the viewport.
|
// Set size to 1/2 of the viewport.
|
||||||
|
|
@ -334,8 +356,9 @@ describe('screencast', suite => {
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
await page.close();
|
await page.close();
|
||||||
|
|
||||||
const videoFile = await video.path();
|
const tmp = await video.path();
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmp)).toBe(true);
|
||||||
|
fs.renameSync(tmp, videoFile);
|
||||||
|
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
const duration = await videoPlayer.duration();
|
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 size = {width: 800, height: 600};
|
||||||
const context = await browser.newContext({_recordVideos: true, viewport: size});
|
const context = await browser.newContext({_recordVideos: true, viewport: size});
|
||||||
|
|
||||||
|
|
@ -369,18 +392,19 @@ describe('screencast', suite => {
|
||||||
context.newPage(),
|
context.newPage(),
|
||||||
]);
|
]);
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
const [videoFile] = await Promise.all([
|
const [tmpPath] = await Promise.all([
|
||||||
video.path(),
|
video.path(),
|
||||||
context.close(),
|
context.close(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmpPath)).toBe(true);
|
||||||
|
fs.renameSync(tmpPath, videoFile);
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
expect(await videoPlayer.videoWidth()).toBe(size.width);
|
expect(await videoPlayer.videoWidth()).toBe(size.width);
|
||||||
expect(await videoPlayer.videoHeight()).toBe(size.height);
|
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 context = await browser.newContext({_recordVideos: true});
|
||||||
|
|
||||||
const [video] = await Promise.all([
|
const [video] = await Promise.all([
|
||||||
|
|
@ -388,12 +412,13 @@ describe('screencast', suite => {
|
||||||
context.newPage(),
|
context.newPage(),
|
||||||
]);
|
]);
|
||||||
await new Promise(r => setTimeout(r, 1000));
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
const [videoFile] = await Promise.all([
|
const [tmpPath] = await Promise.all([
|
||||||
video.path(),
|
video.path(),
|
||||||
context.close(),
|
context.close(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
expect(fs.existsSync(tmpPath)).toBe(true);
|
||||||
|
fs.renameSync(tmpPath, videoFile);
|
||||||
await videoPlayer.load(videoFile);
|
await videoPlayer.load(videoFile);
|
||||||
expect(await videoPlayer.videoWidth()).toBe(1280);
|
expect(await videoPlayer.videoWidth()).toBe(1280);
|
||||||
expect(await videoPlayer.videoHeight()).toBe(720);
|
expect(await videoPlayer.videoHeight()).toBe(720);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue