Skip to content

Commit

Permalink
element screenshot method added (#2521)
Browse files Browse the repository at this point in the history
  • Loading branch information
suniljaiswal01 authored Aug 4, 2020
1 parent 8bc6cf9 commit 7e354b7
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 6 deletions.
42 changes: 42 additions & 0 deletions docs/helpers/Nightmare.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,34 @@ console.log(`Current URL is [${url}]`);
Returns **[Promise][8]<[string][3]>** current URL
### grabElementBoundingRect
Grab the width, height, location of given locator.
Provide `width` or `height`as second param to get your desired prop.
Resumes test execution, so **should be used inside an async function with `await`** operator.
Returns an object with `x`, `y`, `width`, `height` keys.
```js
const value = await I.grabElementBoundingRect('h3');
// value is like { x: 226.5, y: 89, width: 527, height: 220 }
```
To get only one metric use second parameter:
```js
const width = await I.grabElementBoundingRect('h3', 'width');
// width == 527
```
#### Parameters
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
- `prop`
- `elementSize` **[string][3]** x, y, width or height of the given element.
Returns **[object][4]** Element bounding rectangle
### grabHAR
Get HAR
Expand Down Expand Up @@ -637,6 +665,20 @@ I.rightClick('Click me', '.context');
- `locator` **([string][3] | [object][4])** clickable element located by CSS|XPath|strict locator.
- `context` **([string][3]? | [object][4])** (optional, `null` by default) element located by CSS|XPath|strict locator.
### saveElementScreenshot
Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.
```js
I.saveElementScreenshot(`#submit`,'debug.png');
```
#### Parameters
- `locator` **([string][3] | [object][4])** element located by CSS|XPath|strict locator.
- `fileName` **[string][3]** file name to save.
### saveScreenshot
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
14 changes: 14 additions & 0 deletions docs/helpers/Playwright.md
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,20 @@ I.rightClick('Click me', '.context');
- `locator` **([string][7] | [object][5])** clickable element located by CSS|XPath|strict locator.
- `context` **([string][7]? | [object][5])** (optional, `null` by default) element located by CSS|XPath|strict locator.

### saveElementScreenshot

Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.

```js
I.saveElementScreenshot(`#submit`,'debug.png');
```

#### Parameters

- `locator` **([string][7] | [object][5])** element located by CSS|XPath|strict locator.
- `fileName` **[string][7]** file name to save.

### saveScreenshot

Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
14 changes: 14 additions & 0 deletions docs/helpers/Protractor.md
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,20 @@ I.rightClick('Click me', '.context');
- `locator` **([string][9] | [object][10])** clickable element located by CSS|XPath|strict locator.
- `context` **([string][9]? | [object][10])** (optional, `null` by default) element located by CSS|XPath|strict locator.
### saveElementScreenshot
Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.
```js
I.saveElementScreenshot(`#submit`,'debug.png');
```
#### Parameters
- `locator` **([string][9] | [object][10])** element located by CSS|XPath|strict locator.
- `fileName` **[string][9]** file name to save.
### saveScreenshot
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
16 changes: 15 additions & 1 deletion docs/helpers/Puppeteer.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This helper should be configured in codecept.json or codecept.conf.js
- `waitForAction`: (optional) how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
- `waitForNavigation`: . When to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API][3]. Array values are accepted as well.
- `pressKeyDelay`: . Delay between key presses in ms. Used when calling Puppeteers page.type(...) in fillField/appendField
- `getPageTimeout` config option to set maximum navigation time in milliseconds.
- `getPageTimeout` config option to set maximum navigation time in milliseconds. If the timeout is set to 0, then timeout will be disabled.
- `waitForTimeout`: (optional) default wait* timeout in ms. Default: 1000.
- `windowSize`: (optional) default window size. Set a dimension like `640x480`.
- `userAgent`: (optional) user-agent string.
Expand Down Expand Up @@ -1194,6 +1194,20 @@ I.rightClick('Click me', '.context');
This action supports [React locators](https://codecept.io/react#locators)
### saveElementScreenshot
Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.
```js
I.saveElementScreenshot(`#submit`,'debug.png');
```
#### Parameters
- `locator` **([string][8] | [object][6])** element located by CSS|XPath|strict locator.
- `fileName` **[string][8]** file name to save.
### saveScreenshot
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
14 changes: 14 additions & 0 deletions docs/helpers/TestCafe.md
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,20 @@ I.rightClick('Click me', '.context');
- `locator` **([string][4] | [object][5])** clickable element located by CSS|XPath|strict locator.
- `context` **([string][4]? | [object][5])** (optional, `null` by default) element located by CSS|XPath|strict locator.

### saveElementScreenshot

Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.

```js
I.saveElementScreenshot(`#submit`,'debug.png');
```

#### Parameters

- `locator` **([string][4] | [object][5])** element located by CSS|XPath|strict locator.
- `fileName` **[string][4]** file name to save.

### saveScreenshot

Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
35 changes: 30 additions & 5 deletions docs/helpers/WebDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -913,18 +913,29 @@ This action supports [React locators](https://codecept.io/react#locators)
### forceRightClick
{{> forceRightClick }}
Emulates right click on an element.
Unlike normal click instead of sending native event, emulates a click with JavaScript.
This works on hidden, animated or inactive elements as well.
If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
For buttons, the "value" attribute, "name" attribute, and inner text are searched. For links, the link text is searched.
For images, the "alt" attribute and inner text of any parent links are searched.
The second parameter is a context (CSS or XPath locator) to narrow the search.
```js
// simple link
I.forceRightClick('Menu');
```
This action supports [React locators](https://codecept.io/react#locators)
#### Parameters
- `locator` **([string][19] | [object][18])** clickable link or button located by text, or any element located by CSS|XPath|strict locator.
- `context` **([string][19]? | [object][18])** (optional, `null` by default) element to search in CSS|XPath|Strict locator.
#### Parameters
- `locator`
- `context`
This action supports [React locators](https://codecept.io/react#locators)
### grabAllWindowHandles
Expand Down Expand Up @@ -1368,6 +1379,20 @@ Placeholder for ~ locator only test case write once run on both Appium and WebDr
- `caps`
- `fn`
### saveElementScreenshot
Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.
```js
I.saveElementScreenshot(`#submit`,'debug.png');
```
#### Parameters
- `locator` **([string][19] | [object][18])** element located by CSS|XPath|strict locator.
- `fileName` **[string][19]** file name to save.
### saveScreenshot
Saves a screenshot to ouput folder (set in codecept.json or codecept.conf.js).
Expand Down
9 changes: 9 additions & 0 deletions docs/webapi/saveElementScreenshot.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Saves screenshot of the specified locator to ouput folder (set in codecept.json or codecept.conf.js).
Filename is relative to output folder.

```js
I.saveElementScreenshot(`#submit`,'debug.png');
```

@param {string|object} locator element located by CSS|XPath|strict locator.
@param {string} fileName file name to save.
52 changes: 52 additions & 0 deletions lib/helper/Nightmare.js
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,58 @@ class Nightmare extends Helper {
return this.browser.refresh();
}

/**
* {{> saveElementScreenshot }}
*
*/
async saveElementScreenshot(locator, fileName) {

const outputFile = screenshotOutputFolder(fileName);

const rect = await this.grabElementBoundingRect(locator);

const button_clip = {
x: Math.floor(rect.x),
y: Math.floor(rect.y),
width: Math.floor(rect.width),
height: Math.floor(rect.height)
}

this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
// take the screenshot
await this.browser.screenshot(outputFile, button_clip)
}

/**
* {{> grabElementBoundingRect }}
*/
async grabElementBoundingRect(locator, prop) {

locator = new Locator(locator, 'css');

const rect = await this.browser.evaluate(async (by, locator) => {

// store the button in a variable

const build_cluster_btn = await window.codeceptjs.findElement(by, locator);

// use the getClientRects() function on the button to determine
// the size and location
const rect = build_cluster_btn.getBoundingClientRect();

// convert the rectangle to a clip object and return it
return {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height
};
}, locator.type, locator.value);

if (prop) return rect[prop];
return rect;
}

/**
* {{> saveScreenshot }}
*/
Expand Down
16 changes: 16 additions & 0 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,22 @@ class Playwright extends Helper {
return array.length === 1 ? array[0] : array;
}

/**
* {{> saveElementScreenshot }}
*
*/
async saveElementScreenshot(locator, fileName) {

const outputFile = screenshotOutputFolder(fileName);

const res = await this._locate(locator);
assertElementExists(res, locator);
if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
const elem = res[0];
this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
return elem.screenshot({ path: outputFile, type: 'png' });
}

/**
* {{> saveScreenshot }}
*/
Expand Down
26 changes: 26 additions & 0 deletions lib/helper/Protractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,32 @@ class Protractor extends Helper {
return this.browser.getCurrentUrl().then(currentUrl => urlEquals(this.options.url).negate(url, currentUrl));
}

/**
* {{> saveElementScreenshot }}
*
*/
async saveElementScreenshot(locator, fileName) {

const outputFile = screenshotOutputFolder(fileName);

const writeFile = (png, outputFile) => {
const fs = require('fs');
const stream = fs.createWriteStream(outputFile);
stream.write(Buffer.from(png, 'base64'));
stream.end();
return new Promise(resolve => stream.on('finish', resolve));
};

const res = await this._locate(locator);
assertElementExists(res, locator);
if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
const elem = res[0];
this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
const png = await elem.takeScreenshot();
return writeFile(png, outputFile);

}

/**
* {{> saveScreenshot }}
*/
Expand Down
16 changes: 16 additions & 0 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,22 @@ class Puppeteer extends Helper {
return array.length === 1 ? array[0] : array;
}

/**
* {{> saveElementScreenshot }}
*
*/
async saveElementScreenshot(locator, fileName) {

const outputFile = screenshotOutputFolder(fileName);

const res = await this._locate(locator);
assertElementExists(res, locator);
if (res.length > 1) this.debug(`[Elements] Using first element out of ${res.length}`);
const elem = res[0];
this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
return elem.screenshot({ path: outputFile, type: 'png' });
}

/**
* {{> saveScreenshot }}
*/
Expand Down
17 changes: 17 additions & 0 deletions lib/helper/TestCafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,23 @@ class TestCafe extends Helper {
stringIncludes('HTML source of a page').negate(text, source);
}

/**
* {{> saveElementScreenshot }}
*
*/
async saveElementScreenshot(locator, fileName) {

const outputFile = path.join(global.output_dir, fileName);

const sel = await findElements.call(this, this.context, locator);
assertElementExists(sel);
const firstElement = await sel.filterVisible().nth(0);

this.debug(`Screenshot of ${locator} element has been saved to ${outputFile}`);
return this.t.takeElementScreenshot(firstElement,fileName);
}


/**
* {{> saveScreenshot }}
*/
Expand Down
Loading

0 comments on commit 7e354b7

Please sign in to comment.