mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
test(screencast): more tests on Chromium, new seek impl (#3699)
This commit is contained in:
parent
fcc1680f98
commit
f23dbfb009
56
test/assets/player.html
Normal file
56
test/assets/player.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<script>
|
||||||
|
async function playToTheEnd() {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
const result = new Promise(r => video.onended = r);
|
||||||
|
video.play();
|
||||||
|
return await result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function playOneFrame() {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
const result = new Promise(r => video.onpause = r);
|
||||||
|
video.ontimeupdate = () => {
|
||||||
|
video.pause();
|
||||||
|
video.ontimeupdate = null;
|
||||||
|
};
|
||||||
|
video.play();
|
||||||
|
return await result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function playNFrames(n) {
|
||||||
|
for (let i = 0; i < n; i++)
|
||||||
|
await playOneFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function countFrames() {
|
||||||
|
const video = document.querySelector('video');
|
||||||
|
|
||||||
|
if (!video.duration)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (video.currentTime)
|
||||||
|
await playToTheEnd();
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
while (true) {
|
||||||
|
++count;
|
||||||
|
await playOneFrame();
|
||||||
|
if (video.ended)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function seekLastFrame() {
|
||||||
|
const frameCount = await countFrames();
|
||||||
|
await playNFrames(frameCount);
|
||||||
|
return frameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<body>
|
||||||
|
<video controls>
|
||||||
|
<source src="v.webm" type="video/webm">
|
||||||
|
Your browser does not support HTML video.
|
||||||
|
</video>
|
||||||
|
</body>
|
@ -102,21 +102,7 @@ class VideoPlayer {
|
|||||||
this._server.serveFile(req, response, videoFile);
|
this._server.serveFile(req, response, videoFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
await this._page.goto(this._server.PREFIX + servertPath);
|
await this._page.goto(this._server.PREFIX + '/player.html');
|
||||||
await this._page.$eval('video', (v: HTMLVideoElement) => {
|
|
||||||
return new Promise(fulfil => {
|
|
||||||
// In case video playback autostarts.
|
|
||||||
v.pause();
|
|
||||||
v.onplaying = fulfil;
|
|
||||||
v.play();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
await this._page.$eval('video', (v: HTMLVideoElement) => {
|
|
||||||
v.pause();
|
|
||||||
const result = new Promise(f => v.onseeked = f);
|
|
||||||
v.currentTime = v.duration;
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async duration() {
|
async duration() {
|
||||||
@ -131,36 +117,31 @@ class VideoPlayer {
|
|||||||
return await this._page.$eval('video', (v: HTMLVideoElement) => v.videoHeight);
|
return await this._page.$eval('video', (v: HTMLVideoElement) => v.videoHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
async seek(timestamp) {
|
|
||||||
await this._page.$eval('video', (v: HTMLVideoElement, timestamp) => {
|
|
||||||
v.pause();
|
|
||||||
const result = new Promise(f => v.onseeked = f);
|
|
||||||
v.currentTime = timestamp;
|
|
||||||
return result;
|
|
||||||
}, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
async seekFirstNonEmptyFrame() {
|
async seekFirstNonEmptyFrame() {
|
||||||
let time = 0;
|
await this._page.evaluate(async () => await (window as any).playToTheEnd());
|
||||||
for (let i = 0; i < 10; i++) {
|
while (true) {
|
||||||
await this.seek(time);
|
await this._page.evaluate(async () => await (window as any).playOneFrame());
|
||||||
|
const ended = await this._page.$eval('video', (video: HTMLVideoElement) => video.ended);
|
||||||
|
if (ended)
|
||||||
|
throw new Error('All frames are empty');
|
||||||
const pixels = await this.pixels();
|
const pixels = await this.pixels();
|
||||||
if (!pixels.every(p => p === 255))
|
if (!pixels.every(p => p === 255))
|
||||||
return;
|
return;
|
||||||
time += 0.1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async seekLastNonEmptyFrame() {
|
async countFrames() {
|
||||||
const duration = await this.duration();
|
return await this._page.evaluate(async () => await (window as any).countFrames());
|
||||||
let time = duration - 0.01;
|
}
|
||||||
for (let i = 0; i < 10; i++) {
|
async currentTime() {
|
||||||
await this.seek(time);
|
return await this._page.$eval('video', (v: HTMLVideoElement) => v.currentTime);
|
||||||
const pixels = await this.pixels();
|
}
|
||||||
if (!pixels.every(p => p === 0))
|
async playOneFrame() {
|
||||||
return;
|
return await this._page.evaluate(async () => await (window as any).playOneFrame());
|
||||||
time -= 0.1;
|
}
|
||||||
}
|
|
||||||
|
async seekLastFrame() {
|
||||||
|
return await this._page.evaluate(async () => await (window as any).seekLastFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
async pixels(point = {x: 0, y: 0}) {
|
async pixels(point = {x: 0, y: 0}) {
|
||||||
@ -179,38 +160,41 @@ class VideoPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should capture static page', test => {
|
|
||||||
test.skip(options.WIRE);
|
|
||||||
}, async ({page, tmpDir, videoPlayer, toImpl}) => {
|
|
||||||
const videoFile = path.join(tmpDir, 'v.webm');
|
|
||||||
await page.evaluate(() => document.body.style.backgroundColor = 'red');
|
|
||||||
await toImpl(page)._delegate.startScreencast({outputFile: videoFile, width: 640, height: 480});
|
|
||||||
// TODO: in WebKit figure out why video size is not reported correctly for
|
|
||||||
// static pictures.
|
|
||||||
if (options.HEADLESS && options.WEBKIT)
|
|
||||||
await page.setViewportSize({width: 1270, height: 950});
|
|
||||||
await new Promise(r => setTimeout(r, 300));
|
|
||||||
await toImpl(page)._delegate.stopScreencast();
|
|
||||||
expect(fs.existsSync(videoFile)).toBe(true);
|
|
||||||
|
|
||||||
await videoPlayer.load(videoFile);
|
|
||||||
const duration = await videoPlayer.duration();
|
|
||||||
expect(duration).toBeGreaterThan(0);
|
|
||||||
|
|
||||||
expect(await videoPlayer.videoWidth()).toBe(640);
|
|
||||||
expect(await videoPlayer.videoHeight()).toBe(480);
|
|
||||||
|
|
||||||
await videoPlayer.seekLastNonEmptyFrame();
|
|
||||||
const pixels = await videoPlayer.pixels();
|
|
||||||
expectAll(pixels, almostRed);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('screencast', suite => {
|
describe('screencast', suite => {
|
||||||
suite.skip(options.WIRE || options.CHROMIUM);
|
suite.slow();
|
||||||
|
suite.skip(options.WIRE);
|
||||||
}, () => {
|
}, () => {
|
||||||
|
it('should capture static page', test => {
|
||||||
|
test.flaky(options.CHROMIUM && LINUX && !options.HEADLESS);
|
||||||
|
test.flaky(options.WEBKIT && LINUX);
|
||||||
|
}, async ({page, tmpDir, videoPlayer, toImpl}) => {
|
||||||
|
const videoFile = path.join(tmpDir, 'v.webm');
|
||||||
|
await page.evaluate(() => document.body.style.backgroundColor = 'red');
|
||||||
|
await toImpl(page)._delegate.startScreencast({outputFile: videoFile, width: 640, height: 480});
|
||||||
|
// TODO: in WebKit figure out why video size is not reported correctly for
|
||||||
|
// static pictures.
|
||||||
|
if (options.HEADLESS && options.WEBKIT)
|
||||||
|
await page.setViewportSize({width: 1270, height: 950});
|
||||||
|
await new Promise(r => setTimeout(r, 300));
|
||||||
|
await toImpl(page)._delegate.stopScreencast();
|
||||||
|
expect(fs.existsSync(videoFile)).toBe(true);
|
||||||
|
|
||||||
|
await videoPlayer.load(videoFile);
|
||||||
|
const duration = await videoPlayer.duration();
|
||||||
|
expect(duration).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
expect(await videoPlayer.videoWidth()).toBe(640);
|
||||||
|
expect(await videoPlayer.videoHeight()).toBe(480);
|
||||||
|
|
||||||
|
await videoPlayer.seekLastFrame();
|
||||||
|
const pixels = await videoPlayer.pixels();
|
||||||
|
expectAll(pixels, almostRed);
|
||||||
|
});
|
||||||
|
|
||||||
it('should capture navigation', test => {
|
it('should capture navigation', test => {
|
||||||
|
test.flaky(options.CHROMIUM && MAC);
|
||||||
|
test.flaky(options.FIREFOX && LINUX && !options.HEADLESS);
|
||||||
test.flaky(options.WEBKIT);
|
test.flaky(options.WEBKIT);
|
||||||
test.flaky(options.FIREFOX);
|
|
||||||
}, async ({page, tmpDir, server, videoPlayer, toImpl}) => {
|
}, async ({page, tmpDir, server, videoPlayer, toImpl}) => {
|
||||||
const videoFile = path.join(tmpDir, 'v.webm');
|
const videoFile = path.join(tmpDir, 'v.webm');
|
||||||
await page.goto(server.PREFIX + '/background-color.html#rgb(0,0,0)');
|
await page.goto(server.PREFIX + '/background-color.html#rgb(0,0,0)');
|
||||||
@ -236,12 +220,17 @@ describe('screencast', suite => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
await videoPlayer.seekLastNonEmptyFrame();
|
await videoPlayer.seekLastFrame();
|
||||||
const pixels = await videoPlayer.pixels();
|
const pixels = await videoPlayer.pixels();
|
||||||
expectAll(pixels, almostGrey);
|
expectAll(pixels, almostGrey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('screencast', suite => {
|
||||||
|
suite.slow();
|
||||||
|
suite.skip(options.WIRE || options.CHROMIUM);
|
||||||
|
}, () => {
|
||||||
it('should capture css transformation', test => {
|
it('should capture css transformation', test => {
|
||||||
test.fixme(options.WEBKIT && WIN, 'Accelerated compositing is disabled in WebKit on Windows.');
|
test.fixme(options.WEBKIT && WIN, 'Accelerated compositing is disabled in WebKit on Windows.');
|
||||||
test.flaky(options.WEBKIT && LINUX);
|
test.flaky(options.WEBKIT && LINUX);
|
||||||
@ -262,14 +251,13 @@ describe('screencast', suite => {
|
|||||||
expect(duration).toBeGreaterThan(0);
|
expect(duration).toBeGreaterThan(0);
|
||||||
|
|
||||||
{
|
{
|
||||||
await videoPlayer.seekLastNonEmptyFrame();
|
await videoPlayer.seekLastFrame();
|
||||||
const pixels = await videoPlayer.pixels({x: 95, y: 45});
|
const pixels = await videoPlayer.pixels({x: 95, y: 45});
|
||||||
expectAll(pixels, almostRed);
|
expectAll(pixels, almostRed);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fire start/stop events when page created/closed', test => {
|
it('should fire start/stop events when page created/closed', test => {
|
||||||
test.slow();
|
|
||||||
test.flaky(options.FIREFOX, 'Even slow is not slow enough');
|
test.flaky(options.FIREFOX, 'Even slow is not slow enough');
|
||||||
}, async ({browser, tmpDir, toImpl}) => {
|
}, async ({browser, tmpDir, toImpl}) => {
|
||||||
// Use server side of the context. All the code below also uses server side APIs.
|
// Use server side of the context. All the code below also uses server side APIs.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user