@cloudscape-design/browser-test-tools 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +21 -0
- package/browser.d.ts +1 -0
- package/browser.js +1 -0
- package/chrome-launcher.d.ts +1 -0
- package/chrome-launcher.js +1 -0
- package/dist/browser-scripts/events-spy.d.ts +8 -0
- package/dist/browser-scripts/events-spy.js +27 -0
- package/dist/browser-scripts/index.d.ts +3 -0
- package/dist/browser-scripts/index.js +21 -0
- package/dist/browser-scripts/scroll.d.ts +10 -0
- package/dist/browser-scripts/scroll.js +45 -0
- package/dist/browser-scripts/sizes.d.ts +3 -0
- package/dist/browser-scripts/sizes.js +33 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +40 -0
- package/dist/browsers/browser-creator.d.ts +21 -0
- package/dist/browsers/browser-creator.js +66 -0
- package/dist/browsers/browserstack.d.ts +21 -0
- package/dist/browsers/browserstack.js +138 -0
- package/dist/browsers/capabilities.d.ts +4 -0
- package/dist/browsers/capabilities.js +84 -0
- package/dist/browsers/devicefarm-mobile.d.ts +8 -0
- package/dist/browsers/devicefarm-mobile.js +33 -0
- package/dist/browsers/devicefarm.d.ts +15 -0
- package/dist/browsers/devicefarm.js +78 -0
- package/dist/browsers/index.d.ts +4 -0
- package/dist/browsers/index.js +16 -0
- package/dist/browsers/local.d.ts +8 -0
- package/dist/browsers/local.js +76 -0
- package/dist/chrome-launcher.d.ts +2 -0
- package/dist/chrome-launcher.js +52 -0
- package/dist/exceptions.d.ts +17 -0
- package/dist/exceptions.js +48 -0
- package/dist/image-utils/compare.d.ts +10 -0
- package/dist/image-utils/compare.js +68 -0
- package/dist/image-utils/crop.d.ts +5 -0
- package/dist/image-utils/crop.js +21 -0
- package/dist/image-utils/index.d.ts +3 -0
- package/dist/image-utils/index.js +11 -0
- package/dist/image-utils/merge.d.ts +1 -0
- package/dist/image-utils/merge.js +23 -0
- package/dist/image-utils/utils.d.ts +7 -0
- package/dist/image-utils/utils.js +59 -0
- package/dist/page-objects/base.d.ts +76 -0
- package/dist/page-objects/base.js +186 -0
- package/dist/page-objects/browser-scripts.d.ts +1 -0
- package/dist/page-objects/browser-scripts.js +11 -0
- package/dist/page-objects/events-spy.d.ts +10 -0
- package/dist/page-objects/events-spy.js +22 -0
- package/dist/page-objects/full-page-screenshot.d.ts +2 -0
- package/dist/page-objects/full-page-screenshot.js +66 -0
- package/dist/page-objects/index.d.ts +4 -0
- package/dist/page-objects/index.js +14 -0
- package/dist/page-objects/screenshot.d.ts +10 -0
- package/dist/page-objects/screenshot.js +57 -0
- package/dist/page-objects/types.d.ts +27 -0
- package/dist/page-objects/types.js +2 -0
- package/dist/page-objects/utils.d.ts +8 -0
- package/dist/page-objects/utils.js +72 -0
- package/dist/use-browser.d.ts +15 -0
- package/dist/use-browser.js +50 -0
- package/image-utils.d.ts +1 -0
- package/image-utils.js +1 -0
- package/package.json +63 -0
- package/page-objects.d.ts +1 -0
- package/page-objects.js +1 -0
- package/use-browser.d.ts +1 -0
- package/use-browser.js +1 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cropAndCompare = void 0;
|
|
7
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
8
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
const pngjs_1 = require("pngjs");
|
|
10
|
+
const pixelmatch_1 = __importDefault(require("pixelmatch"));
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
function compareImages(firstImage, secondImage, { width, height }) {
|
|
13
|
+
// fast path when two image files are identical
|
|
14
|
+
if (firstImage.data.equals(secondImage.data)) {
|
|
15
|
+
return { diffPixels: 0, diffImage: null };
|
|
16
|
+
}
|
|
17
|
+
const diffImage = new pngjs_1.PNG({ width, height });
|
|
18
|
+
const diffPixels = (0, pixelmatch_1.default)(firstImage.data, secondImage.data, diffImage.data, width, height, { threshold: 0.01 });
|
|
19
|
+
return { diffPixels, diffImage };
|
|
20
|
+
}
|
|
21
|
+
function normalizeSize(firstScreenshot, secondScreenshot) {
|
|
22
|
+
return {
|
|
23
|
+
height: Math.round(Math.max(firstScreenshot.height, secondScreenshot.height)),
|
|
24
|
+
width: Math.round(Math.max(firstScreenshot.width, secondScreenshot.width)),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function scaleSize(size, pixelRatio) {
|
|
28
|
+
return {
|
|
29
|
+
width: Math.ceil(size.width * pixelRatio),
|
|
30
|
+
height: Math.ceil(size.height * pixelRatio),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function cropAndCompare(firstScreenshot, secondScreenshot) {
|
|
34
|
+
const pixelRatio = firstScreenshot.pixelRatio || 1;
|
|
35
|
+
const size = normalizeSize(firstScreenshot, secondScreenshot);
|
|
36
|
+
const firstImageCropRect = {
|
|
37
|
+
height: size.height,
|
|
38
|
+
width: size.width,
|
|
39
|
+
bottom: firstScreenshot.offset.top + size.height,
|
|
40
|
+
right: firstScreenshot.offset.left + size.width,
|
|
41
|
+
top: firstScreenshot.offset.top,
|
|
42
|
+
left: firstScreenshot.offset.left,
|
|
43
|
+
};
|
|
44
|
+
const secondImageCropRect = {
|
|
45
|
+
height: size.height,
|
|
46
|
+
width: size.width,
|
|
47
|
+
bottom: secondScreenshot.offset.top + size.height,
|
|
48
|
+
right: secondScreenshot.offset.left + size.width,
|
|
49
|
+
top: secondScreenshot.offset.top,
|
|
50
|
+
left: secondScreenshot.offset.left,
|
|
51
|
+
};
|
|
52
|
+
const firstImage = (0, utils_1.cropImage)(firstScreenshot.image, firstImageCropRect, pixelRatio);
|
|
53
|
+
const secondImage = (0, utils_1.cropImage)(secondScreenshot.image, secondImageCropRect, pixelRatio);
|
|
54
|
+
const { diffImage, diffPixels } = compareImages(firstImage, secondImage, scaleSize(size, pixelRatio));
|
|
55
|
+
const [firstPacked, secondPacked, diffPacked] = await Promise.all([
|
|
56
|
+
(0, utils_1.packPng)(firstImage),
|
|
57
|
+
(0, utils_1.packPng)(secondImage),
|
|
58
|
+
diffImage && (0, utils_1.packPng)(diffImage),
|
|
59
|
+
]);
|
|
60
|
+
return {
|
|
61
|
+
firstImage: firstPacked,
|
|
62
|
+
secondImage: secondPacked,
|
|
63
|
+
diffImage: diffPacked,
|
|
64
|
+
isEqual: diffPixels <= 1,
|
|
65
|
+
diffPixels,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.cropAndCompare = cropAndCompare;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PNG } from 'pngjs';
|
|
3
|
+
import { ElementOffset, ElementRect } from '../page-objects/types';
|
|
4
|
+
export declare function cropByOffset(encodedImage: PNG, offset: ElementOffset): Promise<Buffer>;
|
|
5
|
+
export declare function cropByRect(encodedImage: PNG, rect: ElementRect): Promise<Buffer>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cropByRect = exports.cropByOffset = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
async function cropByOffset(encodedImage, offset) {
|
|
6
|
+
const rect = {
|
|
7
|
+
top: offset.top,
|
|
8
|
+
left: offset.left,
|
|
9
|
+
bottom: encodedImage.height,
|
|
10
|
+
right: encodedImage.width,
|
|
11
|
+
height: encodedImage.height - offset.top,
|
|
12
|
+
width: encodedImage.width - offset.left,
|
|
13
|
+
};
|
|
14
|
+
return cropByRect(encodedImage, rect);
|
|
15
|
+
}
|
|
16
|
+
exports.cropByOffset = cropByOffset;
|
|
17
|
+
async function cropByRect(encodedImage, rect) {
|
|
18
|
+
const image = await (0, utils_1.cropImage)(encodedImage, rect);
|
|
19
|
+
return (0, utils_1.packPng)(image);
|
|
20
|
+
}
|
|
21
|
+
exports.cropByRect = cropByRect;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parsePng = exports.cropByOffset = exports.cropAndCompare = void 0;
|
|
4
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
var compare_1 = require("./compare");
|
|
7
|
+
Object.defineProperty(exports, "cropAndCompare", { enumerable: true, get: function () { return compare_1.cropAndCompare; } });
|
|
8
|
+
var crop_1 = require("./crop");
|
|
9
|
+
Object.defineProperty(exports, "cropByOffset", { enumerable: true, get: function () { return crop_1.cropByOffset; } });
|
|
10
|
+
var utils_1 = require("./utils");
|
|
11
|
+
Object.defineProperty(exports, "parsePng", { enumerable: true, get: function () { return utils_1.parsePng; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function mergeImages(images: string[], width: number, height: number, lastImageOffset: number, offsetTop: number): Promise<string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
const pngjs_1 = require("pngjs");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
async function mergeImages(images, width, height, lastImageOffset, offsetTop) {
|
|
8
|
+
const outImage = new pngjs_1.PNG({ width, height: height * images.length - lastImageOffset });
|
|
9
|
+
if (images.length === 1) {
|
|
10
|
+
const png = await (0, utils_1.parsePng)(images[0]);
|
|
11
|
+
png.bitblt(outImage, 0, offsetTop, width, height - lastImageOffset, 0, 0);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
for (let index = 0; index < images.length; index++) {
|
|
15
|
+
const png = await (0, utils_1.parsePng)(images[index]);
|
|
16
|
+
const verticalOffset = index < images.length - 1 ? index * height : index * height - lastImageOffset;
|
|
17
|
+
png.bitblt(outImage, 0, offsetTop, Math.min(width, png.width), Math.min(height, png.height), 0, verticalOffset);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const encoded = await (0, utils_1.packPng)(outImage);
|
|
21
|
+
return encoded.toString('base64');
|
|
22
|
+
}
|
|
23
|
+
exports.default = mergeImages;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PNG } from 'pngjs';
|
|
3
|
+
import { ElementRect } from '../page-objects/types';
|
|
4
|
+
export declare function parsePng(encodedImage: string): Promise<PNG>;
|
|
5
|
+
export declare function packPng(png: PNG): Promise<Buffer>;
|
|
6
|
+
export declare function isValidImage(pixels: Buffer): boolean;
|
|
7
|
+
export declare function cropImage(inImage: PNG, rect: ElementRect, pixelRatio?: number): PNG;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cropImage = exports.isValidImage = exports.packPng = exports.parsePng = void 0;
|
|
7
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
8
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
const pngjs_1 = require("pngjs");
|
|
10
|
+
const util_1 = require("util");
|
|
11
|
+
const get_stream_1 = __importDefault(require("get-stream"));
|
|
12
|
+
const exceptions_1 = require("../exceptions");
|
|
13
|
+
function roundDimensions(rect) {
|
|
14
|
+
const result = {};
|
|
15
|
+
Object.keys(rect).forEach(key => {
|
|
16
|
+
result[key] = Math.round(rect[key]);
|
|
17
|
+
});
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
async function parsePng(encodedImage) {
|
|
21
|
+
const png = new pngjs_1.PNG();
|
|
22
|
+
await (0, util_1.promisify)(png.parse.bind(png))(Buffer.from(encodedImage, 'base64'));
|
|
23
|
+
return png;
|
|
24
|
+
}
|
|
25
|
+
exports.parsePng = parsePng;
|
|
26
|
+
function packPng(png) {
|
|
27
|
+
return get_stream_1.default.buffer(png.pack());
|
|
28
|
+
}
|
|
29
|
+
exports.packPng = packPng;
|
|
30
|
+
function isValidImage(pixels) {
|
|
31
|
+
let lastColor;
|
|
32
|
+
for (let i = 0; i < pixels.length; i += 4) {
|
|
33
|
+
const color = (pixels[i] << 24) + (pixels[i + 1] << 16) + (pixels[i + 2] << 8) + pixels[i + 3];
|
|
34
|
+
if (!lastColor) {
|
|
35
|
+
lastColor = color;
|
|
36
|
+
}
|
|
37
|
+
else if (color !== lastColor) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
exports.isValidImage = isValidImage;
|
|
44
|
+
function cropImage(inImage, rect, pixelRatio = 1) {
|
|
45
|
+
const roundedRect = roundDimensions(rect);
|
|
46
|
+
const imageWidth = Math.ceil(roundedRect.width * pixelRatio || inImage.width);
|
|
47
|
+
const imageHeight = Math.ceil(roundedRect.height * pixelRatio || inImage.height);
|
|
48
|
+
const outImage = new pngjs_1.PNG({ width: imageWidth, height: imageHeight });
|
|
49
|
+
const safeLeft = Math.max(roundedRect.left, 0) * pixelRatio;
|
|
50
|
+
const safeTop = Math.max(roundedRect.top, 0) * pixelRatio;
|
|
51
|
+
const safeWidth = Math.min(imageWidth, inImage.width - safeLeft);
|
|
52
|
+
const safeHeight = Math.min(imageHeight, inImage.height - safeTop);
|
|
53
|
+
inImage.bitblt(outImage, safeLeft, safeTop, safeWidth, safeHeight, 0, 0);
|
|
54
|
+
if (!isValidImage(outImage.data)) {
|
|
55
|
+
throw new exceptions_1.ScreenshotTakeError('Image does not contain enough colors');
|
|
56
|
+
}
|
|
57
|
+
return outImage;
|
|
58
|
+
}
|
|
59
|
+
exports.cropImage = cropImage;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/// <reference types="webdriverio/async" />
|
|
2
|
+
import { ScrollPosition } from '../browser-scripts';
|
|
3
|
+
import EventsSpy from './events-spy';
|
|
4
|
+
import { ElementRect } from './types';
|
|
5
|
+
export default class BasePageObject {
|
|
6
|
+
protected browser: WebdriverIO.Browser;
|
|
7
|
+
constructor(browser: WebdriverIO.Browser);
|
|
8
|
+
pause(milliseconds: number): Promise<void>;
|
|
9
|
+
keys(keys: string | string[]): Promise<void>;
|
|
10
|
+
setWindowSize({ width, height }: {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
spyOnEvents(selector: string, events: string[]): Promise<EventsSpy>;
|
|
15
|
+
click(selector: string): Promise<void>;
|
|
16
|
+
hoverElement(selector: string, xOffset?: number, yOffset?: number): Promise<void>;
|
|
17
|
+
buttonDownOnElement(selector: string): Promise<void>;
|
|
18
|
+
buttonUp(): Promise<void>;
|
|
19
|
+
dragAndDrop(sourceSelector: string, xOffset?: number, yOffset?: number): Promise<void>;
|
|
20
|
+
getValue(selector: string): Promise<string>;
|
|
21
|
+
setValue(selector: string, value: number | string | string[]): Promise<void>;
|
|
22
|
+
getViewportSize(): Promise<import("./types").ViewportSize>;
|
|
23
|
+
getWindowScroll(): Promise<ScrollPosition>;
|
|
24
|
+
windowScrollTo({ top, left }: Partial<ScrollPosition>): Promise<void>;
|
|
25
|
+
getElementScroll(selector: string): Promise<ScrollPosition>;
|
|
26
|
+
elementScrollTo(selector: string, { top, left }: Partial<ScrollPosition>): Promise<void>;
|
|
27
|
+
waitForVisible(selector: string, shouldDisplay?: boolean, timeout?: number): Promise<void>;
|
|
28
|
+
waitForAssertion(expression: () => Promise<void>): Promise<void>;
|
|
29
|
+
waitForJsTimers(timeout?: number): Promise<void>;
|
|
30
|
+
isFocused(selector: string): Promise<boolean>;
|
|
31
|
+
isSelected(selector: string): Promise<boolean>;
|
|
32
|
+
isExisting(selector: string): Promise<boolean>;
|
|
33
|
+
isDisplayed(selector: string): Promise<boolean>;
|
|
34
|
+
getElementAttribute(selector: string, attributeName: string): Promise<string>;
|
|
35
|
+
getElementProperty(selector: string, propertyName: string): Promise<string | number | boolean | Element | ChildNode | ParentNode | Document | HTMLElement | CSSStyleDeclaration | DOMStringMap | DOMTokenList | HTMLCollection | HTMLSlotElement | NamedNodeMap | ShadowRoot | OnErrorEventHandler | NodeListOf<ChildNode> | {
|
|
36
|
+
<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined): void;
|
|
37
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | undefined): void;
|
|
38
|
+
} | {
|
|
39
|
+
<K_1 extends keyof HTMLElementEventMap>(type: K_1, listener: (this: HTMLElement, ev: HTMLElementEventMap[K_1]) => any, options?: boolean | EventListenerOptions | undefined): void;
|
|
40
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions | undefined): void;
|
|
41
|
+
} | {
|
|
42
|
+
<K_2 extends keyof HTMLElementTagNameMap>(selector: K_2): HTMLElementTagNameMap[K_2] | null;
|
|
43
|
+
<K_3 extends keyof SVGElementTagNameMap>(selector: K_3): SVGElementTagNameMap[K_3] | null;
|
|
44
|
+
<E extends Element = Element>(selectors: string): E | null;
|
|
45
|
+
} | {
|
|
46
|
+
<K_4 extends keyof HTMLElementTagNameMap>(qualifiedName: K_4): HTMLCollectionOf<HTMLElementTagNameMap[K_4]>;
|
|
47
|
+
<K_5 extends keyof SVGElementTagNameMap>(qualifiedName: K_5): HTMLCollectionOf<SVGElementTagNameMap[K_5]>;
|
|
48
|
+
(qualifiedName: string): HTMLCollectionOf<Element>;
|
|
49
|
+
} | {
|
|
50
|
+
(namespaceURI: "http://www.w3.org/1999/xhtml", localName: string): HTMLCollectionOf<HTMLElement>;
|
|
51
|
+
(namespaceURI: "http://www.w3.org/2000/svg", localName: string): HTMLCollectionOf<SVGElement>;
|
|
52
|
+
(namespace: string | null, localName: string): HTMLCollectionOf<Element>;
|
|
53
|
+
} | {
|
|
54
|
+
(options?: ScrollToOptions | undefined): void;
|
|
55
|
+
(x: number, y: number): void;
|
|
56
|
+
} | {
|
|
57
|
+
(options?: ScrollToOptions | undefined): void;
|
|
58
|
+
(x: number, y: number): void;
|
|
59
|
+
} | {
|
|
60
|
+
(options?: ScrollToOptions | undefined): void;
|
|
61
|
+
(x: number, y: number): void;
|
|
62
|
+
} | {
|
|
63
|
+
<K_6 extends keyof HTMLElementTagNameMap>(selectors: K_6): HTMLElementTagNameMap[K_6] | null;
|
|
64
|
+
<K_7 extends keyof SVGElementTagNameMap>(selectors: K_7): SVGElementTagNameMap[K_7] | null;
|
|
65
|
+
<E_1 extends Element = Element>(selectors: string): E_1 | null;
|
|
66
|
+
} | {
|
|
67
|
+
<K_8 extends keyof HTMLElementTagNameMap>(selectors: K_8): NodeListOf<HTMLElementTagNameMap[K_8]>;
|
|
68
|
+
<K_9 extends keyof SVGElementTagNameMap>(selectors: K_9): NodeListOf<SVGElementTagNameMap[K_9]>;
|
|
69
|
+
<E_2 extends Element = Element>(selectors: string): NodeListOf<E_2>;
|
|
70
|
+
} | (() => DOMRect) | ((event: Event) => boolean) | ((this: GlobalEventHandlers, ev: UIEvent) => any) | ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: FocusEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: DragEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: FocusEvent) => any) | ((this: GlobalEventHandlers, ev: FormDataEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | ((this: GlobalEventHandlers, ev: KeyboardEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: MouseEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: PointerEvent) => any) | ((this: GlobalEventHandlers, ev: ProgressEvent<EventTarget>) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: UIEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: SecurityPolicyViolationEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: SubmitEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: TouchEvent) => any) | ((this: GlobalEventHandlers, ev: TouchEvent) => any) | ((this: GlobalEventHandlers, ev: TouchEvent) => any) | ((this: GlobalEventHandlers, ev: TouchEvent) => any) | ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | ((this: GlobalEventHandlers, ev: TransitionEvent) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: Event) => any) | ((this: GlobalEventHandlers, ev: WheelEvent) => any) | (() => ElementInternals) | (() => void) | ((this: Element, ev: Event) => any) | ((this: Element, ev: Event) => any) | ((init: ShadowRootInit) => ShadowRoot) | ((qualifiedName: string) => string | null) | ((namespace: string | null, localName: string) => string | null) | (() => string[]) | ((qualifiedName: string) => Attr | null) | ((namespace: string | null, localName: string) => Attr | null) | (() => DOMRectList) | ((classNames: string) => HTMLCollectionOf<Element>) | ((qualifiedName: string) => boolean) | ((namespace: string | null, localName: string) => boolean) | (() => boolean) | ((pointerId: number) => boolean) | ((where: InsertPosition, element: Element) => Element | null) | ((position: InsertPosition, text: string) => void) | ((where: InsertPosition, data: string) => void) | ((selectors: string) => boolean) | ((pointerId: number) => void) | ((qualifiedName: string) => void) | ((namespace: string | null, localName: string) => void) | ((attr: Attr) => Attr) | ((options?: FullscreenOptions | undefined) => Promise<void>) | (() => void) | ((arg?: boolean | ScrollIntoViewOptions | undefined) => void) | ((qualifiedName: string, value: string) => void) | ((namespace: string | null, qualifiedName: string, value: string) => void) | ((attr: Attr) => Attr | null) | ((attr: Attr) => Attr | null) | ((pointerId: number) => void) | ((qualifiedName: string, force?: boolean | undefined) => boolean) | ((selectors: string) => boolean) | (<T extends Node>(node: T) => T) | ((deep?: boolean | undefined) => Node) | ((other: Node) => number) | ((other: Node | null) => boolean) | ((options?: GetRootNodeOptions | undefined) => Node) | (() => boolean) | (<T_1 extends Node>(node: T_1, child: Node | null) => T_1) | ((namespace: string | null) => boolean) | ((otherNode: Node | null) => boolean) | ((otherNode: Node | null) => boolean) | ((prefix: string | null) => string | null) | ((namespace: string | null) => string | null) | (() => void) | (<T_2 extends Node>(child: T_2) => T_2) | (<T_3 extends Node>(node: Node, child: T_3) => T_3) | ((keyframes: PropertyIndexedKeyframes | Keyframe[] | null, options?: number | KeyframeAnimationOptions | undefined) => Animation) | ((options?: GetAnimationsOptions | undefined) => Animation[]) | ((...nodes: (string | Node)[]) => void) | ((...nodes: (string | Node)[]) => void) | (() => void) | ((...nodes: (string | Node)[]) => void) | ((...nodes: (string | Node)[]) => void) | ((...nodes: (string | Node)[]) => void) | ((...nodes: (string | Node)[]) => void) | ((this: DocumentAndElementEventHandlers, ev: ClipboardEvent) => any) | ((this: DocumentAndElementEventHandlers, ev: ClipboardEvent) => any) | ((this: DocumentAndElementEventHandlers, ev: ClipboardEvent) => any) | (() => void) | ((options?: FocusOptions | undefined) => void) | undefined>;
|
|
71
|
+
getElementsCount(selector: string): Promise<number>;
|
|
72
|
+
getFocusedElementText(): Promise<string>;
|
|
73
|
+
getBoundingBox(selector: string): Promise<ElementRect>;
|
|
74
|
+
getText(selector: string): Promise<string>;
|
|
75
|
+
getElementsText(selector: string): Promise<string[]>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
7
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
8
|
+
const p_retry_1 = __importDefault(require("p-retry"));
|
|
9
|
+
const browser_scripts_1 = require("../browser-scripts");
|
|
10
|
+
const events_spy_1 = __importDefault(require("./events-spy"));
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
const browser_scripts_2 = require("./browser-scripts");
|
|
13
|
+
class BasePageObject {
|
|
14
|
+
constructor(browser) {
|
|
15
|
+
this.browser = browser;
|
|
16
|
+
}
|
|
17
|
+
async pause(milliseconds) {
|
|
18
|
+
await this.browser.pause(milliseconds);
|
|
19
|
+
}
|
|
20
|
+
async keys(keys) {
|
|
21
|
+
await this.browser.keys(keys);
|
|
22
|
+
}
|
|
23
|
+
async setWindowSize({ width, height }) {
|
|
24
|
+
await this.browser.setWindowSize(width, height);
|
|
25
|
+
}
|
|
26
|
+
async spyOnEvents(selector, events) {
|
|
27
|
+
const spy = new events_spy_1.default(this.browser, selector, events);
|
|
28
|
+
await spy.init();
|
|
29
|
+
return spy;
|
|
30
|
+
}
|
|
31
|
+
async click(selector) {
|
|
32
|
+
const element = await this.browser.$(selector);
|
|
33
|
+
await element.click();
|
|
34
|
+
}
|
|
35
|
+
async hoverElement(selector, xOffset, yOffset) {
|
|
36
|
+
const element = await this.browser.$(selector);
|
|
37
|
+
await element.moveTo({ xOffset, yOffset });
|
|
38
|
+
}
|
|
39
|
+
async buttonDownOnElement(selector) {
|
|
40
|
+
// buttonDown exists only in JSON Wire protocol
|
|
41
|
+
if (this.browser.buttonDown) {
|
|
42
|
+
await this.hoverElement(selector);
|
|
43
|
+
await this.browser.buttonDown();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Clean up all previous actions before stating a new batch. Without this line Safari emits extra "mouseup" events
|
|
47
|
+
await this.browser.releaseActions();
|
|
48
|
+
const box = await this.getBoundingBox(selector);
|
|
49
|
+
const center = (0, utils_1.getElementCenter)(box);
|
|
50
|
+
// W3C alternative is `performActions`. All consecutive actions have to be a part of a single call
|
|
51
|
+
await this.browser.performActions([
|
|
52
|
+
{
|
|
53
|
+
type: 'pointer',
|
|
54
|
+
id: 'mouse',
|
|
55
|
+
parameters: { pointerType: 'mouse' },
|
|
56
|
+
actions: [
|
|
57
|
+
{ type: 'pointerMove', duration: 0, x: center.x, y: center.y },
|
|
58
|
+
{ type: 'pointerDown', button: 0 },
|
|
59
|
+
// extra delay to let event listeners to be fired
|
|
60
|
+
{ type: 'pause', duration: 10 },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async buttonUp() {
|
|
67
|
+
// buttonUp exists only in JSON Wire protocol
|
|
68
|
+
if (this.browser.buttonUp) {
|
|
69
|
+
await this.browser.buttonUp();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// W3C alternative is `performActions`
|
|
73
|
+
await this.browser.performActions([
|
|
74
|
+
{
|
|
75
|
+
type: 'pointer',
|
|
76
|
+
id: 'mouse',
|
|
77
|
+
parameters: { pointerType: 'mouse' },
|
|
78
|
+
actions: [
|
|
79
|
+
{ type: 'pointerUp', button: 0 },
|
|
80
|
+
// extra delay for Safari to process the event before moving the cursor away
|
|
81
|
+
{ type: 'pause', duration: 10 },
|
|
82
|
+
// return cursor back to the corner to avoid hover effects on screenshots
|
|
83
|
+
{ type: 'pointerMove', duration: 0, x: 0, y: 0 },
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
]);
|
|
87
|
+
// make sure all controls are properly released to avoid conflicts with further actions
|
|
88
|
+
await this.browser.releaseActions();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async dragAndDrop(sourceSelector, xOffset = 0, yOffset = 0) {
|
|
92
|
+
const element = await this.browser.$(sourceSelector);
|
|
93
|
+
await element.dragAndDrop({ x: xOffset, y: yOffset });
|
|
94
|
+
}
|
|
95
|
+
async getValue(selector) {
|
|
96
|
+
const element = await this.browser.$(selector);
|
|
97
|
+
return element.getValue();
|
|
98
|
+
}
|
|
99
|
+
async setValue(selector, value) {
|
|
100
|
+
const element = await this.browser.$(selector);
|
|
101
|
+
await element.setValue(value);
|
|
102
|
+
}
|
|
103
|
+
async getViewportSize() {
|
|
104
|
+
return this.browser.execute(browser_scripts_1.getViewportSize);
|
|
105
|
+
}
|
|
106
|
+
async getWindowScroll() {
|
|
107
|
+
return this.browser.execute(browser_scripts_1.getWindowScrollPosition);
|
|
108
|
+
}
|
|
109
|
+
async windowScrollTo({ top = 0, left = 0 }) {
|
|
110
|
+
await this.browser.execute(browser_scripts_1.windowScrollTo, top, left);
|
|
111
|
+
}
|
|
112
|
+
async getElementScroll(selector) {
|
|
113
|
+
return this.browser.execute(browser_scripts_1.getElementScrollPosition, selector);
|
|
114
|
+
}
|
|
115
|
+
async elementScrollTo(selector, { top = 0, left = 0 }) {
|
|
116
|
+
await this.browser.execute(browser_scripts_1.elementScrollTo, selector, top, left);
|
|
117
|
+
}
|
|
118
|
+
async waitForVisible(selector, shouldDisplay = true, timeout) {
|
|
119
|
+
await this.browser.waitUntil(async () => {
|
|
120
|
+
const isDisplayed = await this.isDisplayed(selector);
|
|
121
|
+
return isDisplayed === shouldDisplay;
|
|
122
|
+
}, {
|
|
123
|
+
timeout,
|
|
124
|
+
timeoutMsg: shouldDisplay
|
|
125
|
+
? `Element "${selector}" is not visible upon waiting`
|
|
126
|
+
: `Element "${selector}" is still visible after waiting`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async waitForAssertion(expression) {
|
|
130
|
+
const retryOptions = { minTimeout: 100, retries: 5 };
|
|
131
|
+
await (0, p_retry_1.default)(expression, retryOptions);
|
|
132
|
+
}
|
|
133
|
+
// setTimeout and requestAnimationFrame on the page
|
|
134
|
+
async waitForJsTimers(timeout = 0) {
|
|
135
|
+
await this.browser.executeAsync(browser_scripts_2.waitForTimerAndAnimationFrame, timeout);
|
|
136
|
+
}
|
|
137
|
+
async isFocused(selector) {
|
|
138
|
+
const element = await this.browser.$(selector);
|
|
139
|
+
return element.isFocused();
|
|
140
|
+
}
|
|
141
|
+
async isSelected(selector) {
|
|
142
|
+
const element = await this.browser.$(selector);
|
|
143
|
+
return element.isSelected();
|
|
144
|
+
}
|
|
145
|
+
async isExisting(selector) {
|
|
146
|
+
const elements = await this.browser.$$(selector);
|
|
147
|
+
return elements.length > 0;
|
|
148
|
+
}
|
|
149
|
+
async isDisplayed(selector) {
|
|
150
|
+
// browser.$ throws an error if element is not found, so we use this method to avoid try/catch
|
|
151
|
+
const elements = await this.browser.$$(selector);
|
|
152
|
+
if (elements.length === 0) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
return elements[0].isDisplayed();
|
|
156
|
+
}
|
|
157
|
+
async getElementAttribute(selector, attributeName) {
|
|
158
|
+
const element = await this.browser.$(selector);
|
|
159
|
+
return element.getAttribute(attributeName);
|
|
160
|
+
}
|
|
161
|
+
async getElementProperty(selector, propertyName) {
|
|
162
|
+
const element = await this.browser.$(selector);
|
|
163
|
+
return element.getProperty(propertyName);
|
|
164
|
+
}
|
|
165
|
+
async getElementsCount(selector) {
|
|
166
|
+
const elements = await this.browser.$$(selector);
|
|
167
|
+
return elements.length;
|
|
168
|
+
}
|
|
169
|
+
async getFocusedElementText() {
|
|
170
|
+
const activeNode = await this.browser.getActiveElement();
|
|
171
|
+
const element = await this.browser.$(activeNode);
|
|
172
|
+
return element.getText();
|
|
173
|
+
}
|
|
174
|
+
async getBoundingBox(selector) {
|
|
175
|
+
return this.browser.execute(browser_scripts_1.getBoundingClientRect, selector);
|
|
176
|
+
}
|
|
177
|
+
async getText(selector) {
|
|
178
|
+
const element = await this.browser.$(selector);
|
|
179
|
+
return element.getText();
|
|
180
|
+
}
|
|
181
|
+
async getElementsText(selector) {
|
|
182
|
+
const elements = await this.browser.$$(selector);
|
|
183
|
+
return Promise.all(elements.map(async (element) => element.getText()));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.default = BasePageObject;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function waitForTimerAndAnimationFrame(timeout: number, done: () => void): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.waitForTimerAndAnimationFrame = void 0;
|
|
4
|
+
function waitForTimerAndAnimationFrame(timeout, done) {
|
|
5
|
+
setTimeout(function () {
|
|
6
|
+
requestAnimationFrame(function () {
|
|
7
|
+
done();
|
|
8
|
+
});
|
|
9
|
+
}, timeout);
|
|
10
|
+
}
|
|
11
|
+
exports.waitForTimerAndAnimationFrame = waitForTimerAndAnimationFrame;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="webdriverio/async" />
|
|
2
|
+
export default class EventsSpy {
|
|
3
|
+
private browser;
|
|
4
|
+
private selector;
|
|
5
|
+
private events;
|
|
6
|
+
constructor(browser: WebdriverIO.Browser, selector: string, events: string[]);
|
|
7
|
+
init(): Promise<void>;
|
|
8
|
+
getEvents(): Promise<string[]>;
|
|
9
|
+
reset(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
const browser_scripts_1 = require("../browser-scripts");
|
|
6
|
+
class EventsSpy {
|
|
7
|
+
constructor(browser, selector, events) {
|
|
8
|
+
this.browser = browser;
|
|
9
|
+
this.selector = selector;
|
|
10
|
+
this.events = events;
|
|
11
|
+
}
|
|
12
|
+
async init() {
|
|
13
|
+
await this.browser.execute(browser_scripts_1.initEventsSpy, this.selector, this.events);
|
|
14
|
+
}
|
|
15
|
+
async getEvents() {
|
|
16
|
+
return this.browser.execute(browser_scripts_1.getEvents);
|
|
17
|
+
}
|
|
18
|
+
async reset() {
|
|
19
|
+
await this.browser.execute(browser_scripts_1.resetEventsSpy);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = EventsSpy;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const browser_scripts_1 = require("../browser-scripts");
|
|
7
|
+
const merge_1 = __importDefault(require("../image-utils/merge"));
|
|
8
|
+
const browser_scripts_2 = require("./browser-scripts");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
const MAX_SCREENSHOT_HEIGHT = 20000;
|
|
11
|
+
async function scroll(browser, topOffset) {
|
|
12
|
+
await browser.execute(browser_scripts_1.windowScrollTo, topOffset, 0);
|
|
13
|
+
}
|
|
14
|
+
async function checkDocumentSize(browser) {
|
|
15
|
+
const viewPortSize = await browser.execute(browser_scripts_1.getViewportSize);
|
|
16
|
+
if (viewPortSize.pageHeight > MAX_SCREENSHOT_HEIGHT) {
|
|
17
|
+
console.warn(`The permutation page is higher than ${MAX_SCREENSHOT_HEIGHT}. Taking a screenshot might cause problems.`);
|
|
18
|
+
}
|
|
19
|
+
return viewPortSize;
|
|
20
|
+
}
|
|
21
|
+
async function scrollAndMergeStrategy(browser) {
|
|
22
|
+
const { width, height, pageHeight, screenWidth, screenHeight, pixelRatio } = await checkDocumentSize(browser);
|
|
23
|
+
let offset = 0;
|
|
24
|
+
const screenshots = [];
|
|
25
|
+
while (offset < pageHeight) {
|
|
26
|
+
await scroll(browser, offset);
|
|
27
|
+
// Wait for scroll effects to settle.
|
|
28
|
+
await browser.executeAsync(browser_scripts_2.waitForTimerAndAnimationFrame, 200);
|
|
29
|
+
const value = await browser.takeScreenshot();
|
|
30
|
+
screenshots.push(value);
|
|
31
|
+
offset += height;
|
|
32
|
+
}
|
|
33
|
+
// skip images merge when there is only one screenshot
|
|
34
|
+
if (screenshots.length === 1 && !browser.isIOS) {
|
|
35
|
+
return screenshots[0];
|
|
36
|
+
}
|
|
37
|
+
const lastImageOffset = offset - pageHeight;
|
|
38
|
+
let offsetTop = 0;
|
|
39
|
+
if (browser.isIOS) {
|
|
40
|
+
offsetTop = (0, utils_1.calculateIosTopOffset)({ screenWidth, screenHeight, pixelRatio });
|
|
41
|
+
}
|
|
42
|
+
return (0, merge_1.default)(screenshots, width * pixelRatio, height * pixelRatio, lastImageOffset * pixelRatio, offsetTop);
|
|
43
|
+
}
|
|
44
|
+
async function fullPageScreenshot(browser) {
|
|
45
|
+
const puppeteer = await (0, utils_1.getPuppeteer)(browser);
|
|
46
|
+
if (puppeteer) {
|
|
47
|
+
// casting due to mismatch in NodeJS types of EventEmitter
|
|
48
|
+
return puppeteerStrategy(browser, puppeteer);
|
|
49
|
+
}
|
|
50
|
+
console.warn('Falling back to scroll-and-merge strategy');
|
|
51
|
+
return scrollAndMergeStrategy(browser);
|
|
52
|
+
}
|
|
53
|
+
exports.default = fullPageScreenshot;
|
|
54
|
+
async function puppeteerStrategy(browser, puppeteer) {
|
|
55
|
+
const image = await browser.call(async () => {
|
|
56
|
+
// Assuming only one page open
|
|
57
|
+
const [current] = await puppeteer.pages();
|
|
58
|
+
return current.screenshot({
|
|
59
|
+
fullPage: true,
|
|
60
|
+
encoding: 'base64',
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
// encoding=base64 returns a string
|
|
64
|
+
// See: https://pptr.dev/#?product=Puppeteer&version=v13.2.0&show=api-pagescreenshotoptions
|
|
65
|
+
return image;
|
|
66
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EventsSpy = exports.ScreenshotPageObject = exports.BasePageObject = void 0;
|
|
7
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
8
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
9
|
+
var base_1 = require("./base");
|
|
10
|
+
Object.defineProperty(exports, "BasePageObject", { enumerable: true, get: function () { return __importDefault(base_1).default; } });
|
|
11
|
+
var screenshot_1 = require("./screenshot");
|
|
12
|
+
Object.defineProperty(exports, "ScreenshotPageObject", { enumerable: true, get: function () { return __importDefault(screenshot_1).default; } });
|
|
13
|
+
var events_spy_1 = require("./events-spy");
|
|
14
|
+
Object.defineProperty(exports, "EventsSpy", { enumerable: true, get: function () { return __importDefault(events_spy_1).default; } });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import BasePageObject from './base';
|
|
2
|
+
import { ScreenshotCapturingOptions, ScreenshotWithOffset } from './types';
|
|
3
|
+
export default class ScreenshotPageObject extends BasePageObject {
|
|
4
|
+
focusNextElement(): Promise<void>;
|
|
5
|
+
scrollToBottom(selector: string): Promise<void>;
|
|
6
|
+
scrollToRight(selector: string): Promise<void>;
|
|
7
|
+
fullPageScreenshot(): Promise<string>;
|
|
8
|
+
captureBySelector(selector: string, options?: ScreenshotCapturingOptions): Promise<ScreenshotWithOffset>;
|
|
9
|
+
captureViewport(): Promise<ScreenshotWithOffset>;
|
|
10
|
+
}
|