2020-08-03 22:41:48 +02: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 .
* /
2021-04-03 06:07:45 +02:00
2024-06-11 22:14:30 +02:00
import { devices } from '@playwright/test' ;
2022-03-26 00:05:50 +01:00
import { contextTest as it , expect } from '../config/browserTest' ;
import { browserTest } from '../config/browserTest' ;
import { verifyViewport } from '../config/utils' ;
2024-06-14 10:49:50 +02:00
import * as os from 'os' ;
2021-04-03 06:07:45 +02:00
2021-09-27 18:58:08 +02:00
it ( 'should get the proper default viewport size' , async ( { page , server } ) = > {
2020-09-19 00:52:14 +02:00
await verifyViewport ( page , 1280 , 720 ) ;
2020-08-03 22:41:48 +02:00
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should set the proper viewport size' , async ( { page , server } ) = > {
2020-09-19 00:52:14 +02:00
await verifyViewport ( page , 1280 , 720 ) ;
2022-06-09 00:13:39 +02:00
await page . setViewportSize ( { width : 345 , height : 456 } ) ;
await verifyViewport ( page , 345 , 456 ) ;
2020-08-03 22:41:48 +02:00
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should return correct outerWidth and outerHeight' , async ( { page } ) = > {
2022-05-12 19:46:03 +02:00
await page . setViewportSize ( { width : 410 , height : 420 } ) ;
2020-08-03 22:41:48 +02:00
const size = await page . evaluate ( ( ) = > {
return {
innerWidth : window.innerWidth ,
innerHeight : window.innerHeight ,
outerWidth : window.outerWidth ,
outerHeight : window.outerHeight ,
} ;
} ) ;
2022-05-12 19:46:03 +02:00
expect ( size . innerWidth ) . toBe ( 410 ) ;
expect ( size . innerHeight ) . toBe ( 420 ) ;
2020-08-03 22:41:48 +02:00
expect ( size . outerWidth >= size . innerWidth ) . toBeTruthy ( ) ;
expect ( size . outerHeight >= size . innerHeight ) . toBeTruthy ( ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should emulate device width' , async ( { page , server } ) = > {
expect ( page . viewportSize ( ) ) . toEqual ( { width : 1280 , height : 720 } ) ;
2023-05-14 16:59:15 +02:00
await page . setViewportSize ( { width : 300 , height : 300 } ) ;
expect ( await page . evaluate ( ( ) = > window . screen . width ) ) . toBe ( 300 ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-width: 200px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-width: 400px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-width: 200px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-width: 400px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-width: 600px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-width: 300px)' ) . matches ) ) . toBe ( true ) ;
2021-09-27 18:58:08 +02:00
await page . setViewportSize ( { width : 500 , height : 500 } ) ;
2020-08-03 22:41:48 +02:00
expect ( await page . evaluate ( ( ) = > window . screen . width ) ) . toBe ( 500 ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-width: 400px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-width: 600px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-width: 400px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-width: 600px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-width: 200px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-width: 500px)' ) . matches ) ) . toBe ( true ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should emulate device height' , async ( { page , server } ) = > {
expect ( page . viewportSize ( ) ) . toEqual ( { width : 1280 , height : 720 } ) ;
2023-05-14 16:59:15 +02:00
await page . setViewportSize ( { width : 300 , height : 300 } ) ;
expect ( await page . evaluate ( ( ) = > window . screen . height ) ) . toBe ( 300 ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-height: 200px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-height: 400px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-height: 200px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-height: 400px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-height: 600px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-height: 300px)' ) . matches ) ) . toBe ( true ) ;
2021-09-27 18:58:08 +02:00
await page . setViewportSize ( { width : 500 , height : 500 } ) ;
2020-08-03 22:41:48 +02:00
expect ( await page . evaluate ( ( ) = > window . screen . height ) ) . toBe ( 500 ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-height: 400px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(min-device-height: 600px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-height: 400px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(max-device-height: 600px)' ) . matches ) ) . toBe ( true ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-height: 200px)' ) . matches ) ) . toBe ( false ) ;
expect ( await page . evaluate ( ( ) = > matchMedia ( '(device-height: 500px)' ) . matches ) ) . toBe ( true ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should emulate availWidth and availHeight' , async ( { page } ) = > {
await page . setViewportSize ( { width : 500 , height : 600 } ) ;
2020-09-30 13:14:29 +02:00
expect ( await page . evaluate ( ( ) = > window . screen . availWidth ) ) . toBe ( 500 ) ;
expect ( await page . evaluate ( ( ) = > window . screen . availHeight ) ) . toBe ( 600 ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should not have touch by default' , async ( { page , server } ) = > {
2020-08-03 22:41:48 +02:00
await page . goto ( server . PREFIX + '/mobile.html' ) ;
expect ( await page . evaluate ( ( ) = > 'ontouchstart' in window ) ) . toBe ( false ) ;
await page . goto ( server . PREFIX + '/detect-touch.html' ) ;
expect ( await page . evaluate ( ( ) = > document . body . textContent . trim ( ) ) ) . toBe ( 'NO' ) ;
} ) ;
2023-01-28 00:51:57 +01:00
it ( 'should throw on tap if hasTouch is not enabled' , async ( { page } ) = > {
await page . setContent ( ` <div>a</div> ` ) ;
{
const error = await page . tap ( 'div' ) . catch ( e = > e ) ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toContain ( 'The page does not support tap' ) ;
}
{
const error = await page . locator ( 'div' ) . tap ( ) . catch ( e = > e ) ;
expect ( error ) . toBeTruthy ( ) ;
expect ( error . message ) . toContain ( 'The page does not support tap' ) ;
}
} ) ;
2021-09-27 18:58:08 +02:00
browserTest ( 'should support touch with null viewport' , async ( { browser , server } ) = > {
2020-08-03 22:41:48 +02:00
const context = await browser . newContext ( { viewport : null , hasTouch : true } ) ;
const page = await context . newPage ( ) ;
await page . goto ( server . PREFIX + '/mobile.html' ) ;
expect ( await page . evaluate ( ( ) = > 'ontouchstart' in window ) ) . toBe ( true ) ;
await context . close ( ) ;
} ) ;
2021-10-18 19:45:47 +02:00
it ( 'should set both screen and viewport options' , async ( { contextFactory , browserName } ) = > {
it . fail ( browserName === 'firefox' , 'Screen size is reset to viewport' ) ;
const context = await contextFactory ( {
screen : { 'width' : 1280 , 'height' : 720 } ,
viewport : { 'width' : 1000 , 'height' : 600 } ,
} ) ;
const page = await context . newPage ( ) ;
const screen = await page . evaluate ( ( ) = > ( { w : screen.width , h : screen.height } ) ) ;
expect ( screen ) . toEqual ( { w : 1280 , h : 720 } ) ;
const inner = await page . evaluate ( ( ) = > ( { w : window.innerWidth , h : window.innerHeight } ) ) ;
expect ( inner ) . toEqual ( { w : 1000 , h : 600 } ) ;
} ) ;
2021-09-27 18:58:08 +02:00
browserTest ( 'should report null viewportSize when given null viewport' , async ( { browser , server } ) = > {
2020-08-03 22:41:48 +02:00
const context = await browser . newContext ( { viewport : null } ) ;
const page = await context . newPage ( ) ;
expect ( page . viewportSize ( ) ) . toBe ( null ) ;
await context . close ( ) ;
} ) ;
2021-07-13 00:20:08 +02:00
2021-09-27 18:58:08 +02:00
browserTest ( 'should drag with high dpi' , async ( { browser , server } ) = > {
2021-07-13 00:20:08 +02:00
const page = await browser . newPage ( { deviceScaleFactor : 2 } ) ;
await page . goto ( server . PREFIX + '/drag-n-drop.html' ) ;
await page . hover ( '#source' ) ;
await page . mouse . down ( ) ;
await page . hover ( '#target' ) ;
await page . mouse . up ( ) ;
expect ( await page . $eval ( '#target' , target = > target . contains ( document . querySelector ( '#source' ) ) ) ) . toBe ( true ) ; // could not find source in target
await page . close ( ) ;
} ) ;
2023-05-11 17:54:05 +02:00
it ( 'WebKit Windows headed should have a minimal viewport' , async ( { contextFactory , browserName , headless , isWindows } ) = > {
it . skip ( browserName !== 'webkit' || headless || ! isWindows , 'Not relevant for this browser' ) ;
await expect ( contextFactory ( {
viewport : { 'width' : 100 , 'height' : 100 } ,
2023-05-14 16:59:15 +02:00
} ) ) . rejects . toThrow ( 'WebKit on Windows has a minimal viewport of 250x240.' ) ;
2023-05-11 17:54:05 +02:00
const context = await contextFactory ( ) ;
const page = await context . newPage ( ) ;
2023-05-14 16:59:15 +02:00
await expect ( page . setViewportSize ( { width : 100 , height : 100 } ) ) . rejects . toThrow ( 'WebKit on Windows has a minimal viewport of 250x240.' ) ;
2023-05-11 17:54:05 +02:00
await context . close ( ) ;
} ) ;
2023-06-23 20:34:09 +02:00
browserTest ( 'should be able to get correct orientation angle on non-mobile devices' , async ( { browser , browserName , server } ) = > {
browserTest . skip ( browserName === 'webkit' , 'Desktop webkit dont support orientation API' ) ;
const context = await browser . newContext ( { viewport : { width : 300 , height : 400 } , isMobile : false } ) ;
const page = await context . newPage ( ) ;
await page . goto ( server . PREFIX + '/index.html' ) ;
expect ( await page . evaluate ( ( ) = > window . screen . orientation . angle ) ) . toBe ( 0 ) ;
await page . setViewportSize ( { width : 400 , height : 300 } ) ;
expect ( await page . evaluate ( ( ) = > window . screen . orientation . angle ) ) . toBe ( 0 ) ;
await context . close ( ) ;
} ) ;
2024-06-11 22:14:30 +02:00
2024-06-14 10:49:50 +02:00
it ( 'should set window.screen.orientation.type for mobile devices' , async ( { contextFactory , browserName , server , isMac } ) = > {
2024-06-11 22:14:30 +02:00
it . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/31151' } ) ;
it . skip ( browserName === 'firefox' , 'Firefox does not support mobile emulation' ) ;
2024-07-24 18:45:03 +02:00
it . skip ( browserName === 'webkit' && isMac && parseInt ( os . release ( ) . split ( '.' ) [ 0 ] , 10 ) <= 21 , 'WebKit on macOS 12 is frozen and does not support orientation.type override' ) ;
2024-06-11 22:14:30 +02:00
const context = await contextFactory ( devices [ 'iPhone 14' ] ) ;
const page = await context . newPage ( ) ;
await page . goto ( server . PREFIX + '/index.html' ) ;
expect ( await page . evaluate ( ( ) = > window . screen . orientation . type ) ) . toBe ( 'portrait-primary' ) ;
await context . close ( ) ;
} ) ;