Skip to content

Commit

Permalink
FTR: fix WebDriver Actions calls (#44605) (#45111)
Browse files Browse the repository at this point in the history
* [services/web_element_wrapper] add actions API methods

* fixes

* [services/browser] fix dragAnDrop to work in both w3c/non-w3c modes

* small review changes

* dragAndDrop: add default values for offset
  • Loading branch information
dmlemeshko authored Sep 9, 2019
1 parent 815aa23 commit 07c89a0
Show file tree
Hide file tree
Showing 15 changed files with 148 additions and 143 deletions.
1 change: 0 additions & 1 deletion test/functional/apps/dashboard/dashboard_grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export default function ({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['dashboard']);

describe('dashboard grid', function () {
this.tags(['skipFirefox']);

before(async () => {
await PageObjects.dashboard.gotoDashboardLandingPage();
Expand Down
3 changes: 1 addition & 2 deletions test/functional/apps/dashboard/full_screen_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import expect from '@kbn/expect';

export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
const browser = getService('browser');
const dashboardPanelActions = getService('dashboardPanelActions');
const PageObjects = getPageObjects(['dashboard', 'common']);

Expand Down Expand Up @@ -69,7 +68,7 @@ export default function ({ getService, getPageObjects }) {

it('exits when the text button is clicked on', async () => {
const logoButton = await PageObjects.dashboard.getExitFullScreenLogoButton();
await browser.moveMouseTo(logoButton);
await logoButton.moveMouseTo();
await PageObjects.dashboard.clickExitFullScreenTextButton();

await retry.try(async () => {
Expand Down
2 changes: 1 addition & 1 deletion test/functional/apps/discover/_discover.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export default function ({ getService, getPageObjects }) {

const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours();
expect(Math.round(newDurationHours)).to.be(3);
const rowData = await PageObjects.discover.getDocTableIndex(1);
const rowData = await PageObjects.discover.getDocTableField(1);
expect(rowData).to.have.string('Sep 20, 2015 @ 02:51:53.327');
});

Expand Down
4 changes: 2 additions & 2 deletions test/functional/page_objects/common_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ export function CommonPageProvider({ getService, getPageObjects }) {
throw new Error('Toast is not visible yet');
}
});
await browser.moveMouseTo(toast);
await toast.moveMouseTo();
const title = await (await find.byCssSelector('.euiToastHeader__title')).getVisibleText();
log.debug(title);
await find.clickByCssSelector('.euiToast__closeButton');
Expand All @@ -378,7 +378,7 @@ export function CommonPageProvider({ getService, getPageObjects }) {
const toasts = await find.allByCssSelector('.euiToast');
for (const toastElement of toasts) {
try {
await browser.moveMouseTo(toastElement);
await toastElement.moveMouseTo();
const closeBtn = await toastElement.findByCssSelector('.euiToast__closeButton');
await closeBtn.click();
} catch (err) {
Expand Down
7 changes: 7 additions & 0 deletions test/functional/page_objects/discover_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
return await row.getVisibleText();
}

async getDocTableField(index) {
const field = await find.byCssSelector(
`tr.kbnDocTable__row:nth-child(${index}) > [data-test-subj='docTableField']`
);
return await field.getVisibleText();
}

async clickDocSortDown() {
await find.clickByCssSelector('.fa-sort-down');
}
Expand Down
2 changes: 1 addition & 1 deletion test/functional/page_objects/visualize_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
await retry.try(async () => {
const table = await testSubjects.find('tableVis');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
await browser.moveMouseTo(cell);
await cell.moveMouseTo();
const filterBtn = await testSubjects.findDescendant('filterForCellValue', cell);
await filterBtn.click();
});
Expand Down
165 changes: 54 additions & 111 deletions test/functional/services/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,49 +155,26 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
}

/**
* Moves the remote environment’s mouse cursor to the specified element or relative
* position.
* Moves the remote environment’s mouse cursor to the specified point {x, y} which is
* offset to browser page top left corner.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#move
*
* @param {WebElementWrapper} element Optional
* @param {number} xOffset Optional
* @param {number} yOffset Optional
* @param {x: number, y: number} point on browser page
* @return {Promise<void>}
*/
public async moveMouseTo(element: any, xOffset: number, yOffset: number): Promise<void>;
public async moveMouseTo(element: WebElementWrapper): Promise<void>;
public async moveMouseTo(
element: WebElementWrapper,
xOffset?: number,
yOffset?: number
): Promise<void> {
public async moveMouseTo(point: { x: number; y: number }): Promise<void> {
if (this.isW3CEnabled) {
// Workaround for scrolling bug in W3C mode: move pointer to { x: 0, y: 0 }
// https://github.com/mozilla/geckodriver/issues/776
await this.getActions()
.move({ x: 0, y: 0 })
.perform();
if (element instanceof WebElementWrapper) {
await this.getActions()
.move({ x: xOffset || 10, y: yOffset || 10, origin: element._webElement })
.perform();
} else {
await this.getActions()
.move({ origin: { x: xOffset, y: yOffset } })
.perform();
}
await this.getActions()
.move({ x: point.x, y: point.y, origin: 'pointer' })
.perform();
} else {
if (element instanceof WebElementWrapper) {
await this.getActions()
.pause(this.getActions().mouse)
.move({ origin: element._webElement })
.perform();
} else {
await this.getActions()
.pause(this.getActions().mouse)
.move({ origin: { x: xOffset, y: yOffset } })
.perform();
}
await this.getActions()
.pause(this.getActions().mouse)
.move({ x: point.x, y: point.y, origin: 'pointer' })
.perform();
}
}

Expand All @@ -213,70 +190,47 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
from: { offset: { x: any; y: any }; location: any },
to: { offset: { x: any; y: any }; location: any }
) {
// tslint:disable-next-line:variable-name
let _from;
// tslint:disable-next-line:variable-name
let _to;
// tslint:disable-next-line:variable-name
const _fromOffset = from.offset
? { x: from.offset.x || 0, y: from.offset.y || 0 }
: { x: 0, y: 0 };
// tslint:disable-next-line:variable-name
const _toOffset = to.offset ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 };
// tslint:disable-next-line:variable-name
const _convertPointW3C = async (point: any, offset: { x: any; y: any }) => {
if (point.location instanceof WebElementWrapper) {
const position = await point.location.getPosition();
return {
x: Math.round(position.x + offset.x),
y: Math.round(position.y + offset.y),
};
} else {
return {
x: Math.round(point.location.x + offset.x),
y: Math.round(point.location.y + offset.y),
};
}
};
// tslint:disable-next-line:variable-name
const _convertPoint = (point: any) => {
return point.location instanceof WebElementWrapper
? point.location._webElement
: point.location;
};

if (this.isW3CEnabled) {
// tslint:disable-next-line:variable-name
_from = await _convertPointW3C(from, _fromOffset);
// tslint:disable-next-line:variable-name
_to = await _convertPointW3C(to, _toOffset);
// tslint:disable-next-line:variable-name
const _offset = { x: _to.x - _from.x, y: _to.y - _from.y };
// The offset should be specified in pixels relative to the center of the element's bounding box
const getW3CPoint = (data: any) => {
if (!data.offset) {
data.offset = {};
}
return data.location instanceof WebElementWrapper
? { x: data.offset.x || 0, y: data.offset.y || 0, origin: data.location._webElement }
: { x: data.location.x, y: data.location.y, origin: 'pointer' };
};

const startPoint = getW3CPoint(from);
const endPoint = getW3CPoint(to);
await this.getActions()
.move({ x: 0, y: 0 })
.perform();
return await this.getActions()
.move({ x: _from.x, y: _from.y, origin: 'pointer' })
.move(startPoint)
.press()
.move({ x: _offset.x, y: _offset.y, origin: 'pointer' })
.move(endPoint)
.release()
.perform();
} else {
// until Chromedriver is not supporting W3C Webdriver Actions API
// tslint:disable-next-line:variable-name
_from = _convertPoint(from);
// tslint:disable-next-line:variable-name
_to = _convertPoint(to);
if (from.location instanceof WebElementWrapper && typeof to.location.x === 'number') {
// The offset should be specified in pixels relative to the top-left corner of the element's bounding box
const getOffset: any = (offset: { x: number; y: number }) =>
offset ? { x: offset.x || 0, y: offset.y || 0 } : { x: 0, y: 0 };

if (from.location instanceof WebElementWrapper === false) {
throw new Error('Dragging point should be WebElementWrapper instance');
} else if (typeof to.location.x === 'number') {
return await this.getActions()
.move({ origin: _from })
.move({ origin: from.location._webElement })
.press()
.move({ x: _to.x, y: _to.y, origin: 'pointer' })
.move({ x: to.location.x, y: to.location.y, origin: 'pointer' })
.release()
.perform();
} else {
return await new LegacyActionSequence(driver)
.mouseMove(_from, _fromOffset)
.mouseMove(from.location._webElement, getOffset(from.offset))
.mouseDown()
.mouseMove(_to, _toOffset)
.mouseMove(to.location._webElement, getOffset(to.offset))
.mouseUp()
.perform();
}
Expand Down Expand Up @@ -320,34 +274,29 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
}

/**
* Inserts an action for moving the mouse x and y pixels relative to the specified origin.
* The origin may be defined as the mouse's current position, the viewport, or the center
* of a specific WebElement. Then adds an action for left-click (down/up) with the mouse.
* Moves the remote environment’s mouse cursor to the specified point {x, y} which is
* offset to browser page top left corner.
* Then adds an action for left-click (down/up) with the mouse.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#click
*
* @param {WebElementWrapper} element Optional
* @param {number} xOffset Optional
* @param {number} yOffset Optional
* @param {x: number, y: number} point on browser page
* @return {Promise<void>}
*/
public async clickMouseButton(element: any, xOffset: number, yOffset: number): Promise<void>;
public async clickMouseButton(element: WebElementWrapper): Promise<void>;
public async clickMouseButton(...args: unknown[]): Promise<void> {
const arg0 = args[0];
if (arg0 instanceof WebElementWrapper) {
public async clickMouseButton(point: { x: number; y: number }): Promise<void> {
if (this.isW3CEnabled) {
await this.getActions()
.pause(this.getActions().mouse)
.move({ origin: arg0._webElement })
.move({ x: 0, y: 0 })
.perform();
await this.getActions()
.move({ x: point.x, y: point.y, origin: 'pointer' })
.click()
.perform();
} else if (isNaN(args[1] as number) || isNaN(args[2] as number) === false) {
} else {
await this.getActions()
.pause(this.getActions().mouse)
.move({ origin: { x: args[1], y: args[2] } })
.move({ x: point.x, y: point.y, origin: 'pointer' })
.click()
.perform();
} else {
throw new Error('Element or coordinates should be provided');
}
}

Expand Down Expand Up @@ -378,16 +327,10 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
* @param {WebElementWrapper} element
* @return {Promise<void>}
*/
public async doubleClick(element?: WebElementWrapper): Promise<void> {
if (element instanceof WebElementWrapper) {
await this.getActions()
.doubleClick(element._webElement)
.perform();
} else {
await this.getActions()
.doubleClick()
.perform();
}
public async doubleClick(): Promise<void> {
await this.getActions()
.doubleClick()
.perform();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/functional/services/combo_box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
}

private async clickOption(isMouseClick: boolean, element: WebElementWrapper) {
return isMouseClick ? await browser.clickMouseButton(element) : await element.click();
return isMouseClick ? await element.clickMouseButton() : await element.click();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion test/functional/services/dashboard/panel_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
// Sometimes Geckodriver throws MoveTargetOutOfBoundsError here
// https://github.com/mozilla/geckodriver/issues/776
try {
await (parent ? browser.moveMouseTo(parent) : testSubjects.moveMouseTo('dashboardPanelTitle'));
await (parent ? parent.moveMouseTo() : testSubjects.moveMouseTo('dashboardPanelTitle'));
} catch(err) {
log.error(err);
}
Expand Down
5 changes: 2 additions & 3 deletions test/functional/services/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import expect from '@kbn/expect';
export function InspectorProvider({ getService }) {
const log = getService('log');
const retry = getService('retry');
const browser = getService('browser');
const renderable = getService('renderable');
const flyout = getService('flyout');
const testSubjects = getService('testSubjects');
Expand Down Expand Up @@ -132,7 +131,7 @@ export function InspectorProvider({ getService }) {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
await browser.moveMouseTo(cell);
await cell.moveMouseTo();
const filterBtn = await testSubjects.findDescendant('filterForInspectorCellValue', cell);
await filterBtn.click();
});
Expand All @@ -143,7 +142,7 @@ export function InspectorProvider({ getService }) {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
await browser.moveMouseTo(cell);
await cell.moveMouseTo();
const filterBtn = await testSubjects.findDescendant('filterOutInspectorCellValue', cell);
await filterBtn.click();
});
Expand Down
Loading

0 comments on commit 07c89a0

Please sign in to comment.