2020-08-03 13:41:48 -07:00
/ * *
* Copyright Microsoft Corporation . All rights reserved .
*
* 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-10-21 01:48:00 +02:00
import os from 'os' ;
2020-08-06 14:12:14 -07:00
import url from 'url' ;
2022-03-25 15:05:50 -08:00
import { contextTest as it , expect } from '../config/browserTest' ;
2023-11-16 20:39:32 +01:00
import { hostPlatform } from '../../packages/playwright-core/src/utils/hostPlatform' ;
2020-08-03 13:41:48 -07:00
2022-03-10 19:42:52 +01:00
it ( 'SharedArrayBuffer should work @smoke' , async function ( { contextFactory , httpsServer , browserName } ) {
2021-09-01 13:27:37 +03:00
it . fail ( browserName === 'webkit' , 'no shared array buffer on webkit' ) ;
const context = await contextFactory ( { ignoreHTTPSErrors : true } ) ;
const page = await context . newPage ( ) ;
httpsServer . setRoute ( '/sharedarraybuffer' , ( req , res ) = > {
res . setHeader ( 'Cross-Origin-Opener-Policy' , 'same-origin' ) ;
res . setHeader ( 'Cross-Origin-Embedder-Policy' , 'require-corp' ) ;
res . end ( ) ;
} ) ;
await page . goto ( httpsServer . PREFIX + '/sharedarraybuffer' ) ;
expect ( await page . evaluate ( ( ) = > typeof SharedArrayBuffer ) ) . toBe ( 'function' ) ;
} ) ;
2023-11-16 16:31:42 -08:00
it ( 'Web Assembly should work @smoke' , async function ( { page , server } ) {
2020-08-03 13:41:48 -07:00
await page . goto ( server . PREFIX + '/wasm/table2.html' ) ;
2020-08-06 14:12:14 -07:00
expect ( await page . evaluate ( 'loadTable()' ) ) . toBe ( '42, 83' ) ;
2020-08-03 13:41:48 -07:00
} ) ;
2022-03-10 19:42:52 +01:00
it ( 'WebSocket should work @smoke' , async ( { page , server } ) = > {
2021-05-26 15:18:52 -07:00
server . sendOnWebSocketConnection ( 'incoming' ) ;
2020-08-28 04:20:29 -07:00
const value = await page . evaluate ( port = > {
2020-08-03 13:41:48 -07:00
let cb ;
const result = new Promise ( f = > cb = f ) ;
const ws = new WebSocket ( 'ws://localhost:' + port + '/ws' ) ;
ws . addEventListener ( 'message' , data = > { ws . close ( ) ; cb ( data . data ) ; } ) ;
ws . addEventListener ( 'error' , error = > cb ( 'Error' ) ) ;
return result ;
} , server . PORT ) ;
expect ( value ) . toBe ( 'incoming' ) ;
} ) ;
2022-03-10 19:42:52 +01:00
it ( 'should respect CSP @smoke' , async ( { page , server } ) = > {
2020-08-03 13:41:48 -07:00
server . setRoute ( '/empty.html' , async ( req , res ) = > {
res . setHeader ( 'Content-Security-Policy' , ` script-src 'unsafe-inline'; ` ) ;
res . end ( `
< script >
window . testStatus = 'SUCCESS' ;
window . testStatus = eval ( "'FAILED'" ) ;
< / script > ` );
} ) ;
await page . goto ( server . EMPTY_PAGE ) ;
2020-08-06 14:12:14 -07:00
expect ( await page . evaluate ( ( ) = > window [ 'testStatus' ] ) ) . toBe ( 'SUCCESS' ) ;
2020-08-03 13:41:48 -07:00
} ) ;
2022-09-14 15:05:18 -07:00
it ( 'should play video @smoke' , async ( { page , asset , browserName , platform , mode } ) = > {
2020-08-03 13:41:48 -07:00
// TODO: the test passes on Windows locally but fails on GitHub Action bot,
// apparently due to a Media Pack issue in the Windows Server.
2020-08-07 09:53:34 -07:00
// Also the test is very flaky on Linux WebKit.
2021-04-02 21:07:45 -07:00
it . fixme ( browserName === 'webkit' && platform !== 'darwin' ) ;
2021-10-14 02:35:39 -07:00
it . fixme ( browserName === 'firefox' , 'https://github.com/microsoft/playwright/issues/5721' ) ;
2023-01-26 17:09:22 -08:00
it . fixme ( browserName === 'webkit' && platform === 'darwin' && parseInt ( os . release ( ) , 10 ) === 20 , 'Does not work on BigSur' ) ;
2023-07-25 16:47:04 -07:00
it . skip ( mode . startsWith ( 'service' ) ) ;
2021-04-02 21:07:45 -07:00
2020-08-03 16:06:57 -07:00
// Safari only plays mp4 so we test WebKit with an .mp4 clip.
2021-05-13 10:22:23 -07:00
const fileName = browserName === 'webkit' ? 'video_mp4.html' : 'video.html' ;
2020-08-13 17:32:27 -07:00
const absolutePath = asset ( fileName ) ;
2020-08-03 13:41:48 -07:00
// Our test server doesn't support range requests required to play on Mac,
// so we load the page using a file url.
2020-08-04 17:26:42 -07:00
await page . goto ( url . pathToFileURL ( absolutePath ) . href ) ;
2020-08-03 13:41:48 -07:00
await page . $eval ( 'video' , v = > v . play ( ) ) ;
2023-01-27 09:48:47 -08:00
await page . $eval ( 'video' , v = > v . pause ( ) ) ;
} ) ;
it ( 'should play webm video @smoke' , async ( { page , asset , browserName , platform , mode } ) = > {
it . fixme ( browserName === 'webkit' && platform === 'darwin' && parseInt ( os . release ( ) , 10 ) === 20 , 'Does not work on BigSur' ) ;
it . fixme ( browserName === 'webkit' && platform === 'win32' ) ;
2023-07-25 16:47:04 -07:00
it . skip ( mode . startsWith ( 'service' ) ) ;
2023-01-27 09:48:47 -08:00
const absolutePath = asset ( 'video_webm.html' ) ;
// Our test server doesn't support range requests required to play on Mac,
// so we load the page using a file url.
await page . goto ( url . pathToFileURL ( absolutePath ) . href ) ;
await page . $eval ( 'video' , v = > v . play ( ) ) ;
2020-08-03 13:41:48 -07:00
await page . $eval ( 'video' , v = > v . pause ( ) ) ;
} ) ;
2020-11-04 13:24:30 -08:00
2022-03-10 19:42:52 +01:00
it ( 'should play audio @smoke' , async ( { page , server , browserName , platform } ) = > {
2021-12-13 15:02:06 -08:00
it . fixme ( browserName === 'firefox' && platform === 'win32' , 'https://github.com/microsoft/playwright/issues/10887' ) ;
it . fixme ( browserName === 'firefox' && platform === 'linux' , 'https://github.com/microsoft/playwright/issues/10887' ) ;
it . fixme ( browserName === 'webkit' && platform === 'win32' , 'https://github.com/microsoft/playwright/issues/10892' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
await page . setContent ( ` <audio src=" ${ server . PREFIX } /example.mp3"></audio> ` ) ;
await page . $eval ( 'audio' , e = > e . play ( ) ) ;
await page . waitForTimeout ( 1000 ) ;
await page . $eval ( 'audio' , e = > e . pause ( ) ) ;
2022-02-04 16:14:48 -08:00
expect ( await page . $eval ( 'audio' , e = > e . currentTime ) ) . toBeGreaterThan ( 0.2 ) ;
2021-12-13 15:02:06 -08:00
} ) ;
2023-12-06 13:52:49 -08:00
it ( 'should support webgl @smoke' , async ( { page , browserName , platform } ) = > {
it . fixme ( browserName === 'chromium' && platform === 'darwin' && os . arch ( ) === 'arm64' , 'SwiftShader is not available on macOS-arm64 - https://github.com/microsoft/playwright/issues/28216' ) ;
2020-11-16 16:18:50 -08:00
const hasWebGL = await page . evaluate ( ( ) = > {
2020-11-04 13:24:30 -08:00
const canvas = document . createElement ( 'canvas' ) ;
return ! ! canvas . getContext ( 'webgl' ) ;
} ) ;
2020-11-16 16:18:50 -08:00
expect ( hasWebGL ) . toBe ( true ) ;
2020-11-04 13:24:30 -08:00
} ) ;
2023-12-06 13:52:49 -08:00
it ( 'should support webgl 2 @smoke' , async ( { page , browserName , headless , isWindows , platform } ) = > {
2021-04-02 21:07:45 -07:00
it . skip ( browserName === 'webkit' , 'WebKit doesn\'t have webgl2 enabled yet upstream.' ) ;
2023-01-27 21:52:34 -08:00
it . fixme ( browserName === 'firefox' && isWindows ) ;
2021-05-13 10:22:23 -07:00
it . fixme ( browserName === 'chromium' && ! headless , 'chromium doesn\'t like webgl2 when running under xvfb' ) ;
2023-12-06 13:52:49 -08:00
it . fixme ( browserName === 'chromium' && platform === 'darwin' && os . arch ( ) === 'arm64' , 'SwiftShader is not available on macOS-arm64 - https://github.com/microsoft/playwright/issues/28216' ) ;
2021-04-02 21:07:45 -07:00
2020-11-04 13:24:30 -08:00
const hasWebGL2 = await page . evaluate ( ( ) = > {
const canvas = document . createElement ( 'canvas' ) ;
return ! ! canvas . getContext ( 'webgl2' ) ;
} ) ;
expect ( hasWebGL2 ) . toBe ( true ) ;
} ) ;
2021-12-20 12:44:06 -08:00
2022-03-10 19:42:52 +01:00
it ( 'should not crash on page with mp4 @smoke' , async ( { page , server , platform , browserName } ) = > {
2021-12-20 12:44:06 -08:00
it . fixme ( browserName === 'webkit' && platform === 'win32' , 'https://github.com/microsoft/playwright/issues/11009, times out in setContent' ) ;
2022-01-10 04:56:50 -07:00
it . fixme ( browserName === 'firefox' , 'https://bugzilla.mozilla.org/show_bug.cgi?id=1697004' ) ;
2021-12-20 12:44:06 -08:00
await page . setContent ( ` <video><source src=" ${ server . PREFIX } /movie.mp4"/></video> ` ) ;
await page . waitForTimeout ( 1000 ) ;
2021-12-29 19:51:28 -07:00
} ) ;
2022-01-06 09:08:13 -08:00
2022-01-27 11:40:06 -08:00
it ( 'should not crash on showDirectoryPicker' , async ( { page , server , browserName , browserMajorVersion } ) = > {
2022-01-06 09:08:13 -08:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/7339' } ) ;
2022-01-27 11:40:06 -08:00
it . skip ( browserName === 'chromium' && browserMajorVersion < 99 , 'Fixed in Chromium r956769' ) ;
2022-01-06 09:08:13 -08:00
it . skip ( browserName !== 'chromium' , 'showDirectoryPicker is only available in Chromium' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
2022-01-27 11:40:06 -08:00
await Promise . race ( [
page . evaluate ( async ( ) = > {
const dir = await ( window as any ) . showDirectoryPicker ( ) ;
return dir . name ;
} ) . catch ( e = > expect ( e . message ) . toContain ( 'DOMException: The user aborted a request' ) ) ,
// The dialog will not be accepted, so we just wait for some time to
// to give the browser a chance to crash.
new Promise ( r = > setTimeout ( r , 1000 ) )
] ) ;
2022-01-06 09:08:13 -08:00
} ) ;
2022-10-26 15:41:36 -07:00
it ( 'should not crash on storage.getDirectory()' , async ( { page , server , browserName , isMac } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/18235' } ) ;
it . skip ( browserName === 'firefox' , 'navigator.storage.getDirectory is not a function' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const error = await page . evaluate ( async ( ) = > {
const dir = await navigator . storage . getDirectory ( ) ;
return dir . name ;
} ) . catch ( e = > e ) ;
if ( browserName === 'webkit' ) {
if ( isMac )
expect ( error . message ) . toContain ( 'UnknownError: The operation failed for an unknown transient reason' ) ;
else
expect ( error . message ) . toContain ( 'TypeError: undefined is not an object' ) ;
} else {
expect ( error ) . toBeFalsy ( ) ;
}
} ) ;
2023-01-26 10:15:19 -08:00
2023-02-21 23:49:14 +01:00
it ( 'navigator.clipboard should be present' , async ( { page , server } ) = > {
2023-01-26 10:15:19 -08:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/18901' } ) ;
await page . goto ( server . EMPTY_PAGE ) ;
expect ( await page . evaluate ( ( ) = > navigator . clipboard ) ) . toBeTruthy ( ) ;
} ) ;
2023-02-02 19:04:26 +01:00
2023-02-21 23:49:14 +01:00
it ( 'should set CloseEvent.wasClean to false when the server terminates a WebSocket connection' , async ( { page , server } ) = > {
2023-02-02 19:04:26 +01:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/12353' } ) ;
server . onceWebSocketConnection ( socket = > {
socket . terminate ( ) ;
} ) ;
const wasClean = await page . evaluate ( port = > new Promise < boolean > ( resolve = > {
const ws = new WebSocket ( 'ws://localhost:' + port + '/ws' ) ;
ws . addEventListener ( 'close' , error = > resolve ( error . wasClean ) ) ;
} ) , server . PORT ) ;
expect ( wasClean ) . toBe ( false ) ;
} ) ;
2023-02-21 19:36:19 +01:00
2023-03-16 19:24:13 +01:00
it ( 'serviceWorker should intercept document request' , async ( { page , server } ) = > {
2023-02-21 19:36:19 +01:00
server . setRoute ( '/sw.js' , ( req , res ) = > {
res . setHeader ( 'Content-Type' , 'application/javascript' ) ;
res . end ( `
self . addEventListener ( 'fetch' , event = > {
event . respondWith ( new Response ( 'intercepted' ) ) ;
} ) ;
2023-03-16 19:24:13 +01:00
self . addEventListener ( 'activate' , event = > {
event . waitUntil ( clients . claim ( ) ) ;
} ) ;
2023-02-21 19:36:19 +01:00
` );
} ) ;
await page . goto ( server . EMPTY_PAGE ) ;
2023-03-16 19:24:13 +01:00
await page . evaluate ( async ( ) = > {
await navigator . serviceWorker . register ( '/sw.js' ) ;
await new Promise ( resolve = > navigator . serviceWorker . oncontrollerchange = resolve ) ;
} ) ;
2023-02-21 19:36:19 +01:00
await page . reload ( ) ;
expect ( await page . textContent ( 'body' ) ) . toBe ( 'intercepted' ) ;
} ) ;
2023-03-03 13:38:13 -08:00
it ( 'webkit should define window.safari' , async ( { page , server , browserName } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/21037' } ) ;
it . skip ( browserName !== 'webkit' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const defined = await page . evaluate ( ( ) = > ! ! ( window as any ) . safari ) ;
expect ( defined ) . toBeTruthy ( ) ;
} ) ;
2023-03-09 16:21:01 +01:00
2023-03-17 12:32:55 +01:00
it ( 'make sure that XMLHttpRequest upload events are emitted correctly' , async ( { page , server } ) = > {
2023-03-09 16:21:01 +01:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/21489' } ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const events = await page . evaluate ( async ( ) = > {
const events : string [ ] = [ ] ;
const xhr = new XMLHttpRequest ( ) ;
xhr . upload . addEventListener ( 'loadstart' , ( ) = > events . push ( 'loadstart' ) ) ;
xhr . upload . addEventListener ( 'progress' , ( ) = > events . push ( 'progress' ) ) ;
xhr . upload . addEventListener ( 'load' , ( ) = > events . push ( 'load' ) ) ;
xhr . upload . addEventListener ( 'loadend' , ( ) = > events . push ( 'loadend' ) ) ;
xhr . open ( 'POST' , '/simple.json' ) ;
xhr . send ( 'hello' ) ;
await new Promise ( f = > xhr . onload = f ) ;
return events ;
} ) ;
expect ( events ) . toEqual ( [ 'loadstart' , 'progress' , 'load' , 'loadend' ] ) ;
} ) ;
2023-05-01 14:55:20 -07:00
2023-05-09 10:39:44 -07:00
it ( 'loading in HTMLImageElement.prototype' , async ( { page , server , browserName , isMac } ) = > {
2023-05-01 14:55:20 -07:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22738' } ) ;
2023-05-16 03:13:58 -07:00
it . skip ( browserName === 'webkit' && isMac && parseInt ( os . release ( ) , 10 ) < 21 , 'macOS 11 is frozen' ) ;
2023-05-01 14:55:20 -07:00
await page . goto ( server . EMPTY_PAGE ) ;
const defined = await page . evaluate ( ( ) = > 'loading' in HTMLImageElement . prototype ) ;
expect ( defined ) . toBeTruthy ( ) ;
} ) ;
2023-05-05 11:37:28 -07:00
it ( 'window.GestureEvent in WebKit' , async ( { page , server , browserName } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22735' } ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const defined = await page . evaluate ( ( ) = > 'GestureEvent' in window ) ;
expect ( defined ) . toBe ( browserName === 'webkit' ) ;
const type = await page . evaluate ( ( ) = > typeof ( window as any ) . GestureEvent ) ;
expect ( type ) . toBe ( browserName === 'webkit' ? 'function' : 'undefined' ) ;
} ) ;
2023-05-10 09:31:20 -07:00
it ( 'requestFullscreen' , async ( { page , server , browserName , headless , isLinux } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22832' } ) ;
it . fixme ( browserName === 'chromium' && headless , 'fullscreenchange is not fired in headless Chromium' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
await page . evaluate ( ( ) = > {
const result = new Promise ( resolve = > document . addEventListener ( 'fullscreenchange' , resolve ) ) ;
2023-06-02 21:59:12 +02:00
void document . documentElement . requestFullscreen ( ) ;
2023-05-10 09:31:20 -07:00
return result ;
} ) ;
expect ( await page . evaluate ( ( ) = > document . fullscreenElement === document . documentElement ) ) . toBeTruthy ( ) ;
await page . evaluate ( ( ) = > {
const result = new Promise ( resolve = > document . addEventListener ( 'fullscreenchange' , resolve ) ) ;
2023-06-02 21:59:12 +02:00
void document . exitFullscreen ( ) ;
2023-05-10 09:31:20 -07:00
return result ;
} ) ;
expect ( await page . evaluate ( ( ) = > ! ! document . fullscreenElement ) ) . toBeFalsy ( ) ;
} ) ;
2023-08-21 22:12:12 +02:00
it ( 'should send no Content-Length header for GET requests with a Content-Type' , async ( { page , server , browserName } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22569' } ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const [ request ] = await Promise . all ( [
server . waitForRequest ( '/empty.html' ) ,
page . evaluate ( ( ) = > fetch ( '/empty.html' , {
'headers' : { 'Content-Type' : 'application/json' } ,
'method' : 'GET'
} ) )
] ) ;
expect ( request . headers [ 'content-length' ] ) . toBe ( undefined ) ;
} ) ;
2023-11-15 18:47:42 -08:00
2023-11-16 20:39:32 +01:00
it ( 'Intl.ListFormat should work' , async ( { page , server , browserName } ) = > {
2023-11-15 18:47:42 -08:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/23978' } ) ;
2023-11-16 20:39:32 +01:00
it . skip ( browserName === 'webkit' && hostPlatform . startsWith ( 'ubuntu20.04' ) , 'libicu is too old and WebKit disables Intl.ListFormat by default then' ) ;
2023-11-15 18:47:42 -08:00
await page . goto ( server . EMPTY_PAGE ) ;
const formatted = await page . evaluate ( ( ) = > {
const data = [ 'first' , 'second' , 'third' ] ;
const listFormat = new Intl . ListFormat ( 'en' , {
type : 'disjunction' ,
style : 'short' ,
} ) ;
return listFormat . format ( data ) ;
} ) ;
expect ( formatted ) . toBe ( 'first, second, or third' ) ;
} ) ;