2020-08-03 13:41:48 -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-18 23:00:45 -07:00
2022-03-25 15:05:50 -08:00
import { contextTest as it , browserTest , expect } from '../config/browserTest' ;
import { attachFrame } from '../config/utils' ;
2020-08-03 13:41:48 -07:00
2021-09-27 18:58:08 +02:00
it ( 'should think that it is focused by default' , async ( { page } ) = > {
2020-08-03 13:41:48 -07:00
expect ( await page . evaluate ( 'document.hasFocus()' ) ) . toBe ( true ) ;
} ) ;
2022-03-10 19:42:52 +01:00
it ( 'should think that all pages are focused @smoke' , async ( { page } ) = > {
2020-08-03 13:41:48 -07:00
const page2 = await page . context ( ) . newPage ( ) ;
expect ( await page . evaluate ( 'document.hasFocus()' ) ) . toBe ( true ) ;
expect ( await page2 . evaluate ( 'document.hasFocus()' ) ) . toBe ( true ) ;
await page2 . close ( ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should focus popups by default' , async ( { page , server } ) = > {
2020-08-03 13:41:48 -07:00
await page . goto ( server . EMPTY_PAGE ) ;
const [ popup ] = await Promise . all ( [
page . waitForEvent ( 'popup' ) ,
page . evaluate ( url = > { window . open ( url ) ; } , server . EMPTY_PAGE ) ,
] ) ;
expect ( await popup . evaluate ( 'document.hasFocus()' ) ) . toBe ( true ) ;
expect ( await page . evaluate ( 'document.hasFocus()' ) ) . toBe ( true ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should provide target for keyboard events' , async ( { page , server } ) = > {
2020-08-03 13:41:48 -07:00
const page2 = await page . context ( ) . newPage ( ) ;
await Promise . all ( [
page . goto ( server . PREFIX + '/input/textarea.html' ) ,
page2 . goto ( server . PREFIX + '/input/textarea.html' ) ,
] ) ;
await Promise . all ( [
page . focus ( 'input' ) ,
page2 . focus ( 'input' ) ,
] ) ;
const text = 'first' ;
const text2 = 'second' ;
await Promise . all ( [
page . keyboard . type ( text ) ,
page2 . keyboard . type ( text2 ) ,
] ) ;
const results = await Promise . all ( [
page . evaluate ( 'result' ) ,
page2 . evaluate ( 'result' ) ,
] ) ;
expect ( results ) . toEqual ( [ text , text2 ] ) ;
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should not affect mouse event target page' , async ( { page , server } ) = > {
2020-08-03 13:41:48 -07:00
const page2 = await page . context ( ) . newPage ( ) ;
function clickCounter() {
2020-08-11 15:50:53 -07:00
document . onclick = ( ) = > window [ 'clickCount' ] = ( window [ 'clickCount' ] || 0 ) + 1 ;
2020-08-03 13:41:48 -07:00
}
await Promise . all ( [
page . evaluate ( clickCounter ) ,
page2 . evaluate ( clickCounter ) ,
page . focus ( 'body' ) ,
page2 . focus ( 'body' ) ,
] ) ;
await Promise . all ( [
page . mouse . click ( 1 , 1 ) ,
page2 . mouse . click ( 1 , 1 ) ,
] ) ;
const counters = await Promise . all ( [
page . evaluate ( 'window.clickCount' ) ,
page2 . evaluate ( 'window.clickCount' ) ,
] ) ;
2022-08-18 20:12:33 +02:00
expect ( counters ) . toEqual ( [ 1 , 1 ] ) ;
2020-08-03 13:41:48 -07:00
} ) ;
2021-09-27 18:58:08 +02:00
it ( 'should change document.activeElement' , async ( { page , server } ) = > {
2020-08-03 13:41:48 -07:00
const page2 = await page . context ( ) . newPage ( ) ;
await Promise . all ( [
page . goto ( server . PREFIX + '/input/textarea.html' ) ,
page2 . goto ( server . PREFIX + '/input/textarea.html' ) ,
] ) ;
await Promise . all ( [
page . focus ( 'input' ) ,
page2 . focus ( 'textarea' ) ,
] ) ;
const active = await Promise . all ( [
page . evaluate ( 'document.activeElement.tagName' ) ,
page2 . evaluate ( 'document.activeElement.tagName' ) ,
] ) ;
expect ( active ) . toEqual ( [ 'INPUT' , 'TEXTAREA' ] ) ;
} ) ;
2025-05-28 14:22:59 +00:00
it ( 'should not affect screenshots' , async ( { page , server , browserName , headless , isWindows , isLinux , isHeadlessShell , channel } ) = > {
2023-05-11 17:54:05 +02:00
it . skip ( browserName === 'webkit' && isWindows && ! headless , 'WebKit/Windows/headed has a larger minimal viewport. See https://github.com/microsoft/playwright/issues/22616' ) ;
2024-11-21 23:42:21 +01:00
it . skip ( browserName === 'webkit' && isLinux && ! headless , 'WebKit headed has a larger minimal viewport on gtk4.' ) ;
2023-05-11 17:54:05 +02:00
it . skip ( browserName === 'firefox' && ! headless , 'Firefox headed produces a different image' ) ;
2025-05-28 14:22:59 +00:00
it . fixme ( browserName === 'chromium' && ! isHeadlessShell && channel !== 'chromium-tip-of-tree' , 'https://github.com/microsoft/playwright/issues/33330' ) ;
2021-04-04 19:32:14 -07:00
2020-08-03 13:41:48 -07:00
const page2 = await page . context ( ) . newPage ( ) ;
await Promise . all ( [
2021-09-27 18:58:08 +02:00
page . setViewportSize ( { width : 500 , height : 500 } ) ,
2020-08-03 13:41:48 -07:00
page . goto ( server . PREFIX + '/grid.html' ) ,
2021-09-27 18:58:08 +02:00
page2 . setViewportSize ( { width : 50 , height : 50 } ) ,
2020-08-03 13:41:48 -07:00
page2 . goto ( server . PREFIX + '/grid.html' ) ,
] ) ;
await Promise . all ( [
page . focus ( 'body' ) ,
page2 . focus ( 'body' ) ,
] ) ;
const screenshots = await Promise . all ( [
page . screenshot ( ) ,
page2 . screenshot ( ) ,
] ) ;
2020-10-06 15:51:18 -07:00
expect ( screenshots [ 0 ] ) . toMatchSnapshot ( 'screenshot-sanity.png' ) ;
expect ( screenshots [ 1 ] ) . toMatchSnapshot ( 'grid-cell-0.png' ) ;
2020-08-03 13:41:48 -07:00
} ) ;
2022-06-09 11:56:07 -08:00
it ( 'should change focused iframe' , async ( { page , server , browserName , headless } ) = > {
it . skip ( browserName === 'firefox' && ! headless , 'Headed FF might lose focus' ) ;
2020-08-03 13:41:48 -07:00
await page . goto ( server . EMPTY_PAGE ) ;
const [ frame1 , frame2 ] = await Promise . all ( [
2020-09-18 15:52:14 -07:00
attachFrame ( page , 'frame1' , server . PREFIX + '/input/textarea.html' ) ,
attachFrame ( page , 'frame2' , server . PREFIX + '/input/textarea.html' ) ,
2020-08-03 13:41:48 -07:00
] ) ;
function logger() {
2020-08-11 15:50:53 -07:00
self [ '_events' ] = [ ] ;
2020-08-03 13:41:48 -07:00
const element = document . querySelector ( 'input' ) ;
2020-08-28 04:20:29 -07:00
element . onfocus = element . onblur = e = > self [ '_events' ] . push ( e . type ) ;
2020-08-03 13:41:48 -07:00
}
await Promise . all ( [
frame1 . evaluate ( logger ) ,
frame2 . evaluate ( logger ) ,
] ) ;
const focused = await Promise . all ( [
frame1 . evaluate ( 'document.hasFocus()' ) ,
frame2 . evaluate ( 'document.hasFocus()' ) ,
] ) ;
expect ( focused ) . toEqual ( [ false , false ] ) ;
{
await frame1 . focus ( 'input' ) ;
const events = await Promise . all ( [
frame1 . evaluate ( 'self._events' ) ,
frame2 . evaluate ( 'self._events' ) ,
] ) ;
expect ( events ) . toEqual ( [ [ 'focus' ] , [ ] ] ) ;
const focused = await Promise . all ( [
frame1 . evaluate ( 'document.hasFocus()' ) ,
frame2 . evaluate ( 'document.hasFocus()' ) ,
] ) ;
expect ( focused ) . toEqual ( [ true , false ] ) ;
}
{
await frame2 . focus ( 'input' ) ;
const events = await Promise . all ( [
frame1 . evaluate ( 'self._events' ) ,
frame2 . evaluate ( 'self._events' ) ,
] ) ;
expect ( events ) . toEqual ( [ [ 'focus' , 'blur' ] , [ 'focus' ] ] ) ;
const focused = await Promise . all ( [
frame1 . evaluate ( 'document.hasFocus()' ) ,
frame2 . evaluate ( 'document.hasFocus()' ) ,
] ) ;
expect ( focused ) . toEqual ( [ false , true ] ) ;
}
} ) ;
2020-11-04 22:42:35 -08:00
// @see https://github.com/microsoft/playwright/issues/3476
2021-09-27 18:58:08 +02:00
browserTest ( 'should focus with more than one page/context' , async ( { contextFactory } ) = > {
2020-11-04 22:42:35 -08:00
const page1 = await ( await contextFactory ( ) ) . newPage ( ) ;
const page2 = await ( await contextFactory ( ) ) . newPage ( ) ;
await page1 . setContent ( ` <button id="foo" onfocus="window.gotFocus=true">foo</button> ` ) ;
await page2 . setContent ( ` <button id="foo" onfocus="window.gotFocus=true">foo</button> ` ) ;
await page1 . focus ( '#foo' ) ;
await page2 . focus ( '#foo' ) ;
expect ( await page1 . evaluate ( ( ) = > ! ! window [ 'gotFocus' ] ) ) . toBe ( true ) ;
expect ( await page2 . evaluate ( ( ) = > ! ! window [ 'gotFocus' ] ) ) . toBe ( true ) ;
} ) ;
2023-11-09 08:27:34 -08:00
2024-04-18 10:49:09 -07:00
browserTest ( 'should not fire blur events when interacting with more than one page/context' , async ( { contextFactory , browserName } ) = > {
browserTest . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/30399' } ) ;
const page1 = await ( await contextFactory ( ) ) . newPage ( ) ;
const page2 = await ( await contextFactory ( ) ) . newPage ( ) ;
await page1 . setContent ( ` <button id="foo" onblur="window.gotBlur=true">foo</button> ` ) ;
await page2 . setContent ( ` <button id="foo" onblur="window.gotBlur=true">foo</button> ` ) ;
await page1 . click ( '#foo' ) ;
await page2 . click ( '#foo' ) ;
expect ( await page1 . evaluate ( ( ) = > ! ! window [ 'gotBlur' ] ) ) . toBe ( false ) ;
expect ( await page2 . evaluate ( ( ) = > ! ! window [ 'gotBlur' ] ) ) . toBe ( false ) ;
} ) ;
2024-10-02 06:58:21 -07:00
browserTest ( 'should trigger hover state concurrently' , async ( { browserType , browserName , headless } ) = > {
2023-11-09 08:27:34 -08:00
browserTest . info ( ) . annotations . push ( { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/27969' } ) ;
2024-10-02 06:58:21 -07:00
browserTest . skip ( ! headless , 'headed messes up with hover' ) ;
2023-11-09 08:27:34 -08:00
browserTest . fixme ( browserName === 'firefox' ) ;
const browser1 = await browserType . launch ( ) ;
const context1 = await browser1 . newContext ( ) ;
const page1 = await context1 . newPage ( ) ;
const page2 = await context1 . newPage ( ) ;
const browser2 = await browserType . launch ( ) ;
const page3 = await browser2 . newPage ( ) ;
for ( const page of [ page1 , page2 , page3 ] ) {
await page . setContent ( `
< style >
button { display : none ; }
div :hover button { display : inline } ;
< / style >
< div > < span > hover me < / span > < button onclick = "window.clicked=1+(window.clicked || 0)" > click me < / button > < / div >
` );
}
for ( const page of [ page1 , page2 , page3 ] )
await page . hover ( 'span' ) ;
for ( const page of [ page1 , page2 , page3 ] )
await page . click ( 'button' ) ;
for ( const page of [ page1 , page2 , page3 ] )
expect ( await page . evaluate ( 'window.clicked' ) ) . toBe ( 1 ) ;
for ( const page of [ page1 , page2 , page3 ] )
await page . click ( 'button' ) ;
for ( const page of [ page1 , page2 , page3 ] )
expect ( await page . evaluate ( 'window.clicked' ) ) . toBe ( 2 ) ;
} ) ;