Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Toggle page visibility that affects document.visibilityState #2286

Closed
abhayp5 opened this issue May 18, 2020 · 18 comments
Closed

[Feature] Toggle page visibility that affects document.visibilityState #2286

abhayp5 opened this issue May 18, 2020 · 18 comments

Comments

@abhayp5
Copy link

abhayp5 commented May 18, 2020

No description provided.

@yury-s
Copy link
Member

yury-s commented May 18, 2020

There is no API for that at the moment, all pages behave as if they are all visible and active. Can you describe your scenario where minimizing matters? Do you want to test document.visibilityState similar to #1290 or something else?

@abhayp5
Copy link
Author

abhayp5 commented May 19, 2020

The scenario is:- perform some action on page minimise the browser so that elements are not visible, read network logs of from browser (requests). I tried page.press(“//html ”, “Alt+Space+n”) but it is not working too.

@yury-s
Copy link
Member

yury-s commented May 19, 2020

The scenario is:- perform some action on page minimise the browser so that elements are not visible

Does your page listen to events related to visibility changes or do you try to test how the page would behave when its tab becomes background (e.g. if the user switches to another tab in the browser or the browser window is minimized)? As of today all pages created by playwright behave as if they are active foreground tabs and the browser window is visible (not minimized). We could try and extend the API to support emulation of background tabs but we'd need to better understand what behavior you would like to emulate.

@GeorgeWL
Copy link

The scenario is:- perform some action on page minimise the browser so that elements are not visible, read network logs of from browser (requests). I tried page.press(“//html ”, “Alt+Space+n”) but it is not working too.

But why?

What's the reason for that? As that can be done without minimizing.

@abhayp5
Copy link
Author

abhayp5 commented May 20, 2020

My product deals with visibility, What an end user experiences, so to test features it is required that the framework should support browser handling. Yes I checked that all the pages of current context remains active but that is what I am not looking for. During the test browser should get minimize so that I can have some logs. If you guys can extend it will be a nice feature. As of now I am using other library to do key press so that I can minimize browser.

@yury-s
Copy link
Member

yury-s commented May 20, 2020

During the test browser should get minimize so that I can have some logs.

Can you shed some light on how those logs are produced? Are they not a part of the page scripts?

@abhayp5
Copy link
Author

abhayp5 commented May 25, 2020

There are some events which are fired only if the page is visible and visibility is true for the page, so to test the functionality if it is working fine or not I have to do a minimize the browser for some time and check the events in network logs, again maximize the page and check if the events are getting fired again on page visibility=true.

@yury-s
Copy link
Member

yury-s commented May 25, 2020

From what I hear it sounds to me that you want to emulate 'visibilitychange' event and document.visibilityState. Basically changing visibilityState to 'hidden' should be equivalent to hiding/minimizing the tab and changing it back to 'visible' would be equivalent to you switching back which is similar to the request #1290. I believe we can support that, just need to make it work well with changes of document.hasFocus(). Meanwhile you can try the workaround from #1290.

@yury-s yury-s self-assigned this May 25, 2020
@abhayp5
Copy link
Author

abhayp5 commented May 26, 2020

Thanks @yury-s

@mbm3
Copy link

mbm3 commented Sep 20, 2020

Also interested in this feature, any updates @abhayp5 @yury-s ?
I've tried sending the system shortcuts for minimize with no luck

@mbm3
Copy link

mbm3 commented Oct 15, 2020

For Chrome, you can use DevTools Protocol.

  1. Get windowId from Browser.getWindowForTarget
  2. Use Browser.setWindowBounds with parameters windowId and {windowState: 'minimized'}

Found using CDP w/ chrome-launcher to be much better than Puppeteer/Playwright for Chrome as you can do anything without lots of extra implementations not needed for your use case.

@dgozman dgozman changed the title How to minimize the current page or current context. [Feature] Toggle page visibility that affects document.visibilityState Nov 23, 2020
@micahjon
Copy link

Just wanted to chime-in with another use case.

I work at BeFunky, an online photo editor, and we use quite a few async browser APIs, namely FileReader, ImageBitmap, and IndexedDB. We often find that due to browsers restricting resources & throttling tasks in background tabs, there are bugs that only occur when our tab is in the background.

We wrap some of these APIs (especially less-reliable ones like FileReader) to ensure that they always give us a result or error within a reasonable timeframe. For instance, if FileReader hasn't fired an onload or onerror event for 15 seconds we give up instead of showing the user an infinite load screen. However, if the tab is in the background, we could easily wait much longer, so I'm working on a setTimeout-style wrapper that only runs the timer when the tab is active:
https://github.com/micahjon/while-tab-visible-setTimeout

I'd like to write some automated tests in Tab A, where I occasionally switch to Tab B, then back to Tab A, etc. I understand Playwright was not built for this use case, but just wanted to throw it out there as a legitimate testing scenario. Thanks for all your hard work on this great library.

@mtt87
Copy link

mtt87 commented Jun 21, 2021

I was doing some research and landed here as well.

What I'm trying to test?

Scenario: I'm using next-auth which is an authentication "framework" for nextjs and one of the feature is the automatic sync of browser tabs. This is useful because when as a user you have 2+ tabs open and you are logged in, then in one tab you logout and an event is broadcasted to the other tabs and they all log the user out correctly.

This is problematic when there is a scenario with an access_token and refresh_token since you can refresh an access token with one refresh token only once, then they become unusable. If you have multiple tabs trying to sync a session and refresh an access token, then you end up with race conditions and errors.

I'm trying to write an e2e test that cover this and I was oping to find an API that could trigger a page focus/blur in order to change the visibilitystate property and therefore document.hidden to become true or false.

Reading other issues seems like it "should" be possible with this ugly hack:

EDIT: it doesn't work

await page.$eval(
  'document',
  (d) => Object.defineProperty(document, 'visibilityState', {get() { return "hidden";}}),
),

await page.$eval(
  'document',
  (d) => Object.defineProperty(document, 'visibilityState', {get() { return "visible";}}),
),

I wonder if there is a better way or a plan to support a first class API in order to achieve this?

@mtt87
Copy link

mtt87 commented Jun 28, 2021

I actually tried that doesn't seem to be working, I'm trying to do something different now but also not working

await page.dispatchEvent("document", "visibilitychange")

I think the reason is that document is not a valid CSS selector.

I found a way to do it

await page1.$eval("html", () => {
  const ev = document.createEvent("Event")
  ev.initEvent("visibilitychange")
  document.dispatchEvent(ev)
})

But I'm wondering if there are better ways

@pavelfeldman
Copy link
Member

Why was this issue closed?

We are prioritizing the features based on the upvotes, recency and activity in the issue thread. It looks like this issue only has a handful of upvotes, has not been touched recently and/or we lack sufficient feedback to act on it. We are closing issues like this one to keep our bug database maintainable. Please feel free to open a new issue and link this one to it if you think this is a mistake.

@krskrs
Copy link

krskrs commented Dec 17, 2022

Hi @yury-s I'm commenting on this issue, as I've ended up here while searching if there was a way in playwright to test visibility changes. Our use case is a simple listener like the one below, which we are using as a best-effort approach for refreshing our app data in case an user is editing on multiple tabs.
From what I've read in this Issue I was not able to understand if this feature is still being evaluated, as a lot of time has passed, anyway I'm adding our use case-here in case it might help.

Thank you :)

    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        console.log("Browser tab is hidden");
      } else {
        setIsRefreshing(true);
        loadData().then(() => {
          setIsRefreshing(false);
        });
      }
    }

@zerodevx
Copy link

I too landed here when searching how to test this - then I realised you can probably mock it like so:

async function hideTab(hide = true) {
  await page.evaluate((hide) => {
    Object.defineProperty(document, 'visibilityState', { value: hide ? 'hidden' : 'visible', writable: true })
    Object.defineProperty(document, 'hidden', { value: hide, writable: true })
    document.dispatchEvent(new Event('visibilitychange'))
  }, hide)
}

await hideTab() // simulate page hidden
// run your tests

await hideTab(false) // simulate page restored
// run your tests

Writing this comment for posterity.

@negyxo
Copy link

negyxo commented Nov 22, 2023

@zerodevx for me this didn't work, visibilitychnage is not triggered, and when I test the same code in console window document.dispatchEvent(new Event('visibilitychange')) it won't trigger the event. So, I tried with window object, and then it started to work:
window.dispatchEvent(new Event('visibilitychange'))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests