@v4fire/client
Version:
V4Fire client core library
201 lines (177 loc) • 4.66 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
import delay from 'delay';
import type { Page, ElementHandle } from 'playwright';
import DOM from 'tests/helpers/dom';
import type { ScrollToBottomWhileOptions } from 'tests/helpers/scroll/interface';
export * from 'tests/helpers/scroll/interface';
/**
* Class provides API to work with scroll on a page
*/
export default class Scroll {
/**
* Scrolls a page by the specified parameters
*
* @param page
* @param opts
*/
static scrollBy(page: Page, opts: ScrollToOptions): Promise<void> {
return page.evaluate((options) => globalThis.scrollBy(options), opts);
}
/**
* Scrolls a page to the specified parameters
*
* @param page
* @param opts
*/
static scrollTo(page: Page, opts: ScrollToOptions): Promise<void> {
return page.evaluate((options) => globalThis.scrollTo(options), opts);
}
/**
* Waits an element by the specified selector appear and scrolls a page to it if needed.
* Throws an error when `elementHandle` does not refer to an element connected to a document or shadow root.
*
* @param ctx
* @param selector
* @param [scrollIntoViewOpts]
*/
static async scrollIntoViewIfNeeded(
ctx: Page | ElementHandle,
selector: string,
scrollIntoViewOpts: Dictionary
): Promise<void> {
const el = await ctx.waitForSelector(selector);
return el.scrollIntoViewIfNeeded(scrollIntoViewOpts);
}
/**
* Waits a ref by the specified name appear and scrolls a page to it if needed.
* Throws an error when `elementHandle` does not refer to an element connected to a document or shadow root.
*
* @param ctx
* @param refName
* @param [scrollIntoViewOpts]
*/
static async scrollRefIntoViewIfNeeded(
ctx: Page | ElementHandle,
refName: string,
scrollIntoViewOpts: Dictionary
): Promise<void> {
const ref = await DOM.waitRef(ctx, refName);
return ref.scrollIntoViewIfNeeded(scrollIntoViewOpts);
}
/**
* @param page
* @param [options]
*/
static scrollToBottom(page: Page, options?: ScrollOptions): Promise<void> {
return this.scrollBy(page, {top: 1e7, left: 0, ...options});
}
/**
* @param page
* @param [options]
*/
static scrollToTop(page: Page, options?: ScrollOptions): Promise<void> {
return this.scrollTo(page, {top: 0, left: 0, ...options});
}
/**
* Scrolls a page until the passed function returns true, or until a time specified in` timeout` expires
*
* @param page
* @param [checkFn]
* @param [opts]
*/
static async scrollToBottomWhile(
page: Page,
checkFn?: () => CanPromise<boolean>,
opts?: ScrollToBottomWhileOptions
): Promise<void> {
const normalizedOptions = {
timeout: 1000,
tick: 100,
...opts
};
checkFn = checkFn ?? (() => false);
let
isDone = await checkFn(),
didTimeout = <boolean>false;
const
timeout = setTimeout(() => didTimeout = true, normalizedOptions.timeout);
if (isDone) {
return;
}
while (!isDone) {
if (didTimeout) {
return;
}
await this.scrollToBottom(page);
isDone = await checkFn();
await delay(normalizedOptions.tick);
}
clearTimeout(timeout);
}
/**
* @param ctx
* @param selector
* @param [scrollIntoViewOpts]
* @deprecated
* @see [[Scroll.scrollIntoViewIfNeeded]]
*/
async scrollIntoViewIfNeeded(
ctx: Page | ElementHandle,
selector: string,
scrollIntoViewOpts: Dictionary
): Promise<void> {
return Scroll.scrollRefIntoViewIfNeeded(ctx, selector, scrollIntoViewOpts);
}
/**
* @param ctx
* @param refName
* @param [scrollIntoViewOpts]
* @deprecated
* @see [[Scroll.scrollRefIntoViewIfNeeded]]
*/
async scrollRefIntoViewIfNeeded(
ctx: Page | ElementHandle,
refName: string,
scrollIntoViewOpts: Dictionary
): Promise<void> {
return Scroll.scrollRefIntoViewIfNeeded(ctx, refName, scrollIntoViewOpts);
}
/**
* @param page
* @param opts
* @deprecated
* @see [[Scroll.scrollBy]]
*/
scrollBy(page: Page, opts: ScrollToOptions): Promise<void> {
return Scroll.scrollBy(page, opts);
}
/**
* @param page
* @param [opts]
* @deprecated
* @see [[Scroll.scrollToBottom]]
*/
scrollToBottom(page: Page, opts?: ScrollOptions): Promise<void> {
return Scroll.scrollToBottom(page, opts);
}
/**
* @param page
* @param [checkFn]
* @param [opts]
* @deprecated
* @see [[Scroll.scrollToBottomWhile]]
*/
async scrollToBottomWhile(
page: Page,
checkFn?: () => CanPromise<boolean>,
opts?: ScrollToBottomWhileOptions
): Promise<void> {
return Scroll.scrollToBottomWhile(page, checkFn, opts);
}
}