@applitools/core 1.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.
Files changed (90) hide show
  1. package/LICENSE +26 -0
  2. package/dist/automation/get-viewport-size.js +12 -0
  3. package/dist/automation/locate.js +22 -0
  4. package/dist/automation/set-viewport-size.js +12 -0
  5. package/dist/automation/utils/take-screenshot.js +55 -0
  6. package/dist/check-and-close.js +11 -0
  7. package/dist/check.js +55 -0
  8. package/dist/classic/check-and-close.js +67 -0
  9. package/dist/classic/check.js +78 -0
  10. package/dist/classic/core.js +50 -0
  11. package/dist/classic/extract-text.js +71 -0
  12. package/dist/classic/locate-text.js +53 -0
  13. package/dist/classic/open-eyes.js +78 -0
  14. package/dist/classic/utils/take-dom-capture.js +135 -0
  15. package/dist/classic/utils/transform-check-settings.js +68 -0
  16. package/dist/close-manager.js +62 -0
  17. package/dist/close.js +20 -0
  18. package/dist/core.js +51 -0
  19. package/dist/errors/test-error.js +29 -0
  20. package/dist/extract-text.js +37 -0
  21. package/dist/index.js +32 -0
  22. package/dist/locate-text.js +11 -0
  23. package/dist/locate.js +11 -0
  24. package/dist/make-manager.js +65 -0
  25. package/dist/open-eyes.js +84 -0
  26. package/dist/troubleshoot/check-network.js +106 -0
  27. package/dist/troubleshoot/eyes.js +85 -0
  28. package/dist/troubleshoot/ufg.js +130 -0
  29. package/dist/troubleshoot/utils.js +68 -0
  30. package/dist/ufg/abort.js +18 -0
  31. package/dist/ufg/check-and-close.js +7 -0
  32. package/dist/ufg/check.js +192 -0
  33. package/dist/ufg/close.js +31 -0
  34. package/dist/ufg/core.js +78 -0
  35. package/dist/ufg/open-eyes.js +123 -0
  36. package/dist/ufg/utils/generate-safe-selectors.js +60 -0
  37. package/dist/ufg/utils/take-dom-snapshot.js +132 -0
  38. package/dist/ufg/utils/take-dom-snapshots.js +141 -0
  39. package/dist/ufg/utils/take-snapshots.js +38 -0
  40. package/dist/ufg/utils/take-vhses.js +258 -0
  41. package/dist/utils/execute-poll-script.js +75 -0
  42. package/dist/utils/extract-broker-url.js +19 -0
  43. package/dist/utils/format-results.js +185 -0
  44. package/dist/utils/to-base-check-settings.js +69 -0
  45. package/dist/utils/wait-for-lazy-load.js +25 -0
  46. package/package.json +105 -0
  47. package/types/automation/get-viewport-size.d.ts +11 -0
  48. package/types/automation/locate.d.ts +16 -0
  49. package/types/automation/set-viewport-size.d.ts +12 -0
  50. package/types/automation/utils/take-screenshot.d.ts +15 -0
  51. package/types/check-and-close.d.ts +15 -0
  52. package/types/check.d.ts +15 -0
  53. package/types/classic/check-and-close.d.ts +16 -0
  54. package/types/classic/check.d.ts +16 -0
  55. package/types/classic/core.d.ts +13 -0
  56. package/types/classic/extract-text.d.ts +16 -0
  57. package/types/classic/locate-text.d.ts +16 -0
  58. package/types/classic/open-eyes.d.ts +15 -0
  59. package/types/classic/utils/take-dom-capture.d.ts +13 -0
  60. package/types/classic/utils/transform-check-settings.d.ts +11 -0
  61. package/types/close-manager.d.ts +18 -0
  62. package/types/close.d.ts +14 -0
  63. package/types/core.d.ts +14 -0
  64. package/types/errors/test-error.d.ts +5 -0
  65. package/types/extract-text.d.ts +15 -0
  66. package/types/index.d.ts +3 -0
  67. package/types/locate-text.d.ts +15 -0
  68. package/types/locate.d.ts +15 -0
  69. package/types/make-manager.d.ts +19 -0
  70. package/types/open-eyes.d.ts +19 -0
  71. package/types/troubleshoot/check-network.d.ts +20 -0
  72. package/types/troubleshoot/eyes.d.ts +11 -0
  73. package/types/troubleshoot/ufg.d.ts +10 -0
  74. package/types/troubleshoot/utils.d.ts +4 -0
  75. package/types/ufg/abort.d.ts +17 -0
  76. package/types/ufg/check-and-close.d.ts +17 -0
  77. package/types/ufg/check.d.ts +27 -0
  78. package/types/ufg/close.d.ts +16 -0
  79. package/types/ufg/core.d.ts +16 -0
  80. package/types/ufg/open-eyes.d.ts +18 -0
  81. package/types/ufg/utils/generate-safe-selectors.d.ts +12 -0
  82. package/types/ufg/utils/take-dom-snapshot.d.ts +23 -0
  83. package/types/ufg/utils/take-dom-snapshots.d.ts +24 -0
  84. package/types/ufg/utils/take-snapshots.d.ts +21 -0
  85. package/types/ufg/utils/take-vhses.d.ts +17 -0
  86. package/types/utils/execute-poll-script.d.ts +20 -0
  87. package/types/utils/extract-broker-url.d.ts +2 -0
  88. package/types/utils/format-results.d.ts +16 -0
  89. package/types/utils/to-base-check-settings.d.ts +17 -0
  90. package/types/utils/wait-for-lazy-load.d.ts +13 -0
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.makeCore = void 0;
30
+ const logger_1 = require("@applitools/logger");
31
+ const core_base_1 = require("@applitools/core-base");
32
+ const get_viewport_size_1 = require("../automation/get-viewport-size");
33
+ const set_viewport_size_1 = require("../automation/set-viewport-size");
34
+ const locate_1 = require("../automation/locate");
35
+ const open_eyes_1 = require("./open-eyes");
36
+ const utils = __importStar(require("@applitools/utils"));
37
+ const throat_1 = __importDefault(require("throat"));
38
+ function makeCore({ concurrency, spec, client, core, agentId = 'core-ufg', cwd = process.cwd(), logger, }) {
39
+ var _a;
40
+ logger = (_a = logger === null || logger === void 0 ? void 0 : logger.extend({ label: 'core-ufg' })) !== null && _a !== void 0 ? _a : (0, logger_1.makeLogger)({ label: 'core-ufg' });
41
+ logger.log(`Core ufg is initialized ${core ? 'with' : 'without'} custom base core`);
42
+ const throttle = (0, throat_1.default)(concurrency);
43
+ core !== null && core !== void 0 ? core : (core = (0, core_base_1.makeCore)({ agentId, cwd, logger }));
44
+ // open eyes with concurrency
45
+ core.openEyes = utils.general.wrap(core.openEyes, (openEyes, options) => {
46
+ return new Promise((resolve, rejects) => {
47
+ throttle(() => {
48
+ return new Promise(async (done) => {
49
+ try {
50
+ const eyes = await openEyes(options);
51
+ resolve(utils.general.extend(eyes, {
52
+ // release concurrency slot when closed
53
+ close: utils.general.wrap(eyes.close, (close, options) => close(options).finally(done)),
54
+ // release concurrency slot when aborted
55
+ abort: utils.general.wrap(eyes.abort, (abort, options) => abort(options).finally(done)),
56
+ }));
57
+ }
58
+ catch (error) {
59
+ rejects(error);
60
+ // release concurrency slot when error thrown
61
+ done();
62
+ }
63
+ });
64
+ });
65
+ });
66
+ });
67
+ return utils.general.extend(core, {
68
+ type: 'ufg',
69
+ isDriver: spec === null || spec === void 0 ? void 0 : spec.isDriver,
70
+ isElement: spec === null || spec === void 0 ? void 0 : spec.isElement,
71
+ isSelector: spec === null || spec === void 0 ? void 0 : spec.isSelector,
72
+ getViewportSize: (0, get_viewport_size_1.makeGetViewportSize)({ spec, logger }),
73
+ setViewportSize: (0, set_viewport_size_1.makeSetViewportSize)({ spec, logger }),
74
+ locate: (0, locate_1.makeLocate)({ spec, core, logger }),
75
+ openEyes: (0, open_eyes_1.makeOpenEyes)({ spec, client, core, logger }),
76
+ });
77
+ }
78
+ exports.makeCore = makeCore;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.makeOpenEyes = void 0;
27
+ const abort_controller_1 = require("abort-controller");
28
+ const driver_1 = require("@applitools/driver");
29
+ const ufg_client_1 = require("@applitools/ufg-client");
30
+ const check_1 = require("./check");
31
+ const check_and_close_1 = require("./check-and-close");
32
+ const close_1 = require("./close");
33
+ const abort_1 = require("./abort");
34
+ const utils = __importStar(require("@applitools/utils"));
35
+ function makeOpenEyes({ spec, core, client, logger: defaultLogger, }) {
36
+ return async function openEyes({ target, settings, logger = defaultLogger, }) {
37
+ var _a, _b, _c;
38
+ logger.log(`Command "openEyes" is called with ${(spec === null || spec === void 0 ? void 0 : spec.isDriver(target)) ? 'default driver and' : ''} settings`, settings);
39
+ if (spec === null || spec === void 0 ? void 0 : spec.isDriver(target)) {
40
+ const driver = await (0, driver_1.makeDriver)({ spec, driver: target, logger });
41
+ if ((_a = settings.environment) === null || _a === void 0 ? void 0 : _a.viewportSize) {
42
+ await driver.setViewportSize(settings.environment.viewportSize);
43
+ }
44
+ }
45
+ const account = await core.getAccountInfo({ settings, logger });
46
+ const test = {
47
+ userTestId: settings.userTestId,
48
+ batchId: (_b = settings.batch) === null || _b === void 0 ? void 0 : _b.id,
49
+ server: { serverUrl: settings.serverUrl, apiKey: settings.apiKey, proxy: settings.proxy },
50
+ account,
51
+ };
52
+ client !== null && client !== void 0 ? client : (client = (0, ufg_client_1.makeUFGClient)({ config: { ...account.ufg, ...account }, concurrency: (_c = settings.renderConcurrency) !== null && _c !== void 0 ? _c : 5, logger }));
53
+ const controller = new abort_controller_1.AbortController();
54
+ // get eyes per environment
55
+ const getEyes = utils.general.cachify(async ({ rawEnvironment }) => {
56
+ const eyes = await core.openEyes({ settings: { ...settings, environment: { rawEnvironment } }, logger });
57
+ const aborted = makeHolderPromise();
58
+ const queue = [];
59
+ eyes.check = utils.general.wrap(eyes.check, async (check, options) => {
60
+ var _a, _b;
61
+ var _c;
62
+ const index = options.settings.index;
63
+ (_a = queue[index]) !== null && _a !== void 0 ? _a : (queue[index] = makeHolderPromise());
64
+ if (index > 0)
65
+ await Promise.race([((_b = queue[_c = index - 1]) !== null && _b !== void 0 ? _b : (queue[_c] = makeHolderPromise())).promise, aborted.promise]);
66
+ return check(options).finally(queue[index].resolve);
67
+ });
68
+ eyes.abort = utils.general.wrap(eyes.abort, async (abort, options) => {
69
+ aborted.reject(new Error('Command "check" was aborted due to possible error in previous step'));
70
+ return abort(options);
71
+ });
72
+ return eyes;
73
+ });
74
+ const storage = [];
75
+ let index = 0;
76
+ // check with indexing and storage
77
+ const check = utils.general.wrap((0, check_1.makeCheck)({ spec, getEyes, client, signal: controller.signal, test, target, logger }), async (check, options) => {
78
+ ;
79
+ options.settings.index = index++;
80
+ const results = await check(options);
81
+ storage.push(...results.map(result => result.promise));
82
+ return results;
83
+ });
84
+ let closed = false;
85
+ // close only once
86
+ const close = utils.general.wrap((0, close_1.makeClose)({ storage, logger }), async (close, options) => {
87
+ if (closed || aborted)
88
+ return [];
89
+ closed = true;
90
+ return close(options);
91
+ });
92
+ let aborted = false;
93
+ // abort only once
94
+ const abort = utils.general.wrap((0, abort_1.makeAbort)({ storage, controller, logger }), async (abort, options) => {
95
+ if (aborted || closed)
96
+ return [];
97
+ aborted = true;
98
+ return abort(options);
99
+ });
100
+ return {
101
+ test,
102
+ get running() {
103
+ return !closed && !aborted;
104
+ },
105
+ get closed() {
106
+ return closed;
107
+ },
108
+ get aborted() {
109
+ return aborted;
110
+ },
111
+ check,
112
+ checkAndClose: (0, check_and_close_1.makeCheckAndClose)({ spec, getEyes, client, test, target, logger }),
113
+ close,
114
+ abort,
115
+ };
116
+ };
117
+ }
118
+ exports.makeOpenEyes = makeOpenEyes;
119
+ function makeHolderPromise() {
120
+ let resolve, reject;
121
+ const promise = new Promise((...args) => ([resolve, reject] = args));
122
+ return { promise, resolve, reject };
123
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.generateSafeSelectors = void 0;
27
+ const snippets = __importStar(require("@applitools/snippets"));
28
+ const utils = __importStar(require("@applitools/utils"));
29
+ async function generateSafeSelectors({ context, elementReferences, }) {
30
+ const mapping = {
31
+ elements: [],
32
+ ids: [],
33
+ };
34
+ for (const elementReference of elementReferences) {
35
+ const elements = await context.elements(elementReference);
36
+ mapping.elements.push(elements);
37
+ mapping.ids.push(Array(elements.length).fill(utils.general.guid()));
38
+ }
39
+ const generatedSelectors = await context.execute(snippets.addElementIds, [mapping.elements.flat(), mapping.ids.flat()]);
40
+ let offset = 0;
41
+ const selectors = mapping.elements.map(elements => {
42
+ if (elements.length === 0)
43
+ return null;
44
+ const safeSelector = generatedSelectors[offset].reduce((selector, value) => {
45
+ return selector ? { ...selector, shadow: { type: 'css', selector: value } } : { type: 'css', selector: value };
46
+ }, null);
47
+ offset += elements.length;
48
+ return { safeSelector, originalSelector: elements[0].commonSelector };
49
+ });
50
+ return {
51
+ selectors,
52
+ cleanupGeneratedSelectors,
53
+ };
54
+ async function cleanupGeneratedSelectors() {
55
+ if (!mapping.elements.length)
56
+ return;
57
+ await context.execute(snippets.cleanupElementIds, [mapping.elements.flat()]);
58
+ }
59
+ }
60
+ exports.generateSafeSelectors = generateSafeSelectors;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.extractCrossFrames = exports.deserializeDomSnapshot = exports.takeDomSnapshot = void 0;
27
+ const dom_snapshot_1 = require("@applitools/dom-snapshot");
28
+ const execute_poll_script_1 = require("../../utils/execute-poll-script");
29
+ const utils = __importStar(require("@applitools/utils"));
30
+ async function takeDomSnapshot({ context, settings, logger, }) {
31
+ var _a;
32
+ const driver = context.driver;
33
+ const isLegacyBrowser = driver.isIE || driver.isEdgeLegacy;
34
+ const arg = {
35
+ dontFetchResources: settings === null || settings === void 0 ? void 0 : settings.disableBrowserFetching,
36
+ skipResources: settings === null || settings === void 0 ? void 0 : settings.skipResources,
37
+ removeReverseProxyURLPrefixes: Boolean(process.env.APPLITOOLS_SCRIPT_REMOVE_REVERSE_PROXY_URL_PREFIXES),
38
+ chunkByteLength: (_a = settings === null || settings === void 0 ? void 0 : settings.chunkByteLength) !== null && _a !== void 0 ? _a : (Number(process.env.APPLITOOLS_SCRIPT_RESULT_MAX_BYTE_LENGTH) || (driver.isIOS ? 100000 : 250 * 1024 * 1024)),
39
+ serializeResources: true,
40
+ compressResources: false,
41
+ showLogs: settings === null || settings === void 0 ? void 0 : settings.showLogs,
42
+ };
43
+ const scripts = {
44
+ main: {
45
+ script: `return (${isLegacyBrowser ? await (0, dom_snapshot_1.getProcessPagePollForIE)() : await (0, dom_snapshot_1.getProcessPagePoll)()}).apply(null, arguments);`,
46
+ args: [arg],
47
+ },
48
+ poll: {
49
+ script: `return (${isLegacyBrowser ? await (0, dom_snapshot_1.getPollResultForIE)() : await (0, dom_snapshot_1.getPollResult)()}).apply(null, arguments);`,
50
+ args: [arg],
51
+ },
52
+ };
53
+ const cookies = driver.features.allCookies ? await driver.getCookies().catch(() => []) : [];
54
+ const snapshot = await takeContextDomSnapshot({ context });
55
+ snapshot.cookies = cookies;
56
+ return deserializeDomSnapshot({ snapshot });
57
+ async function takeContextDomSnapshot({ context }) {
58
+ // logger.log(`taking dom snapshot. ${context._reference ? `context referece: ${JSON.stringify(context._reference)}` : ''}`)
59
+ var _a, _b;
60
+ if (!driver.features.allCookies) {
61
+ cookies.push(...(await context.getCookies()));
62
+ }
63
+ const snapshot = await (0, execute_poll_script_1.executePollScript)({
64
+ context,
65
+ scripts,
66
+ settings: { executionTimeout: (_a = settings === null || settings === void 0 ? void 0 : settings.executionTimeout) !== null && _a !== void 0 ? _a : 5 * 60 * 1000, pollTimeout: (_b = settings === null || settings === void 0 ? void 0 : settings.pollTimeout) !== null && _b !== void 0 ? _b : 200 },
67
+ logger,
68
+ });
69
+ const crossFrames = extractCrossFrames({ snapshot, logger });
70
+ for (const { reference, parentSnapshot, cdtNode } of crossFrames) {
71
+ const frameContext = await context
72
+ .context(reference)
73
+ .then(context => context.focus())
74
+ .catch(err => {
75
+ logger.log(`could not switch to frame during takeDomSnapshot. Path to frame: ${JSON.stringify(reference)}`, err);
76
+ });
77
+ if (frameContext) {
78
+ const frameSnapshot = await takeContextDomSnapshot({ context: frameContext });
79
+ let url = new URL(frameSnapshot.url);
80
+ if (url.protocol === 'data:')
81
+ url = new URL(`http://data-url-frame${url.search}`);
82
+ if (!url.searchParams.has('applitools-iframe'))
83
+ url.searchParams.set('applitools-iframe', utils.general.guid());
84
+ frameSnapshot.url = url.href;
85
+ parentSnapshot.frames.push(frameSnapshot);
86
+ cdtNode.attributes.push({ name: 'data-applitools-src', value: frameSnapshot.url });
87
+ }
88
+ }
89
+ logger.log(`dom snapshot cdt length: ${snapshot.cdt.length}`);
90
+ logger.log(`blobs urls (${snapshot.blobs.length}):`, JSON.stringify(snapshot.blobs.map(({ url }) => url))); // eslint-disable-line prettier/prettier
91
+ logger.log(`resource urls (${snapshot.resourceUrls.length}):`, JSON.stringify(snapshot.resourceUrls)); // eslint-disable-line prettier/prettier
92
+ return snapshot;
93
+ }
94
+ }
95
+ exports.takeDomSnapshot = takeDomSnapshot;
96
+ function deserializeDomSnapshot({ snapshot }) {
97
+ const deserializedSnapshot = {
98
+ ...snapshot,
99
+ resourceContents: snapshot.blobs.reduce((resourceContents, blob) => {
100
+ if (blob.value === undefined)
101
+ return { ...resourceContents, [blob.url]: blob };
102
+ else
103
+ return { ...resourceContents, [blob.url]: { ...blob, value: Buffer.from(blob.value, 'base64') } };
104
+ }, {}),
105
+ frames: snapshot.frames.map(frameSnapshot => deserializeDomSnapshot({ snapshot: frameSnapshot })),
106
+ };
107
+ delete deserializedSnapshot.blobs;
108
+ delete deserializedSnapshot.selector;
109
+ delete deserializedSnapshot.crossFrames;
110
+ return deserializedSnapshot;
111
+ }
112
+ exports.deserializeDomSnapshot = deserializeDomSnapshot;
113
+ function extractCrossFrames({ snapshot, parent = null, logger }) {
114
+ var _a;
115
+ const crossFrames = [snapshot, ...((_a = snapshot.frames) !== null && _a !== void 0 ? _a : [])].flatMap((snapshot, index) => {
116
+ var _a;
117
+ const crossFrames = ((_a = snapshot.crossFrames) !== null && _a !== void 0 ? _a : []).map(({ selector, index }) => ({
118
+ reference: { reference: { type: 'css', selector }, parent },
119
+ parentSnapshot: snapshot,
120
+ cdtNode: snapshot.cdt[index],
121
+ }));
122
+ return [
123
+ ...crossFrames,
124
+ ...(index > 0
125
+ ? extractCrossFrames({ snapshot, parent: { reference: { type: 'css', selector: snapshot.selector }, parent }, logger })
126
+ : []),
127
+ ];
128
+ });
129
+ logger.log(`frames paths for ${snapshot.crossFrames}`, crossFrames.map(selector => JSON.stringify(selector)).join(' , '));
130
+ return crossFrames;
131
+ }
132
+ exports.extractCrossFrames = extractCrossFrames;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
+ };
28
+ var __importDefault = (this && this.__importDefault) || function (mod) {
29
+ return (mod && mod.__esModule) ? mod : { "default": mod };
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.takeDomSnapshots = void 0;
33
+ const take_dom_snapshot_1 = require("./take-dom-snapshot");
34
+ const chalk_1 = __importDefault(require("chalk"));
35
+ const utils = __importStar(require("@applitools/utils"));
36
+ __exportStar(require("./take-dom-snapshot"), exports);
37
+ async function takeDomSnapshots({ driver, settings, hooks, provides, logger, }) {
38
+ var _a, _b, _c, _d;
39
+ const currentContext = driver.currentContext;
40
+ await ((_a = hooks === null || hooks === void 0 ? void 0 : hooks.beforeSnapshots) === null || _a === void 0 ? void 0 : _a.call(hooks));
41
+ if (!settings.layoutBreakpoints) {
42
+ logger.log(`taking single dom snapshot`);
43
+ await ((_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _b === void 0 ? void 0 : _b.call(hooks));
44
+ await utils.general.sleep(settings.waitBeforeCapture);
45
+ const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
46
+ return Array(settings.renderers.length).fill(snapshot);
47
+ }
48
+ const isStrictBreakpoints = utils.types.isArray(settings.layoutBreakpoints);
49
+ const requiredWidths = await settings.renderers.reduce(async (prev, renderer, index) => {
50
+ const { name, width } = await extractRendererInfo({ renderer });
51
+ const requiredWidths = await prev;
52
+ const requiredWidth = isStrictBreakpoints
53
+ ? calculateBreakpoint({ breakpoints: settings.layoutBreakpoints, value: width })
54
+ : width;
55
+ let renderers = requiredWidths.get(requiredWidth);
56
+ if (!renderers)
57
+ requiredWidths.set(requiredWidth, (renderers = []));
58
+ renderers.push({ name, width, index });
59
+ return requiredWidths;
60
+ }, Promise.resolve(new Map()));
61
+ const smallestBreakpoint = Math.min(...(isStrictBreakpoints ? settings.layoutBreakpoints : []));
62
+ if (isStrictBreakpoints && requiredWidths.has(smallestBreakpoint - 1)) {
63
+ const smallestBrowsers = requiredWidths
64
+ .get(smallestBreakpoint - 1)
65
+ .map(({ name, width }) => `(${name}, ${width})`)
66
+ .join(', ');
67
+ const message = chalk_1.default.yellow(`The following configuration's viewport-widths are smaller than the smallest configured layout breakpoint (${smallestBreakpoint} pixels): [${smallestBrowsers}]. As a fallback, the resources that will be used for these configurations have been captured on a viewport-width of ${smallestBreakpoint} - 1 pixels. If an additional layout breakpoint is needed for you to achieve better results - please add it to your configuration.`);
68
+ logger.console.log(message);
69
+ }
70
+ logger.log(`taking multiple dom snapshots for breakpoints:`, settings.layoutBreakpoints);
71
+ logger.log(`required widths: ${[...requiredWidths.keys()].join(', ')}`);
72
+ const viewportSize = await driver.getViewportSize();
73
+ const snapshots = Array(settings.renderers.length);
74
+ if (requiredWidths.has(viewportSize.width)) {
75
+ logger.log(`taking dom snapshot for existing width ${viewportSize.width}`);
76
+ await ((_c = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _c === void 0 ? void 0 : _c.call(hooks));
77
+ await utils.general.sleep(settings.waitBeforeCapture);
78
+ const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
79
+ requiredWidths.get(viewportSize.width).forEach(({ index }) => (snapshots[index] = snapshot));
80
+ }
81
+ for (const [requiredWidth, browsersInfo] of requiredWidths.entries()) {
82
+ logger.log(`taking dom snapshot for width ${requiredWidth}`);
83
+ try {
84
+ await driver.setViewportSize({ width: requiredWidth, height: viewportSize.height });
85
+ }
86
+ catch (err) {
87
+ logger.error(err);
88
+ const actualViewportSize = await driver.getViewportSize();
89
+ if (isStrictBreakpoints) {
90
+ const failedBrowsers = browsersInfo.map(({ name, width }) => `(${name}, ${width})`).join(', ');
91
+ const message = chalk_1.default.yellow(`One of the configured layout breakpoints is ${requiredWidth} pixels, while your local browser has a limit of ${actualViewportSize.width}, so the SDK couldn't resize it to the desired size. As a fallback, the resources that will be used for the following configurations: [${failedBrowsers}] have been captured on the browser's limit (${actualViewportSize.width} pixels). To resolve this, you may use a headless browser as it can be resized to any size.`);
92
+ logger.console.log(message);
93
+ logger.log(message);
94
+ }
95
+ else {
96
+ const failedBrowsers = browsersInfo.map(({ name }) => `(${name})`).join(', ');
97
+ const message = chalk_1.default.yellow(`The following configurations [${failedBrowsers}] have a viewport-width of ${requiredWidth} pixels, while your local browser has a limit of ${actualViewportSize.width} pixels, so the SDK couldn't resize it to the desired size. As a fallback, the resources that will be used for these checkpoints have been captured on the browser's limit (${actualViewportSize.width} pixels). To resolve this, you may use a headless browser as it can be resized to any size.`);
98
+ logger.console.log(message);
99
+ logger.log(message);
100
+ }
101
+ }
102
+ await ((_d = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _d === void 0 ? void 0 : _d.call(hooks));
103
+ await utils.general.sleep(settings.waitBeforeCapture);
104
+ const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
105
+ browsersInfo.forEach(({ index }) => (snapshots[index] = snapshot));
106
+ }
107
+ await driver.setViewportSize(viewportSize);
108
+ return snapshots;
109
+ function calculateBreakpoint({ breakpoints, value }) {
110
+ const nextBreakpointIndex = breakpoints
111
+ .sort((item1, item2) => (item1 > item2 ? 1 : -1))
112
+ .findIndex(breakpoint => breakpoint > value);
113
+ if (nextBreakpointIndex === -1)
114
+ return breakpoints[breakpoints.length - 1];
115
+ else if (nextBreakpointIndex === 0)
116
+ return breakpoints[0] - 1;
117
+ else
118
+ return breakpoints[nextBreakpointIndex - 1];
119
+ }
120
+ async function extractRendererInfo({ renderer }) {
121
+ if (utils.types.has(renderer, ['width', 'height'])) {
122
+ const { name, width, height } = renderer;
123
+ return { name, width, height };
124
+ }
125
+ else {
126
+ let devices, info;
127
+ if (utils.types.has(renderer, 'chromeEmulationInfo')) {
128
+ info = renderer.chromeEmulationInfo;
129
+ devices = await provides.getChromeEmulationDevices();
130
+ }
131
+ else if (utils.types.has(renderer, 'iosDeviceInfo')) {
132
+ info = renderer.iosDeviceInfo;
133
+ devices = await provides.getIOSDevices();
134
+ }
135
+ const { deviceName, screenOrientation = 'portrait' } = info;
136
+ const size = devices[deviceName][screenOrientation];
137
+ return { name: deviceName, screenOrientation, ...size };
138
+ }
139
+ }
140
+ }
141
+ exports.takeDomSnapshots = takeDomSnapshots;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.takeSnapshots = void 0;
18
+ const take_dom_snapshots_1 = require("./take-dom-snapshots");
19
+ const take_vhses_1 = require("./take-vhses");
20
+ const nml_client_1 = require("@applitools/nml-client");
21
+ const extract_broker_url_1 = require("../../utils/extract-broker-url");
22
+ __exportStar(require("./take-dom-snapshots"), exports);
23
+ __exportStar(require("./take-vhses"), exports);
24
+ async function takeSnapshots({ driver, settings, hooks, provides, logger, }) {
25
+ if (driver.isWeb) {
26
+ return (0, take_dom_snapshots_1.takeDomSnapshots)({ driver, settings, hooks, provides, logger });
27
+ }
28
+ else {
29
+ const brokerUrl = await (0, extract_broker_url_1.extractBrokerUrl)(driver);
30
+ if (brokerUrl) {
31
+ return (0, nml_client_1.takeSnapshots)({ url: brokerUrl, settings, logger });
32
+ }
33
+ else {
34
+ return (0, take_vhses_1.takeVHSes)({ driver, settings, hooks, logger });
35
+ }
36
+ }
37
+ }
38
+ exports.takeSnapshots = takeSnapshots;