Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/webapi/appendField.mustache
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
Appends text to a input field or textarea.
Field is located by name, label, CSS or XPath

The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.appendField('#myTextField', 'appended');
// typing secret
I.appendField('password', secret('123456'));
// within a context
I.appendField('name', 'John', '.form-container');
```
@param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator
@param {string} value text value to append.
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
@returns {void} automatically synchronized promise through #recorder
5 changes: 5 additions & 0 deletions docs/webapi/attachFile.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ Attaches a file to element located by label, name, CSS or XPath
Path to file is relative current codecept directory (where codecept.conf.ts or codecept.conf.js is located).
File will be uploaded to remote system (if tests are running remotely).

The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.attachFile('Avatar', 'data/avatar.jpg');
I.attachFile('form input[name=avatar]', 'data/avatar.jpg');
// within a context
I.attachFile('Avatar', 'data/avatar.jpg', '.form-container');
```

@param {CodeceptJS.LocatorOrString} locator field located by label|name|CSS|XPath|strict locator.
@param {string} pathToFile local file path relative to codecept.conf.ts or codecept.conf.js config file.
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
@returns {void} automatically synchronized promise through #recorder
2 changes: 1 addition & 1 deletion docs/webapi/checkOption.mustache
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Selects a checkbox or radio button.
Element is located by label or name or CSS or XPath.

The second parameter is a context (CSS or XPath locator) to narrow the search.
The second parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.checkOption('#agree');
Expand Down
5 changes: 5 additions & 0 deletions docs/webapi/clearField.mustache
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
Clears a `<textarea>` or text `<input>` element's value.

The second parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.clearField('Email');
I.clearField('user[email]');
I.clearField('#email');
// within a context
I.clearField('Email', '.form-container');
```
@param {LocatorOrString} editable field located by label|name|CSS|XPath|strict locator.
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
@returns {void} automatically synchronized promise through #recorder.
5 changes: 5 additions & 0 deletions docs/webapi/dontSeeInField.mustache
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
Checks that value of input field or textarea doesn't equal to given value
Opposite to `seeInField`.

The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.dontSeeInField('email', 'user@user.com'); // field by name
I.dontSeeInField({ css: 'form input.email' }, 'user@user.com'); // field by CSS
// within a context
I.dontSeeInField('Name', 'old_value', '.form-container');
```

@param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
@param {CodeceptJS.StringOrSecret} value value to check.
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
@returns {void} automatically synchronized promise through #recorder
2 changes: 1 addition & 1 deletion docs/webapi/fillField.mustache
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Fills a text field or textarea, after clearing its value, with the given string.
Field is located by name, label, CSS, or XPath.

The third parameter is a context (CSS or XPath locator) to narrow the search.
The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
// by label
Expand Down
5 changes: 5 additions & 0 deletions docs/webapi/seeInField.mustache
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
Checks that the given input field or textarea equals to given value.
For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath.

The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.seeInField('Username', 'davert');
I.seeInField({css: 'form textarea'},'Type your comment here');
I.seeInField('form input[type=hidden]','hidden_value');
I.seeInField('#searchform input','Search');
// within a context
I.seeInField('Name', 'John', '.form-container');
```
@param {CodeceptJS.LocatorOrString} field located by label|name|CSS|XPath|strict locator.
@param {CodeceptJS.StringOrSecret} value value to check.
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
@returns {void} automatically synchronized promise through #recorder
2 changes: 1 addition & 1 deletion docs/webapi/selectOption.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Selects an option in a drop-down select.
Field is searched by label | name | CSS | XPath.
Option is selected by visible text or by value.

The third parameter is a context (CSS or XPath locator) to narrow the search.
The third parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.selectOption('Choose Plan', 'Monthly'); // select by label
Expand Down
2 changes: 1 addition & 1 deletion docs/webapi/uncheckOption.mustache
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Unselects a checkbox or radio button.
Element is located by label or name or CSS or XPath.

The second parameter is a context (CSS or XPath locator) to narrow the search.
The second parameter is an optional context (CSS or XPath locator) to narrow the search.

```js
I.uncheckOption('#agree');
Expand Down
40 changes: 13 additions & 27 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -2278,24 +2278,10 @@ class Playwright extends Helper {
}

/**
* Clears the text input element: `<input>`, `<textarea>` or `[contenteditable]` .
*
*
* Examples:
*
* ```js
* I.clearField('.text-area')
*
* // if this doesn't work use force option
* I.clearField('#submit', { force: true })
* ```
* Use `force` to bypass the [actionability](https://playwright.dev/docs/actionability) checks.
*
* @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-clear) for available options object as 2nd argument.
* {{> clearField }}
*/
async clearField(locator, options = {}) {
const els = await findFields.call(this, locator)
async clearField(locator, context = null) {
const els = await findFields.call(this, locator, context)
assertElementExists(els, locator, 'Field to clear')
if (this.options.strict) assertOnlyOneElement(els, locator)

Expand All @@ -2311,8 +2297,8 @@ class Playwright extends Helper {
/**
* {{> appendField }}
*/
async appendField(field, value) {
const els = await findFields.call(this, field)
async appendField(field, value, context = null) {
const els = await findFields.call(this, field, context)
assertElementExists(els, field, 'Field')
if (this.options.strict) assertOnlyOneElement(els, field)
await highlightActiveElement.call(this, els[0])
Expand All @@ -2324,30 +2310,30 @@ class Playwright extends Helper {
/**
* {{> seeInField }}
*/
async seeInField(field, value) {
async seeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeInField.call(this, 'assert', field, _value)
return proceedSeeInField.call(this, 'assert', field, _value, context)
}

/**
* {{> dontSeeInField }}
*/
async dontSeeInField(field, value) {
async dontSeeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeInField.call(this, 'negate', field, _value)
return proceedSeeInField.call(this, 'negate', field, _value, context)
}

/**
* {{> attachFile }}
*
*/
async attachFile(locator, pathToFile) {
async attachFile(locator, pathToFile, context = null) {
const file = path.join(global.codecept_dir, pathToFile)

if (!fileExists(file)) {
throw new Error(`File at ${file} can not be found on local system`)
}
const els = await findFields.call(this, locator)
const els = await findFields.call(this, locator, context)
assertElementExists(els, locator, 'Field')
await els[0].setInputFiles(file)
return this._waitForAction()
Expand Down Expand Up @@ -4487,8 +4473,8 @@ async function proceedSelect(context, el, option) {
return this._waitForAction()
}

async function proceedSeeInField(assertType, field, value) {
const els = await findFields.call(this, field)
async function proceedSeeInField(assertType, field, value, context) {
const els = await findFields.call(this, field, context)
assertElementExists(els, field, 'Field')
const el = els[0]
const tag = await el.evaluate(e => e.tagName)
Expand Down
24 changes: 12 additions & 12 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1580,17 +1580,17 @@ class Puppeteer extends Helper {
/**
* {{> clearField }}
*/
async clearField(field) {
return this.fillField(field, '')
async clearField(field, context = null) {
return this.fillField(field, '', context)
}

/**
* {{> appendField }}
*
* {{ react }}
*/
async appendField(field, value) {
const els = await findVisibleFields.call(this, field)
async appendField(field, value, context = null) {
const els = await findVisibleFields.call(this, field, context)
assertElementExists(els, field, 'Field')
highlightActiveElement.call(this, els[0], await this._getContext())
await els[0].press('End')
Expand All @@ -1601,31 +1601,31 @@ class Puppeteer extends Helper {
/**
* {{> seeInField }}
*/
async seeInField(field, value) {
async seeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeInField.call(this, 'assert', field, _value)
return proceedSeeInField.call(this, 'assert', field, _value, context)
}

/**
* {{> dontSeeInField }}
*/
async dontSeeInField(field, value) {
async dontSeeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeInField.call(this, 'negate', field, _value)
return proceedSeeInField.call(this, 'negate', field, _value, context)
}

/**
* > ⚠ There is an [issue with file upload in Puppeteer 2.1.0 & 2.1.1](https://github.com/puppeteer/puppeteer/issues/5420), downgrade to 2.0.0 if you face it.
*
* {{> attachFile }}
*/
async attachFile(locator, pathToFile) {
async attachFile(locator, pathToFile, context = null) {
const file = path.join(global.codecept_dir, pathToFile)

if (!fileExists(file)) {
throw new Error(`File at ${file} can not be found on local system`)
}
const els = await findFields.call(this, locator)
const els = await findFields.call(this, locator, context)
assertElementExists(els, locator, 'Field')
await els[0].uploadFile(file)
return this._waitForAction()
Expand Down Expand Up @@ -3286,8 +3286,8 @@ async function proceedDragAndDrop(sourceLocator, destinationLocator) {
await this._waitForAction()
}

async function proceedSeeInField(assertType, field, value) {
const els = await findVisibleFields.call(this, field)
async function proceedSeeInField(assertType, field, value, context) {
const els = await findVisibleFields.call(this, field, context)
assertElementExists(els, field, 'Field')
const el = els[0]
const tag = await el.getProperty('tagName').then(el => el.jsonValue())
Expand Down
24 changes: 12 additions & 12 deletions lib/helper/WebDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -1289,8 +1289,8 @@ class WebDriver extends Helper {
* {{> appendField }}
* {{ react }}
*/
async appendField(field, value) {
const res = await findFields.call(this, field)
async appendField(field, value, context = null) {
const res = await findFields.call(this, field, context)
assertElementExists(res, field, 'Field')
const elem = usingFirstElement(res)
highlightActiveElement.call(this, elem)
Expand All @@ -1301,8 +1301,8 @@ class WebDriver extends Helper {
* {{> clearField }}
*
*/
async clearField(field) {
const res = await findFields.call(this, field)
async clearField(field, context = null) {
const res = await findFields.call(this, field, context)
assertElementExists(res, field, 'Field')
const elem = usingFirstElement(res)
highlightActiveElement.call(this, elem)
Expand Down Expand Up @@ -1344,13 +1344,13 @@ class WebDriver extends Helper {
*
* {{> attachFile }}
*/
async attachFile(locator, pathToFile) {
async attachFile(locator, pathToFile, context = null) {
let file = path.join(global.codecept_dir, pathToFile)
if (!fileExists(file)) {
throw new Error(`File at ${file} can not be found on local system`)
}

const res = await findFields.call(this, locator)
const res = await findFields.call(this, locator, context)
this.debug(`Uploading ${file}`)
assertElementExists(res, locator, 'File field')
const el = usingFirstElement(res)
Expand Down Expand Up @@ -1598,18 +1598,18 @@ class WebDriver extends Helper {
* {{> seeInField }}
*
*/
async seeInField(field, value) {
async seeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeField.call(this, 'assert', field, _value)
return proceedSeeField.call(this, 'assert', field, _value, context)
}

/**
* {{> dontSeeInField }}
*
*/
async dontSeeInField(field, value) {
async dontSeeInField(field, value, context = null) {
const _value = typeof value === 'boolean' ? value : value.toString()
return proceedSeeField.call(this, 'negate', field, _value)
return proceedSeeField.call(this, 'negate', field, _value, context)
}

/**
Expand Down Expand Up @@ -3075,8 +3075,8 @@ async function findFields(locator, context = null) {
return await locateFn(locator.value) // by css or xpath
}

async function proceedSeeField(assertType, field, value) {
const res = await findFields.call(this, field)
async function proceedSeeField(assertType, field, value, context) {
const res = await findFields.call(this, field, context)
assertElementExists(res, field, 'Field')
const elem = usingFirstElement(res)
const elemId = getElementId(elem)
Expand Down
8 changes: 6 additions & 2 deletions test/data/app/view/form/context.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
<body>
<div id="area1">
<label for="name1">Name</label>
<input type="text" id="name1" name="name" value="" />
<input type="text" id="name1" name="name" value="old1" />
<select name="age" id="age1">
<option value="child">below 13</option>
<option value="teenage">13-21</option>
<option value="adult">21-60</option>
</select>
<label for="file1">Avatar</label>
<input type="file" id="file1" name="avatar" />
<button type="button">Submit</button>
</div>
<div id="area2">
<label for="name2">Name</label>
<input type="text" id="name2" name="name" value="" />
<input type="text" id="name2" name="name" value="old2" />
<select name="age" id="age2">
<option value="child">below 13</option>
<option value="teenage">13-21</option>
<option value="adult">21-60</option>
</select>
<label for="file2">Avatar</label>
<input type="file" id="file2" name="avatar" />
<span class="unique-element">Only here</span>
</div>
</body>
Expand Down
Loading