GoogleChrome / GoogleChrome/lighthouse
Prevent destructive behavior in user flows
- Dominant language
- JavaScript
- Stars
- 30.8k
- Forks
- 9.8k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 20
Description
**Summary**
So I followed this example (more or less) https://web.dev/lighthouse-user-flows/#looking-for-feedback
What I am trying to do is navigate to a page, scroll to the bottom, and scroll back to the top.
However, if I put the scroll to the bottom in a timespan at the end it resets to the top of the page.
How do I avoid this?
```ts
const url = new URL(targetUrl);
const browser = await launch({headless: false});
const page = await browser.newPage();
const flow = await new UserFlow(page);
const scrollAction = new ScrollAction(page);
await flow.navigate(url.href, { stepName: "Cold Initial Navigation" });
await flow.startTimespan({ stepName: 'Scroll To Bottom Of Page' } );
await scrollAction.swipeToPageBottom();
await flow.endTimespan();
await flow.startTimespan({ stepName: 'Scroll To Top Of Page' });
await scrollAction!.swipeToPageTop();
await flow.endTimespan();
const report = await flow.createFlowResult();
await browser.close();
```
and the scroll action
```ts
import { CDPSession, Page, Protocol } from "puppeteer";
export class ScrollAction {
private session?: CDPSession;
constructor(private page: Page) {}
async swipeToPageBottom(): Promise {
await this.page.waitForSelector("body");
await this._synthesizeTouchScroll('down');
}
async swipeToPageTop(): Promise {
await this.page.waitForSelector("body");
await this._synthesizeTouchScroll('up');
}
private async _synthesizeTouchScroll(direction: 'down' | 'up'): Promise {
const scrollParams = await this._getScrollParams(direction);
if (!this.session) {
this.session = await this.page.target().createCDPSession();
}
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await this.session.send('Input.synthesizeScrollGesture', scrollParams);
}
private async _getScrollParams(direction: 'down' | 'up'): Promise {
const innerHeight = await this._getInnerContentHeight();
const x = 200;
const y = direction === 'up' ? 200 : 600;
const scrollDistance = 1500;
const speed = 800;
const repeatDelayMs = 250;
const yDistance = direction === 'up' ? scrollDistance : scrollDistance * (-1);
const repeatCount = Math.ceil(innerHeight/scrollDistance) -1;
const gestureSourceType = 'touch';
return {x, y, yDistance, speed, repeatCount, repeatDelayMs, gestureSourceType};
}
private async _getInnerContentHeight(): Promise {
const innerContentHandle = await this.page.$("body");
const innerContentBox = await innerContentHandle!.boundingBox();
return innerContentBox!.height;
}
}
```
Now what is interesting is that if I remove the timestamp it works fine.
If I don't, its scrolls to the bottom and then appears at the top and tries to scroll from there.
What am I doing wrong or is it a config that I am missing?
Thanks so much in advance :)
Contributor guide
Research direction
Start with the Lighthouse user-flow entry points in the report: startTimespan(), endTimespan(), and createFlowResult(). Reproduce the supplied navigation and custom ScrollAction example, then trace how the timespan is handled around the scroll gesture. Done means the scroll sequence no longer resets to the top when wrapped in a timespan, with the behavior covered by an appropriate test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100