2020-08-03 15:23:53 -07:00
/ * *
* Copyright 2018 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-08-19 21:32:12 -07:00
2021-11-03 10:44:50 -07:00
import { attachFrame , detachFrame } from '../config/utils' ;
2021-05-06 07:08:22 -07:00
import { test as it , expect } from './pageTest' ;
2020-08-03 15:23:53 -07:00
2022-03-10 19:42:52 +01:00
it ( 'should work @smoke' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > 7 * 3 ) ;
expect ( result ) . toBe ( 21 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer NaN' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a , NaN ) ;
expect ( Object . is ( result , NaN ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer -0' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a , - 0 ) ;
expect ( Object . is ( result , - 0 ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer Infinity' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a , Infinity ) ;
expect ( Object . is ( result , Infinity ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer -Infinity' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a , - Infinity ) ;
expect ( Object . is ( result , - Infinity ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should roundtrip unserializable values' , async ( { page } ) = > {
const value = {
infinity : Infinity ,
nInfinity : - Infinity ,
nZero : - 0 ,
nan : NaN ,
} ;
const result = await page . evaluate ( value = > value , value ) ;
expect ( result ) . toEqual ( value ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should roundtrip promise to value' , async ( { page } ) = > {
{
const result = await page . evaluate ( value = > Promise . resolve ( value ) , null ) ;
expect ( result === null ) . toBeTruthy ( ) ;
}
{
const result = await page . evaluate ( value = > Promise . resolve ( value ) , Infinity ) ;
expect ( result === Infinity ) . toBeTruthy ( ) ;
}
{
const result = await page . evaluate ( value = > Promise . resolve ( value ) , - 0 ) ;
expect ( result === - 0 ) . toBeTruthy ( ) ;
}
{
const result = await page . evaluate ( value = > Promise . resolve ( value ) , undefined ) ;
expect ( result === undefined ) . toBeTruthy ( ) ;
}
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should roundtrip promise to unserializable values' , async ( { page } ) = > {
const value = {
infinity : Infinity ,
nInfinity : - Infinity ,
nZero : - 0 ,
nan : NaN ,
} ;
const result = await page . evaluate ( value = > Promise . resolve ( value ) , value ) ;
expect ( result ) . toEqual ( value ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer arrays' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a , [ 1 , 2 , 3 ] ) ;
expect ( result ) . toEqual ( [ 1 , 2 , 3 ] ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should transfer arrays as arrays, not objects' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > Array . isArray ( a ) , [ 1 , 2 , 3 ] ) ;
expect ( result ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2025-03-26 18:04:45 +01:00
it ( 'should transfer typed arrays' , async ( { page } ) = > {
const testCases = [
new Int8Array ( [ 1 , 2 , 3 ] ) ,
new Uint8Array ( [ 1 , 2 , 3 ] ) ,
new Uint8ClampedArray ( [ 1 , 2 , 3 ] ) ,
new Int16Array ( [ 1 , 2 , 3 ] ) ,
new Uint16Array ( [ 1 , 2 , 3 ] ) ,
new Int32Array ( [ 1 , 2 , 3 ] ) ,
new Uint32Array ( [ 1 , 2 , 3 ] ) ,
new Float32Array ( [ 1.1 , 2.2 , 3.3 ] ) ,
new Float64Array ( [ 1.1 , 2.2 , 3.3 ] ) ,
new BigInt64Array ( [ 1 n , 2 n , 3 n ] ) ,
new BigUint64Array ( [ 1 n , 2 n , 3 n ] )
] ;
for ( const typedArray of testCases ) {
const result = await page . evaluate ( a = > a , typedArray ) ;
expect ( result ) . toEqual ( typedArray ) ;
}
} ) ;
2023-06-28 08:55:45 -07:00
it ( 'should transfer bigint' , async ( { page } ) = > {
expect ( await page . evaluate ( ( ) = > 42 n ) ) . toBe ( 42 n ) ;
expect ( await page . evaluate ( a = > a , 17 n ) ) . toBe ( 17 n ) ;
} ) ;
2023-09-20 18:31:09 -07:00
it ( 'should transfer maps as empty objects' , async ( { page } ) = > {
const result = await page . evaluate ( a = > a . x . constructor . name + ' ' + JSON . stringify ( a . x ) , { x : new Map ( [ [ 1 , 2 ] ] ) } ) ;
expect ( result ) . toBe ( 'Object {}' ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should modify global environment' , async ( { page } ) = > {
2020-08-11 15:50:53 -07:00
await page . evaluate ( ( ) = > window [ 'globalVar' ] = 123 ) ;
2020-08-03 15:23:53 -07:00
expect ( await page . evaluate ( 'globalVar' ) ) . toBe ( 123 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should evaluate in the page context' , async ( { page , server } ) = > {
await page . goto ( server . PREFIX + '/global-var.html' ) ;
expect ( await page . evaluate ( 'globalVar' ) ) . toBe ( 123 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return undefined for objects with symbols' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
expect ( await page . evaluate ( ( ) = > [ Symbol ( 'foo4' ) ] ) ) . toEqual ( [ undefined ] ) ;
expect ( await page . evaluate ( ( ) = > {
const a = { } ;
a [ Symbol ( 'foo4' ) ] = 42 ;
return a ;
} ) ) . toEqual ( { } ) ;
expect ( await page . evaluate ( ( ) = > {
return { foo : [ { a : Symbol ( 'foo4' ) } ] } ;
} ) ) . toEqual ( { foo : [ { a : undefined } ] } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should work with function shorthands' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const a = {
2021-04-02 14:23:42 -07:00
sum ( [ a , b ] : number [ ] ) { return a + b ; } ,
async mult ( [ a , b ] : number [ ] ) { return a * b ; }
2020-08-03 15:23:53 -07:00
} ;
expect ( await page . evaluate ( a . sum , [ 1 , 2 ] ) ) . toBe ( 3 ) ;
expect ( await page . evaluate ( a . mult , [ 2 , 4 ] ) ) . toBe ( 8 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should work with unicode chars' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( a = > a [ '中文字符' ] , { '中文字符' : 42 } ) ;
expect ( result ) . toBe ( 42 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2022-08-09 10:44:52 -07:00
it ( 'should work with large strings' , async ( { page } ) = > {
const expected = 'x' . repeat ( 40000 ) ;
expect ( await page . evaluate ( data = > data , expected ) ) . toBe ( expected ) ;
} ) ;
it ( 'should work with large unicode strings' , async ( { page , browserName , platform } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/16367' } ) ;
const expected = '🎭' . repeat ( 10000 ) ;
expect ( await page . evaluate ( data = > data , expected ) ) . toBe ( expected ) ;
} ) ;
2021-03-19 07:20:35 +08:00
it ( 'should throw when evaluation triggers reload' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
let error = null ;
await page . evaluate ( ( ) = > {
location . reload ( ) ;
return new Promise ( ( ) = > { } ) ;
} ) . catch ( e = > error = e ) ;
expect ( error . message ) . toContain ( 'navigation' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should await promise' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > Promise . resolve ( 8 * 7 ) ) ;
expect ( result ) . toBe ( 56 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work right after framenavigated' , async ( { page , server } ) = > {
let frameEvaluation = null ;
page . on ( 'framenavigated' , async frame = > {
frameEvaluation = frame . evaluate ( ( ) = > 6 * 7 ) ;
} ) ;
await page . goto ( server . EMPTY_PAGE ) ;
expect ( await frameEvaluation ) . toBe ( 42 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work right after a cross-origin navigation' , async ( { page , server } ) = > {
await page . goto ( server . EMPTY_PAGE ) ;
let frameEvaluation = null ;
page . on ( 'framenavigated' , async frame = > {
frameEvaluation = frame . evaluate ( ( ) = > 6 * 7 ) ;
} ) ;
await page . goto ( server . CROSS_PROCESS_PREFIX + '/empty.html' ) ;
expect ( await frameEvaluation ) . toBe ( 42 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should work from-inside an exposed function' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
// Setup inpage callback, which calls Page.evaluate
2020-08-28 04:20:29 -07:00
await page . exposeFunction ( 'callController' , async function ( a , b ) {
2020-08-03 15:23:53 -07:00
return await page . evaluate ( ( { a , b } ) = > a * b , { a , b } ) ;
} ) ;
2020-08-28 04:20:29 -07:00
const result = await page . evaluate ( async function ( ) {
2020-08-11 15:50:53 -07:00
return await window [ 'callController' ] ( 9 , 3 ) ;
2020-08-03 15:23:53 -07:00
} ) ;
expect ( result ) . toBe ( 27 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should reject promise with exception' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
let error = null ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await page . evaluate ( ( ) = > not_existing_object . property ) . catch ( e = > error = e ) ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toContain ( 'not_existing_object' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should support thrown strings as error messages' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
let error = null ;
await page . evaluate ( ( ) = > { throw 'qwerty' ; } ) . catch ( e = > error = e ) ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toContain ( 'qwerty' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should support thrown numbers as error messages' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
let error = null ;
await page . evaluate ( ( ) = > { throw 100500 ; } ) . catch ( e = > error = e ) ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toContain ( '100500' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return complex objects' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const object = { foo : 'bar!' } ;
const result = await page . evaluate ( a = > a , object ) ;
expect ( result ) . not . toBe ( object ) ;
expect ( result ) . toEqual ( object ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return NaN' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > NaN ) ;
expect ( Object . is ( result , NaN ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return -0' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > - 0 ) ;
expect ( Object . is ( result , - 0 ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return Infinity' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > Infinity ) ;
expect ( Object . is ( result , Infinity ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should return -Infinity' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > - Infinity ) ;
expect ( Object . is ( result , - Infinity ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should work with overwritten Promise' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
await page . evaluate ( ( ) = > {
const originalPromise = window . Promise ;
class Promise2 {
2020-08-11 15:50:53 -07:00
_promise : Promise < any > ;
static all ( arg ) {
return wrap ( originalPromise . all ( arg ) ) ;
2020-08-03 15:23:53 -07:00
}
2020-08-11 15:50:53 -07:00
static race ( arg ) {
return wrap ( originalPromise . race ( arg ) ) ;
2020-08-03 15:23:53 -07:00
}
2020-08-11 15:50:53 -07:00
static resolve ( arg ) {
return wrap ( originalPromise . resolve ( arg ) ) ;
2020-08-03 15:23:53 -07:00
}
2020-08-11 15:50:53 -07:00
constructor ( f ) {
this . _promise = new originalPromise ( f ) ;
2020-08-03 15:23:53 -07:00
}
then ( f , r ) {
return wrap ( this . _promise . then ( f , r ) ) ;
}
catch ( f ) {
return wrap ( this . _promise . catch ( f ) ) ;
}
finally ( f ) {
return wrap ( this . _promise . finally ( f ) ) ;
}
2020-08-28 04:20:29 -07:00
}
2020-08-03 15:23:53 -07:00
const wrap = p = > {
2020-08-11 15:50:53 -07:00
const result = new Promise2 ( ( ) = > { } ) ;
2020-08-03 15:23:53 -07:00
result . _promise = p ;
return result ;
} ;
2020-08-28 04:20:29 -07:00
// @ts-ignore;
2020-08-03 15:23:53 -07:00
window . Promise = Promise2 ;
2020-08-28 04:20:29 -07:00
window [ '__Promise2' ] = Promise2 ;
2020-08-03 15:23:53 -07:00
} ) ;
// Sanity check.
expect ( await page . evaluate ( ( ) = > {
const p = Promise . all ( [ Promise . race ( [ ] ) , new Promise ( ( ) = > { } ) . then ( ( ) = > { } ) ] ) ;
2020-08-28 04:20:29 -07:00
return p instanceof window [ '__Promise2' ] ;
2020-08-03 15:23:53 -07:00
} ) ) . toBe ( true ) ;
// Now, the new promise should be awaitable.
expect ( await page . evaluate ( ( ) = > Promise . resolve ( 42 ) ) ) . toBe ( 42 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should throw when passed more than one parameter' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const expectThrow = async f = > {
let error ;
await f ( ) . catch ( e = > error = e ) ;
expect ( '' + error ) . toContain ( 'Too many arguments' ) ;
2020-08-28 04:20:29 -07:00
} ;
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > page . evaluate ( ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > page . evaluateHandle ( ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > page . $eval ( 'sel' , ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > page . $ $eval ( 'sel' , ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > page . evaluate ( ( a , b ) = > false , 1 , 2 ) ) ;
const frame = page . mainFrame ( ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > frame . evaluate ( ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > frame . evaluateHandle ( ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > frame . $eval ( 'sel' , ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > frame . $ $eval ( 'sel' , ( a , b ) = > false , 1 , 2 ) ) ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
await expectThrow ( ( ) = > frame . evaluate ( ( a , b ) = > false , 1 , 2 ) ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should accept "undefined" as one of multiple parameters' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( { a , b } ) = > Object . is ( a , undefined ) && Object . is ( b , 'foo' ) , { a : undefined , b : 'foo' } ) ;
expect ( result ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should properly serialize undefined arguments' , async ( { page } ) = > {
expect ( await page . evaluate ( x = > ( { a : x } ) , undefined ) ) . toEqual ( { } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should properly serialize undefined fields' , async ( { page } ) = > {
expect ( await page . evaluate ( ( ) = > ( { a : undefined } ) ) ) . toEqual ( { } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should return undefined properties' , async ( { page } ) = > {
const value = await page . evaluate ( ( ) = > ( { a : undefined } ) ) ;
expect ( 'a' in value ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should properly serialize null arguments' , async ( { page } ) = > {
expect ( await page . evaluate ( x = > x , null ) ) . toEqual ( null ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should properly serialize null fields' , async ( { page } ) = > {
expect ( await page . evaluate ( ( ) = > ( { a : null } ) ) ) . toEqual ( { a : null } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2022-06-29 08:07:32 +02:00
it ( 'should properly serialize PerformanceMeasure object' , async ( { page } ) = > {
expect ( await page . evaluate ( ( ) = > {
2025-03-25 13:49:28 +00:00
window . builtins . performance . mark ( 'start' ) ;
window . builtins . performance . mark ( 'end' ) ;
window . builtins . performance . measure ( 'my-measure' , 'start' , 'end' ) ;
return window . builtins . performance . getEntriesByType ( 'measure' ) ;
2022-06-29 08:07:32 +02:00
} ) ) . toEqual ( [ {
duration : expect.any ( Number ) ,
entryType : 'measure' ,
name : 'my-measure' ,
startTime : expect.any ( Number ) ,
} ] ) ;
} ) ;
2023-01-30 09:53:28 +01:00
it ( 'should properly serialize window.performance object' , async ( { page } ) = > {
2024-06-17 09:17:38 -07:00
it . skip ( ! ! process . env . PW_CLOCK ) ;
2024-05-31 14:44:26 -07:00
2022-06-29 08:07:32 +02:00
expect ( await page . evaluate ( ( ) = > performance ) ) . toEqual ( {
'navigation' : {
'redirectCount' : 0 ,
2022-09-07 20:09:22 +02:00
'type' : expect . any ( Number ) ,
2022-06-29 08:07:32 +02:00
} ,
'timeOrigin' : expect . any ( Number ) ,
'timing' : {
'connectEnd' : expect . any ( Number ) ,
'connectStart' : expect . any ( Number ) ,
'domComplete' : expect . any ( Number ) ,
'domContentLoadedEventEnd' : expect . any ( Number ) ,
'domContentLoadedEventStart' : expect . any ( Number ) ,
'domInteractive' : expect . any ( Number ) ,
'domLoading' : expect . any ( Number ) ,
'domainLookupEnd' : expect . any ( Number ) ,
'domainLookupStart' : expect . any ( Number ) ,
'fetchStart' : expect . any ( Number ) ,
'loadEventEnd' : expect . any ( Number ) ,
'loadEventStart' : expect . any ( Number ) ,
'navigationStart' : expect . any ( Number ) ,
'redirectEnd' : expect . any ( Number ) ,
'redirectStart' : expect . any ( Number ) ,
'requestStart' : expect . any ( Number ) ,
'responseEnd' : expect . any ( Number ) ,
'responseStart' : expect . any ( Number ) ,
'secureConnectionStart' : expect . any ( Number ) ,
'unloadEventEnd' : expect . any ( Number ) ,
'unloadEventStart' : expect . any ( Number ) ,
}
} ) ;
} ) ;
2021-03-19 07:20:35 +08:00
it ( 'should return undefined for non-serializable objects' , async ( { page } ) = > {
2022-05-09 17:51:53 -08:00
expect ( await page . evaluate ( ( ) = > function ( ) { } ) ) . toBe ( undefined ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2024-12-13 13:38:26 -08:00
it ( 'should throw for too deep reference chain' , {
annotation : { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/33997' }
} , async ( { page , browserName } ) = > {
2025-05-12 16:46:12 +02:00
it . fixme ( browserName === 'firefox' , 'Firefox Juggler -> Playwright serialiser does not throw for deep references.\nThis causes large objects to get serialised back to the Playwright client.\nThere our validators throw \'Maximum call stack size exceeded\'.' ) ;
2024-12-13 13:38:26 -08:00
await expect ( page . evaluate ( depth = > {
const obj = { } ;
let temp = obj ;
for ( let i = 0 ; i < depth ; i ++ ) {
temp [ i ] = { } ;
temp = temp [ i ] ;
}
return obj ;
2025-05-12 16:46:12 +02:00
} , 1000 ) ) . rejects . toThrow ( 'Cannot serialize result: object reference chain is too long.' ) ;
2024-12-13 13:38:26 -08:00
} ) ;
2025-03-25 10:32:44 -07:00
it ( 'should throw usable message for unserializable shallow function' , async ( { page } ) = > {
await expect ( ( ) = > page . evaluate ( arg = > arg , ( ) = > { } ) )
. rejects . toThrow ( /Attempting to serialize unexpected value: \(\) => {}/ ) ;
} ) ;
it ( 'should throw usable message for unserializable object one deep function' , async ( { page } ) = > {
await expect ( ( ) = > page . evaluate ( arg = > arg , { aProperty : ( ) = > { } } ) )
. rejects . toThrow ( /Attempting to serialize unexpected value at position "aProperty": \(\) => {}/ ) ;
} ) ;
it ( 'should throw usable message for unserializable object nested function' , async ( { page } ) = > {
await expect ( ( ) = > page . evaluate ( arg = > arg , { a : { inner : { property : ( ) = > { } } } } ) )
. rejects . toThrow ( /Attempting to serialize unexpected value at position "a\.inner\.property": \(\) => {}/ ) ;
} ) ;
it ( 'should throw usable message for unserializable array nested function' , async ( { page } ) = > {
await expect ( ( ) = > page . evaluate ( arg = > arg , { a : { inner : [ 'firstValue' , { property : ( ) = > { } } ] } } ) )
. rejects . toThrow ( /Attempting to serialize unexpected value at position "a\.inner\[1\]\.property": \(\) => {}/ ) ;
} ) ;
2022-05-09 17:51:53 -08:00
it ( 'should alias Window, Document and Node' , async ( { page } ) = > {
const object = await page . evaluate ( '[window, document, document.body]' ) ;
expect ( object ) . toEqual ( [ 'ref: <Window>' , 'ref: <Document>' , 'ref: <Node>' ] ) ;
} ) ;
it ( 'should work for circular object' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > {
2020-08-11 15:50:53 -07:00
const a = { } as any ;
2022-05-09 17:51:53 -08:00
a . b = a ;
2020-08-03 15:23:53 -07:00
return a ;
} ) ;
2022-05-09 17:51:53 -08:00
const a = { } as any ;
a . b = a ;
expect ( result ) . toEqual ( a ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should be able to throw a tricky error' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const windowHandle = await page . evaluateHandle ( ( ) = > window ) ;
const errorText = await windowHandle . jsonValue ( ) . catch ( e = > e . message ) ;
const error = await page . evaluate ( errorText = > {
throw new Error ( errorText ) ;
} , errorText ) . catch ( e = > e ) ;
expect ( error . message ) . toContain ( errorText ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should accept a string' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( '1 + 2' ) ;
expect ( result ) . toBe ( 3 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should accept a string with semi colons' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( '1 + 5;' ) ;
expect ( result ) . toBe ( 6 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should accept a string with comments' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( '2 + 5;\n// do some math!' ) ;
expect ( result ) . toBe ( 7 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should accept element handle as an argument' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
await page . setContent ( '<section>42</section>' ) ;
const element = await page . $ ( 'section' ) ;
const text = await page . evaluate ( e = > e . textContent , element ) ;
expect ( text ) . toBe ( '42' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should throw if underlying element was disposed' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
await page . setContent ( '<section>39</section>' ) ;
const element = await page . $ ( 'section' ) ;
expect ( element ) . toBeTruthy ( ) ;
await element . dispose ( ) ;
let error = null ;
await page . evaluate ( e = > e . textContent , element ) . catch ( e = > error = e ) ;
2023-11-01 16:36:39 -07:00
expect ( error . message ) . toContain ( 'no object with guid' ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should simulate a user gesture' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > {
document . body . appendChild ( document . createTextNode ( 'test' ) ) ;
document . execCommand ( 'selectAll' ) ;
return document . execCommand ( 'copy' ) ;
} ) ;
expect ( result ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-03-19 07:20:35 +08:00
it ( 'should throw a nice error after a navigation' , async ( { page } ) = > {
2020-08-11 15:50:53 -07:00
const errorPromise = page . evaluate ( ( ) = > new Promise ( f = > window [ '__resolve' ] = f ) ) . catch ( e = > e ) as Promise < Error > ;
2020-08-03 15:23:53 -07:00
await Promise . all ( [
page . waitForNavigation ( ) ,
page . evaluate ( ( ) = > {
window . location . reload ( ) ;
2020-08-11 15:50:53 -07:00
setTimeout ( ( ) = > window [ '__resolve' ] ( 42 ) , 1000 ) ;
2020-08-03 15:23:53 -07:00
} )
] ) ;
const error = await errorPromise ;
expect ( error . message ) . toContain ( 'navigation' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should not throw an error when evaluation does a navigation' , async ( { page , server } ) = > {
await page . goto ( server . PREFIX + '/one-style.html' ) ;
const result = await page . evaluate ( ( ) = > {
2020-08-11 15:50:53 -07:00
window . location . href = '/empty.html' ;
2020-08-03 15:23:53 -07:00
return [ 42 ] ;
} ) ;
expect ( result ) . toEqual ( [ 42 ] ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-05-13 10:22:23 -07:00
it ( 'should not throw an error when evaluation does a synchronous navigation and returns an object' , async ( { page , server , browserName } ) = > {
2023-01-30 09:53:28 +01:00
// It is important to be on about:blank for sync reload.
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > {
window . location . reload ( ) ;
return { a : 42 } ;
} ) ;
expect ( result ) . toEqual ( { a : 42 } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should not throw an error when evaluation does a synchronous navigation and returns undefined' , async ( { page } ) = > {
2023-01-30 09:53:28 +01:00
// It is important to be on about:blank for sync reload.
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > {
window . location . reload ( ) ;
return undefined ;
} ) ;
expect ( result ) . toBe ( undefined ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-04-02 14:23:42 -07:00
it ( 'should transfer 100Mb of data from page to node.js' , async ( { mode , page } ) = > {
it . skip ( mode !== 'default' ) ;
2020-08-13 16:00:23 -07:00
// This is too slow with wire.
2020-08-03 15:23:53 -07:00
const a = await page . evaluate ( ( ) = > Array ( 100 * 1024 * 1024 + 1 ) . join ( 'a' ) ) ;
expect ( a . length ) . toBe ( 100 * 1024 * 1024 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should throw error with detailed information on exception inside promise ' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
let error = null ;
await page . evaluate ( ( ) = > new Promise ( ( ) = > {
throw new Error ( 'Error in promise' ) ;
} ) ) . catch ( e = > error = e ) ;
expect ( error . message ) . toContain ( 'Error in promise' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work even when JSON is set to null' , async ( { page } ) = > {
await page . evaluate ( ( ) = > { window . JSON . stringify = null ; window . JSON = null ; } ) ;
const result = await page . evaluate ( ( ) = > ( { abc : 123 } ) ) ;
expect ( result ) . toEqual ( { abc : 123 } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-28 00:32:00 -07:00
it ( 'should await promise from popup' , async ( { page , server } ) = > {
2020-08-03 15:23:53 -07:00
// Something is wrong about the way Firefox waits for the chained promise
await page . goto ( server . EMPTY_PAGE ) ;
const result = await page . evaluate ( ( ) = > {
const win = window . open ( 'about:blank' ) ;
2020-08-11 15:50:53 -07:00
return new win [ 'Promise' ] ( f = > f ( 42 ) ) ;
2020-08-03 15:23:53 -07:00
} ) ;
expect ( result ) . toBe ( 42 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work with new Function() and CSP' , async ( { page , server } ) = > {
server . setCSP ( '/empty.html' , 'script-src ' + server . PREFIX ) ;
await page . goto ( server . PREFIX + '/empty.html' ) ;
expect ( await page . evaluate ( ( ) = > new Function ( 'return true' ) ( ) ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work with non-strict expressions' , async ( { page , server } ) = > {
expect ( await page . evaluate ( ( ) = > {
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
y = 3.14 ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
return y ;
} ) ) . toBe ( 3.14 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should respect use strict expression' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const error = await page . evaluate ( ( ) = > {
2020-08-28 04:20:29 -07:00
'use strict' ;
// @ts-ignore
2020-08-03 15:23:53 -07:00
variableY = 3.14 ;
2020-08-28 04:20:29 -07:00
// @ts-ignore
2020-08-03 15:23:53 -07:00
return variableY ;
} ) . catch ( e = > e ) ;
expect ( error . message ) . toContain ( 'variableY' ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should not leak utility script' , async function ( { page } ) {
2020-08-03 15:23:53 -07:00
expect ( await page . evaluate ( ( ) = > this === window ) ) . toBe ( true ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should not leak handles' , async ( { page } ) = > {
2020-08-11 15:50:53 -07:00
const error = await page . evaluate ( 'handles.length' ) . catch ( e = > e ) ;
expect ( ( error as Error ) . message ) . toContain ( ' handles' ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should work with CSP' , async ( { page , server } ) = > {
server . setCSP ( '/empty.html' , ` script-src 'self' ` ) ;
await page . goto ( server . EMPTY_PAGE ) ;
expect ( await page . evaluate ( ( ) = > 2 + 2 ) ) . toBe ( 4 ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-07-09 08:36:11 +02:00
it ( 'should evaluate exception with a function on the stack' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const error = await page . evaluate ( ( ) = > {
return ( function functionOnStack() {
return new Error ( 'error message' ) ;
} ) ( ) ;
} ) ;
2024-07-15 05:47:40 -07:00
expect ( error . message ) . toBe ( 'error message' ) ;
expect ( error . stack ) . toContain ( 'functionOnStack' ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2020-09-26 16:05:58 -07:00
it ( 'should evaluate exception' , async ( { page } ) = > {
2024-07-15 05:47:40 -07:00
const error = await page . evaluate ( ( ) = > {
function innerFunction() {
const e = new Error ( 'error message' ) ;
e . name = 'foobar' ;
return e ;
}
return innerFunction ( ) ;
} ) ;
expect ( error ) . toBeInstanceOf ( Error ) ;
expect ( ( error as Error ) . message ) . toBe ( 'error message' ) ;
expect ( ( error as Error ) . name ) . toBe ( 'foobar' ) ;
expect ( ( error as Error ) . stack ) . toContain ( 'innerFunction' ) ;
} ) ;
it ( 'should pass exception argument' , async ( { page } ) = > {
function innerFunction() {
const e = new Error ( 'error message' ) ;
e . name = 'foobar' ;
return e ;
}
const received = await page . evaluate ( e = > {
return { message : e.message , name : e.name , stack : e.stack } ;
} , innerFunction ( ) ) ;
expect ( received . message ) . toBe ( 'error message' ) ;
expect ( received . name ) . toBe ( 'foobar' ) ;
expect ( received . stack ) . toContain ( 'innerFunction' ) ;
2020-08-03 15:23:53 -07:00
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should evaluate date' , async ( { page } ) = > {
const result = await page . evaluate ( ( ) = > ( { date : new Date ( '2020-05-27T01:31:38.506Z' ) } ) ) ;
expect ( result ) . toEqual ( { date : new Date ( '2020-05-27T01:31:38.506Z' ) } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should roundtrip date' , async ( { page } ) = > {
const date = new Date ( '2020-05-27T01:31:38.506Z' ) ;
const result = await page . evaluate ( date = > date , date ) ;
expect ( result . toUTCString ( ) ) . toEqual ( date . toUTCString ( ) ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should roundtrip regex' , async ( { page } ) = > {
const regex = /hello/im ;
const result = await page . evaluate ( regex = > regex , regex ) ;
expect ( result . toString ( ) ) . toEqual ( regex . toString ( ) ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2020-08-03 15:23:53 -07:00
it ( 'should jsonValue() date' , async ( { page } ) = > {
const resultHandle = await page . evaluateHandle ( ( ) = > ( { date : new Date ( '2020-05-27T01:31:38.506Z' ) } ) ) ;
expect ( await resultHandle . jsonValue ( ) ) . toEqual ( { date : new Date ( '2020-05-27T01:31:38.506Z' ) } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2022-07-05 11:53:02 -04:00
it ( 'should evaluate url' , async ( { page } ) = > {
const result = await page . evaluate ( ( ) = > ( { url : new URL ( 'https://example.com' ) } ) ) ;
expect ( result ) . toEqual ( { url : new URL ( 'https://example.com' ) } ) ;
} ) ;
it ( 'should roundtrip url' , async ( { page } ) = > {
const url = new URL ( 'https://example.com' ) ;
const result = await page . evaluate ( url = > url , url ) ;
expect ( result . toString ( ) ) . toEqual ( url . toString ( ) ) ;
} ) ;
it ( 'should jsonValue() url' , async ( { page } ) = > {
const resultHandle = await page . evaluateHandle ( ( ) = > ( { url : new URL ( 'https://example.com' ) } ) ) ;
expect ( await resultHandle . jsonValue ( ) ) . toEqual ( { url : new URL ( 'https://example.com' ) } ) ;
} ) ;
2020-09-26 16:05:58 -07:00
it ( 'should not use toJSON when evaluating' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const result = await page . evaluate ( ( ) = > ( { toJSON : ( ) = > 'string' , data : 'data' } ) ) ;
expect ( result ) . toEqual ( { data : 'data' , toJSON : { } } ) ;
} ) ;
2020-08-04 15:09:24 -07:00
2021-06-10 10:53:30 -07:00
it ( 'should not use Array.prototype.toJSON when evaluating' , async ( { page } ) = > {
2021-05-26 23:02:21 +00:00
const result = await page . evaluate ( ( ) = > {
( Array . prototype as any ) . toJSON = ( ) = > 'busted' ;
return [ 1 , 2 , 3 ] ;
} ) ;
2022-08-18 20:12:33 +02:00
expect ( result ) . toEqual ( [ 1 , 2 , 3 ] ) ;
2021-05-26 23:02:21 +00:00
} ) ;
2021-06-10 10:53:30 -07:00
it ( 'should not add a toJSON property to newly created Arrays after evaluation' , async ( { page , browserName } ) = > {
await page . evaluate ( ( ) = > [ ] ) ;
2021-06-23 11:08:35 +02:00
const hasToJSONProperty = await page . evaluate ( ( ) = > 'toJSON' in [ ] ) ;
2021-06-10 10:53:30 -07:00
expect ( hasToJSONProperty ) . toEqual ( false ) ;
} ) ;
2020-09-26 16:05:58 -07:00
it ( 'should not use toJSON in jsonValue' , async ( { page } ) = > {
2020-08-03 15:23:53 -07:00
const resultHandle = await page . evaluateHandle ( ( ) = > ( { toJSON : ( ) = > 'string' , data : 'data' } ) ) ;
expect ( await resultHandle . jsonValue ( ) ) . toEqual ( { data : 'data' , toJSON : { } } ) ;
} ) ;
2021-01-08 16:15:05 -08:00
2023-09-21 13:31:28 -07:00
it ( 'should ignore buggy toJSON' , async ( { page } ) = > {
const result = await page . evaluate ( ( ) = > {
class Foo {
toJSON() {
throw new Error ( 'Bad' ) ;
}
}
class Bar {
get toJSON() {
throw new Error ( 'Also bad' ) ;
}
}
return { foo : new Foo ( ) , bar : new Bar ( ) } ;
} ) ;
expect ( result ) . toEqual ( { foo : { } , bar : { } } ) ;
} ) ;
2021-01-08 16:15:05 -08:00
it ( 'should not expose the injected script export' , async ( { page } ) = > {
expect ( await page . evaluate ( 'typeof pwExport === "undefined"' ) ) . toBe ( true ) ;
} ) ;
2021-11-03 10:44:50 -07:00
it ( 'should throw when frame is detached' , async ( { page , server } ) = > {
await attachFrame ( page , 'frame1' , server . EMPTY_PAGE ) ;
const frame = page . frames ( ) [ 1 ] ;
const promise = frame . evaluate ( ( ) = > new Promise < void > ( ( ) = > { } ) ) . catch ( e = > e ) ;
await detachFrame ( page , 'frame1' ) ;
const error = await promise ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toMatch ( /frame.evaluate: (Frame was detached|Execution context was destroyed)/ ) ;
} ) ;
2022-09-06 17:25:02 -07:00
it ( 'should work with overridden Object.defineProperty' , async ( { page , server } ) = > {
server . setRoute ( '/test' , ( req , res ) = > {
res . writeHead ( 200 , {
'content-type' : 'text/html' ,
} ) ;
res . end ( ` <script>
Object . create = null ;
Object . defineProperty = null ;
Object . getOwnPropertyDescriptor = null ;
Object . getOwnPropertyNames = null ;
Object . getPrototypeOf = null ;
Object . prototype . hasOwnProperty = null ;
< / script > ` );
} ) ;
await page . goto ( server . PREFIX + '/test' ) ;
expect ( await page . evaluate ( '1+2' ) ) . toBe ( 3 ) ;
} ) ;
2022-09-13 18:21:07 +02:00
2023-04-21 19:52:13 +02:00
it ( 'should work with busted Array.prototype.map/push' , async ( { page , server } ) = > {
server . setRoute ( '/test' , ( req , res ) = > {
res . writeHead ( 200 , {
'content-type' : 'text/html' ,
} ) ;
res . end ( ` <script>
Array . prototype . map = null ;
Array . prototype . push = null ;
< / script > ` );
} ) ;
await page . goto ( server . PREFIX + '/test' ) ;
expect ( await page . evaluate ( '1+2' ) ) . toBe ( 3 ) ;
expect ( await ( ( await page . evaluateHandle ( '1+2' ) ) . jsonValue ( ) ) ) . toBe ( 3 ) ;
} ) ;
2022-09-13 18:21:07 +02:00
it ( 'should work with overridden globalThis.Window/Document/Node' , async ( { page , server } ) = > {
const testCases = [
// @ts-ignore
( ) = > globalThis . Window = { } ,
// @ts-ignore
( ) = > globalThis . Document = { } ,
// @ts-ignore
( ) = > globalThis . Node = { } ,
( ) = > globalThis . Window = null ,
( ) = > globalThis . Document = null ,
( ) = > globalThis . Node = null ,
] ;
for ( const testCase of testCases ) {
await it . step ( testCase . toString ( ) , async ( ) = > {
await page . goto ( server . EMPTY_PAGE ) ;
await page . evaluate ( testCase ) ;
expect ( await page . evaluate ( '1+2' ) ) . toBe ( 3 ) ;
expect ( await page . evaluate ( ( ) = > [ 'foo' ] ) ) . toEqual ( [ 'foo' ] ) ;
} ) ;
}
} ) ;
2022-11-29 16:57:11 -08:00
2023-03-10 09:25:54 -08:00
it ( 'should work with overridden URL/Date/RegExp' , async ( { page , server } ) = > {
2023-02-22 16:36:39 -08:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/21109' } ) ;
2023-02-22 15:45:42 -08:00
const testCases = [
// @ts-ignore
( ) = > globalThis . URL = 'foo' ,
// @ts-ignore
( ) = > globalThis . RegExp = 'foo' ,
// @ts-ignore
( ) = > globalThis . Date = 'foo' ,
] ;
for ( const testCase of testCases ) {
await it . step ( testCase . toString ( ) , async ( ) = > {
await page . goto ( server . EMPTY_PAGE ) ;
await page . evaluate ( testCase ) ;
expect ( await page . evaluate ( '1+2' ) ) . toBe ( 3 ) ;
expect ( await page . evaluate ( ( ) = > ( { 'a' : 2023 } ) ) ) . toEqual ( { 'a' : 2023 } ) ;
} ) ;
}
} ) ;
2023-12-08 10:55:26 -08:00
it ( 'should work with Array.from/map' , async ( { page } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/28520' } ) ;
expect ( await page . evaluate ( ( ) = > {
const r = ( str , amount ) = > Array . from ( Array ( amount ) ) . map ( ( ) = > str ) . join ( '' ) ;
return r ( '([a-f0-9]{2})' , 3 ) ;
} ) ) . toBe ( '([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})' ) ;
} ) ;
2025-03-25 13:49:28 +00:00
2025-05-14 13:43:50 +02:00
it ( 'should ignore dangerous object keys' , async ( { page } ) = > {
const input = {
__proto__ : { polluted : true } ,
safeKey : 'safeValue'
} ;
const result = await page . evaluate ( arg = > arg , input ) ;
expect ( result ) . toEqual ( { safeKey : 'safeValue' } ) ;
} ) ;