Skip to content

Instantly share code, notes, and snippets.

@isheraz
Last active September 30, 2020 08:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isheraz/40d3e849c9cc25014fa830d0f58b7da4 to your computer and use it in GitHub Desktop.
Save isheraz/40d3e849c9cc25014fa830d0f58b7da4 to your computer and use it in GitHub Desktop.
This is a library for basic browser operations needed in e2e testing
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)'
);
}
}
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