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

t.scrollBy and t.scroll methods not working properly on virtual scrollers #8172

Closed
port-eighty opened this issue Apr 17, 2024 · 3 comments
Closed
Labels
TYPE: bug The described behavior is considered as wrong (bug).

Comments

@port-eighty
Copy link

What is your Scenario?

I would like to scroll through a virtual scroller and iterate through all the data to assert correct data displayed.

What is the Current behavior?

The scroll and scrollBy methods are only scrolling a tiny bit before reverting to top of the scroller, thus never reaching the end.

What is the Expected behavior?

The scroll methods should move the scroller properly to the designated positions.

What is the public URL of the test page? (attach your complete example)

Not my project but was similar to the module that was implemented in the page that I am testing:
https://angular-yni1jw.stackblitz.io/

What is your TestCafe test code?

//example.js

import { Selector, ClientFunction } from 'testcafe'

const startProject = Selector('#promptToRun button')
const scroller = Selector(
  'body > app-root > ul > cdk-virtual-scroll-viewport'
).addCustomDOMProperties({
  maxScroll: el => {
    const calculatedHeight = el.scrollHeight - el.clientHeight
    return calculatedHeight
  },
  getScrollerPos: el => {
    return el.getBoundingClientRect().y
  },
  getLastItemPos: el => {
    let allItems = el.querySelectorAll('li')
    return allItems[allItems.length - 1].getBoundingClientRect().y
  },
})
const initScroll = ClientFunction(scroller => {
  scroller.scrollTop = 0
  return
})

fixture`Scroller bug`
  .page('https://angular-yni1jw.stackblitz.io/')
  .beforeEach(async t => {
    await t.click(startProject)
    await t
      .expect(scroller.exists)
      .ok(`Scroller did not load in time`, { timeout: 20000 })
    await initScroll(scroller)
  })

test(`Scroll using scroll`, async t => {
  let lastKnownPos = new Set().add(0)
  let tryCount = 0
  let maxScroll = await scroller.maxScroll
  do {
    //store initial position
    lastKnownPos.add(await scroller.scrollTop)

    await t.scroll(
      scroller,
      0, //no x
      Math.floor(
        (await scroller.getLastItemPos) - (await scroller.getScrollerPos)
      )
    )
    //If scroll did not work then add tryCount
    if (lastKnownPos.has(await scroller.scrollTop)) {
      tryCount += 1
    }
  } while ((await scroller.scrollTop) != maxScroll && tryCount != 3)

  await t.expect(lastKnownPos.has(maxScroll)).ok(`Did not scroll to the end`)
})
test(`Scroll using scrollBy`, async t => {
  let lastKnownPos = new Set().add(0)
  let tryCount = 0
  let maxScroll = await scroller.maxScroll
  do {
    //store initial position
    lastKnownPos.add(await scroller.scrollTop)

    await t.scrollBy(
      scroller,
      0, //no x
      Math.floor(
        (await scroller.getLastItemPos) - (await scroller.getScrollerPos)
      )
    )
    //If scroll did not work then add tryCount
    if (lastKnownPos.has(await scroller.scrollTop)) {
      tryCount += 1
    }
  } while ((await scroller.scrollTop) != maxScroll && tryCount != 3)

  await t.expect(lastKnownPos.has(maxScroll)).ok(`Did not scroll to the end`)
})

Your complete configuration file

//.testcaferc.js

module.exports = {
  browsers: ['chrome'],
  skipJsErrors: true,
  pageLoadTimeout: 60000,
  reporter: 'list',
  nativeAutomation: true,
  disableMultipleWindows: true, //if false, nativeAutomation breaks it.
  screenshots: {
    takeOnFails: true,
    path: './screenshots/',
  },
}

Your complete test report

% testcafe chrome ./example.js
Using locally installed version of TestCafe.
The "browsers" option from the configuration file will be ignored.
Running tests in:

  • Chrome 123.0.0.0 / macOS 10.15.7

✖ Scroller bug - Scroll using scroll (screenshots:
/*****/screenshots/2024-04-16_22-48-33/test-1/Chrome_123.0.0.0_macOS_10.15.7/errors/1.png)[10:48:41
PM] [7s.098ms]

  1. AssertionError: Did not scroll to the end: expected false to be truthy

    Browser: Chrome 123.0.0.0 / macOS 10.15.7
    Screenshot:

/*******/screenshots/2024-04-16_22-48-33/test-1/Chrome_123.0.0.0_macOS_10.15.7/errors/1.png

     50 |    if (lastKnownPos.has(await scroller.scrollTop)) {
     51 |      tryCount += 1
     52 |    }
     53 |  } while ((await scroller.scrollTop) != maxScroll && tryCount != 3)
     54 |
   > 55 |  await t.expect(lastKnownPos.has(maxScroll)).ok(`Did not scroll to the end`)
     56 |})
     57 |test(`Scroll using scrollBy`, async t => {
     58 |  let lastKnownPos = new Set().add(0)
     59 |  let tryCount = 0
     60 |  let maxScroll = await scroller.maxScroll

     at <anonymous> (/*******/example.js:55:47)
     at asyncGeneratorStep (/*******/example.js:1:52)
     at _next (/*******/example.js:1:52)

✖ Scroller bug - Scroll using scrollBy (screenshots:
/*******/screenshots/2024-04-16_22-48-33/test-2/Chrome_123.0.0.0_macOS_10.15.7/errors/1.png)[10:48:48
PM] [6s.585ms]

  1. AssertionError: Did not scroll to the end: expected false to be truthy

    Browser: Chrome 123.0.0.0 / macOS 10.15.7
    Screenshot:

/*******/screenshots/2024-04-16_22-48-33/test-2/Chrome_123.0.0.0_macOS_10.15.7/errors/1.png

     73 |    if (lastKnownPos.has(await scroller.scrollTop)) {
     74 |      tryCount += 1
     75 |    }
     76 |  } while ((await scroller.scrollTop) != maxScroll && tryCount != 3)
     77 |
   > 78 |  await t.expect(lastKnownPos.has(maxScroll)).ok(`Did not scroll to the end`)
     79 |})
     80 |

     at <anonymous> (/*******/example.js:78:47)
     at asyncGeneratorStep (/*******/example.js:1:52)
     at _next (/*******/example.js:1:52)

2/2 failed (16s)

Warnings (1):

The "browsers" option from the configuration file will be ignored.

Screenshots

Console Screenshot

Steps to Reproduce

  1. Copy test code
  2. Run test code
  3. Observe the run

TestCafe version

3.5.0

Node.js version

20.11.1

Command-line arguments

testcafe chrome ./example.js

Browser name(s) and version(s)

Chrome 123.0.0.0

Platform(s) and version(s)

macOS 10.15.7, Windows 11, Windows 10

Other

No response

@port-eighty port-eighty added the TYPE: bug The described behavior is considered as wrong (bug). label Apr 17, 2024
@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Apr 17, 2024
@PavelMor25
Copy link
Collaborator

Hello @port-eighty,

Thank you for your report.

We have investigated the issue and found a workaround for you. In cases of virtual scrollers, a solution is to use the browser’s native API. For example, you can use the window.scrollBy method. To access this method, use the ClientFunction generator. Calculate the offset between the elements and pass these values to the scrollBy method.

import { Selector, ClientFunction } from 'testcafe'
 
const startProject = Selector('#promptToRun button')
const scroller = Selector(
  'body > app-root > ul > cdk-virtual-scroll-viewport'
).addCustomDOMProperties({
  maxScroll: el => {
    const calculatedHeight = el.scrollHeight - el.clientHeight
    return calculatedHeight
  },
  getScrollerPos: el => {
    return el.getBoundingClientRect().y
  },
  getLastItemPos: el => {
    let allItems = el.querySelectorAll('li')
    return allItems[allItems.length - 1].getBoundingClientRect().y
  },
})
const initScroll = ClientFunction(scroller => {
  scroller.scrollTop = 0
  return
})
// client function scrollBy 
const scrollBy = ClientFunction((x, y) => { 
  document.querySelector('body > app-root > ul > cdk-virtual-scroll-viewport').scrollBy(x, y);
});
 
 
fixture`Scroller bug`
  .page('[https://angular-yni1jw.stackblitz.io/')](https://angular-yni1jw.stackblitz.io/%27))
  .beforeEach(async t => {
    await t.click(startProject)
    await t
      .expect(scroller.exists)
      .ok(`Scroller did not load in time`, { timeout: 20000 })
    await initScroll(scroller)
  })
 
  test(`Scroll using scroll`, async t => {
    let lastKnownPos = new Set().add(0)
    let tryCount = 0
    let maxScroll = await scroller.maxScroll
    do {
      //store initial position
      lastKnownPos.add(await scroller.scrollTop)
      // client function scrollBy
      await scrollBy(
        0, //no x
        Math.floor(
          (await scroller.getLastItemPos) - (await scroller.getScrollerPos)
        )
      )
      //If scroll did not work then add tryCount
      if (lastKnownPos.has(await scroller.scrollTop)) {
        tryCount += 1
      }
    } while ((await scroller.scrollTop) != maxScroll && tryCount != 3)
    await t.expect(lastKnownPos.has(maxScroll)).ok(`Did not scroll to the end`)
})

Please let us know your results.

@PavelMor25 PavelMor25 added STATE: Need clarification An issue lacks information for further research. and removed STATE: Need response An issue that requires a response or attention from the team. labels Apr 24, 2024
@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Apr 24, 2024
@PavelMor25 PavelMor25 removed the STATE: Need response An issue that requires a response or attention from the team. label Apr 24, 2024
@port-eighty
Copy link
Author

Thanks for the work around! This works perfectly for our application.

@github-actions github-actions bot removed the STATE: Need clarification An issue lacks information for further research. label Apr 24, 2024
@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Apr 24, 2024
@PavelMor25
Copy link
Collaborator

I'm glad to hear that.

We are closing the issue for now since the workaround was helpful.

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
TYPE: bug The described behavior is considered as wrong (bug).
Projects
None yet
Development

No branches or pull requests

2 participants