2020-08-03 22:41:48 +02: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 23:12:14 +02:00
import url from 'url' ;
2022-03-26 00:05:50 +01: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 22:41:48 +02:00
2024-11-14 02:21:21 +01:00
it ( 'SharedArrayBuffer should work @smoke' , async function ( { contextFactory , httpsServer } ) {
2021-09-01 12:27:37 +02:00
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' ) ;
} ) ;
2024-05-15 11:34:39 +02:00
it ( 'Web Assembly should work @smoke' , async ( { page , server , browserName , platform } ) = > {
it . fixme ( browserName === 'webkit' && platform === 'win32' , 'Windows JIT is disabled: https://bugs.webkit.org/show_bug.cgi?id=273854' ) ;
2020-08-03 22:41:48 +02:00
await page . goto ( server . PREFIX + '/wasm/table2.html' ) ;
2020-08-06 23:12:14 +02:00
expect ( await page . evaluate ( 'loadTable()' ) ) . toBe ( '42, 83' ) ;
2020-08-03 22:41:48 +02:00
} ) ;
2022-03-10 19:42:52 +01:00
it ( 'WebSocket should work @smoke' , async ( { page , server } ) = > {
2021-05-27 00:18:52 +02:00
server . sendOnWebSocketConnection ( 'incoming' ) ;
2020-08-28 13:20:29 +02:00
const value = await page . evaluate ( port = > {
2020-08-03 22:41:48 +02: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 22:41:48 +02: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 23:12:14 +02:00
expect ( await page . evaluate ( ( ) = > window [ 'testStatus' ] ) ) . toBe ( 'SUCCESS' ) ;
2020-08-03 22:41:48 +02:00
} ) ;
2024-10-04 17:22:27 +02:00
it ( 'should play video @smoke' , async ( { page , asset , browserName , isWindows , isLinux , mode } ) = > {
it . skip ( browserName === 'webkit' && isWindows , 'passes locally but fails on GitHub Action bot, apparently due to a Media Pack issue in the Windows Server' ) ;
it . fixme ( browserName === 'firefox' && isLinux , 'https://github.com/microsoft/playwright/issues/5721' ) ;
2023-07-26 01:47:04 +02:00
it . skip ( mode . startsWith ( 'service' ) ) ;
2021-04-03 06:07:45 +02:00
2020-08-04 01:06:57 +02:00
// Safari only plays mp4 so we test WebKit with an .mp4 clip.
2021-05-13 19:22:23 +02:00
const fileName = browserName === 'webkit' ? 'video_mp4.html' : 'video.html' ;
2020-08-14 02:32:27 +02:00
const absolutePath = asset ( fileName ) ;
2020-08-03 22:41:48 +02: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-05 02:26:42 +02:00
await page . goto ( url . pathToFileURL ( absolutePath ) . href ) ;
2020-08-03 22:41:48 +02:00
await page . $eval ( 'video' , v = > v . play ( ) ) ;
2023-01-27 18:48:47 +01:00
await page . $eval ( 'video' , v = > v . pause ( ) ) ;
} ) ;
2024-09-27 16:06:37 +02:00
it ( 'should play webm video @smoke' , async ( { page , asset , browserName , platform , macVersion , mode } ) = > {
2024-10-04 17:22:27 +02:00
it . skip ( browserName === 'webkit' && platform === 'win32' , 'not supported' ) ;
2023-07-26 01:47:04 +02:00
it . skip ( mode . startsWith ( 'service' ) ) ;
2023-01-27 18:48:47 +01: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 22:41:48 +02:00
await page . $eval ( 'video' , v = > v . pause ( ) ) ;
} ) ;
2020-11-04 22:24:30 +01:00
2022-03-10 19:42:52 +01:00
it ( 'should play audio @smoke' , async ( { page , server , browserName , platform } ) = > {
2021-12-14 00:02:06 +01:00
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-05 01:14:48 +01:00
expect ( await page . $eval ( 'audio' , e = > e . currentTime ) ) . toBeGreaterThan ( 0.2 ) ;
2021-12-14 00:02:06 +01:00
} ) ;
2023-12-06 22:52:49 +01:00
it ( 'should support webgl @smoke' , async ( { page , browserName , platform } ) = > {
2024-07-12 20:12:56 +02:00
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-17 01:18:50 +01:00
const hasWebGL = await page . evaluate ( ( ) = > {
2020-11-04 22:24:30 +01:00
const canvas = document . createElement ( 'canvas' ) ;
return ! ! canvas . getContext ( 'webgl' ) ;
} ) ;
2020-11-17 01:18:50 +01:00
expect ( hasWebGL ) . toBe ( true ) ;
2020-11-04 22:24:30 +01:00
} ) ;
2023-12-06 22:52:49 +01:00
it ( 'should support webgl 2 @smoke' , async ( { page , browserName , headless , isWindows , platform } ) = > {
2024-07-12 20:12:56 +02:00
it . skip ( browserName === 'webkit' , 'WebKit doesn\'t have webgl2 enabled yet upstream.' ) ;
2023-01-28 06:52:34 +01:00
it . fixme ( browserName === 'firefox' && isWindows ) ;
2024-07-12 20:12:56 +02:00
it . fixme ( browserName === 'chromium' && ! headless , 'chromium doesn\'t like webgl2 when running under xvfb' ) ;
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-03 06:07:45 +02:00
2020-11-04 22:24:30 +01:00
const hasWebGL2 = await page . evaluate ( ( ) = > {
const canvas = document . createElement ( 'canvas' ) ;
return ! ! canvas . getContext ( 'webgl2' ) ;
} ) ;
expect ( hasWebGL2 ) . toBe ( true ) ;
} ) ;
2021-12-20 21:44:06 +01: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 21:44:06 +01:00
it . fixme ( browserName === 'webkit' && platform === 'win32' , 'https://github.com/microsoft/playwright/issues/11009, times out in setContent' ) ;
await page . setContent ( ` <video><source src=" ${ server . PREFIX } /movie.mp4"/></video> ` ) ;
await page . waitForTimeout ( 1000 ) ;
2021-12-30 03:51:28 +01:00
} ) ;
2022-01-06 18:08:13 +01:00
2022-01-27 20:40:06 +01:00
it ( 'should not crash on showDirectoryPicker' , async ( { page , server , browserName , browserMajorVersion } ) = > {
2022-01-06 18:08:13 +01:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/7339' } ) ;
2022-01-27 20:40:06 +01:00
it . skip ( browserName === 'chromium' && browserMajorVersion < 99 , 'Fixed in Chromium r956769' ) ;
2022-01-06 18:08:13 +01:00
it . skip ( browserName !== 'chromium' , 'showDirectoryPicker is only available in Chromium' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
2024-09-27 16:06:37 +02:00
// "User activation is required to show a file picker." - so we click first.
await page . locator ( 'body' ) . click ( ) ;
2024-06-26 16:51:57 +02:00
page . evaluate ( async ( ) = > {
const dir = await ( window as any ) . showDirectoryPicker ( ) ;
return dir . name ;
// In headless it throws (aborted), in headed it stalls (Test ended) and waits for the picker to be accepted.
2024-08-01 15:13:15 +02:00
} ) . catch ( e = > expect ( e . message ) . toMatch ( /((DOMException|AbortError): .*The user aborted a request|Test ended)/ ) ) ;
2024-06-26 16:51:57 +02:00
// The dialog will not be accepted, so we just wait for some time to
// to give the browser a chance to crash.
await page . waitForTimeout ( 3 _000 ) ;
2022-01-06 18:08:13 +01:00
} ) ;
2022-10-27 00:41:36 +02: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 19:15:19 +01:00
2023-02-21 23:49:14 +01:00
it ( 'navigator.clipboard should be present' , async ( { page , server } ) = > {
2023-01-26 19:15:19 +01: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 22:38:13 +01: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' } ) ;
2024-01-23 00:44:13 +01:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/29032' } ) ;
2023-03-03 22:38:13 +01:00
it . skip ( browserName !== 'webkit' ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const defined = await page . evaluate ( ( ) = > ! ! ( window as any ) . safari ) ;
expect ( defined ) . toBeTruthy ( ) ;
2024-01-23 00:44:13 +01:00
expect ( await page . evaluate ( ( ) = > typeof ( window as any ) . safari . pushNotification ) ) . toBe ( 'object' ) ;
expect ( await page . evaluate ( ( ) = > ( window as any ) . safari . pushNotification . toString ( ) ) ) . toBe ( '[object SafariRemoteNotification]' ) ;
2023-03-03 22:38:13 +01:00
} ) ;
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 23:55:20 +02:00
2024-11-14 02:21:21 +01:00
it ( 'loading in HTMLImageElement.prototype' , async ( { page , server } ) = > {
2023-05-01 23:55:20 +02:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22738' } ) ;
await page . goto ( server . EMPTY_PAGE ) ;
const defined = await page . evaluate ( ( ) = > 'loading' in HTMLImageElement . prototype ) ;
expect ( defined ) . toBeTruthy ( ) ;
} ) ;
2023-05-05 20:37:28 +02: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 18:31:20 +02:00
2024-11-14 02:21:21 +01:00
it ( 'requestFullscreen' , async ( { page , server } ) = > {
2023-05-10 18:31:20 +02:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/22832' } ) ;
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 18:31:20 +02: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 18:31:20 +02:00
return result ;
} ) ;
expect ( await page . evaluate ( ( ) = > ! ! document . fullscreenElement ) ) . toBeFalsy ( ) ;
} ) ;
2023-08-21 22:12:12 +02:00
2024-11-14 02:21:21 +01:00
it ( 'should send no Content-Length header for GET requests with a Content-Type' , async ( { page , server } ) = > {
2023-08-21 22:12:12 +02:00
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-16 03:47:42 +01:00
2023-11-16 20:39:32 +01:00
it ( 'Intl.ListFormat should work' , async ( { page , server , browserName } ) = > {
2023-11-16 03:47:42 +01: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-16 03:47:42 +01: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' ) ;
} ) ;
2024-03-21 19:27:27 +01:00
it ( 'service worker should cover the iframe' , async ( { page , server } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/29267' } ) ;
server . setRoute ( '/sw.html' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'text/html' } ) . end ( `
< script >
window . registrationPromise = navigator . serviceWorker . register ( 'sw.js' ) ;
window . activationPromise = new Promise ( resolve = > navigator . serviceWorker . oncontrollerchange = resolve ) ;
< / script >
` );
} ) ;
server . setRoute ( '/iframe.html' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'text/html' } ) . end ( ` <div>from the server</div> ` ) ;
} ) ;
server . setRoute ( '/sw.js' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'application/javascript' } ) . end ( `
const kIframeHtml = "<div>from the service worker</div>" ;
self . addEventListener ( 'fetch' , event = > {
if ( event . request . url . endsWith ( 'iframe.html' ) ) {
const blob = new Blob ( [ kIframeHtml ] , { type : 'text/html' } ) ;
const response = new Response ( blob , { status : 200 , statusText : 'OK' } ) ;
event . respondWith ( response ) ;
return ;
}
event . respondWith ( fetch ( event . request ) ) ;
} ) ;
self . addEventListener ( 'activate' , event = > {
event . waitUntil ( clients . claim ( ) ) ;
} ) ;
` );
} ) ;
await page . goto ( server . PREFIX + '/sw.html' ) ;
await page . evaluate ( ( ) = > window [ 'activationPromise' ] ) ;
await page . evaluate ( ( ) = > {
const iframe = document . createElement ( 'iframe' ) ;
iframe . src = '/iframe.html' ;
document . body . appendChild ( iframe ) ;
} ) ;
await expect ( page . frameLocator ( 'iframe' ) . locator ( 'div' ) ) . toHaveText ( 'from the service worker' ) ;
} ) ;
2024-03-21 23:34:23 +01:00
it ( 'service worker should register in an iframe' , async ( { page , server } ) = > {
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/29267' } ) ;
server . setRoute ( '/main.html' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'text/html' } ) . end ( `
< iframe src = '/dir/iframe.html' > < / iframe >
` );
} ) ;
server . setRoute ( '/dir/iframe.html' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'text/html' } ) . end ( `
< script >
window . registrationPromise = navigator . serviceWorker . register ( 'sw.js' ) ;
window . activationPromise = new Promise ( resolve = > navigator . serviceWorker . oncontrollerchange = resolve ) ;
< / script >
` );
} ) ;
server . setRoute ( '/dir/sw.js' , ( req , res ) = > {
res . writeHead ( 200 , { 'content-type' : 'application/javascript' } ) . end ( `
const kIframeHtml = "<div>from the service worker</div>" ;
self . addEventListener ( 'fetch' , event = > {
if ( event . request . url . endsWith ( 'html' ) ) {
event . respondWith ( fetch ( event . request ) ) ;
return ;
}
const blob = new Blob ( [ 'responseFromServiceWorker' ] , { type : 'text/plain' } ) ;
const response = new Response ( blob , { status : 200 , statusText : 'OK' } ) ;
event . respondWith ( response ) ;
} ) ;
self . addEventListener ( 'activate' , event = > {
event . waitUntil ( clients . claim ( ) ) ;
} ) ;
` );
} ) ;
await page . goto ( server . PREFIX + '/main.html' ) ;
const iframe = page . frames ( ) [ 1 ] ;
await iframe . evaluate ( ( ) = > window [ 'activationPromise' ] ) ;
const response = await iframe . evaluate ( async ( ) = > {
const response = await fetch ( 'foo.txt' ) ;
return response . text ( ) ;
} ) ;
expect ( response ) . toBe ( 'responseFromServiceWorker' ) ;
} ) ;
2024-09-27 19:02:54 +02:00
2024-09-30 10:30:45 +02:00
it ( 'should be able to render avif images' , {
annotation : {
type : 'issue' ,
description : 'https://github.com/microsoft/playwright/issues/32673' ,
}
} , async ( { page , server , browserName , platform } ) = > {
2024-09-27 19:02:54 +02:00
it . fixme ( browserName === 'webkit' && platform === 'win32' ) ;
2024-10-22 22:30:54 +02:00
it . skip ( browserName === 'webkit' && hostPlatform . startsWith ( 'ubuntu20.04' ) , 'Ubuntu 20.04 is frozen' ) ;
2024-10-24 16:49:35 +02:00
it . skip ( browserName === 'webkit' && hostPlatform . startsWith ( 'debian11' ) , 'Debian 11 is too old' ) ;
2024-09-27 19:02:54 +02:00
await page . goto ( server . EMPTY_PAGE ) ;
await page . setContent ( ` <img src=" ${ server . PREFIX } /rgb.avif" onerror="window.error = true"> ` ) ;
await expect . poll ( ( ) = > page . locator ( 'img' ) . boundingBox ( ) ) . toEqual ( expect . objectContaining ( {
width : 128 ,
height : 128 ,
} ) ) ;
expect ( await page . evaluate ( ( ) = > ( window as any ) . error ) ) . toBe ( undefined ) ;
} ) ;
2024-11-18 16:56:59 +01:00
it ( 'should not crash when clicking a label with a <input type="file"/>' , {
annotation : {
type : 'issue' ,
description : 'https://github.com/microsoft/playwright/issues/33257'
}
} , async ( { page } ) = > {
await page . setContent ( `
< form >
< label >
A second file
< input type = "file" / >
< / label >
< / form >
` );
const fileChooserPromise = page . waitForEvent ( 'filechooser' ) ;
await page . getByText ( 'A second file' ) . click ( ) ;
const fileChooser = await fileChooserPromise ;
expect ( fileChooser . page ( ) ) . toBe ( page ) ;
} ) ;
2024-11-22 23:53:29 +01:00
2025-02-03 13:30:54 +01:00
it ( 'should not crash when clicking a color input' , {
annotation : {
type : 'issue' ,
description : 'https://github.com/microsoft/playwright/issues/33864'
}
} , async ( { page , browserMajorVersion , browserName } ) = > {
it . skip ( browserName === 'firefox' && browserMajorVersion < 135 ) ;
await page . setContent ( '<input type="color">' ) ;
const input = page . locator ( 'input' ) ;
await expect ( input ) . toBeVisible ( ) ;
await input . click ( ) ;
await expect ( input ) . toBeVisible ( ) ;
} ) ;
2024-11-22 23:53:29 +01:00
it ( 'should not auto play audio' , {
annotation : {
type : 'issue' ,
description : 'https://github.com/microsoft/playwright/issues/33590'
}
} , async ( { page , browserName , isWindows } ) = > {
it . fixme ( browserName === 'webkit' && isWindows ) ;
2024-11-28 15:36:49 +01:00
it . skip ( process . env . PW_CLOCK === 'frozen' , 'no way to inject real setTimeout' ) ;
2024-11-22 23:53:29 +01:00
await page . route ( '**/*' , async route = > {
await route . fulfill ( {
status : 200 ,
contentType : 'text/html' ,
body : `
< script >
async function onLoad() {
const log = document . getElementById ( 'log' ) ;
const audioContext = new AudioContext ( ) ;
const gainNode = new GainNode ( audioContext ) ;
gainNode . connect ( audioContext . destination ) ;
gainNode . gain . value = 0.025 ;
const sineNode = new OscillatorNode ( audioContext ) ;
sineNode . connect ( gainNode ) ;
sineNode . start ( ) ;
await new Promise ( ( resolve ) = > setTimeout ( resolve , 1000 ) ) ;
log . innerHTML = 'State: ' + audioContext . state ;
}
< / script >
< body onload = "onLoad()" >
< div id = "log" > < / div >
< / body > ` ,
} ) ;
} ) ;
await page . goto ( 'http://127.0.0.1/audio.html' ) ;
await expect ( page . locator ( '#log' ) ) . toHaveText ( 'State: suspended' ) ;
} ) ;