@applitools/core 4.13.1 → 4.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,68 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.15.0](https://github.com/Applitools-Dev/sdk/compare/js/core@4.14.0...js/core@4.15.0) (2024-05-07)
4
+
5
+
6
+ ### Features
7
+
8
+ * expose git latest commit info in env vars ([#2349](https://github.com/Applitools-Dev/sdk/issues/2349)) ([1db248c](https://github.com/Applitools-Dev/sdk/commit/1db248c83ee1cbc83f905163fe5bd63dd5e293c2))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * @applitools/dom-capture bumped to 11.2.7
14
+ #### Bug Fixes
15
+
16
+ * capture user input from input elements ([#2347](https://github.com/Applitools-Dev/sdk/issues/2347)) ([f82d3bb](https://github.com/Applitools-Dev/sdk/commit/f82d3bbc79c624ab7e8eeade7559b523f6adfeac))
17
+ * @applitools/ec-client bumped to 1.8.5
18
+
19
+ * @applitools/core-base bumped to 1.14.0
20
+ #### Features
21
+
22
+ * expose git latest commit info in env vars ([#2349](https://github.com/Applitools-Dev/sdk/issues/2349)) ([1db248c](https://github.com/Applitools-Dev/sdk/commit/1db248c83ee1cbc83f905163fe5bd63dd5e293c2))
23
+ * long eyes requests with custom domain ([#2343](https://github.com/Applitools-Dev/sdk/issues/2343)) ([d54beea](https://github.com/Applitools-Dev/sdk/commit/d54beea8c33a56a0516904773daaa5095340fd12))
24
+
25
+ ## [4.14.0](https://github.com/Applitools-Dev/sdk/compare/js/core@4.13.1...js/core@4.14.0) (2024-05-01)
26
+
27
+
28
+ ### Features
29
+
30
+ * `matchTimeout` ([#2309](https://github.com/Applitools-Dev/sdk/issues/2309)) ([626529e](https://github.com/Applitools-Dev/sdk/commit/626529e839fd2a96ac0de98332f42873c0f387a4))
31
+
32
+
33
+ ### Bug Fixes
34
+
35
+ * cache nml client per driver ([#2336](https://github.com/Applitools-Dev/sdk/issues/2336)) ([02c09a5](https://github.com/Applitools-Dev/sdk/commit/02c09a53eb6ca6340c93365908f4c485ab389c21))
36
+ * support for using unicode and just using escape with numbers ([#2241](https://github.com/Applitools-Dev/sdk/issues/2241)) ([c59f47f](https://github.com/Applitools-Dev/sdk/commit/c59f47f73585d7f308c43c9ee1845e097a2111a3))
37
+
38
+
39
+ ### Dependencies
40
+
41
+ * @applitools/dom-snapshot bumped to 4.11.1
42
+ #### Bug Fixes
43
+
44
+ * support for using unicode and just using escape with numbers ([#2241](https://github.com/Applitools-Dev/sdk/issues/2241)) ([c59f47f](https://github.com/Applitools-Dev/sdk/commit/c59f47f73585d7f308c43c9ee1845e097a2111a3))
45
+ * @applitools/spec-driver-webdriver bumped to 1.1.7
46
+
47
+ * @applitools/spec-driver-selenium bumped to 1.5.78
48
+
49
+ * @applitools/spec-driver-puppeteer bumped to 1.4.7
50
+
51
+ * @applitools/driver bumped to 1.17.2
52
+ #### Bug Fixes
53
+
54
+ * cache nml client per driver ([#2336](https://github.com/Applitools-Dev/sdk/issues/2336)) ([02c09a5](https://github.com/Applitools-Dev/sdk/commit/02c09a53eb6ca6340c93365908f4c485ab389c21))
55
+ * @applitools/screenshoter bumped to 3.8.31
56
+
57
+ * @applitools/nml-client bumped to 1.8.4
58
+
59
+ * @applitools/ec-client bumped to 1.8.4
60
+
61
+ * @applitools/core-base bumped to 1.13.0
62
+ #### Features
63
+
64
+ * `matchTimeout` ([#2309](https://github.com/Applitools-Dev/sdk/issues/2309)) ([626529e](https://github.com/Applitools-Dev/sdk/commit/626529e839fd2a96ac0de98332f42873c0f387a4))
65
+
3
66
  ## [4.13.1](https://github.com/Applitools-Dev/sdk/compare/js/core@4.13.0...js/core@4.13.1) (2024-04-22)
4
67
 
5
68
 
package/dist/check.js CHANGED
@@ -48,7 +48,7 @@ function makeCheck({ type: defaultType = 'classic', eyes, target: defaultTarget,
48
48
  (_g = settings.sendDom) !== null && _g !== void 0 ? _g : (settings.sendDom = eyes.test.account.rcaEnabled || settings.matchLevel === 'Layout' || settings.enablePatterns || settings.useDom);
49
49
  (_h = settings.autProxy) !== null && _h !== void 0 ? _h : (settings.autProxy = eyes.test.eyesServer.proxy);
50
50
  (_j = settings.useDom) !== null && _j !== void 0 ? _j : (settings.useDom = false);
51
- (_k = (_q = settings).retryTimeout) !== null && _k !== void 0 ? _k : (_q.retryTimeout = 2000);
51
+ (_k = (_q = settings).retryTimeout) !== null && _k !== void 0 ? _k : (_q.retryTimeout = 0);
52
52
  settings.lazyLoad = settings.lazyLoad === true ? {} : settings.lazyLoad;
53
53
  if (settings.lazyLoad) {
54
54
  (_l = (_r = settings.lazyLoad).scrollLength) !== null && _l !== void 0 ? _l : (_r.scrollLength = 300);
@@ -40,9 +40,11 @@ const utils = __importStar(require("@applitools/utils"));
40
40
  const lang = __importStar(require("../lang"));
41
41
  function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironments = [], spec, signal, logger: mainLogger, }) {
42
42
  return async function check({ target = defaultTarget, settings = {}, logger = mainLogger, } = {}) {
43
- var _a, _b, _c;
43
+ var _a;
44
+ // logging
44
45
  logger = logger.extend(mainLogger);
45
46
  logger.log('Command "check" is called with settings', settings);
47
+ // input validation and sanitization
46
48
  if (!target)
47
49
  throw new Error('Method was called with no target');
48
50
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
@@ -50,173 +52,275 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
50
52
  throw new abort_error_1.AbortError('Command "check" was called after test was already aborted');
51
53
  }
52
54
  const uniqueEnvironments = (0, uniquify_environments_1.uniquifyEnvironments)((_a = settings.environments) !== null && _a !== void 0 ? _a : defaultEnvironments);
53
- const baseTargets = [];
54
- const baseSettings = [];
55
- const exactEnvironments = [];
56
- let driver;
55
+ let driver = undefined;
57
56
  if ((0, driver_1.isDriver)(target, spec)) {
58
57
  driver = await (0, driver_1.makeDriver)({ spec, driver: target, reset: target === defaultTarget, logger });
59
- await driver.currentContext.setScrollingElement((_b = settings.scrollRootElement) !== null && _b !== void 0 ? _b : null);
60
- const driverEnvironment = await driver.getEnvironment();
61
- uniqueEnvironments.forEach(environment => {
62
- var _a, _b;
63
- var _c, _d;
64
- if (utils.types.has(environment, 'iosDeviceInfo')) {
65
- (_a = (_c = environment.iosDeviceInfo).version) !== null && _a !== void 0 ? _a : (_c.version = driverEnvironment.platformVersion);
58
+ if (settings.retryTimeout) {
59
+ // when retry timeout is set, retry checking until it passes or timeout is reached. This will stall the client test execution until it passes or timeout is reached to prevent the test from continuing and changing the state of the app
60
+ logger.log(`Retry timeout is set to ${settings.retryTimeout}ms - will retry checking until it passes or timeout is reached`);
61
+ const start = Date.now();
62
+ if (await isNewTest({ eyes, driver, environments: uniqueEnvironments, logger })) {
63
+ await new Promise(resolve => setTimeout(resolve, settings.retryTimeout));
66
64
  }
67
- else if (utils.types.has(environment, 'androidDeviceInfo')) {
68
- (_b = (_d = environment.androidDeviceInfo).version) !== null && _b !== void 0 ? _b : (_d.version = driverEnvironment.platformVersion);
69
- }
70
- return environment;
71
- });
72
- if (settings.lazyLoad && driverEnvironment.isWeb) {
73
- await (0, wait_for_lazy_load_1.waitForLazyLoad)({
74
- context: driver.currentContext,
75
- settings: settings.lazyLoad !== true ? settings.lazyLoad : {},
76
- logger,
77
- });
78
- }
79
- if (driverEnvironment.isWeb ||
80
- !((_c = driverEnvironment.applitoolsLib) === null || _c === void 0 ? void 0 : _c.instrumented) ||
81
- settings.webview ||
82
- settings.screenshotMode === 'default') {
83
- let actualEnvironments = uniqueEnvironments;
84
- if (settings.screenshotMode === 'default') {
85
- const { localEnvironment, renderEnvironments } = await (0, nml_client_1.getNMLEnvironmentsInfo)({
86
- environments: uniqueEnvironments,
87
- supportedEnvironmentsUrl: eyes.test.supportedEnvironmentsUrl,
88
- proxy: eyes.test.eyesServer.proxy,
89
- logger,
65
+ let asExpected = false, retries = 0;
66
+ do {
67
+ retries++;
68
+ // generate base targets (images to be compared) and settings for each environment
69
+ const baseScreenshotsAndSettings = await generateBaseScreenshotsAndSettings(settings, uniqueEnvironments, eyes, logger, driver);
70
+ const promises = baseScreenshotsAndSettings.map(async ({ exactEnvironment: environment, baseSetting: settings, baseTarget: target }) => {
71
+ return await checkEnvironment({
72
+ eyes,
73
+ driver,
74
+ target,
75
+ environment,
76
+ signal,
77
+ logger,
78
+ settings: {
79
+ ...settings,
80
+ replaceLast: retries > 1,
81
+ },
82
+ });
90
83
  });
91
- actualEnvironments = localEnvironment ? [localEnvironment] : renderEnvironments;
92
- }
93
- const { elementReferences, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({ settings });
94
- const screenshots = await (0, take_screenshots_1.takeScreenshots)({
95
- driver,
96
- settings: {
97
- ...settings,
98
- environments: actualEnvironments,
99
- regionsToCalculate: elementReferences.calculate,
100
- calculateView: !!settings.pageId,
101
- domSettings: settings.sendDom ? { proxy: eyes.test.eyesServer.proxy } : undefined,
102
- },
103
- logger,
104
- });
105
- exactEnvironments.push(...actualEnvironments);
106
- screenshots.forEach(({ calculatedRegions, ...baseTarget }) => {
107
- baseTargets.push(baseTarget);
108
- baseSettings.push(getBaseCheckSettings({ calculatedRegions }));
109
- });
84
+ const results = await Promise.all(promises);
85
+ asExpected = results.every(result => result.asExpected);
86
+ if (retries === 1) {
87
+ baseScreenshotsAndSettings.forEach(({ exactEnvironment }) => {
88
+ // put dummy promises in storage to tell eyes.close that all checks hepped
89
+ putInStorage(exactEnvironment, eyes, Promise.resolve());
90
+ });
91
+ }
92
+ } while (!asExpected && Date.now() - start < settings.retryTimeout);
110
93
  }
111
94
  else {
112
- if (driverEnvironment.applitoolsLib.conflictingCapabilities) {
113
- const message = lang.applitoolsLibConflictingCapabilitiesWarning({
114
- conflictingCapabilities: driverEnvironment.applitoolsLib.conflictingCapabilities,
115
- });
116
- logger.console.log(chalk_1.default.yellow(message));
117
- logger.log(message);
118
- }
119
- const nmlClient = await eyes.core.getNMLClient({
120
- driver,
121
- settings: { ...eyes.test.eyesServer, supportedEnvironmentsUrl: eyes.test.supportedEnvironmentsUrl },
122
- logger,
95
+ // generate base targets (images to be compared) and settings for each environment
96
+ const baseScreenshotsAndSettings = await generateBaseScreenshotsAndSettings(settings, uniqueEnvironments, eyes, logger, driver);
97
+ // when no retry timeout is set, queue all environment checks against the server without stalling the client test execution
98
+ baseScreenshotsAndSettings.forEach(({ exactEnvironment: environment, baseSetting, baseTarget }) => {
99
+ checkInTheBackground(environment, baseTarget, baseSetting);
123
100
  });
124
- if (settings.scrollRootElement || settings.region || (0, to_base_check_settings_1.hasCodedRegions)(settings))
125
- await nmlClient.preTakeScreenshot({ logger });
126
- const { elementReferences, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({
127
- settings: {
128
- ...settings,
129
- ...(await (0, to_base_check_settings_1.extractMobileElementsIntoCheckSettings)({ settings, driver, logger })),
130
- },
131
- });
132
- const calculate = elementReferences.calculate;
133
- const screenshots = await nmlClient.takeScreenshots({
134
- settings: {
135
- environments: uniqueEnvironments,
136
- fully: settings.fully,
137
- stitchMode: settings.stitchMode,
138
- hideScrollbars: settings.hideScrollbars,
139
- hideCaret: settings.hideScrollbars,
140
- overlap: settings.overlap,
141
- waitBeforeCapture: settings.waitBeforeCapture,
142
- waitBetweenStitches: settings.waitBetweenStitches,
143
- lazyLoad: settings.lazyLoad,
144
- name: settings.name,
145
- region: elementReferences.target,
146
- selectorsToFindRegionsFor: calculate.map(({ name }) => name),
147
- scrollRootElement: elementReferences.scrolling,
148
- },
149
- logger,
101
+ }
102
+ }
103
+ else {
104
+ uniqueEnvironments.forEach(environment => checkInTheBackground(environment, target, settings));
105
+ }
106
+ function checkInTheBackground(environment, target, settings) {
107
+ putInStorage(environment, eyes, checkEnvironment({ eyes, driver, target, environment, signal, logger, settings }));
108
+ }
109
+ };
110
+ function putInStorage(environment, eyes, promise) {
111
+ const key = (0, to_environment_key_1.toEnvironmentKey)(environment);
112
+ let item = eyes.storage.get(key);
113
+ if (!item) {
114
+ item = { eyes: utils.promises.makeControlledPromise(), jobs: [] };
115
+ eyes.storage.set(key, item);
116
+ }
117
+ item.jobs.push(promise.then());
118
+ return item;
119
+ }
120
+ }
121
+ exports.makeCheck = makeCheck;
122
+ async function isNewTest({ eyes, driver, environments, logger, }) {
123
+ const environmentLogger = logger.extend({ tags: [`environment-${utils.general.shortid()}`] });
124
+ return (await Promise.all(environments.map(async (environment) => await eyes.getBaseEyes({ settings: { environment, driver }, logger: environmentLogger }))))
125
+ .map(baseEyes => baseEyes.test.isNew)
126
+ .some(isNew => isNew);
127
+ }
128
+ async function checkEnvironment({ eyes, driver, target, environment, signal, logger, settings, }) {
129
+ var _a, _b;
130
+ const environmentLogger = logger.extend({ tags: [`environment-${utils.general.shortid()}`] });
131
+ environmentLogger.log('Command "check" is called with settings', settings);
132
+ try {
133
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
134
+ abortError({ logger: environmentLogger, message: 'Command "check" was aborted before checking' });
135
+ }
136
+ const baseEyes = await eyes.getBaseEyes({ settings: { environment, driver }, logger: environmentLogger });
137
+ try {
138
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
139
+ abortError({
140
+ logger: environmentLogger,
141
+ message: `Command "check" was aborted before checking`,
150
142
  });
151
- screenshots.forEach(({ environment, calculateRegions, ...baseTarget }) => {
152
- const aggregateCalculatedRegions = [];
153
- calculate.forEach(({ reference }, index) => {
154
- const regions = calculateRegions === null || calculateRegions === void 0 ? void 0 : calculateRegions[index];
155
- if (regions) {
156
- aggregateCalculatedRegions.push({ regions, selector: reference });
157
- }
158
- else {
159
- logger.log(`Regions "${reference}" was not found in the screenshot`);
160
- }
161
- });
162
- exactEnvironments.push(environment);
163
- baseTargets.push({ ...baseTarget, isTransformed: true });
164
- baseSettings.push(getBaseCheckSettings({
165
- calculatedRegions: aggregateCalculatedRegions,
166
- }));
143
+ }
144
+ else if (!baseEyes.running) {
145
+ abortError({
146
+ logger: environmentLogger,
147
+ message: `Check on environment with id "${(_a = baseEyes.test.environment) === null || _a === void 0 ? void 0 : _a.environmentId}" was aborted during one of the previous steps`,
167
148
  });
168
149
  }
150
+ return await baseEyes.check({
151
+ target,
152
+ settings: settings,
153
+ logger: environmentLogger,
154
+ });
169
155
  }
170
- else {
171
- exactEnvironments.push(...uniqueEnvironments);
172
- baseTargets.push(target);
173
- baseSettings.push(settings);
156
+ catch (error) {
157
+ environmentLogger.error(`Check on environment with id "${(_b = baseEyes.test.environment) === null || _b === void 0 ? void 0 : _b.environmentId}" failed due to an error`, error);
158
+ if (baseEyes.running && !(signal === null || signal === void 0 ? void 0 : signal.aborted))
159
+ baseEyes.abort({ logger: environmentLogger, settings: { reason: error } });
174
160
  }
175
- const promises = exactEnvironments.map(async (environment, index) => {
176
- var _a, _b, _c;
177
- const environmentLogger = logger.extend({ tags: [`environment-${utils.general.shortid()}`] });
178
- try {
179
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
180
- environmentLogger.warn('Command "check" was aborted before checking');
181
- throw new abort_error_1.AbortError('Command "check" was aborted before checking');
182
- }
183
- const baseEyes = await eyes.getBaseEyes({ settings: { environment, driver }, logger: environmentLogger });
184
- try {
185
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
186
- environmentLogger.warn('Command "check" was aborted before checking');
187
- throw new abort_error_1.AbortError('Command "check" was aborted before checking');
188
- }
189
- else if (!baseEyes.running) {
190
- environmentLogger.warn(`Check on environment with id "${(_a = baseEyes.test.environment) === null || _a === void 0 ? void 0 : _a.environmentId}" was aborted during one of the previous steps`);
191
- throw new abort_error_1.AbortError(`Check on environment with id "${(_b = baseEyes.test.environment) === null || _b === void 0 ? void 0 : _b.environmentId}" was aborted during one of the previous steps`);
192
- }
193
- await baseEyes.check({
194
- target: baseTargets[index],
195
- settings: baseSettings[index],
196
- logger: environmentLogger,
197
- });
198
- }
199
- catch (error) {
200
- environmentLogger.error(`Check on environment with id "${(_c = baseEyes.test.environment) === null || _c === void 0 ? void 0 : _c.environmentId}" failed due to an error`, error);
201
- if (baseEyes.running && !(signal === null || signal === void 0 ? void 0 : signal.aborted))
202
- await baseEyes.abort({ logger: environmentLogger, settings: { reason: error } });
203
- }
161
+ }
162
+ catch (error) {
163
+ environmentLogger.error(`Environment with id ${environment.environmentId} failed before checking started due to an error`, error);
164
+ error.info = { ...error.info, userTestId: eyes.test.userTestId, environment };
165
+ throw error;
166
+ }
167
+ return { asExpected: false };
168
+ }
169
+ /**
170
+ * @throws {AbortError}
171
+ */
172
+ function abortError({ logger, message }) {
173
+ logger.warn(message);
174
+ throw new abort_error_1.AbortError(message);
175
+ }
176
+ /**
177
+ * create base targets (array of screenshots) and base settings (array of check settings) for each environment
178
+ */
179
+ async function generateBaseScreenshotsAndSettings(settings, uniqueEnvironments, eyes, logger, driver) {
180
+ var _a;
181
+ const driverEnvironment = await driver.getEnvironment();
182
+ uniqueEnvironments = addMobileDeviceInfo(uniqueEnvironments, driverEnvironment);
183
+ await beforeScreenshot();
184
+ const shouldTakeWebScreenshot = driverEnvironment.isWeb ||
185
+ !((_a = driverEnvironment.applitoolsLib) === null || _a === void 0 ? void 0 : _a.instrumented) ||
186
+ settings.webview ||
187
+ settings.screenshotMode === 'default';
188
+ if (shouldTakeWebScreenshot) {
189
+ return await takeWebScreenshot({
190
+ driver,
191
+ settings,
192
+ environments: uniqueEnvironments,
193
+ logger,
194
+ eyes,
195
+ });
196
+ }
197
+ else {
198
+ // take screenshot using NML
199
+ checkConflictingCapabilities();
200
+ return await takeNMLScreenshot({
201
+ driver,
202
+ settings,
203
+ environments: uniqueEnvironments,
204
+ logger,
205
+ eyes,
206
+ });
207
+ }
208
+ async function beforeScreenshot() {
209
+ var _a;
210
+ await driver.currentContext.setScrollingElement((_a = settings.scrollRootElement) !== null && _a !== void 0 ? _a : null);
211
+ if (settings.lazyLoad && driverEnvironment.isWeb) {
212
+ await (0, wait_for_lazy_load_1.waitForLazyLoad)({
213
+ context: driver.currentContext,
214
+ settings: settings.lazyLoad !== true ? settings.lazyLoad : {},
215
+ logger,
216
+ });
217
+ }
218
+ }
219
+ function checkConflictingCapabilities() {
220
+ var _a;
221
+ if ((_a = driverEnvironment.applitoolsLib) === null || _a === void 0 ? void 0 : _a.conflictingCapabilities) {
222
+ const message = lang.applitoolsLibConflictingCapabilitiesWarning({
223
+ conflictingCapabilities: driverEnvironment.applitoolsLib.conflictingCapabilities,
224
+ });
225
+ logger.console.log(chalk_1.default.yellow(message));
226
+ logger.log(message);
227
+ }
228
+ }
229
+ function addMobileDeviceInfo(environments, driverEnvironment) {
230
+ return environments.map(environment => {
231
+ var _a, _b;
232
+ var _c, _d;
233
+ if (utils.types.has(environment, 'iosDeviceInfo')) {
234
+ (_a = (_c = environment.iosDeviceInfo).version) !== null && _a !== void 0 ? _a : (_c.version = driverEnvironment.platformVersion);
204
235
  }
205
- catch (error) {
206
- environmentLogger.error(`Environment with id ${environment.environmentId} failed before checking started due to an error`, error);
207
- error.info = { ...error.info, userTestId: eyes.test.userTestId, environment };
208
- throw error;
236
+ else if (utils.types.has(environment, 'androidDeviceInfo')) {
237
+ (_b = (_d = environment.androidDeviceInfo).version) !== null && _b !== void 0 ? _b : (_d.version = driverEnvironment.platformVersion);
209
238
  }
239
+ return environment;
240
+ });
241
+ }
242
+ }
243
+ async function takeWebScreenshot({ driver, settings, environments, logger, eyes, }) {
244
+ let actualEnvironments = environments;
245
+ if (settings.screenshotMode === 'default') {
246
+ const { localEnvironment, renderEnvironments } = await (0, nml_client_1.getNMLEnvironmentsInfo)({
247
+ environments: environments,
248
+ supportedEnvironmentsUrl: eyes.test.supportedEnvironmentsUrl,
249
+ proxy: eyes.test.eyesServer.proxy,
250
+ logger,
210
251
  });
211
- exactEnvironments.forEach((environment, index) => {
212
- const key = (0, to_environment_key_1.toEnvironmentKey)(environment);
213
- let item = eyes.storage.get(key);
214
- if (!item) {
215
- item = { eyes: utils.promises.makeControlledPromise(), jobs: [] };
216
- eyes.storage.set(key, item);
252
+ actualEnvironments = localEnvironment ? [localEnvironment] : renderEnvironments;
253
+ }
254
+ const { elementReferences, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({ settings });
255
+ const screenshots = await (0, take_screenshots_1.takeScreenshots)({
256
+ driver,
257
+ settings: {
258
+ ...settings,
259
+ environments: actualEnvironments,
260
+ regionsToCalculate: elementReferences.calculate,
261
+ calculateView: !!settings.pageId,
262
+ domSettings: settings.sendDom ? { proxy: eyes.test.eyesServer.proxy } : undefined,
263
+ },
264
+ logger,
265
+ });
266
+ return screenshots.map(({ calculatedRegions, ...baseTarget }, i) => {
267
+ return {
268
+ baseTarget,
269
+ baseSetting: getBaseCheckSettings({ calculatedRegions }),
270
+ exactEnvironment: actualEnvironments[i],
271
+ };
272
+ });
273
+ }
274
+ async function takeNMLScreenshot({ driver, settings, environments, logger, eyes, }) {
275
+ const nmlClient = await eyes.core.getNMLClient({
276
+ driver,
277
+ settings: { ...eyes.test.eyesServer, supportedEnvironmentsUrl: eyes.test.supportedEnvironmentsUrl },
278
+ logger,
279
+ });
280
+ if (settings.scrollRootElement || settings.region || (0, to_base_check_settings_1.hasCodedRegions)(settings))
281
+ await nmlClient.preTakeScreenshot({ logger });
282
+ const { elementReferences, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({
283
+ settings: {
284
+ ...settings,
285
+ ...(await (0, to_base_check_settings_1.extractMobileElementsIntoCheckSettings)({ settings, driver, logger })),
286
+ },
287
+ });
288
+ const calculate = elementReferences.calculate;
289
+ const screenshots = await nmlClient.takeScreenshots({
290
+ settings: {
291
+ environments: environments,
292
+ fully: settings.fully,
293
+ stitchMode: settings.stitchMode,
294
+ hideScrollbars: settings.hideScrollbars,
295
+ hideCaret: settings.hideScrollbars,
296
+ overlap: settings.overlap,
297
+ waitBeforeCapture: settings.waitBeforeCapture,
298
+ waitBetweenStitches: settings.waitBetweenStitches,
299
+ lazyLoad: settings.lazyLoad,
300
+ name: settings.name,
301
+ region: elementReferences.target,
302
+ selectorsToFindRegionsFor: calculate.map(({ name }) => name),
303
+ scrollRootElement: elementReferences.scrolling,
304
+ },
305
+ logger,
306
+ });
307
+ return screenshots.map(({ calculateRegions, ...baseTarget }) => {
308
+ const aggregateCalculatedRegions = [];
309
+ calculate.forEach(({ reference }, index) => {
310
+ const regions = calculateRegions === null || calculateRegions === void 0 ? void 0 : calculateRegions[index];
311
+ if (regions) {
312
+ aggregateCalculatedRegions.push({ regions, selector: reference });
313
+ }
314
+ else {
315
+ logger.log(`Regions "${reference}" was not found in the screenshot`);
217
316
  }
218
- item.jobs.push(promises[index]);
219
317
  });
220
- };
318
+ return {
319
+ baseTarget: { ...baseTarget, isTransformed: true },
320
+ baseSetting: getBaseCheckSettings({
321
+ calculatedRegions: aggregateCalculatedRegions,
322
+ }),
323
+ exactEnvironment: baseTarget.environment,
324
+ };
325
+ });
221
326
  }
222
- exports.makeCheck = makeCheck;
package/dist/core.js CHANGED
@@ -26,6 +26,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.makeCore = void 0;
27
27
  const logger_1 = require("@applitools/logger");
28
28
  const core_base_1 = require("@applitools/core-base");
29
+ const core_1 = require("./classic/core");
30
+ const core_2 = require("./ufg/core");
29
31
  const get_viewport_size_1 = require("./automation/get-viewport-size");
30
32
  const set_viewport_size_1 = require("./automation/set-viewport-size");
31
33
  const get_account_info_1 = require("./get-account-info");
@@ -50,6 +52,10 @@ function makeCore({ spec, clients, base: defaultBase, concurrency = utils.genera
50
52
  if (environment.sdk)
51
53
  (0, validate_sdk_version_1.validateSdkVersion)(environment.sdk, { logger });
52
54
  const base = defaultBase !== null && defaultBase !== void 0 ? defaultBase : (0, core_base_1.makeCore)({ agentId, concurrency, cwd, logger });
55
+ const cores = {
56
+ ufg: (0, core_2.makeCore)({ spec, clients, base, asyncCache, logger }),
57
+ classic: (0, core_1.makeCore)({ spec, clients, base, logger }),
58
+ };
53
59
  return utils.general.extend(base, core => {
54
60
  return {
55
61
  base: base,
@@ -58,11 +64,23 @@ function makeCore({ spec, clients, base: defaultBase, concurrency = utils.genera
58
64
  getNMLClient: (0, get_nml_client_1.makeGetNMLClient)({ client: clients === null || clients === void 0 ? void 0 : clients.nml, logger }),
59
65
  getECClient: (0, get_ec_client_1.makeGetECClient)({ logger }),
60
66
  getAccountInfo: (0, get_account_info_1.makeGetAccountInfo)({ core, logger }),
61
- makeManager: (0, make_manager_1.makeMakeManager)({ spec, clients, core, agentId, cwd, environment, asyncCache, logger }),
67
+ // Note: `defaultBase` is passesd for `base`, and `cores` is not passed here on purpose, so that a manager will create its own base, which would apply the correct concurrency value that was passed to the manager.
68
+ // `defaultBase` is here for testing purposes
69
+ makeManager: (0, make_manager_1.makeMakeManager)({
70
+ spec,
71
+ clients,
72
+ core,
73
+ base: defaultBase,
74
+ agentId,
75
+ cwd,
76
+ environment,
77
+ asyncCache,
78
+ logger,
79
+ }),
62
80
  locate: (0, locate_1.makeLocate)({ spec, core, logger }),
63
81
  locateText: (0, locate_text_1.makeLocateText)({ spec, core, logger }),
64
82
  extractText: (0, extract_text_1.makeExtractText)({ spec, core, logger }),
65
- openEyes: (0, open_eyes_1.makeOpenEyes)({ spec, clients, core, environment, asyncCache, logger }),
83
+ openEyes: (0, open_eyes_1.makeOpenEyes)({ spec, clients, core, cores, environment, asyncCache, logger }),
66
84
  closeBatch: (0, close_batch_1.makeCloseBatch)({ core, logger }),
67
85
  deleteTest: (0, delete_test_1.makeDeleteTest)({ core, logger }),
68
86
  };
@@ -44,8 +44,8 @@ function makeMakeManager({ spec, clients, core, base: defaultBase, agentId: defa
44
44
  logger.log('Command "makeManager" is called with settings', settings);
45
45
  const base = defaultBase !== null && defaultBase !== void 0 ? defaultBase : (0, core_base_1.makeCore)({ agentId: settings.agentId, concurrency: settings.concurrency, cwd, logger });
46
46
  const cores = {
47
- ufg: (0, core_2.makeCore)({ spec, base, fetchConcurrency: settings.fetchConcurrency, asyncCache, logger }),
48
- classic: (0, core_1.makeCore)({ spec, base, logger }),
47
+ ufg: (0, core_2.makeCore)({ spec, clients, base, fetchConcurrency: settings.fetchConcurrency, asyncCache, logger }),
48
+ classic: (0, core_1.makeCore)({ spec, clients, base, logger }),
49
49
  };
50
50
  const storage = [];
51
51
  return {
package/dist/open-eyes.js CHANGED
@@ -37,26 +37,27 @@ const populate_eyes_server_settings_1 = require("./utils/populate-eyes-server-se
37
37
  const utils = __importStar(require("@applitools/utils"));
38
38
  function makeOpenEyes({ type: defaultType = 'classic', clients, batch, core, cores, spec, environment, logger: mainLogger, asyncCache, }) {
39
39
  return async function openEyes({ type = defaultType, settings, config, target, logger = mainLogger, }) {
40
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
41
- var _t, _u, _v, _w, _x;
40
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
41
+ var _u, _v, _w, _x, _y;
42
42
  logger = logger.extend(mainLogger, { tags: [`eyes-${type}-${utils.general.shortid()}`] });
43
43
  settings = { ...config === null || config === void 0 ? void 0 : config.open, ...settings };
44
44
  (0, populate_eyes_server_settings_1.populateEyesServerSettings)(settings);
45
45
  (_a = settings.userTestId) !== null && _a !== void 0 ? _a : (settings.userTestId = `${settings.testName}--${utils.general.guid()}`);
46
46
  settings.batch = { ...batch, ...settings.batch };
47
- (_b = (_t = settings.batch).id) !== null && _b !== void 0 ? _b : (_t.id = (_c = utils.general.getEnvValue('BATCH_ID')) !== null && _c !== void 0 ? _c : `generated-${utils.general.guid()}`);
48
- (_d = (_u = settings.batch).buildId) !== null && _d !== void 0 ? _d : (_u.buildId = utils.general.getEnvValue('BATCH_BUILD_ID'));
49
- (_e = (_v = settings.batch).name) !== null && _e !== void 0 ? _e : (_v.name = utils.general.getEnvValue('BATCH_NAME'));
50
- (_f = (_w = settings.batch).sequenceName) !== null && _f !== void 0 ? _f : (_w.sequenceName = utils.general.getEnvValue('BATCH_SEQUENCE'));
51
- (_g = (_x = settings.batch).notifyOnCompletion) !== null && _g !== void 0 ? _g : (_x.notifyOnCompletion = utils.general.getEnvValue('BATCH_NOTIFY', 'boolean'));
47
+ (_b = (_u = settings.batch).id) !== null && _b !== void 0 ? _b : (_u.id = (_c = utils.general.getEnvValue('BATCH_ID')) !== null && _c !== void 0 ? _c : `generated-${utils.general.guid()}`);
48
+ (_d = (_v = settings.batch).buildId) !== null && _d !== void 0 ? _d : (_v.buildId = utils.general.getEnvValue('BATCH_BUILD_ID'));
49
+ (_e = (_w = settings.batch).name) !== null && _e !== void 0 ? _e : (_w.name = utils.general.getEnvValue('BATCH_NAME'));
50
+ (_f = (_x = settings.batch).sequenceName) !== null && _f !== void 0 ? _f : (_x.sequenceName = utils.general.getEnvValue('BATCH_SEQUENCE'));
51
+ (_g = (_y = settings.batch).notifyOnCompletion) !== null && _g !== void 0 ? _g : (_y.notifyOnCompletion = utils.general.getEnvValue('BATCH_NOTIFY', 'boolean'));
52
52
  (_h = settings.keepBatchOpen) !== null && _h !== void 0 ? _h : (settings.keepBatchOpen = utils.general.getEnvValue('DONT_CLOSE_BATCHES', 'boolean'));
53
53
  (_j = settings.branchName) !== null && _j !== void 0 ? _j : (settings.branchName = utils.general.getEnvValue('BRANCH'));
54
54
  (_k = settings.parentBranchName) !== null && _k !== void 0 ? _k : (settings.parentBranchName = utils.general.getEnvValue('PARENT_BRANCH'));
55
55
  (_l = settings.baselineBranchName) !== null && _l !== void 0 ? _l : (settings.baselineBranchName = utils.general.getEnvValue('BASELINE_BRANCH'));
56
56
  (_m = settings.gitBranchingTimestamp) !== null && _m !== void 0 ? _m : (settings.gitBranchingTimestamp = utils.general.getEnvValue('GIT_MERGE_BASE_TIMESTAMP'));
57
- (_o = settings.ufgServerUrl) !== null && _o !== void 0 ? _o : (settings.ufgServerUrl = utils.general.getEnvValue('UFG_SERVER_URL'));
58
- (_p = settings.ignoreBaseline) !== null && _p !== void 0 ? _p : (settings.ignoreBaseline = false);
59
- (_q = settings.compareWithParentBranch) !== null && _q !== void 0 ? _q : (settings.compareWithParentBranch = false);
57
+ (_o = settings.latestCommitInfo) !== null && _o !== void 0 ? _o : (settings.latestCommitInfo = getLatestCommitInfoFromEnvVars(logger));
58
+ (_p = settings.ufgServerUrl) !== null && _p !== void 0 ? _p : (settings.ufgServerUrl = utils.general.getEnvValue('UFG_SERVER_URL'));
59
+ (_q = settings.ignoreBaseline) !== null && _q !== void 0 ? _q : (settings.ignoreBaseline = false);
60
+ (_r = settings.compareWithParentBranch) !== null && _r !== void 0 ? _r : (settings.compareWithParentBranch = false);
60
61
  const driver = target && (await (0, driver_1.makeDriver)({ spec, driver: target, logger, customConfig: settings }));
61
62
  const driverEnvironment = await (driver === null || driver === void 0 ? void 0 : driver.getEnvironment());
62
63
  const driverUrl = await (driver === null || driver === void 0 ? void 0 : driver.getDriverUrl());
@@ -67,7 +68,7 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, core, cor
67
68
  event: {
68
69
  type: 'openEyes',
69
70
  userTestId: settings.userTestId,
70
- concurrency: (_r = cores === null || cores === void 0 ? void 0 : cores[type].concurrency) !== null && _r !== void 0 ? _r : core.concurrency,
71
+ concurrency: (_s = cores === null || cores === void 0 ? void 0 : cores[type].concurrency) !== null && _s !== void 0 ? _s : core.concurrency,
71
72
  environment,
72
73
  driver: {
73
74
  deviceName: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.deviceName,
@@ -75,7 +76,7 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, core, cor
75
76
  browserVersion: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.browserVersion,
76
77
  platformName: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.platformName,
77
78
  platformVersion: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.platformVersion,
78
- isApplitoolsLib: (_s = driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.applitoolsLib) === null || _s === void 0 ? void 0 : _s.instrumented,
79
+ isApplitoolsLib: (_t = driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.applitoolsLib) === null || _t === void 0 ? void 0 : _t.instrumented,
79
80
  isEC: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.isEC,
80
81
  },
81
82
  driverUrl,
@@ -108,3 +109,17 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, core, cor
108
109
  };
109
110
  }
110
111
  exports.makeOpenEyes = makeOpenEyes;
112
+ function getLatestCommitInfoFromEnvVars(logger) {
113
+ const timestamp = utils.general.getEnvValue('GIT_LATEST_COMMIT_TIMESTAMP');
114
+ const sha = utils.general.getEnvValue('GIT_LATEST_COMMIT_SHA');
115
+ if (timestamp && sha) {
116
+ return { timestamp, sha };
117
+ }
118
+ else if (timestamp && !sha) {
119
+ logger.warn(`APPLITOOLS_GIT_LATEST_COMMIT_TIMESTAMP was provided without APPLITOOLS_GIT_LATEST_COMMIT_SHA. Proceeding provided timestamp ${timestamp} and NO_SHA_PROVIDED`);
120
+ return { timestamp, sha: 'NO_SHA_PROVIDED' };
121
+ }
122
+ else if (sha && !timestamp) {
123
+ logger.warn(`APPLITOOLS_GIT_LATEST_COMMIT_SHA was provided without APPLITOOLS_GIT_LATEST_COMMIT_TIMESTAMP. Not populating latestCommitInfo with the provided sha ${sha}.`);
124
+ }
125
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/core",
3
- "version": "4.13.1",
3
+ "version": "4.15.0",
4
4
  "homepage": "https://applitools.com",
5
5
  "bugs": {
6
6
  "url": "https://github.com/applitools/eyes.sdk.javascript1/issues"
@@ -74,18 +74,18 @@
74
74
  }
75
75
  },
76
76
  "dependencies": {
77
- "@applitools/core-base": "1.12.1",
78
- "@applitools/dom-capture": "11.2.6",
79
- "@applitools/dom-snapshot": "4.11.0",
80
- "@applitools/driver": "1.17.1",
81
- "@applitools/ec-client": "1.8.3",
77
+ "@applitools/core-base": "1.14.0",
78
+ "@applitools/dom-capture": "11.2.7",
79
+ "@applitools/dom-snapshot": "4.11.1",
80
+ "@applitools/driver": "1.17.2",
81
+ "@applitools/ec-client": "1.8.5",
82
82
  "@applitools/logger": "2.0.16",
83
- "@applitools/nml-client": "1.8.3",
83
+ "@applitools/nml-client": "1.8.4",
84
84
  "@applitools/req": "1.6.7",
85
- "@applitools/screenshoter": "3.8.30",
85
+ "@applitools/screenshoter": "3.8.31",
86
86
  "@applitools/snippets": "2.4.25",
87
87
  "@applitools/socket": "1.1.16",
88
- "@applitools/spec-driver-webdriver": "1.1.6",
88
+ "@applitools/spec-driver-webdriver": "1.1.7",
89
89
  "@applitools/ufg-client": "1.11.2",
90
90
  "@applitools/utils": "1.7.2",
91
91
  "@types/ws": "8.5.5",
@@ -100,8 +100,8 @@
100
100
  "devDependencies": {
101
101
  "@applitools/bongo": "^5.10.0",
102
102
  "@applitools/sea": "^1.0.0",
103
- "@applitools/spec-driver-puppeteer": "^1.4.6",
104
- "@applitools/spec-driver-selenium": "^1.5.77",
103
+ "@applitools/spec-driver-puppeteer": "^1.4.7",
104
+ "@applitools/spec-driver-selenium": "^1.5.78",
105
105
  "@applitools/test-server": "^1.2.2",
106
106
  "@applitools/test-utils": "^1.5.17",
107
107
  "@applitools/tunnel-client": "^1.5.2",
@@ -46,7 +46,7 @@ export type ExactEnvironment = BaseCore.Environment & {
46
46
  fallbackBaselineId?: string;
47
47
  };
48
48
  export type Environment = RenderEnvironment | ExactEnvironment;
49
- export interface Core<TSpec extends SpecType> extends BaseCore.Core {
49
+ export interface Core<TSpec extends SpecType> extends Omit<BaseCore.Core, 'openEyes'> {
50
50
  readonly base: BaseCore.Core;
51
51
  getViewportSize?(options: {
52
52
  target: DriverTarget<TSpec>;
@@ -84,7 +84,7 @@ export interface Core<TSpec extends SpecType> extends BaseCore.Core {
84
84
  logger?: Logger;
85
85
  }): Promise<string[]>;
86
86
  }
87
- export interface Eyes<TSpec extends SpecType> extends BaseCore.Eyes {
87
+ export interface Eyes<TSpec extends SpecType> extends Omit<BaseCore.Eyes, 'core' | 'check' | 'checkAndClose'> {
88
88
  readonly core: Core<TSpec>;
89
89
  readonly storage: EyesStorage;
90
90
  getBaseEyes(options: {