Skip to content

Commit

Permalink
feat: blur and focus for other helpers (#3737)
Browse files Browse the repository at this point in the history
  • Loading branch information
kobenguyent authored Jul 7, 2023
1 parent 8251920 commit bd2f7e0
Show file tree
Hide file tree
Showing 15 changed files with 719 additions and 414 deletions.
198 changes: 104 additions & 94 deletions docs/helpers/Playwright.md

Large diffs are not rendered by default.

250 changes: 148 additions & 102 deletions docs/helpers/Puppeteer.md

Large diffs are not rendered by default.

144 changes: 95 additions & 49 deletions docs/helpers/TestCafe.md

Large diffs are not rendered by default.

254 changes: 150 additions & 104 deletions docs/helpers/WebDriver.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions docs/webapi/blur.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Remove focus from a text input, button, etc.
Calls [blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the element.

Examples:

```js
I.blur('.text-area')
```
```js
//element `#product-tile` is focused
I.see('#add-to-cart-btn');
I.blur('#product-tile')
I.dontSee('#add-to-cart-btn');
```

@param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
@param {any} [options] Playwright only: [Additional options](https://playwright.dev/docs/api/class-locator#locator-blur) for available options object as 2nd argument.
12 changes: 12 additions & 0 deletions docs/webapi/focus.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the matching element.

Examples:

```js
I.dontSee('#add-to-cart-btn');
I.focus('#product-tile')
I.see('#add-to-cart-bnt');
```

@param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
@param {any} [options] Playwright only: [Additional options](https://playwright.dev/docs/api/class-locator#locator-focus) for available options object as 2nd argument.
29 changes: 2 additions & 27 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -908,17 +908,7 @@ class Playwright extends Helper {
}

/**
* Calls [focus](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on the matching element.
* @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
* @param {any} [options] [Additional options](https://playwright.dev/docs/api/class-locator#locator-focus) for available options object as 2nd argument.
*
* Examples:
*
* ```js
* I.dontSee('#add-to-cart-btn');
* I.focus('#product-tile')
* I.see('#add-to-cart-bnt');
* ```
* {{> focus }}
*
*/
async focus(locator, options = {}) {
Expand All @@ -931,22 +921,7 @@ class Playwright extends Helper {
}

/**
* Remove focus from a text input, button, etc
* Calls [blur](https://playwright.dev/docs/api/class-locator#locator-blur) on the element.
* @param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
* @param {any} [options] [Additional options](https://playwright.dev/docs/api/class-locator#locator-blur) for available options object as 2nd argument.
*
* Examples:
*
* ```js
* I.blur('.text-area')
* ```
* ```js
* //element `#product-tile` is focused
* I.see('#add-to-cart-btn');
* I.blur('#product-tile')
* I.dontSee('#add-to-cart-btn');
* ```
* {{> blur }}
*
*/
async blur(locator, options = {}) {
Expand Down
27 changes: 27 additions & 0 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const Popup = require('./extras/Popup');
const Console = require('./extras/Console');
const findReact = require('./extras/React');
const { highlightElement } = require('./scripts/highlightElement');
const { blurElement } = require('./scripts/blurElement');
const { focusElement } = require('./scripts/focusElement');

let puppeteer;
let perfTiming;
Expand Down Expand Up @@ -707,6 +709,31 @@ class Puppeteer extends Helper {
return this._waitForAction();
}

/**
* {{> focus }}
*
*/
async focus(locator) {
const els = await this._locate(locator);
assertElementExists(els, locator, 'Element to focus');
const el = els[0];

await focusElement(el, this.page);
return this._waitForAction();
}

/**
* {{> blur }}
*
*/
async blur(locator) {
const els = await this._locate(locator);
assertElementExists(els, locator, 'Element to blur');

await blurElement(els[0], this.page);
return this._waitForAction();
}

/**
* {{> dragAndDrop }}
*/
Expand Down
30 changes: 29 additions & 1 deletion lib/helper/TestCafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,34 @@ class TestCafe extends Helper {
return this.t.resizeWindow(width, height).catch(mapError);
}

/**
* {{> focus }}
*
*/
async focus(locator) {
const els = await this._locate(locator);
await assertElementExists(els, locator, 'Element to focus');
const element = await els.nth(0);

const focusElement = ClientFunction(() => element().focus(), { boundTestRun: this.t, dependencies: { element } });

return focusElement();
}

/**
* {{> blur }}
*
*/
async blur(locator) {
const els = await this._locate(locator);
await assertElementExists(els, locator, 'Element to blur');
const element = await els.nth(0);

const blurElement = ClientFunction(() => element().blur(), { boundTestRun: this.t, dependencies: { element } });

return blurElement();
}

/**
* {{> click }}
*
Expand Down Expand Up @@ -792,7 +820,7 @@ class TestCafe extends Helper {
/**
* {{> executeScript }}
*
* If a function returns a Promise It will wait for it resolution.
* If a function returns a Promise It will wait for its resolution.
*/
async executeScript(fn, ...args) {
const browserFn = createClientFunction(fn, args).with({ boundTestRun: this.t });
Expand Down
26 changes: 26 additions & 0 deletions lib/helper/WebDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const ConnectionRefused = require('./errors/ConnectionRefused');
const Locator = require('../locator');
const { highlightElement } = require('./scripts/highlightElement');
const store = require('../store');
const { focusElement } = require('./scripts/focusElement');
const { blurElement } = require('./scripts/blurElement');

const SHADOW = 'shadow';
const webRoot = 'body';
Expand Down Expand Up @@ -1934,6 +1936,30 @@ class WebDriver extends Helper {
}
}

/**
* {{> focus }}
*
*/
async focus(locator) {
const els = await this._locate(locator);
assertElementExists(els, locator, 'Element to focus');
const el = usingFirstElement(els);

await focusElement(el, this.browser);
}

/**
* {{> blur }}
*
*/
async blur(locator) {
const els = await this._locate(locator);
assertElementExists(els, locator, 'Element to blur');
const el = usingFirstElement(els);

await blurElement(el, this.browser);
}

/**
* {{> dragAndDrop }}
* Appium: not tested
Expand Down
17 changes: 17 additions & 0 deletions lib/helper/scripts/blurElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports.blurElement = (element, context) => {
const clientSideBlurFn = el => {
el.blur();
};

try {
// Puppeteer
context.evaluate(clientSideBlurFn, element);
} catch (e) {
// WebDriver
try {
context.execute(clientSideBlurFn, element);
} catch (err) {
// ignore
}
}
};
17 changes: 17 additions & 0 deletions lib/helper/scripts/focusElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports.focusElement = (element, context) => {
const clientSideFn = el => {
el.focus();
};

try {
// Puppeteer
context.evaluate(clientSideFn, element);
} catch (e) {
// WebDriver
try {
context.execute(clientSideFn, element);
} catch (err) {
// ignore
}
}
};
37 changes: 0 additions & 37 deletions test/helper/Playwright_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,43 +184,6 @@ describe('Playwright', function () {
.then(() => I.dontSee('Hovered', '#show')));
});

describe('#focus, #blur', () => {
it('should focus a button, field and textarea', async () => {
await I.amOnPage('/form/focus_blur_elements');

await I.focus('#button');
await I.see('Button is focused', '#buttonMessage');

await I.focus('#field');
await I.see('Button not focused', '#buttonMessage');
await I.see('Input field is focused', '#fieldMessage');

await I.focus('#textarea');
await I.see('Button not focused', '#buttonMessage');
await I.see('Input field not focused', '#fieldMessage');
await I.see('Textarea is focused', '#textareaMessage');
});

it('should blur focused button, field and textarea', async () => {
await I.amOnPage('/form/focus_blur_elements');

await I.focus('#button');
await I.see('Button is focused', '#buttonMessage');
await I.blur('#button');
await I.see('Button not focused', '#buttonMessage');

await I.focus('#field');
await I.see('Input field is focused', '#fieldMessage');
await I.blur('#field');
await I.see('Input field not focused', '#fieldMessage');

await I.focus('#textarea');
await I.see('Textarea is focused', '#textareaMessage');
await I.blur('#textarea');
await I.see('Textarea not focused', '#textareaMessage');
});
});

describe('#switchToNextTab, #switchToPreviousTab, #openNewTab, #closeCurrentTab, #closeOtherTabs, #grabNumberOfOpenTabs', () => {
it('should only have 1 tab open when the browser starts and navigates to the first page', () => I.amOnPage('/')
.then(() => I.wait(1))
Expand Down
39 changes: 39 additions & 0 deletions test/helper/webapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -1491,4 +1491,43 @@ module.exports.tests = function () {
await I.see('Step Two Button');
});
});

describe('#focus, #blur', () => {
it('should focus a button, field and textarea', async () => {
if (isHelper('Nightmare')) return;
await I.amOnPage('/form/focus_blur_elements');

await I.focus('#button');
await I.see('Button is focused', '#buttonMessage');

await I.focus('#field');
await I.see('Button not focused', '#buttonMessage');
await I.see('Input field is focused', '#fieldMessage');

await I.focus('#textarea');
await I.see('Button not focused', '#buttonMessage');
await I.see('Input field not focused', '#fieldMessage');
await I.see('Textarea is focused', '#textareaMessage');
});

it('should blur focused button, field and textarea', async () => {
if (isHelper('Nightmare')) return;
await I.amOnPage('/form/focus_blur_elements');

await I.focus('#button');
await I.see('Button is focused', '#buttonMessage');
await I.blur('#button');
await I.see('Button not focused', '#buttonMessage');

await I.focus('#field');
await I.see('Input field is focused', '#fieldMessage');
await I.blur('#field');
await I.see('Input field not focused', '#fieldMessage');

await I.focus('#textarea');
await I.see('Textarea is focused', '#textareaMessage');
await I.blur('#textarea');
await I.see('Textarea not focused', '#textareaMessage');
});
});
};
36 changes: 36 additions & 0 deletions typings/tests/helpers/WebDriverIO.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,42 @@ const num = 1;
wd.amOnPage(); // $ExpectError
wd.amOnPage(''); // $ExpectType void

wd.focus(); // $ExpectError
wd.focus('div'); // $ExpectType void
wd.focus({ css: 'div' });
wd.focus({ xpath: '//div' });
wd.focus({ name: 'div' });
wd.focus({ id: 'div' });
wd.focus({ android: 'div' });
wd.focus({ ios: 'div' });
wd.focus(locate('div'));
wd.focus('div', 'body');
wd.focus('div', locate('div'));
wd.focus('div', { css: 'div' });
wd.focus('div', { xpath: '//div' });
wd.focus('div', { name: '//div' });
wd.focus('div', { id: '//div' });
wd.focus('div', { android: '//div' });
wd.focus('div', { ios: '//div' });

wd.blur(); // $ExpectError
wd.blur('div'); // $ExpectType void
wd.blur({ css: 'div' });
wd.blur({ xpath: '//div' });
wd.blur({ name: 'div' });
wd.blur({ id: 'div' });
wd.blur({ android: 'div' });
wd.blur({ ios: 'div' });
wd.blur(locate('div'));
wd.blur('div', 'body');
wd.blur('div', locate('div'));
wd.blur('div', { css: 'div' });
wd.blur('div', { xpath: '//div' });
wd.blur('div', { name: '//div' });
wd.blur('div', { id: '//div' });
wd.blur('div', { android: '//div' });
wd.blur('div', { ios: '//div' });

wd.click(); // $ExpectError
wd.click('div'); // $ExpectType void
wd.click({ css: 'div' });
Expand Down

0 comments on commit bd2f7e0

Please sign in to comment.