Skip to content

Commit

Permalink
feat: screenshot viewport with assertView by default (#988)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kabir-Ivan authored Aug 12, 2024
1 parent e464af3 commit 9e5959e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 5 deletions.
29 changes: 28 additions & 1 deletion docs/writing-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,23 @@ it('some test', async ({ browser }) => {
});
```

With skipped `selector` parameter, assertView will take a screenshot of the current viewport. Example:

```js
it('some test', async ({ browser }) => {
await browser.url('some/url');
// Scroll 1000 px down
await browser.execute(() => window.scrollTo(0, 1000));
// Screen the viewport
await browser.assertView('plain');

// Click the button
await browser.$('.button').click();
// Screen the viewport with custom options
await browser.assertView('clicked', { ignoreDiffPixelCount: 5 });
});
```

Could also be used as element's method:

```js
Expand All @@ -300,7 +317,17 @@ it('some test', async ({ browser }) => {
Parameters:

- state (required) `String` – state name; should be unique within one test
- selector (required) `String|String[]` – DOM-node selector that you need to capture
- selector (optional, can be skipped) `String|String[]` – DOM-node selector that you need to capture. If not specified or skipped, will be set to `body` and the following options will be automatically added to opts:
```
{
allowViewportOverflow: true,
compositeImage: false,
captureElementFromTop: false
}
```

So, assertView without `selector` parameter will take a screenshot of the current viewport.

- opts (optional) `Object`:
- ignoreElements (optional) `String|String[]` – elements, matching specified selectors will be ignored when comparing images
- tolerance (optional) `Number` – overrides config [browsers](#browsers).[tolerance](#tolerance) value
Expand Down
31 changes: 28 additions & 3 deletions src/browser/commands/assert-view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,43 @@ module.exports.default = browser => {
testplaneCtx.assertViewResults.add({ stateName: state, refImg: refImg });
};

session.addCommand("assertView", async function (state, selectors, opts = {}) {
const waitSelectorsForExist = async (browser, selectors) => {
await Promise.map([].concat(selectors), async selector => {
await this.$(selector)
await browser
.$(selector)
.then(el => el.waitForExist())
.catch(() => {
throw new Error(
`element ("${selector}") still not existing after ${this.options.waitforTimeout} ms`,
`element ("${selector}") still not existing after ${browser.options.waitforTimeout} ms`,
);
});
});
};

const assertViewBySelector = async (browser, state, selectors, opts) => {
await waitSelectorsForExist(browser, selectors);

return assertView(state, selectors, opts);
};

const assertViewByViewport = async (state, opts) => {
opts = _.defaults(opts, {
allowViewportOverflow: true,
compositeImage: false,
captureElementFromTop: false,
});

return assertView(state, "body", opts);
};

const shouldAssertViewport = selectorsOrOpts => {
return !(typeof selectorsOrOpts === "string" || _.isArray(selectorsOrOpts));
};

session.addCommand("assertView", async function (state, selectorsOrOpts, opts = {}) {
return shouldAssertViewport(selectorsOrOpts)
? assertViewByViewport(state, selectorsOrOpts || opts)
: assertViewBySelector(this, state, selectorsOrOpts, opts);
});

session.addCommand(
Expand Down
10 changes: 9 additions & 1 deletion src/browser/commands/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,21 @@ export interface AssertViewOpts extends Partial<AssertViewOptsConfig> {
ignoreDiffPixelCount?: `${number}%` | number;
}

export type AssertViewCommand = (
export type AssertViewCommandWithSelector = (
this: WebdriverIO.Browser,
state: string,
selectors: string | string[],
opts?: AssertViewOpts,
) => Promise<void>;

export type AssertViewCommandWithoutSelector = (
this: WebdriverIO.Browser,
state: string,
opts?: AssertViewOpts,
) => Promise<void>;

export type AssertViewCommand = AssertViewCommandWithSelector & AssertViewCommandWithoutSelector;

export type AssertViewElementCommand = (
this: WebdriverIO.Element | ChainablePromiseElement<WebdriverIO.Element>,
state: string,
Expand Down
33 changes: 33 additions & 0 deletions test/src/browser/commands/assert-view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,39 @@ describe("assertView command", () => {
assert.calledOnceWith(browser.prepareScreenshot, [".selector1", ".selector2"]);
});

it("should screenshot the viewport if selector is not provided", async () => {
const browser = await initBrowser_();

await browser.publicAPI.assertView("plain");

assert.calledOnceWith(
browser.prepareScreenshot,
["body"],
sinon.match({
allowViewportOverflow: true,
captureElementFromTop: false,
}),
);
});

it("should add custom options if selector is not provided", async () => {
const browser = await initBrowser_();

await browser.publicAPI.assertView("plain", {
disableAnimation: false,
});

assert.calledOnceWith(
browser.prepareScreenshot,
["body"],
sinon.match({
allowViewportOverflow: true,
captureElementFromTop: false,
disableAnimation: false,
}),
);
});

[
{ scope: "browser", fn: assertViewBrowser },
{ scope: "element", fn: assertViewElement },
Expand Down

0 comments on commit 9e5959e

Please sign in to comment.