2019-11-21 01:18:05 +03:00
/ * *
* Copyright 2017 Google Inc . All rights reserved .
* Modifications copyright ( c ) Microsoft Corporation .
*
* 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-01-07 23:59:01 +03:00
const utils = require ( './utils' ) ;
2019-11-21 01:18:05 +03:00
const { waitEvent } = utils ;
2019-11-19 05:18:28 +03:00
2020-02-11 00:20:13 +03:00
/ * *
* @ type { PageTestSuite }
* /
2020-03-10 22:56:18 +03:00
module . exports . describe = function ( { testRunner , expect , FFOX , CHROMIUM , WEBKIT , LINUX } ) {
2019-11-19 05:18:28 +03:00
const { describe , xdescribe , fdescribe } = testRunner ;
2019-12-20 02:47:35 +03:00
const { it , fit , xit , dit } = testRunner ;
2019-11-19 05:18:28 +03:00
const { beforeAll , beforeEach , afterAll , afterEach } = testRunner ;
2020-01-18 04:51:02 +03:00
describe ( 'Workers' , function ( ) {
2020-03-10 22:56:18 +03:00
// flaky: https://github.com/microsoft/playwright/pull/1297/checks?check_run_id=496348690
it . fail ( FFOX && LINUX ) ( 'Page.workers' , async function ( { page , server } ) {
2019-11-19 05:18:28 +03:00
await Promise . all ( [
2020-02-28 01:02:48 +03:00
page . waitForEvent ( 'worker' ) ,
2019-11-19 05:18:28 +03:00
page . goto ( server . PREFIX + '/worker/worker.html' ) ] ) ;
2019-12-21 20:03:52 +03:00
const worker = page . workers ( ) [ 0 ] ;
2019-11-19 05:18:28 +03:00
expect ( worker . url ( ) ) . toContain ( 'worker.js' ) ;
2019-11-20 04:32:43 +03:00
expect ( await worker . evaluate ( ( ) => self [ 'workerFunction' ] ( ) ) ) . toBe ( 'worker function result' ) ;
2019-11-19 05:18:28 +03:00
await page . goto ( server . EMPTY _PAGE ) ;
2019-12-21 20:03:52 +03:00
expect ( page . workers ( ) . length ) . toBe ( 0 ) ;
2019-11-19 05:18:28 +03:00
} ) ;
it ( 'should emit created and destroyed events' , async function ( { page } ) {
2020-02-28 01:02:48 +03:00
const workerCreatedPromise = page . waitForEvent ( 'worker' ) ;
2020-01-07 23:59:01 +03:00
const workerObj = await page . evaluateHandle ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ '1' ] , { type : 'application/javascript' } ) ) ) ) ;
2019-11-19 05:18:28 +03:00
const worker = await workerCreatedPromise ;
const workerThisObj = await worker . evaluateHandle ( ( ) => this ) ;
2020-02-28 01:02:48 +03:00
const workerDestroyedPromise = new Promise ( x => worker . once ( 'close' , x ) ) ;
2019-11-19 05:18:28 +03:00
await page . evaluate ( workerObj => workerObj . terminate ( ) , workerObj ) ;
expect ( await workerDestroyedPromise ) . toBe ( worker ) ;
const error = await workerThisObj . getProperty ( 'self' ) . catch ( error => error ) ;
expect ( error . message ) . toContain ( 'Most likely the worker has been closed.' ) ;
} ) ;
it ( 'should report console logs' , async function ( { page } ) {
const [ message ] = await Promise . all ( [
waitEvent ( page , 'console' ) ,
2020-01-07 23:59:01 +03:00
page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ 'console.log(1)' ] , { type : 'application/javascript' } ) ) ) ) ,
2019-11-19 05:18:28 +03:00
] ) ;
expect ( message . text ( ) ) . toBe ( '1' ) ;
} ) ;
it ( 'should have JSHandles for console logs' , async function ( { page } ) {
const logPromise = new Promise ( x => page . on ( 'console' , x ) ) ;
2020-01-07 23:59:01 +03:00
await page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ 'console.log(1,2,3,this)' ] , { type : 'application/javascript' } ) ) ) ) ;
2019-11-19 05:18:28 +03:00
const log = await logPromise ;
expect ( log . text ( ) ) . toBe ( '1 2 3 JSHandle@object' ) ;
expect ( log . args ( ) . length ) . toBe ( 4 ) ;
expect ( await ( await log . args ( ) [ 3 ] . getProperty ( 'origin' ) ) . jsonValue ( ) ) . toBe ( 'null' ) ;
} ) ;
2019-12-19 00:51:45 +03:00
it ( 'should evaluate' , async function ( { page } ) {
2020-02-28 01:02:48 +03:00
const workerCreatedPromise = page . waitForEvent ( 'worker' ) ;
2020-01-07 23:59:01 +03:00
page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ 'console.log(1)' ] , { type : 'application/javascript' } ) ) ) ) ;
2019-11-19 05:18:28 +03:00
const worker = await workerCreatedPromise ;
2019-12-19 00:51:45 +03:00
expect ( await worker . evaluate ( '1+1' ) ) . toBe ( 2 ) ;
2019-11-19 05:18:28 +03:00
} ) ;
it ( 'should report errors' , async function ( { page } ) {
const errorPromise = new Promise ( x => page . on ( 'pageerror' , x ) ) ;
2020-01-07 23:59:01 +03:00
page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ ` setTimeout(() => { throw new Error('this is my error'); }) ` ] , { type : 'application/javascript' } ) ) ) ) ;
2019-11-19 05:18:28 +03:00
const errorLog = await errorPromise ;
expect ( errorLog . message ) . toContain ( 'this is my error' ) ;
} ) ;
2020-01-07 23:59:01 +03:00
it ( 'should clear upon navigation' , async function ( { server , page } ) {
await page . goto ( server . EMPTY _PAGE ) ;
2020-02-28 01:02:48 +03:00
const workerCreatedPromise = page . waitForEvent ( 'worker' ) ;
2020-01-07 23:59:01 +03:00
page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ 'console.log(1)' ] , { type : 'application/javascript' } ) ) ) ) ;
2020-02-28 01:02:48 +03:00
const worker = await workerCreatedPromise ;
2020-01-07 23:59:01 +03:00
expect ( page . workers ( ) . length ) . toBe ( 1 ) ;
2020-01-24 04:52:06 +03:00
let destroyed = false ;
2020-02-28 01:02:48 +03:00
worker . once ( 'close' , ( ) => destroyed = true ) ;
2020-01-24 04:52:06 +03:00
await page . goto ( server . PREFIX + '/one-style.html' ) ;
expect ( destroyed ) . toBe ( true ) ;
expect ( page . workers ( ) . length ) . toBe ( 0 ) ;
} ) ;
it ( 'should clear upon cross-process navigation' , async function ( { server , page } ) {
await page . goto ( server . EMPTY _PAGE ) ;
2020-02-28 01:02:48 +03:00
const workerCreatedPromise = page . waitForEvent ( 'worker' ) ;
2020-01-24 04:52:06 +03:00
page . evaluate ( ( ) => new Worker ( URL . createObjectURL ( new Blob ( [ 'console.log(1)' ] , { type : 'application/javascript' } ) ) ) ) ;
2020-02-28 01:02:48 +03:00
const worker = await workerCreatedPromise ;
2020-01-24 04:52:06 +03:00
expect ( page . workers ( ) . length ) . toBe ( 1 ) ;
let destroyed = false ;
2020-02-28 01:02:48 +03:00
worker . once ( 'close' , ( ) => destroyed = true ) ;
2020-01-07 23:59:01 +03:00
await page . goto ( server . CROSS _PROCESS _PREFIX + '/empty.html' ) ;
2020-01-24 04:52:06 +03:00
expect ( destroyed ) . toBe ( true ) ;
2020-01-07 23:59:01 +03:00
expect ( page . workers ( ) . length ) . toBe ( 0 ) ;
} ) ;
2020-03-10 22:56:18 +03:00
// flaky: https://github.com/microsoft/playwright/pull/1277/checks?check_run_id=496461538
it . fail ( FFOX && LINUX ) ( 'should report network activity' , async function ( { page , server } ) {
2020-01-21 21:41:04 +03:00
const [ worker ] = await Promise . all ( [
2020-02-28 01:02:48 +03:00
page . waitForEvent ( 'worker' ) ,
2020-01-21 21:41:04 +03:00
page . goto ( server . PREFIX + '/worker/worker.html' ) ,
] ) ;
const url = server . PREFIX + '/one-style.css' ;
const requestPromise = page . waitForRequest ( url ) ;
const responsePromise = page . waitForResponse ( url ) ;
await worker . evaluate ( url => fetch ( url ) . then ( response => response . text ( ) ) . then ( console . log ) , url ) ;
const request = await requestPromise ;
const response = await responsePromise ;
expect ( request . url ( ) ) . toBe ( url ) ;
expect ( response . request ( ) ) . toBe ( request ) ;
expect ( response . ok ( ) ) . toBe ( true ) ;
} ) ;
2020-02-05 06:36:46 +03:00
it ( 'should report network activity on worker creation' , async function ( { page , server } ) {
2020-01-21 21:41:04 +03:00
// Chromium needs waitForDebugger enabled for this one.
await page . goto ( server . EMPTY _PAGE ) ;
const url = server . PREFIX + '/one-style.css' ;
const requestPromise = page . waitForRequest ( url ) ;
const responsePromise = page . waitForResponse ( url ) ;
await page . evaluate ( url => new Worker ( URL . createObjectURL ( new Blob ( [ `
fetch ( "${url}" ) . then ( response => response . text ( ) ) . then ( console . log ) ;
` ], {type: 'application/javascript'}))), url);
const request = await requestPromise ;
const response = await responsePromise ;
expect ( request . url ( ) ) . toBe ( url ) ;
expect ( response . request ( ) ) . toBe ( request ) ;
expect ( response . ok ( ) ) . toBe ( true ) ;
} ) ;
2020-03-03 00:47:08 +03:00
false && it . fail ( FFOX ) ( 'should report web socket activity' , async function ( { page , server } ) {
2020-01-21 22:48:48 +03:00
const [ worker ] = await Promise . all ( [
2020-02-28 01:02:48 +03:00
page . waitForEvent ( 'worker' ) ,
2020-01-21 22:48:48 +03:00
page . goto ( server . PREFIX + '/worker/worker.html' ) ,
] ) ;
const log = [ ] ;
let socketClosed ;
const socketClosePromise = new Promise ( f => socketClosed = f ) ;
page . on ( 'websocket' , ws => {
ws . on ( 'open' , ( ) => log . push ( ` open< ${ ws . url ( ) } > ` ) ) ;
ws . on ( 'close' , ( ) => { log . push ( 'close' ) ; socketClosed ( ) ; } ) ;
} ) ;
worker . evaluate ( ( port ) => {
const ws = new WebSocket ( 'ws://localhost:' + port + '/ws' ) ;
ws . addEventListener ( 'open' , ( ) => ws . close ( ) ) ;
} , server . PORT ) ;
await socketClosePromise ;
expect ( log . join ( ':' ) ) . toBe ( ` open<ws://localhost: ${ server . PORT } /ws>:close ` ) ;
} ) ;
2019-11-19 05:18:28 +03:00
} ) ;
} ;