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

Intersection Observer not firing even when get() or scrollIntoView etc. #3848

Open
bculley opened this issue Mar 29, 2019 · 25 comments
Open
Labels
E2E Issue related to end-to-end testing prevent-stale mark an issue so it is ignored by stale[bot] stage: needs investigating Someone from Cypress needs to look at this

Comments

@bculley
Copy link

bculley commented Mar 29, 2019

Current behavior:

Getting or scrolling into view an intersection observer does not trigger intersection and loading of content inside intersection observer.

Desired behavior:

Would like to be able to have Intersection Observer render content on scroll such that intersection is observed and content renders. Would then be able to get() content inside IntersectionObserver.

Versions

Chrome 73
Cypress 3.1.5
Mac OS Mojave

@bculley
Copy link
Author

bculley commented Mar 29, 2019

OK, so it does work kinda. I had to trick it to make the intersection happen by scrolling past it once so that we go past the intersection, then go find it again. I also had to use the duration of the scrollIntoView() method to slow it down so that the intersection occurs. Hope this helps someone.

@bculley bculley closed this as completed Mar 29, 2019
@callebstrom
Copy link

@bculley Hi! I seem to have stumbled across the same issue. What is odd is that it only occurs on CI (Jenkins on Linux + electron). Did you have to exaggerate the offsets and durations? I still had no luck with 500 duration and an offset bigger than my viewport (scrolling past the given element).

@tamj0rd2
Copy link

tamj0rd2 commented Feb 2, 2020

I'm also having similar issues with the intersection API in cypress. The rootMargins don't seem to have any effect unless I double them. I've tested the functionality in a several browsers using Browserstack and can't reproduce it. It only seems to be an issue when viewing the page in cypress

@maciekgrzybek
Copy link

@tamj0rd2 I'm having exactly the same issue. Cypress completely ignores rootMargin property. Everything works fine when I run my app normally.

@sunfit
Copy link

sunfit commented Apr 6, 2020

Same issue here.

What is strange is that it works in Electron 78 bundled with Cypress, but does not work with Chrome 80 that I have on my machine.

This issue should not be Closed.

@raylenmargono
Copy link

We are running into the same issue with chrome. Anyone have a solution to this?

@lorenries
Copy link

lorenries commented Aug 17, 2020

You can mock the window.IntersectionObserver api to manually set isIntersecting to true on all observer entries:

cy.visit(url, {
  onBeforeLoad: (win) => {
    win.IntersectionObserver = function (cb, options) {
      const instance = {
        thresholds: Array.isArray(options.threshold)
          ? options.threshold
          : [options.threshold],
        root: options.root,
        rootMargin: options.rootMargin,
        time: Date.now(),
        observe: (element) => {
          const entry = [
            {
              isIntersecting: true,
              boundingClientRect: element.getBoundingClientRect(),
              intersectionRatio: 1,
              intersectionRect: element.getBoundingClientRect(),
              rootBounds: instance.root
                ? instance.root.getBoundingClientRect()
                : {},
              target: element,
              time: Date.now(),
            },
          ];
          cb(entry);
        },
        unobserve: () => undefined,
        disconnect: () => undefined,
      };
      return instance;
    };
  },
}

@wthegamer
Copy link

Same issue here.

What is strange is that it works in Electron 78 bundled with Cypress, but does not work with Chrome 80 that I have on my machine.

This issue should not be Closed.

@jennifer-shehane I can confirm the same experience above. Would it be possible to reopen this issue?

@AskMarvinV
Copy link

Same issue here.
What is strange is that it works in Electron 78 bundled with Cypress, but does not work with Chrome 80 that I have on my machine.
This issue should not be Closed.

@jennifer-shehane I can confirm the same experience above. Would it be possible to reopen this issue?

same here...

@shawnveltman
Copy link

Hey all - I was running into this issue as well, and found that adding in a concrete duration to the scroll made it work.

EG:

cy.get('#terms_and_conditions').scrollTo('bottom', {duration: 300});

@jennifer-shehane
Copy link
Member

Can anyone provide a reproducible example of an app where intersection observer is affected with Cypress? Here are some tips for providing a Short, Self Contained, Correct, Example and our own Troubleshooting Cypress guide.

@jennifer-shehane jennifer-shehane added the stage: needs information Not enough info to reproduce the issue label Dec 21, 2020
@alejandroiglesias
Copy link

alejandroiglesias commented Mar 30, 2021

According to this Chromium issue, IntersectionObserver does not trigger its callback in a Chrome background tab.

Could it be possible that this is related to running headless being treated in the same way as a background tab by Chrome?

@jennifer-shehane
Copy link
Member

@alejandroiglesias I don't see any indication that IntersectionObserver is not triggering in headless mode with Cypress. Cypress passes flags to disable the background throttling Chrome does. Example of intersection obeserver working headlessly.

// spec.js
it('intersection observer', () => {
  const blue = 'rgb(0, 0, 255)'
  const red = 'rgb(255, 0, 0)'

  cy.visit('index.html')
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
  cy.get('h1').should('have.css', 'color', blue)
  cy.get('h1').should('have.css', 'color', red)
})
<html>
<body>
  <h1 id="target">Target</h1>
  <script>
    var target = document.querySelector('#target');
    
    // inspect visibility
    new IntersectionObserver(function(entries) {
    console.log('intersectionRatio', entries[0].intersectionRatio);
    }, {
    threshold: [0]
    }).observe(target);
    
    // toggle color every 2 secs
    var color = false;
    const blue = 'rgb(0, 0, 255)'
    const red = 'rgb(255, 0, 0)'

    setInterval(function() {
    target.style.color = color ? red : blue;
    color = !color;
    }, 500);
  </script>
</body>
</html>

We'll need a reproducible example of the issue with IntersectionObserver and scrolling in order to investigate.

@alevor657
Copy link

Happens to me as well, I am using an IntersectionObserver with { threshold: 0, rootMargin: '-100% 0px 0px 0px', }
Works in Chrome 98.0.4758.80

@faoiseamh
Copy link

Versions

Chrome 73
Cypress 3.1.5
Mac OS Mojave
We've been banging our heads against the wall on this issue for a while and i believe it's what's being described here by you all. It seems we are also experiencing this, but only on our CI/CD (cloud, headless) test-runs and only intermittently (~75% of the time or more).

We're using Cypress 7.7.0 / Electron 89 (headless) / Ubuntu 20.

  const { ref, inView } = useInView({
    threshold: 0,
    trackVisibility: true,
    delay: 50

  });

I'll see if we can get an isolated reproducible sample of this for everyone shortly.

This also seems plausible for us given that only our background (CI/CD) runs were failing, though again only intermittently. And after more testing today none of us can reproduce this again including on CI/CD. Very strange, something we're missing. Will update as we learn more.

According to this Chromium issue, IntersectionObserver does not trigger its callback in a Chrome background tab.

Could it be possible that this is related to running headless being treated in the same way as a background tab by Chrome?

@cypress-bot cypress-bot bot added stage: backlog and removed stage: needs information Not enough info to reproduce the issue labels Apr 29, 2022
@contolini
Copy link

contolini commented Aug 1, 2022

We were running into this issue when using certain rootMargin values. When IntersectionObserver's root is undefined, the bounds of the current viewport are used to calculate intersections. Because Cypress embeds your app in an iframe, you probably want the root to be be the iframe's document and not the entire viewport. This can be fixed by setting root: document, e.g.:

const observer = new IntersectionObserver( handleIntersect, {
    root: document,
    rootMargin: '-50% 0px 0px 0px'
} );

Here's an isolated example that's reproducible w/ both desktop and headless chrome: https://github.com/contolini/cypress-test-intersectionobserver

@JasonLandbridge
Copy link

@jennifer-shehane, could you take a look at the isolated example @contolini posted? This is still a problem in Cypress v12.11.0.

Even with slowing the scrolling down, the Intersection Observer is just not being triggered. This happens with virtual scrolling in my case.

@marktnoonan
Copy link
Contributor

@JasonLandbridge does the root: document suggested (or something similar) work for your use case as a workaround? Any chance you can share an example where you are using virtual scrolling? I'm wondering if root is already set in virtual scrolling situations, and there are 2 different problems.

t's a bit like framebusting - should Cypress overwrite the constructor for IntersectionObserver, and replace an undefined root with document? Seems like there would be pros and cons to this.

I'm going to go ahead and add some tags to this for relevant team to take a closer look since that reproduction does work for me.

@marktnoonan marktnoonan added the E2E Issue related to end-to-end testing label May 11, 2023
@marktnoonan marktnoonan removed their assignment Jun 28, 2023
@flyingduck92
Copy link

I have the same issue, how to fixed it? This is chrome issue :(

@amandaol
Copy link

amandaol commented Jan 8, 2024

I am experiencing the same problem! I was SO hoping there would be an answer at the end of this thread. Is this being worked on? (We may have to use React Testing Library AND Cypress, just because Cypress is not giving us what we need. That's a lot of overhead.) Please help!

@cypress-app-bot

This comment was marked as outdated.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Jul 7, 2024
@SultanWithAGremlin
Copy link

This still is an issue in Cypress 13.13.0

@jennifer-shehane jennifer-shehane added prevent-stale mark an issue so it is ignored by stale[bot] and removed stale no activity on this issue for a long period labels Jul 8, 2024
@bglw
Copy link

bglw commented Dec 3, 2024

Unsure if it will help as I'm not using Cypress, but I am using the underlying Chrome DevTools Protocol for testing purposes and have been hitting this issue.

First observation is that I could only hit this when running tests concurrently. Multiple tests were running, each in their own page (created from one launched browser, with createTarget). None of the optional arguments were supplied.

I could not hit this issue when running tests with concurrency set to 1. If I had to guess, only one page can be actively triggering the IntersectionObserver 🤷

I can't determine exactly why this is occurring in Chrome. I have tried in new, old, and non-headless launch configurations to the same effect. In exploring different parameters though, I have found a method that prevents the issue (at least, for me, on my machine).

For each test, I now create a new BrowserContext (createBrowserContext) and pass that to createTarget when making my page. disposeOnDetach is enabled, though I don't think that is significant.

Now that each page has its own BrowserContext, I haven't had any issues with tests running concurrently with IntersectionObservers.

In my case I prefer the test isolation anyway, so this was a positive change. I can't say whether it would be appropriate for Cypress, but hopefully at a minimum this helps chase down a lead for why this might be happening!

@jennifer-shehane jennifer-shehane added the stage: needs investigating Someone from Cypress needs to look at this label Dec 10, 2024
@jennifer-shehane
Copy link
Member

Are users encountering this when running multiple instances of Cypress on the same machine? We don't recommend Cypress to be run that way.

@SultanWithAGremlin
Copy link

I run Cypress just in a single instance. The event is still not fired in 13.16.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E2E Issue related to end-to-end testing prevent-stale mark an issue so it is ignored by stale[bot] stage: needs investigating Someone from Cypress needs to look at this
Projects
None yet
Development

No branches or pull requests