-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
[Question] What is the best way to scroll page to the bottom? #4302
Comments
You can run JS in the page with await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); |
Thank you @arjunattam but it doesn't work. There is no any scroll in mobile version. |
how to smoothly scroll page to the bottom? It is important for lazyload web pages. |
await page.evaluate(() => {
for (let i = 0; i < document.body.scrollHeight; i+100) {
window.scrollTo(0, i)
}
}); |
await page.evaluate(async () => {
for (let i = 0; i < document.body.scrollHeight; i += 100) {
window.scrollTo(0, i);
}
}); |
await page.evaluate(async () => {
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
for (let i = 0; i < document.body.scrollHeight; i += 100) {
window.scrollTo(0, i);
await delay(100);
}
}); |
I pimped the function because I wanted to simulate two speeds and two directions. let scroll = async (args) => {
const {direction, speed} = args;
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const scrollHeight = () => document.body.scrollHeight;
const start = direction === "down" ? 0 : scrollHeight();
const shouldStop = (position) => direction === "down" ? position > scrollHeight() : position < 0;
const increment = direction === "down" ? 100 : -100;
const delayTime = speed === "slow" ? 50 : 10;
console.error(start, shouldStop(start), increment)
for (let i = start; !shouldStop(i); i += increment) {
window.scrollTo(0, i);
await delay(delayTime);
}
}; Call it that way: await page.evaluate(scroll, {direction: "down", speed: "slow"});
await page.evaluate(scroll, {direction: "up", speed: "fast"}); |
Here is one alternative using mouse events:
Edit: Even though this is probably semantically more correct, this still has the same problems than other instant scrolls and is probably as flaky as |
I got this working (using
|
leveraged this within the context of a backstop js playwright engine_scripts onReady.js file and it worked for me async function scrollToBottom() {
await page.evaluate(async () => {
for (let i = 0; window.scrollY * i < window.document.documentElement.scrollHeight; i++) {
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
window.scrollTo(0, window.scrollY + window.document.documentElement.clientHeight);
await delay(100);
}
});
}
await scrollToBottom(); versions of tooling |
I've used this one to have scrolling and rendering reliably work: async function scrollToBottom(page) {
const [scrollY, scrollHeight] = await page.evaluate(() => [
window.scrollY,
window.document.documentElement.scrollHeight,
])
for (let i = 0; scrollY * i < scrollHeight; i += 100) {
await page.evaluate((i) => {
window.scrollTo(0, i, { behavior: 'smooth' })
}, i)
await sleep(0.1)
}
}
function sleep(seconds) {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000))
} |
Hi bro, i prefer use this :
` |
This works for me this is my playwright.config.ts
|
For waiting for all (visible) lazy-loaded images on the page to load, I wrote a new trick for this, which also tests image loading with const lazyImages = await page.locator('img[loading="lazy"]:visible').all();
for (const lazyImage of lazyImages) {
await lazyImage.scrollIntoViewIfNeeded();
await expect(lazyImage).not.toHaveJSProperty('naturalWidth', 0);
} One workaround for this is to assert the length of the const lazyImagesLocator = page.locator('img[loading="lazy"]:visible');
// Assert on length to wait for image visibility to stabilize
// after client-side JavaScript hides some images
// https://github.com/microsoft/playwright/issues/31737#issuecomment-2233775909
await expect(lazyImagesLocator).toHaveCount(13);
const lazyImages = await lazyImagesLocator.all();
for (const lazyImage of lazyImages) {
await lazyImage.scrollIntoViewIfNeeded();
await expect(lazyImage).not.toHaveJSProperty('naturalWidth', 0);
} Source: https://github.com/karlhorky/playwright-tricks#load-all-lazy-images |
When GitHub comment has multiple positive reactions,. you know this is the answer. Thanks for saving my time :) |
Scrolling is cool but if there is some infinity scroll or DOM changes, the suggestions above will not work, there is my solution which will detect all changes with MutationObserver (lazy load, infinity load etc.) export const scrollPage = async (page) => {
await page.evaluate(async () => {
await new Promise((resolve) => {
let totalHeight = 0;
const distance = 100;
const scroll = () => {
const scrollHeight = document.body.scrollHeight;
window.scrollBy(0, distance);
totalHeight += distance;
if (totalHeight >= scrollHeight) {
clearInterval(timer);
observer.disconnect();
resolve();
}
};
const timer = setInterval(scroll, 100);
const observer = new MutationObserver(() => {
totalHeight = 0;
scroll();
});
observer.observe(document.body, { childList: true, subtree: true });
});
});
}; |
No description provided.
The text was updated successfully, but these errors were encountered: