Last active
September 30, 2020 08:32
-
-
Save isheraz/40d3e849c9cc25014fa830d0f58b7da4 to your computer and use it in GitHub Desktop.
This is a library for basic browser operations needed in e2e testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Builder, | |
ThenableWebDriver, | |
By, | |
WebElementPromise, | |
Key, | |
WebElement, | |
Locator, | |
until | |
} from 'selenium-webdriver'; | |
import * as remote from 'selenium-webdriver/remote'; | |
import { Options } from 'selenium-webdriver/firefox'; | |
import { WaitCondition, elementIsVisible } from '.'; | |
import { SERVER_URL, LOCAL_BROWSER } from '../constants'; | |
import { delay } from './utils'; | |
import { WebComponent } from './components'; | |
export class Browser { | |
private driver: ThenableWebDriver; | |
private env: string; | |
public constructor(private browserName: any, env: string) { | |
this.env = env; | |
if (env === 'dev') { | |
// eslint-disable-next-line no-param-reassign | |
browserName['browserstack.local'] = true; | |
} | |
if (env === 'local') { | |
this.driver = new Builder().forBrowser(LOCAL_BROWSER).build(); | |
} else { | |
this.driver = new Builder() | |
.usingServer(`${SERVER_URL}`) | |
.withCapabilities(browserName) | |
.build(); | |
} | |
this.driver.setFileDetector(new remote.FileDetector()); | |
} | |
public waitUntilElementVisible(selector: string) { | |
if (selector.startsWith('//')) { | |
return this.driver.wait( | |
until.elementLocated(By.xpath(`${selector}`)), | |
20000 | |
); | |
} | |
return this.driver.wait(until.elementLocated(By.css(`${selector}`)), 20000); | |
} | |
public async refresh() { | |
await (await this.driver).navigate().refresh(); | |
} | |
public async navigate(url: string): Promise<void> { | |
await this.driver.navigate().to(url); | |
} | |
public async executeScript(js: string): Promise<void> { | |
await this.driver.executeScript(js); | |
} | |
public async setDownloadAbleBrowser() { | |
await (await this.driver).close(); | |
if (this.env === 'dev') { | |
// eslint-disable-next-line no-param-reassign | |
this.browserName['browserstack.local'] = true; | |
} | |
if (this.env === 'local') { | |
this.driver = new Builder() | |
.forBrowser(LOCAL_BROWSER) | |
.withCapabilities(this.downloadFileFirefox()) | |
.build(); | |
} else { | |
this.driver = new Builder() | |
.usingServer(`${SERVER_URL}`) | |
.withCapabilities(this.browserName) | |
.withCapabilities(this.downloadFileFirefox()) | |
.build(); | |
} | |
this.driver.setFileDetector(new remote.FileDetector()); | |
} | |
public async getUrl() { | |
return await (await this.driver).getCurrentUrl(); | |
} | |
public findElement(selector: string): WebElementPromise { | |
if (selector.startsWith('//')) { | |
return this.driver.findElement(By.xpath(selector)); | |
} | |
return this.driver.findElement(By.css(selector)); | |
} | |
public nativeFindElement(locator: Locator): WebElementPromise { | |
return this.driver.findElement(locator); | |
} | |
public async ctrlAction(action: string) { | |
return this.driver | |
.actions() | |
.sendKeys(Key.CONTROL) | |
.sendKeys(action) | |
.perform(); | |
} | |
public async typeToFocused(text: string) { | |
return this.driver | |
.actions() | |
.sendKeys(text) | |
.perform(); | |
} | |
public async findIframeElement(iframe: string, selector: string) { | |
const frame = await this.driver.findElement(By.xpath(iframe)); | |
await this.driver.switchTo().frame(frame); | |
const element = await this.driver.findElement(By.xpath(selector)); | |
return element; | |
} | |
public async findInIframeByXPath(iframe: string, selector: string) { | |
const frame = await this.driver.findElement(By.css(iframe)); | |
await this.driver.switchTo().frame(frame); | |
await delay(4000); | |
const element = await this.driver.findElement(By.xpath(selector)); | |
return element; | |
} | |
public async findInIframeByCss(iframe: string, selector: string) { | |
const frame = await this.driver.findElement(By.xpath(iframe)); | |
await this.driver.switchTo().frame(frame); | |
await delay(2000); | |
await this.wait( | |
elementIsVisible( | |
() => new WebComponent(this.driver.findElement(By.css(selector)), '') | |
) | |
); | |
const element = await this.driver.findElement(By.css(selector)); | |
return element; | |
} | |
public async switchDefault() { | |
(await this.driver).switchTo().defaultContent(); | |
} | |
public downloadFileFirefox() { | |
const saveTo = `${process.env.INIT_CWD}/e2e/`; | |
const downloadOptions: Options = new Options(); | |
downloadOptions.setPreference('browser.download.folderList', 2); | |
downloadOptions.setPreference( | |
'browser.download.manager.showWhenStarting', | |
false | |
); | |
downloadOptions.setPreference('browser.download.manager.useWindow', false); | |
downloadOptions.setPreference('browser.download.useDownloadDir', true); | |
downloadOptions.setPreference('browser.download.dir', saveTo); | |
downloadOptions.setPreference( | |
'browser.helperApps.neverAsk.saveToDisk', | |
'application/pdf, text/csv' | |
); | |
downloadOptions.setPreference('pdfjs.disabled', true); | |
return downloadOptions; | |
} | |
public async getAllOpenedWindows() { | |
const openedTabs: Array<string> = await ( | |
await this.driver | |
).getAllWindowHandles(); | |
return openedTabs; | |
} | |
public async switchToTab(tabId: string) { | |
await (await this.driver).switchTo().window(tabId); | |
} | |
public async openNewTab(url: string) { | |
console.log('here'); | |
await this.driver.executeScript(`window.open('${url}');`); | |
} | |
public async clearCookies(url?: string): Promise<void> { | |
if (url) { | |
const currentUrl = await this.driver.getCurrentUrl(); | |
await this.navigate(url); | |
await (await this.driver).manage().deleteAllCookies(); | |
await this.navigate(currentUrl); | |
} else { | |
await (await this.driver).manage().deleteAllCookies(); | |
} | |
} | |
public async addTextIframeElement( | |
selector: string, | |
frameSelector: string, | |
random: string | |
) { | |
const editorFrame = await this.driver.findElement(By.css(selector)); | |
await this.driver.switchTo().frame(editorFrame); | |
const tinymce = await this.driver.findElement(By.css(frameSelector)); | |
await tinymce.sendKeys(random); | |
(await this.driver).switchTo().defaultContent(); | |
} | |
public async wait(condition: WaitCondition, timeout = 0) { | |
await this.waitAny(condition, timeout); | |
} | |
public async waitAny( | |
conditions: WaitCondition | WaitCondition[], | |
timeout = 0 | |
): Promise<void> { | |
const all = !(conditions instanceof Array) ? [conditions] : conditions; | |
await this.driver.wait(async () => { | |
for (const condition of all) { | |
try { | |
// eslint-disable-next-line no-await-in-loop | |
if ((await condition(this)) === true) { | |
return true; | |
} | |
continue; | |
} catch (ex) { | |
continue; | |
} | |
} | |
}, timeout || 120000); | |
} | |
public async close(): Promise<void> { | |
await this.driver.quit(); | |
} | |
public async implicitWait(ms: number) { | |
await this.driver.sleep(ms); | |
} | |
public findElements(selector: string): Promise<WebElement[]> { | |
if (selector.startsWith('//')) { | |
return this.driver.findElements(By.xpath(selector)); | |
} | |
return this.driver.findElements(By.css(selector)); | |
} | |
public findElementByClassName(className: string): Promise<WebElement> { | |
return this.driver.findElement(By.className(className)); | |
} | |
public async switchTo(frame: WebElement) { | |
await this.driver.switchTo().frame(frame); | |
} | |
public async scrollDown() { | |
await this.driver.executeScript( | |
'window.scrollTo(0, document.body.scrollHeight)' | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Browser, WebComponent, NewablePage, Page } from '.'; | |
export type WaitCondition = (browser: Browser) => Promise<boolean>; | |
export function elementIsVisible(locator: () => WebComponent): WaitCondition { | |
return async () => await locator().isDisplayed(); | |
} | |
export function elementIsNotVisible( | |
locator: () => WebComponent | |
): WaitCondition { | |
return async () => !(await locator().isDisplayed()); | |
} | |
export function buttonIsEnabled(locator: () => WebComponent): WaitCondition { | |
return async () => await locator().isEnabled(); | |
} | |
export function elementIsPresent(locator: () => WebComponent): WaitCondition { | |
return async () => (await locator()) !== undefined; | |
} | |
export function elementHasTextValue( | |
locator: () => WebComponent | |
): WaitCondition { | |
return async () => (await locator().getValue()) !== ''; | |
} | |
export function elementTextIs( | |
locator: () => WebComponent, | |
text: string | |
): WaitCondition { | |
return async () => (await locator().getValue()) === text; | |
} | |
export function elementIncludeText( | |
locator: () => WebComponent, | |
text: string | |
): WaitCondition { | |
return async () => (await locator().getValue()).includes(text); | |
} | |
export function pageHasLoaded<T extends Page>( | |
Page: NewablePage<T> | |
): WaitCondition { | |
return (browser: Browser) => { | |
const condition = new Page(browser).loadCondition(); | |
return condition(browser); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment