@applitools/core 2.5.2 → 2.5.3-legacy

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 (190) hide show
  1. package/dist/abort.js +40 -0
  2. package/dist/automation/abort.js +47 -0
  3. package/dist/automation/close.js +52 -0
  4. package/dist/automation/extract-text.js +3 -2
  5. package/dist/automation/get-nml-client.js +36 -0
  6. package/dist/automation/get-results.js +21 -0
  7. package/dist/automation/get-viewport-size.js +3 -2
  8. package/dist/automation/locate-text.js +3 -2
  9. package/dist/automation/locate.js +3 -2
  10. package/dist/automation/set-viewport-size.js +3 -2
  11. package/dist/automation/types.js +0 -15
  12. package/dist/automation/utils/report-kobiton.js +21 -0
  13. package/dist/automation/utils/take-screenshot.js +4 -2
  14. package/dist/automation/utils/to-base-check-settings.js +69 -7
  15. package/dist/automation/utils/to-environment-key.js +31 -0
  16. package/dist/automation/utils/uniquify-environments.js +27 -0
  17. package/dist/automation/utils/wait-for-lazy-load.js +9 -8
  18. package/dist/autonomous/core.js +25 -0
  19. package/dist/autonomous/create-render-results.js +49 -0
  20. package/dist/autonomous/create-render-target.js +19 -0
  21. package/dist/autonomous/get-render-results.js +55 -0
  22. package/dist/autonomous/open-eyes.js +13 -0
  23. package/dist/autonomous/start-renders.js +67 -0
  24. package/dist/autonomous/take-snapshots.js +16 -0
  25. package/dist/autonomous/types.js +17 -0
  26. package/dist/check-and-close.js +32 -15
  27. package/dist/check.js +33 -30
  28. package/dist/classic/check-and-close.js +189 -46
  29. package/dist/classic/check.js +319 -60
  30. package/dist/classic/core.js +6 -5
  31. package/dist/classic/get-base-eyes.js +27 -7
  32. package/dist/classic/open-eyes.js +47 -57
  33. package/dist/classic/utils/extract-default-environments.js +73 -0
  34. package/dist/classic/utils/take-dom-capture.js +2 -1
  35. package/dist/classic/utils/take-screenshots.js +63 -0
  36. package/dist/cli/cli.js +99 -3
  37. package/dist/close-batch.js +8 -7
  38. package/dist/close.js +32 -4
  39. package/dist/core.js +43 -9
  40. package/dist/delete-test.js +9 -7
  41. package/dist/extract-text.js +9 -5
  42. package/dist/get-account-info.js +36 -0
  43. package/dist/get-ec-client.js +3 -2
  44. package/dist/get-eyes-results.js +29 -3
  45. package/dist/get-manager-results.js +52 -18
  46. package/dist/get-typed-eyes.js +5 -6
  47. package/dist/index.js +3 -3
  48. package/dist/lang.js +31 -0
  49. package/dist/locate-text.js +7 -5
  50. package/dist/locate.js +7 -5
  51. package/dist/make-manager.js +34 -11
  52. package/dist/offline/merge-configs.js +42 -0
  53. package/dist/offline/run-offline-snapshots.js +341 -0
  54. package/dist/open-eyes.js +192 -48
  55. package/dist/run-offline-snapshots.js +336 -0
  56. package/dist/troubleshoot/check-network.js +5 -1
  57. package/dist/troubleshoot/eyes.js +3 -3
  58. package/dist/troubleshoot/logs.js +76 -0
  59. package/dist/troubleshoot/ufg.js +23 -16
  60. package/dist/ufg/check-and-close.js +109 -174
  61. package/dist/ufg/check.js +111 -178
  62. package/dist/ufg/core.js +10 -8
  63. package/dist/ufg/create-render-target-from-snapshot.js +21 -0
  64. package/dist/ufg/get-base-eyes.js +40 -12
  65. package/dist/ufg/get-ufg-client.js +13 -4
  66. package/dist/ufg/open-eyes.js +33 -57
  67. package/dist/ufg/take-snapshots.js +92 -0
  68. package/dist/ufg/utils/extract-default-environment.js +22 -0
  69. package/dist/ufg/utils/generate-safe-selectors.js +9 -32
  70. package/dist/ufg/utils/take-dom-snapshot.js +61 -26
  71. package/dist/ufg/utils/take-dom-snapshots.js +99 -68
  72. package/dist/ufg/utils/to-generated-selectors.js +67 -0
  73. package/dist/ufg/utils/to-safe-check-settings.js +69 -0
  74. package/dist/universal/core-server.js +53 -22
  75. package/dist/universal/core.js +23 -6
  76. package/dist/universal/history.js +9 -0
  77. package/dist/universal/spec-driver.js +46 -50
  78. package/dist/{ufg/get-nml-client.js → utils/ensure-offline-folder.js} +14 -13
  79. package/dist/utils/extract-branching-timestamp.js +56 -0
  80. package/dist/utils/extract-current-commit.js +72 -0
  81. package/dist/utils/extract-git-info.js +168 -0
  82. package/dist/utils/extract-start-info.js +100 -0
  83. package/dist/utils/extract-test-environment.js +70 -0
  84. package/dist/utils/memory-usage-logging.js +46 -0
  85. package/dist/utils/populate-eyes-server-settings.js +41 -0
  86. package/dist/utils/validate-sdk-version.js +89 -0
  87. package/package.json +3 -3
  88. package/types/abort.d.ts +13 -0
  89. package/types/automation/abort.d.ts +16 -0
  90. package/types/automation/close.d.ts +14 -0
  91. package/types/automation/extract-text.d.ts +1 -1
  92. package/types/automation/get-nml-client.d.ts +16 -0
  93. package/types/automation/get-results.d.ts +11 -0
  94. package/types/automation/get-viewport-size.d.ts +1 -1
  95. package/types/automation/locate-text.d.ts +1 -1
  96. package/types/automation/locate.d.ts +1 -1
  97. package/types/automation/set-viewport-size.d.ts +1 -1
  98. package/types/automation/types.d.ts +107 -16
  99. package/types/automation/utils/report-kobiton.d.ts +12 -0
  100. package/types/automation/utils/take-screenshot.d.ts +5 -2
  101. package/types/automation/utils/to-base-check-settings.d.ts +13 -3
  102. package/types/automation/utils/to-environment-key.d.ts +2 -0
  103. package/types/automation/utils/uniquify-environments.d.ts +2 -0
  104. package/types/automation/utils/wait-for-lazy-load.d.ts +4 -8
  105. package/types/autonomous/core.d.ts +19 -0
  106. package/types/autonomous/create-render-results.d.ts +10 -0
  107. package/types/autonomous/create-render-target.d.ts +12 -0
  108. package/types/autonomous/get-render-results.d.ts +12 -0
  109. package/types/autonomous/open-eyes.d.ts +13 -0
  110. package/types/autonomous/start-renders.d.ts +12 -0
  111. package/types/autonomous/take-snapshots.d.ts +15 -0
  112. package/types/autonomous/types.d.ts +57 -0
  113. package/types/check-and-close.d.ts +3 -3
  114. package/types/check.d.ts +3 -3
  115. package/types/classic/check-and-close.d.ts +12 -5
  116. package/types/classic/check.d.ts +6 -3
  117. package/types/classic/core.d.ts +8 -2
  118. package/types/classic/get-base-eyes.d.ts +4 -8
  119. package/types/classic/open-eyes.d.ts +3 -4
  120. package/types/classic/types.d.ts +4 -5
  121. package/types/classic/utils/extract-default-environments.d.ts +9 -0
  122. package/types/classic/utils/take-dom-capture.d.ts +8 -0
  123. package/types/classic/utils/take-screenshots.d.ts +18 -0
  124. package/types/close-batch.d.ts +1 -1
  125. package/types/close.d.ts +3 -2
  126. package/types/core.d.ts +11 -2
  127. package/types/delete-test.d.ts +1 -1
  128. package/types/extract-text.d.ts +1 -1
  129. package/types/get-account-info.d.ts +11 -0
  130. package/types/get-ec-client.d.ts +1 -1
  131. package/types/get-eyes-results.d.ts +1 -1
  132. package/types/get-manager-results.d.ts +1 -1
  133. package/types/get-typed-eyes.d.ts +2 -4
  134. package/types/index.d.ts +2 -1
  135. package/types/lang.d.ts +32 -0
  136. package/types/locate-text.d.ts +1 -1
  137. package/types/locate.d.ts +1 -1
  138. package/types/make-manager.d.ts +11 -2
  139. package/types/offline/merge-configs.d.ts +1 -0
  140. package/types/offline/run-offline-snapshots.d.ts +11 -0
  141. package/types/open-eyes.d.ts +11 -2
  142. package/types/run-offline-snapshots.d.ts +6 -0
  143. package/types/troubleshoot/logs.d.ts +25 -0
  144. package/types/types.d.ts +19 -11
  145. package/types/ufg/check-and-close.d.ts +18 -10
  146. package/types/ufg/check.d.ts +5 -4
  147. package/types/ufg/core.d.ts +8 -5
  148. package/types/ufg/create-render-target-from-snapshot.d.ts +8 -0
  149. package/types/ufg/get-base-eyes.d.ts +4 -9
  150. package/types/ufg/get-ufg-client.d.ts +6 -3
  151. package/types/ufg/open-eyes.d.ts +3 -4
  152. package/types/ufg/take-snapshots.d.ts +17 -0
  153. package/types/ufg/types.d.ts +39 -39
  154. package/types/ufg/utils/extract-default-environment.d.ts +5 -0
  155. package/types/ufg/utils/generate-safe-selectors.d.ts +3 -12
  156. package/types/ufg/utils/take-dom-snapshot.d.ts +16 -21
  157. package/types/ufg/utils/take-dom-snapshots.d.ts +14 -10
  158. package/types/ufg/utils/to-generated-selectors.d.ts +34 -0
  159. package/types/ufg/utils/to-safe-check-settings.d.ts +22 -0
  160. package/types/universal/core-server.d.ts +6 -2
  161. package/types/universal/core.d.ts +6 -2
  162. package/types/universal/spec-driver.d.ts +6 -5
  163. package/types/universal/types.d.ts +59 -51
  164. package/types/utils/ensure-offline-folder.d.ts +1 -0
  165. package/types/utils/extract-branching-timestamp.d.ts +16 -0
  166. package/types/utils/extract-current-commit.d.ts +24 -0
  167. package/types/utils/extract-git-info.d.ts +59 -0
  168. package/types/utils/extract-start-info.d.ts +29 -0
  169. package/types/utils/extract-test-environment.d.ts +2 -0
  170. package/types/utils/memory-usage-logging.d.ts +7 -0
  171. package/types/utils/populate-eyes-server-settings.d.ts +2 -0
  172. package/types/utils/validate-sdk-version.d.ts +42 -0
  173. package/CHANGELOG.md +0 -222
  174. package/dist/classic/abort.js +0 -22
  175. package/dist/classic/close.js +0 -22
  176. package/dist/ufg/abort.js +0 -32
  177. package/dist/ufg/close.js +0 -37
  178. package/dist/ufg/get-results.js +0 -27
  179. package/dist/ufg/utils/take-vhses.js +0 -153
  180. package/dist/ufg/utils/uniquify-renderers.js +0 -27
  181. package/dist/utils/extract-ci-provider.js +0 -31
  182. package/types/classic/abort.d.ts +0 -16
  183. package/types/classic/close.d.ts +0 -16
  184. package/types/ufg/abort.d.ts +0 -21
  185. package/types/ufg/close.d.ts +0 -19
  186. package/types/ufg/get-nml-client.d.ts +0 -17
  187. package/types/ufg/get-results.d.ts +0 -16
  188. package/types/ufg/utils/take-vhses.d.ts +0 -17
  189. package/types/ufg/utils/uniquify-renderers.d.ts +0 -2
  190. package/types/utils/extract-ci-provider.d.ts +0 -1
@@ -28,81 +28,57 @@ const driver_1 = require("@applitools/driver");
28
28
  const get_base_eyes_1 = require("./get-base-eyes");
29
29
  const check_1 = require("./check");
30
30
  const check_and_close_1 = require("./check-and-close");
31
- const close_1 = require("./close");
32
- const abort_1 = require("./abort");
33
- const get_results_1 = require("./get-results");
31
+ const close_1 = require("../automation/close");
32
+ const abort_1 = require("../automation/abort");
33
+ const get_results_1 = require("../automation/get-results");
34
+ const extract_default_environment_1 = require("./utils/extract-default-environment");
34
35
  const abort_controller_1 = require("abort-controller");
35
36
  const utils = __importStar(require("@applitools/utils"));
36
- function makeOpenEyes({ core, spec, logger: defaultLogger }) {
37
- return async function openEyes({ target, settings, base, logger = defaultLogger, }) {
38
- var _a, _b;
39
- logger.log(`Command "openEyes" is called with ${target ? 'default driver and' : ''}`, ...(settings ? ['settings', settings] : []), base ? 'predefined eyes' : '');
37
+ function makeOpenEyes({ core, spec, logger: mainLogger }) {
38
+ return async function openEyes({ target, settings, storage = new Map(), logger = mainLogger, }) {
39
+ var _a, _b, _c;
40
+ logger = logger.extend(mainLogger);
41
+ logger.log(`Command "openEyes" is called with ${target ? 'default driver' : ''}`, ...(settings ? ['and settings', settings] : []), storage.size > 0 ? 'and default eyes storage' : '');
40
42
  const driver = target && (await (0, driver_1.makeDriver)({ spec, driver: target, logger }));
41
- if (driver && !base) {
42
- const environment = await (driver === null || driver === void 0 ? void 0 : driver.getEnvironment());
43
- const currentContext = driver.currentContext;
44
- (_a = settings.environment) !== null && _a !== void 0 ? _a : (settings.environment = {});
45
- if (environment.isEC) {
46
- settings.environment.ecSessionId = (_b = (await driver.getSessionId())) !== null && _b !== void 0 ? _b : undefined;
47
- }
48
- if (settings.environment.viewportSize) {
43
+ if (driver && storage.size === 0) {
44
+ const environment = await driver.getEnvironment();
45
+ if (((_a = settings.environment) === null || _a === void 0 ? void 0 : _a.viewportSize) && !environment.isMobile) {
49
46
  await driver.setViewportSize(settings.environment.viewportSize);
50
47
  }
51
- await currentContext.focus();
48
+ (_b = settings.environment) !== null && _b !== void 0 ? _b : (settings.environment = {});
49
+ if (environment.isEC) {
50
+ settings.environment.ecSessionId = (_c = (await driver.getSessionId())) !== null && _c !== void 0 ? _c : undefined;
51
+ }
52
52
  }
53
+ const environments = await (0, extract_default_environment_1.extractDefaultEnvironments)({ driver });
53
54
  const controller = new abort_controller_1.AbortController();
55
+ const { signal } = controller;
54
56
  const account = await core.getAccountInfo({ settings, logger });
55
57
  return utils.general.extend({}, eyes => {
56
- var _a;
57
- const storage = new Map();
58
- let running = true;
58
+ var _a, _b, _c, _d;
59
59
  return {
60
60
  type: 'ufg',
61
61
  core,
62
62
  test: {
63
63
  userTestId: settings.userTestId,
64
64
  batchId: (_a = settings.batch) === null || _a === void 0 ? void 0 : _a.id,
65
+ batchBuildId: (_b = settings.batch) === null || _b === void 0 ? void 0 : _b.buildId,
65
66
  keepBatchOpen: settings.keepBatchOpen,
66
- server: account.server,
67
- ufgServer: account.ufgServer,
67
+ eyesServer: account.eyesServer,
68
+ ufgServer: { ...account.ufgServer, ufgServerUrl: (_c = settings.ufgServerUrl) !== null && _c !== void 0 ? _c : (_d = account.ufgServer) === null || _d === void 0 ? void 0 : _d.ufgServerUrl },
69
+ uploadUrl: account.uploadUrl,
70
+ stitchingServiceUrl: account.stitchingServiceUrl,
71
+ supportedEnvironmentsUrl: account.supportedEnvironmentsUrl,
68
72
  account,
69
73
  },
70
- get running() {
71
- return running;
72
- },
73
- getBaseEyes: (0, get_base_eyes_1.makeGetBaseEyes)({ settings, eyes, base, logger }),
74
- // check with indexing and storage
75
- check: utils.general.wrap((0, check_1.makeCheck)({ eyes, target: driver, spec, signal: controller.signal, logger }), async (check, options = {}) => {
76
- const results = await check(options);
77
- results.forEach(result => {
78
- var _a;
79
- const key = JSON.stringify(result.renderer);
80
- storage.set(key, [...((_a = storage.get(key)) !== null && _a !== void 0 ? _a : []), result.promise]);
81
- });
82
- return results;
83
- }),
84
- checkAndClose: utils.general.wrap((0, check_and_close_1.makeCheckAndClose)({ eyes, target: driver, spec, signal: controller.signal, logger }), async (checkAndClose, options = {}) => {
85
- const results = await checkAndClose(options);
86
- results.forEach(result => {
87
- var _a;
88
- const key = JSON.stringify(result.renderer);
89
- storage.set(key, [...((_a = storage.get(key)) !== null && _a !== void 0 ? _a : []), { eyes: result.eyes, renderer: result.renderer }]);
90
- });
91
- return results;
92
- }),
93
- close: utils.general.wrap((0, close_1.makeClose)({ storage, target: driver, logger }), async (close, options) => {
94
- if (!running)
95
- return;
96
- running = false;
97
- return close(options);
98
- }),
99
- abort: utils.general.wrap((0, abort_1.makeAbort)({ storage, target: driver, spec, controller, logger }), async (abort, options) => {
100
- if (!running)
101
- return;
102
- running = false;
103
- return abort(options);
104
- }),
105
- getResults: (0, get_results_1.makeGetResults)({ storage, logger }),
74
+ running: true,
75
+ storage,
76
+ getBaseEyes: (0, get_base_eyes_1.makeGetBaseEyes)({ settings, eyes, logger }),
77
+ check: (0, check_1.makeCheck)({ eyes, target: driver, environments, spec, signal, logger }),
78
+ checkAndClose: (0, check_and_close_1.makeCheckAndClose)({ eyes, target: driver, environments, spec, signal, logger }),
79
+ close: (0, close_1.makeClose)({ eyes, driver, logger }),
80
+ abort: (0, abort_1.makeAbort)({ eyes, driver, controller, logger }),
81
+ getResults: (0, get_results_1.makeGetResults)({ eyes, logger }),
106
82
  };
107
83
  });
108
84
  };
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeTakeSnapshots = void 0;
4
+ const driver_1 = require("@applitools/driver");
5
+ const take_dom_snapshots_1 = require("./utils/take-dom-snapshots");
6
+ const to_safe_check_settings_1 = require("./utils/to-safe-check-settings");
7
+ const to_generated_selectors_1 = require("./utils/to-generated-selectors");
8
+ const abort_error_1 = require("../errors/abort-error");
9
+ function makeTakeSnapshots({ core, spec, signal, logger: mainLogger }) {
10
+ return async function takeSnapshots({ driver, settings = {}, account, logger = mainLogger, }) {
11
+ var _a;
12
+ logger = logger.extend(mainLogger);
13
+ logger.log('Command "takeSnapshots" is called with settings', settings);
14
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
15
+ logger.warn('Command "takeSnapshots" was called after test was already aborted');
16
+ throw new abort_error_1.AbortError('Command "takeSnapshots" was called after test was already aborted');
17
+ }
18
+ const uniqueEnvironments = settings.environments;
19
+ if (!driver)
20
+ throw new Error('Cannot create check snapshot without a driver');
21
+ const environment = await driver.getEnvironment();
22
+ const currentContext = driver.currentContext;
23
+ await currentContext.setScrollingElement((_a = settings.scrollRootElement) !== null && _a !== void 0 ? _a : null);
24
+ const { elementReferences, getSafeCheckSettings } = (0, to_safe_check_settings_1.toSafeCheckSettings)({ settings });
25
+ const { elementReferencesToMark, getGeneratedSelectors } = (0, to_generated_selectors_1.toGeneratedSelectors)({
26
+ elementReferences,
27
+ logger,
28
+ // dead code - `transformElementReference` was used for NMG but it's not longer used anywhere
29
+ transformElementReference: elementReference => { var _a; return ((0, driver_1.isSelector)(elementReference) && ((_a = spec === null || spec === void 0 ? void 0 : spec.toSimpleCommonSelector) === null || _a === void 0 ? void 0 : _a.call(spec, elementReference))) || undefined; },
30
+ });
31
+ let snapshots;
32
+ if (environment.isWeb) {
33
+ const ufgClient = await core.getUFGClient({
34
+ settings: {
35
+ ...account.ufgServer,
36
+ eyesServerUrl: account.eyesServer.eyesServerUrl,
37
+ apiKey: account.eyesServer.apiKey,
38
+ },
39
+ logger,
40
+ });
41
+ snapshots = await (0, take_dom_snapshots_1.takeDomSnapshots)({
42
+ driver,
43
+ settings: {
44
+ waitBeforeCapture: settings.waitBeforeCapture,
45
+ disableBrowserFetching: settings.disableBrowserFetching,
46
+ layoutBreakpoints: settings.layoutBreakpoints,
47
+ environments: uniqueEnvironments,
48
+ skipResources: ufgClient.getCachedResourceUrls(),
49
+ lazyLoad: settings.lazyLoad,
50
+ elementReferences: elementReferencesToMark,
51
+ },
52
+ provides: {
53
+ getChromeEmulationDevices: ufgClient.getChromeEmulationDevices,
54
+ getIOSDevices: ufgClient.getIOSDevices,
55
+ },
56
+ logger,
57
+ });
58
+ }
59
+ else {
60
+ // dead code - used for NMG
61
+ const nmlClient = await core.getNMLClient({
62
+ driver,
63
+ settings: { ...account.eyesServer, supportedEnvironmentsUrl: account.supportedEnvironmentsUrl },
64
+ logger,
65
+ });
66
+ snapshots = await nmlClient.takeSnapshots({
67
+ settings: {
68
+ ...account.eyesServer,
69
+ waitBeforeCapture: settings.waitBeforeCapture,
70
+ environments: uniqueEnvironments,
71
+ },
72
+ logger,
73
+ });
74
+ }
75
+ await currentContext.focus();
76
+ const url = await driver.getUrl();
77
+ const title = await driver.getTitle();
78
+ const userAgent = environment.isWeb ? await driver.getUserAgentLegacy() : undefined;
79
+ return snapshots.map((snapshot, index) => ({
80
+ target: snapshot,
81
+ settings: getSafeCheckSettings({
82
+ selectors: getGeneratedSelectors(snapshot.generatedSelectors),
83
+ }),
84
+ environment: uniqueEnvironments[index],
85
+ account,
86
+ url,
87
+ title,
88
+ userAgent,
89
+ }));
90
+ };
91
+ }
92
+ exports.makeTakeSnapshots = makeTakeSnapshots;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractDefaultEnvironments = void 0;
4
+ async function extractDefaultEnvironments({ driver, }) {
5
+ if (!driver)
6
+ return [];
7
+ const currentContext = driver.currentContext;
8
+ try {
9
+ const environment = await driver.getEnvironment();
10
+ if (environment.isWeb) {
11
+ const viewportSize = await driver.getViewportSize();
12
+ return [{ name: 'chrome', ...viewportSize }];
13
+ }
14
+ else {
15
+ return [];
16
+ }
17
+ }
18
+ finally {
19
+ await currentContext.focus();
20
+ }
21
+ }
22
+ exports.extractDefaultEnvironments = extractDefaultEnvironments;
@@ -25,39 +25,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.generateSafeSelectors = void 0;
27
27
  const utils = __importStar(require("@applitools/utils"));
28
- const { addElementIds, cleanupElementIds } = require('@applitools/snippets');
28
+ const { addElementIds } = require('@applitools/snippets');
29
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(addElementIds, [
40
- mapping.elements.flat(),
41
- mapping.ids.flat(),
42
- ]);
43
- let offset = 0;
44
- const selectors = mapping.elements.map((elements, index) => {
45
- if (elements.length === 0)
46
- return { safeSelector: null, originalSelector: null, elementReference: elementReferences[index] };
47
- const safeSelector = generatedSelectors[offset].reduceRight((selector, value) => {
48
- return selector ? { type: 'css', selector: value, shadow: selector } : { type: 'css', selector: value };
49
- }, undefined);
50
- offset += elements.length;
51
- return { safeSelector, originalSelector: elements[0].commonSelector, elementReference: elementReferences[index] };
52
- });
53
- return {
54
- selectors,
55
- cleanupGeneratedSelectors,
56
- };
57
- async function cleanupGeneratedSelectors() {
58
- if (!mapping.elements.length)
59
- return;
60
- await context.execute(cleanupElementIds, [mapping.elements.flat()]);
30
+ if (!(elementReferences === null || elementReferences === void 0 ? void 0 : elementReferences.length))
31
+ return { generatedSelectors: [] };
32
+ // we can't structure elementsWithIds as object because it's not supported in safari webdriver (https://stackoverflow.com/questions/78953951/ios-safari-webdriver-executescript-fails-to-serialize-objects-with-elements)
33
+ const elementsWithIds = [];
34
+ for (const ref of elementReferences) {
35
+ const elements = await context.elements(ref);
36
+ elementsWithIds.push([elements, utils.general.guid()]); // same id for all elements that match the same ref
61
37
  }
38
+ return { generatedSelectors: await context.execute(addElementIds, elementsWithIds) };
62
39
  }
63
40
  exports.generateSafeSelectors = generateSafeSelectors;
@@ -23,24 +23,27 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.extractCrossFrames = exports.deserializeDomSnapshot = exports.takeDomSnapshot = void 0;
26
+ exports.takeDomSnapshot = void 0;
27
27
  const utils = __importStar(require("@applitools/utils"));
28
- const { getProcessPagePoll, getPollResult, getProcessPagePollForIE, getPollResultForIE, } = require('@applitools/dom-snapshot');
28
+ const { getProcessPagePoll, getPollResult } = require('@applitools/dom-snapshot');
29
29
  async function takeDomSnapshot({ context, settings, logger, }) {
30
+ var _a, _b;
30
31
  const driver = context.driver;
31
32
  const environment = await driver.getEnvironment();
32
33
  const features = await driver.getFeatures();
33
- const cookies = features.allCookies ? await driver.getCookies().catch(() => []) : [];
34
- const snapshot = deserializeDomSnapshot({ snapshot: await takeContextDomSnapshot({ context }) });
35
- snapshot.cookies = cookies;
34
+ const cookies = (_a = settings === null || settings === void 0 ? void 0 : settings.cookies) !== null && _a !== void 0 ? _a : [];
35
+ // assumption is that elementReferences are all in the frame which is `context`
36
+ // otherwise, the elements would still be found inside other frames, but `takeContextDomSnapshot` should be passed only the specific element references that it needs
37
+ const elements = [];
38
+ for (const elementReference of (_b = settings === null || settings === void 0 ? void 0 : settings.elementReferences) !== null && _b !== void 0 ? _b : []) {
39
+ elements.push(await context.elements(elementReference));
40
+ }
41
+ const snapshot = transformRawDomSnapshot(await takeContextDomSnapshot({ context }), elements);
42
+ snapshot.cookies = features.allCookies ? await driver.getCookies().catch(() => []) : cookies; // intentionally fetching cookies after the dom snapshot runs
36
43
  return snapshot;
37
44
  async function takeContextDomSnapshot({ context }) {
38
45
  // logger.log(`taking dom snapshot. ${context._reference ? `context referece: ${JSON.stringify(context._reference)}` : ''}`)
39
46
  var _a, _b, _c;
40
- if (!features.allCookies) {
41
- cookies.push(...(await context.getCookies()));
42
- }
43
- const isLegacyBrowser = environment.isIE || environment.isEdgeLegacy;
44
47
  const arg = {
45
48
  dontFetchResources: settings === null || settings === void 0 ? void 0 : settings.disableBrowserFetching,
46
49
  skipResources: settings === null || settings === void 0 ? void 0 : settings.skipResources,
@@ -50,14 +53,15 @@ async function takeDomSnapshot({ context, settings, logger, }) {
50
53
  serializeResources: true,
51
54
  compressResources: false,
52
55
  showLogs: settings === null || settings === void 0 ? void 0 : settings.showLogs,
56
+ elements,
53
57
  };
54
58
  const scripts = {
55
59
  main: features.canExecuteOnlyFunctionScripts
56
60
  ? require('@applitools/dom-snapshot').processPagePoll
57
- : `return (${isLegacyBrowser ? await getProcessPagePollForIE() : await getProcessPagePoll()}).apply(null, arguments);`,
61
+ : `return (${await getProcessPagePoll()}).apply(null, arguments);`,
58
62
  poll: features.canExecuteOnlyFunctionScripts
59
63
  ? require('@applitools/dom-snapshot').pollResult
60
- : `return (${isLegacyBrowser ? await getPollResultForIE() : await getPollResult()}).apply(null, arguments);`,
64
+ : `return (${await getPollResult()}).apply(null, arguments);`,
61
65
  };
62
66
  const snapshot = await context.executePoll(scripts, {
63
67
  main: arg,
@@ -65,6 +69,10 @@ async function takeDomSnapshot({ context, settings, logger, }) {
65
69
  executionTimeout: (_b = settings === null || settings === void 0 ? void 0 : settings.executionTimeout) !== null && _b !== void 0 ? _b : 5 * 60 * 1000,
66
70
  pollTimeout: (_c = settings === null || settings === void 0 ? void 0 : settings.pollTimeout) !== null && _c !== void 0 ? _c : 200,
67
71
  });
72
+ // intentionally fetching cookies after the dom snapshot runs
73
+ if (!features.allCookies) {
74
+ cookies.push(...(await context.getCookies()));
75
+ }
68
76
  const crossFrames = extractCrossFrames({ snapshot, logger });
69
77
  for (const { reference, parentSnapshot, cdtNode } of crossFrames) {
70
78
  const frameContext = await context
@@ -88,28 +96,34 @@ async function takeDomSnapshot({ context, settings, logger, }) {
88
96
  cdtNode.attributes.push({ name: 'data-applitools-src', value: frameSnapshot.url });
89
97
  }
90
98
  }
91
- logger.log(`dom snapshot cdt length: ${snapshot.cdt.length}`);
92
- logger.log(`blobs urls (${snapshot.blobs.length}):`, JSON.stringify(snapshot.blobs.map(({ url }) => url)));
93
- logger.log(`resource urls (${snapshot.resourceUrls.length}):`, JSON.stringify(snapshot.resourceUrls));
99
+ logSnapshot(logger, snapshot);
94
100
  return snapshot;
95
101
  }
96
102
  }
97
103
  exports.takeDomSnapshot = takeDomSnapshot;
98
- function deserializeDomSnapshot({ snapshot }) {
99
- const { blobs, selector: _, crossFrames: __, ...rest } = snapshot;
100
- const deserializedSnapshot = {
104
+ function transformRawDomSnapshot(snapshot, elements) {
105
+ const { blobs, safeSelectors, selector: _, crossFrames: __, ...rest } = snapshot;
106
+ const domSnapshot = {
101
107
  ...rest,
102
108
  resourceContents: blobs.reduce((resourceContents, blob) => {
103
- if (blob.value === undefined)
104
- return { ...resourceContents, [blob.url]: blob };
105
- else
106
- return { ...resourceContents, [blob.url]: { ...blob, value: Buffer.from(blob.value, 'base64') } };
109
+ return {
110
+ ...resourceContents,
111
+ [blob.url]: blob,
112
+ };
107
113
  }, {}),
108
- frames: snapshot.frames.map(frameSnapshot => deserializeDomSnapshot({ snapshot: frameSnapshot })),
114
+ frames: snapshot.frames.map(frameSnapshot => transformRawDomSnapshot(frameSnapshot)),
109
115
  };
110
- return deserializedSnapshot;
116
+ if (elements === null || elements === void 0 ? void 0 : elements.length) {
117
+ domSnapshot.generatedSelectors = elements.map((elements, i) => {
118
+ var _a, _b;
119
+ return ({
120
+ originalSelector: (_b = (_a = elements[0]) === null || _a === void 0 ? void 0 : _a.commonSelector) !== null && _b !== void 0 ? _b : null,
121
+ safeSelector: safeSelectors[i],
122
+ });
123
+ });
124
+ }
125
+ return domSnapshot;
111
126
  }
112
- exports.deserializeDomSnapshot = deserializeDomSnapshot;
113
127
  function extractCrossFrames({ snapshot, parent = null, logger, }) {
114
128
  var _a;
115
129
  const crossFrames = [snapshot, ...((_a = snapshot.frames) !== null && _a !== void 0 ? _a : [])].flatMap((snapshot, index) => {
@@ -130,7 +144,28 @@ function extractCrossFrames({ snapshot, parent = null, logger, }) {
130
144
  : []),
131
145
  ];
132
146
  });
133
- logger.log(`frames paths for ${snapshot.crossFrames}`, crossFrames.map(selector => JSON.stringify(selector)).join(' , '));
147
+ logger.log(...(snapshot.crossFrames
148
+ ? [
149
+ `dom snapshot - frames paths for ${JSON.stringify(snapshot.crossFrames)}:`,
150
+ crossFrames.map(selector => ({
151
+ // we don't want `selector.parentSnapshot` to be logged - the size of it can be huge
152
+ cdtNode: selector.cdtNode,
153
+ reference: selector.reference,
154
+ })),
155
+ ]
156
+ : ['dom snapshot - no cross frames found']));
134
157
  return crossFrames;
135
158
  }
136
- exports.extractCrossFrames = extractCrossFrames;
159
+ function logSnapshot(logger, snapshot) {
160
+ try {
161
+ logger.log(`dom snapshot - cdt length: ${snapshot.cdt.length}`);
162
+ logger.log(`dom snapshot - blobs urls (${snapshot.blobs.length}):`, JSON.stringify(snapshot.blobs.map(({ url }) => url)));
163
+ logger.log(`dom snapshot - resource urls (${snapshot.resourceUrls.length}):`, JSON.stringify(snapshot.resourceUrls));
164
+ logger.log(`dom snapshot - cdt nodes with data-applitools-selector: ${JSON.stringify(snapshot.cdt.filter(node => { var _a; return (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.some(attr => attr.name === 'data-applitools-selector'); }))}`);
165
+ logger.log('dom snapshot - safeSelectors:', snapshot.safeSelectors);
166
+ logger.log('dom snapshot - warnings:', snapshot.warnings);
167
+ }
168
+ catch (err) {
169
+ logger.error(`error while logging dom snapshot`, err);
170
+ }
171
+ }
@@ -31,89 +31,120 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
32
  exports.takeDomSnapshots = void 0;
33
33
  const take_dom_snapshot_1 = require("./take-dom-snapshot");
34
- const utils = __importStar(require("@applitools/utils"));
34
+ const generate_safe_selectors_1 = require("./generate-safe-selectors");
35
+ const wait_for_lazy_load_1 = require("../../automation/utils/wait-for-lazy-load");
35
36
  const chalk_1 = __importDefault(require("chalk"));
37
+ const utils = __importStar(require("@applitools/utils"));
38
+ const lang = __importStar(require("../../lang"));
36
39
  __exportStar(require("./take-dom-snapshot"), exports);
37
40
  async function takeDomSnapshots({ driver, settings, hooks, provides, logger, }) {
38
- var _a, _b, _c, _d;
41
+ var _a, _b;
42
+ // calculating cookies here once so that we (a) don't do it for each dom snapshot, and (b) do it before generating safe selectors
43
+ const features = await driver.getFeatures();
44
+ settings.cookies = features.allCookies ? await driver.getCookies().catch(() => []) : [];
45
+ settings.lazyLoad = settings.lazyLoad !== true ? settings.lazyLoad : {};
39
46
  const currentContext = driver.currentContext;
40
- const waitBeforeCapture = async () => {
41
- if (utils.types.isFunction(settings.waitBeforeCapture)) {
42
- await settings.waitBeforeCapture();
43
- }
44
- else if (settings.waitBeforeCapture) {
45
- await utils.general.sleep(settings.waitBeforeCapture);
47
+ if (!((_a = settings.layoutBreakpoints) === null || _a === void 0 ? void 0 : _a.breakpoints)) {
48
+ if (settings.lazyLoad) {
49
+ await (0, wait_for_lazy_load_1.waitForLazyLoad)({ context: currentContext, settings: settings.lazyLoad, logger });
46
50
  }
47
- };
48
- await ((_a = hooks === null || hooks === void 0 ? void 0 : hooks.beforeSnapshots) === null || _a === void 0 ? void 0 : _a.call(hooks));
49
- if (!settings.layoutBreakpoints) {
50
51
  logger.log(`taking single dom snapshot`);
51
- await ((_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _b === void 0 ? void 0 : _b.call(hooks));
52
- await waitBeforeCapture();
52
+ await beforeEachSnapshot();
53
53
  const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
54
- return Array(settings.renderers.length).fill(snapshot);
54
+ return Array(settings.environments.length).fill(snapshot);
55
55
  }
56
- const isStrictBreakpoints = utils.types.isArray(settings.layoutBreakpoints);
57
- const requiredWidths = await settings.renderers.reduce(async (prev, renderer, index) => {
58
- const { name, width } = (await extractRendererInfo({ renderer }));
56
+ const isStrictBreakpoints = utils.types.isArray((_b = settings.layoutBreakpoints) === null || _b === void 0 ? void 0 : _b.breakpoints);
57
+ const requiredWidths = await settings.environments.reduce(async (prev, environment, index) => {
58
+ const { name, width } = (await extractEnvironmentInfo(environment));
59
59
  const requiredWidths = await prev;
60
60
  const requiredWidth = isStrictBreakpoints
61
- ? calculateBreakpoint({ breakpoints: settings.layoutBreakpoints, value: width })
61
+ ? calculateBreakpoint({ breakpoints: settings.layoutBreakpoints.breakpoints, value: width })
62
62
  : width;
63
- let renderers = requiredWidths.get(requiredWidth);
64
- if (!renderers)
65
- requiredWidths.set(requiredWidth, (renderers = []));
66
- renderers.push({ name, width, index });
63
+ let environments = requiredWidths.get(requiredWidth);
64
+ if (!environments)
65
+ requiredWidths.set(requiredWidth, (environments = []));
66
+ environments.push({ name, width, index });
67
67
  return requiredWidths;
68
68
  }, Promise.resolve(new Map()));
69
- const smallestBreakpoint = Math.min(...(isStrictBreakpoints ? settings.layoutBreakpoints : []));
69
+ const smallestBreakpoint = Math.min(...(isStrictBreakpoints ? settings.layoutBreakpoints.breakpoints : []));
70
70
  if (isStrictBreakpoints && requiredWidths.has(smallestBreakpoint - 1)) {
71
- const smallestBrowsers = requiredWidths
72
- .get(smallestBreakpoint - 1)
73
- .map(({ name, width }) => `(${name}, ${width})`)
74
- .join(', ');
75
- 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.`);
76
- logger.console.log(message);
71
+ const message = lang.requestedEnvironmentSmallerThenBreakpointWarning({
72
+ breakpoint: smallestBreakpoint,
73
+ browsers: requiredWidths.get(smallestBreakpoint - 1),
74
+ });
75
+ logger.console.log(chalk_1.default.yellow(message));
77
76
  }
78
- logger.log(`taking multiple dom snapshots for breakpoints:`, settings.layoutBreakpoints);
79
- logger.log(`required widths: ${[...requiredWidths.keys()].join(', ')}`);
80
- const viewportSize = await driver.getViewportSize();
81
- const snapshots = Array(settings.renderers.length);
82
- if (requiredWidths.has(viewportSize.width)) {
83
- logger.log(`taking dom snapshot for existing width ${viewportSize.width}`);
84
- await ((_c = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _c === void 0 ? void 0 : _c.call(hooks));
85
- await waitBeforeCapture();
86
- const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
87
- requiredWidths.get(viewportSize.width).forEach(({ index }) => (snapshots[index] = snapshot));
77
+ logger.log(`Taking multiple dom snapshots for the breakpoints`, settings.layoutBreakpoints);
78
+ const initialViewportSize = await driver.getViewportSize();
79
+ const entries = [];
80
+ const initialsBrowsers = requiredWidths.get(initialViewportSize.width);
81
+ if (initialsBrowsers) {
82
+ logger.log(`The first dom snapshot is going to be taking for initial viewport size`, initialViewportSize);
83
+ requiredWidths.delete(initialViewportSize.width);
84
+ entries.push({ browsers: initialsBrowsers });
88
85
  }
89
- for (const [requiredWidth, browsersInfo] of requiredWidths.entries()) {
90
- logger.log(`taking dom snapshot for width ${requiredWidth}`);
91
- try {
92
- await driver.setViewportSize({ width: requiredWidth, height: viewportSize.height });
93
- }
94
- catch (err) {
95
- logger.error(err);
96
- const actualViewportSize = await driver.getViewportSize();
97
- if (isStrictBreakpoints) {
98
- const failedBrowsers = browsersInfo.map(({ name, width }) => `(${name}, ${width})`).join(', ');
99
- 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.`);
100
- logger.console.log(message);
101
- logger.log(message);
86
+ requiredWidths.forEach((browsers, requiredWidth) => entries.push({ viewportSize: { width: requiredWidth, height: initialViewportSize.height }, browsers }));
87
+ logger.log(`All entries to take dom snapshots for`, entries);
88
+ // making safe selectors before any resize in order to make sure fallback selectors are created
89
+ await (0, generate_safe_selectors_1.generateSafeSelectors)({
90
+ context: currentContext,
91
+ elementReferences: settings.elementReferences,
92
+ });
93
+ const snapshots = Array(settings.environments.length);
94
+ for (const [index, { viewportSize, browsers }] of entries.entries()) {
95
+ logger.log(`Taking dom snapshot for viewport size ${viewportSize}`);
96
+ if (viewportSize) {
97
+ try {
98
+ await driver.setViewportSize(viewportSize);
102
99
  }
103
- else {
104
- const failedBrowsers = browsersInfo.map(({ name }) => `(${name})`).join(', ');
105
- 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.`);
106
- logger.console.log(message);
107
- logger.log(message);
100
+ catch (error) {
101
+ logger.error(`Failed to set viewport size to ${viewportSize} due to the error`, error);
102
+ const actualViewportSize = await driver.getViewportSize();
103
+ if (isStrictBreakpoints) {
104
+ const message = lang.breakpointOutOfDriverBoundsWarning({
105
+ requiredWidth: viewportSize.width,
106
+ actualWidth: actualViewportSize.width,
107
+ browsers,
108
+ });
109
+ logger.console.log(chalk_1.default.yellow(message));
110
+ logger.log(message);
111
+ }
112
+ else {
113
+ const message = lang.requestedEnvironmentOutOfDriverBoundsWarning({
114
+ requiredWidth: viewportSize.width,
115
+ actualWidth: actualViewportSize.width,
116
+ browsers,
117
+ });
118
+ logger.console.log(chalk_1.default.yellow(message));
119
+ logger.log(message);
120
+ }
108
121
  }
109
122
  }
110
- await ((_d = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _d === void 0 ? void 0 : _d.call(hooks));
111
- await waitBeforeCapture();
123
+ if (settings.layoutBreakpoints.reload)
124
+ await driver.reloadPage();
125
+ if (settings.lazyLoad && (index === 0 || settings.layoutBreakpoints.reload)) {
126
+ await (0, wait_for_lazy_load_1.waitForLazyLoad)({ context: currentContext, settings: settings.lazyLoad, logger });
127
+ }
128
+ await beforeEachSnapshot();
112
129
  const snapshot = await (0, take_dom_snapshot_1.takeDomSnapshot)({ context: currentContext, settings, logger });
113
- browsersInfo.forEach(({ index }) => (snapshots[index] = snapshot));
130
+ browsers.forEach(({ index }) => (snapshots[index] = snapshot));
131
+ }
132
+ await driver.setViewportSize(initialViewportSize);
133
+ if (settings.layoutBreakpoints.reload) {
134
+ await driver.reloadPage();
135
+ await beforeEachSnapshot();
114
136
  }
115
- await driver.setViewportSize(viewportSize);
116
137
  return snapshots;
138
+ async function beforeEachSnapshot() {
139
+ var _a, _b;
140
+ await ((_a = hooks === null || hooks === void 0 ? void 0 : hooks.beforeEachSnapshot) === null || _a === void 0 ? void 0 : _a.call(hooks));
141
+ if (utils.types.isNumber(settings.waitBeforeCapture)) {
142
+ await utils.general.sleep(settings.waitBeforeCapture);
143
+ }
144
+ else {
145
+ await ((_b = settings.waitBeforeCapture) === null || _b === void 0 ? void 0 : _b.call(settings));
146
+ }
147
+ }
117
148
  function calculateBreakpoint({ breakpoints, value }) {
118
149
  const nextBreakpointIndex = breakpoints
119
150
  .sort((item1, item2) => (item1 > item2 ? 1 : -1))
@@ -125,19 +156,19 @@ async function takeDomSnapshots({ driver, settings, hooks, provides, logger, })
125
156
  else
126
157
  return breakpoints[nextBreakpointIndex - 1];
127
158
  }
128
- async function extractRendererInfo({ renderer }) {
129
- if (utils.types.has(renderer, ['width', 'height'])) {
130
- const { name, width, height } = renderer;
159
+ async function extractEnvironmentInfo(environment) {
160
+ if (utils.types.has(environment, ['width', 'height'])) {
161
+ const { name, width, height } = environment;
131
162
  return { name: name !== null && name !== void 0 ? name : 'default', width, height };
132
163
  }
133
- else if (utils.types.has(renderer, 'chromeEmulationInfo')) {
164
+ else if (utils.types.has(environment, 'chromeEmulationInfo')) {
134
165
  const devices = await provides.getChromeEmulationDevices();
135
- const { deviceName, screenOrientation = 'portrait' } = renderer.chromeEmulationInfo;
166
+ const { deviceName, screenOrientation = 'portrait' } = environment.chromeEmulationInfo;
136
167
  return { name: deviceName, screenOrientation, ...devices[deviceName][screenOrientation] };
137
168
  }
138
- else if (utils.types.has(renderer, 'iosDeviceInfo')) {
169
+ else if (utils.types.has(environment, 'iosDeviceInfo')) {
139
170
  const devices = await provides.getIOSDevices();
140
- const { deviceName, screenOrientation = 'portrait' } = renderer.iosDeviceInfo;
171
+ const { deviceName, screenOrientation = 'portrait' } = environment.iosDeviceInfo;
141
172
  return { name: deviceName, screenOrientation, ...devices[deviceName][screenOrientation] };
142
173
  }
143
174
  }