Skip to content

Commit

Permalink
Adds isDisplayed, scrollIntoView and hover functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Grinberg authored Jan 9, 2019
2 parents 1a749f7 + 9bc352d commit 7810ff4
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ package-lock.json
/*.js
/*.d.ts
!wallaby.js
!protractor.conf.js
!protractor.conf.js
.idea
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "unidriver",
"version": "1.1.3",
"version": "2.0.0",
"description": "",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/wix-incubator/unidriver"
"type": "git",
"url": "https://github.com/wix-incubator/unidriver"
},
"scripts": {
"build": "rm -rf dist && (tsc -p . || true) && npm run build-testsuite && npm run expose-adapters",
"build-testsuite": "cp src/test-suite/index.ejs dist/test-suite/index.ejs && browserify dist/test-suite/app.js > dist/test-suite/bundle.js",
"testsuite-server": "node dist/test-suite/server.js",
"testsuite-server": "node -e 'require(\"./dist/test-suite/server.js\").startServer(3000)'",
"test": "bash support/test.sh",
"expose-adapters": "import-path --path lib --dts"
},
Expand All @@ -28,11 +28,9 @@
"@types/ejs": "^2.5.0",
"@types/express": "^4.11.0",
"@types/mocha": "^2.2.46",
"@types/protractor": "^4.0.0",
"@types/puppeteer": "^0.13.9",
"@types/puppeteer": "^1.11.1",
"@types/react": "^16.0.34",
"@types/react-dom": "^16.0.3",
"@types/selenium-webdriver": "^3.0.8",
"browserify": "^15.2.0",
"chai": "^4.1.2",
"chromedriver": "^2.38.3",
Expand All @@ -44,21 +42,23 @@
"jsdom-global": "^3.0.2",
"mocha": "^4.1.0",
"mocha-teamcity-reporter": "^2.4.0",
"puppeteer": "^1.3.0",
"puppeteer": "^1.11.0",
"react": "^15.2.0",
"react-dom": "^15.2.0",
"selenium-webdriver": "^4.0.0-alpha.1",
"selenium-webdriver": "^3.6.0",
"typescript": "^2.6.2"
},
"peerDependencies": {
"@types/puppeteer": "^0.13.9",
"@types/selenium-webdriver": "^3.0.8",
"@types/puppeteer": "^1.11.1",
"selenium-webdriver": "^3.6.0",
"puppeteer": "^0.13.0",
"puppeteer": "^1.11.0",
"protractor": "^5.4.1",
"react": "^15.2.0",
"react-test-utils": "0.0.1",
"react-dom": "^15.2.0"
},
"dependencies": {}
"dependencies": {
"protractor": "^5.4.2",
"react-test-utils": "0.0.1"
}
}
3 changes: 3 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ export type UniDriver<T = any> = {
$$: (selector: Locator) => UniDriverList;
text: () => Promise<string>;
click: () => Promise<void>;
hover: () => Promise<void>;
value: () => Promise<string>;
enterValue: (value: string) => Promise<void>;
attr: (name: string) => Promise<string>;
hasClass: (name: string) => Promise<boolean>;
exists: () => Promise<boolean>;
isDisplayed: () => Promise<boolean>;
wait: (timeout?: number) => Promise<void>;
type: string;
scrollIntoView: () => Promise<{}>;
getNative: () => Promise<T>;
};
24 changes: 19 additions & 5 deletions src/lib/protractor/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Locator, UniDriverList, UniDriver, MapFn} from '../';
import {ElementFinder} from 'protractor';
import {waitFor} from '../../utils';
import {browser, ElementFinder} from 'protractor';
import {waitFor} from '../../utils';

type ElementGetter = () => Promise<ElementFinder | null>;
type ElementsGetter = () => Promise<ElementFinder[]>;
Expand Down Expand Up @@ -82,11 +82,11 @@ export const protractorUniDriver = (
// done
$$: (selector: Locator) =>
protractorUniDriverList(async () => {
const elemement = await el();
if (!elemement) {
const element = await el();
if (!element) {
throw new Error(`Cannot find element`);
}
return elemement.$$(selector);
return element.$$(selector);
}),
text: async () => {
const text = await (await elem()).getAttribute('textContent');
Expand All @@ -95,6 +95,11 @@ export const protractorUniDriver = (
click: async () => {
return (await elem()).click();
},
hover: async () => {
const e = await elem();

return (await e.browser_.actions().mouseMove(e).perform());
},
hasClass: async (className: string) => {
const cm: any = await (await elem()).getAttribute('classList');
return cm.indexOf(className) !== -1;
Expand All @@ -105,6 +110,10 @@ export const protractorUniDriver = (
await e.type(value);
},
exists,
isDisplayed: async () => {
const e = await elem();
return e.isDisplayed();
},
value: async () => {
const value = await (await elem()).getAttribute('value');
return value || '';
Expand All @@ -117,6 +126,11 @@ export const protractorUniDriver = (
return waitFor(exists);
},
type: 'protractor',
scrollIntoView: async () => {
const el = await elem();

return browser.controlFlow().execute(() => browser.executeScript('arguments[0].scrollIntoView(true)', el.getWebElement()));
},
getNative: elem
};
};
15 changes: 14 additions & 1 deletion src/lib/puppeteer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,24 @@ export const pupUniDriver = (el: ElementGetter): UniDriver<ElementHandle> => {
click: async () => {
return (await elem()).click();
},
hover: async () => {
return (await elem()).hover();
},
hasClass: async (className: string) => {
const el = await elem();
const cm: any = await el.getProperty('classList');
return cm.indexOf(className) !== -1;
},
enterValue: async (value: string) => {
const e = await elem();
await e.focus()
await e.focus();
await e.type(value);
},
exists,
isDisplayed: async () => {
const e = await elem();
return e.isIntersectingViewport();
},
value: async () => {
const el = await elem();
const valueHandle = await el.getProperty('value');
Expand All @@ -118,6 +125,12 @@ export const pupUniDriver = (el: ElementGetter): UniDriver<ElementHandle> => {
return waitFor(exists);
},
type: 'puppeteer',
scrollIntoView: async () => {
const el = await elem();
await el.hover();

return {};
},
getNative: elem
};
};
26 changes: 13 additions & 13 deletions src/lib/puppeteer/spec.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import { runTestSuite } from '../../test-suite/spec';
import { runTestSuite } from '../../test-suite/spec';
import { startServer, getUrl } from '../../test-suite/server';
import * as puppeteer from 'puppeteer';
import { goAndWait } from '../../examples/utils';
import { pupUniDriver } from './index';
import { TodoAppSetupFn } from '../../test-suite';
import { Server } from 'http';
import { Browser } from 'puppeteer';
import * as puppeteer from 'puppeteer';
import { pupUniDriver } from './index';
import { TodoAppSetupFn } from '../../test-suite';
import { Server } from 'http';
import {Browser, Page} from 'puppeteer';

const port = 8082;

let server: Server;
let browser: Browser;
let page: Page;

const before = async () => {
const args = process.env.CI ? ['--no-sandbox'] : [];
const headless = process.env.CI ? true : false;
const headless = !!process.env.CI;
server = await startServer(port);
browser = await puppeteer.launch({headless,args});
page = await browser.newPage();
};

const after = async () => {
server.close();
await page.close();
await browser.close();
};

const setup: TodoAppSetupFn = async (data) => {

const page = await goAndWait(browser, `http://localhost:${port}${getUrl(data)}`);
await page.goto(`http://localhost:${port}${getUrl(data)}`);
const driver = pupUniDriver(() => page.$('body'));

const tearDown = async () => {
await page.close();
};
const tearDown = async () => { }

return {driver, tearDown};
}
Expand All @@ -42,7 +42,7 @@ describe('puppeteer', () => {
});


describe('pupeeter specific tests', () => {
describe('puppeteer specific tests', () => {



Expand Down
27 changes: 24 additions & 3 deletions src/lib/react/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UniDriverList, Locator, UniDriver } from '..';
import { Simulate } from 'react-dom/test-utils';
import { waitFor } from '../../utils';
import { Simulate } from 'react-dom/test-utils';
import { waitFor } from '../../utils';

const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));

Expand Down Expand Up @@ -93,7 +93,7 @@ export const reactUniDriver = (containerOrFn: ElementOrElementFinder): UniDriver
// setting button 0 is now needed in React 16+ as it's not set by react anymore
// 15 - https://github.com/facebook/react/blob/v15.6.1/src/renderers/dom/client/syntheticEvents/SyntheticMouseEvent.js#L45
// 16 - https://github.com/facebook/react/blob/master/packages/react-dom/src/events/SyntheticMouseEvent.js#L33

// native events are preferred, but they will only work in React if the element is part of the DOM
if (document.body.contains(el)) {
const event: any = document.createEvent('HTMLEvents');
Expand All @@ -104,6 +104,23 @@ export const reactUniDriver = (containerOrFn: ElementOrElementFinder): UniDriver
Simulate.click(el, {button: 0});
}
},
hover: async () => {
const el = await elem();

if (document.body.contains(el)) {
const mouseenter: any = document.createEvent('HTMLEvents');
const mouseover: any = document.createEvent('HTMLEvents');

mouseover.initEvent('mouseover', true, false);
mouseenter.initEvent('mouseenter', true, false);

el.dispatchEvent(mouseenter);
el.dispatchEvent(mouseover)
} else {
Simulate.mouseOver(el);
Simulate.mouseEnter(el);
}
},
hasClass: async (className: string) => (await elem()).classList.contains(className),
enterValue: async (value: string) => {
await wait(0);
Expand All @@ -115,10 +132,14 @@ export const reactUniDriver = (containerOrFn: ElementOrElementFinder): UniDriver
return (await elem()).getAttribute(name) || '';
},
exists,
isDisplayed: async () => {
return true;
},
wait: async () => {
return waitFor(exists);
},
type: 'react',
scrollIntoView: async () => { return {} },
getNative: () => elem()
};
};
2 changes: 1 addition & 1 deletion src/lib/react/spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { reactUniDriver } from './index';
import { TodoApp } from '../../test-suite/react-todoapp';
import { TodoAppSetupFn } from '../../test-suite/index';
import { TodoAppSetupFn } from '../../test-suite/';
import { runTestSuite } from '../../test-suite/spec';

const setup: TodoAppSetupFn = (data) => {
Expand Down
35 changes: 32 additions & 3 deletions src/lib/selenium/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Locator, UniDriverList, UniDriver, MapFn } from '..';
import { By, WebElement} from 'selenium-webdriver';
import { waitFor } from '../../utils';

import { By, WebElement} from 'selenium-webdriver';
import { waitFor } from '../../utils';

export type WebElementGetter = () => Promise<WebElement>;
export type WebElementsGetter = () => Promise<WebElement[]>;
Expand Down Expand Up @@ -85,6 +84,13 @@ export const seleniumUniDriver = (wep: WebElementGetter): UniDriver<WebElement>
return el.getAttribute('value');
},
click: async () => (await elem()).click(),
hover: async() => {
const el = await elem();
const driver = await el.getDriver();
const actions = await (driver as any).actions({bridge: true});

return await actions.mouseMove({x:1, y:1, origin: el}).perform();
},
hasClass: async (className: string) => {
const el = await elem();
const cl = await el.getAttribute('class');
Expand All @@ -94,10 +100,33 @@ export const seleniumUniDriver = (wep: WebElementGetter): UniDriver<WebElement>
(await elem()).sendKeys(value);
},
exists,
isDisplayed: async () => {
const el = await elem();

const retValue: boolean =
await el.getDriver().executeScript(
'const elem = arguments[0], ' +
' box = elem.getBoundingClientRect(), ' +
' cx = box.left + box.width / 2, ' +
' cy = box.top + box.height / 2, ' +
' e = document.elementFromPoint(cx, cy); ' +
' for (; e; e = e.parentElement) { ' +
' if ( e === elem) return true; ' +
' } ' +
'' +
' return false;', el);
return retValue;
},
wait: async () => {
return waitFor(exists);
},
type: 'selenium',
scrollIntoView: async () => {
const el = await elem();

//return el.getDriver().executeScript(`window.scrollTo(${location.x}, ${location.y});`);
return el.getDriver().executeScript('arguments[0].scrollIntoView();', el);
},
getNative: elem
};
};
Loading

0 comments on commit 7810ff4

Please sign in to comment.