import { Page } from 'puppeteer-core'; import { constants } from './constants'; import { PageObject } from './pageObjects'; export interface ExpectSelectorConfig { selector: string; containsText?: string; isVisible?: boolean; } export interface TestPageType { init: (page: Page) => Promise; getUrl: () => Promise; getUrlWithoutBaseUrl: () => Promise; navigateTo: () => Promise; expectSelector: (config: ExpectSelectorConfig) => Promise; waitForResponse: () => Promise; waitForNavigation: () => Promise; waitFor: (milliseconds: number) => Promise; pageObjects: PageObjects; } type PageObjects = { [P in keyof T]: T[P] }; export interface TestPageConfig { url?: string; pageObjects?: PageObjects; } export class TestPage implements TestPageType { pageObjects: PageObjects = null; private page: Page = null; private pageUrl: string = null; constructor(config: TestPageConfig) { if (config.url) { this.pageUrl = `${constants.baseUrl}${config.url}`; } if (config.pageObjects) { this.pageObjects = config.pageObjects; } } init = async (page: Page): Promise => { this.page = page; if (!this.pageObjects) { return; } Object.keys(this.pageObjects).forEach(key => { // @ts-ignore const pageObject: PageObject = this.pageObjects[key]; pageObject.init(page); }); }; navigateTo = async (): Promise => { this.throwIfNotInitialized(); console.log('Trying to navigate to:', this.pageUrl); await this.page.goto(this.pageUrl); }; expectSelector = async (config: ExpectSelectorConfig): Promise => { this.throwIfNotInitialized(); const { selector, containsText, isVisible } = config; const visible = isVisible || true; const text = containsText; const options = { visible, text } as any; await expect(this.page).toMatchElement(selector, options); }; waitForResponse = async (): Promise => { this.throwIfNotInitialized(); await this.page.waitForResponse(response => response.url() === this.pageUrl && response.status() === 200); }; waitForNavigation = async (): Promise => { this.throwIfNotInitialized(); await this.page.waitForNavigation(); }; getUrl = async (): Promise => { this.throwIfNotInitialized(); return await this.page.url(); }; getUrlWithoutBaseUrl = async (): Promise => { this.throwIfNotInitialized(); const url = await this.getUrl(); return url.replace(constants.baseUrl, ''); }; waitFor = async (milliseconds: number) => { this.throwIfNotInitialized(); await this.page.waitFor(milliseconds); }; private throwIfNotInitialized = () => { if (!this.page) { throw new Error('pageFactory has not been initilized, did you forget to call init with a page?'); } }; }