@applitools/core 4.37.0-debug-20250429 → 4.37.0-debug-20250429-3

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.
@@ -38,7 +38,7 @@ async function extractMobileElementsIntoCheckSettings({ settings, driver, logger
38
38
  logger = logger.extend({ tags: [`extract-mobile-elements-${utils.general.shortid()}`] });
39
39
  const environment = await driver.getEnvironment();
40
40
  if (settings.region) {
41
- logger.log('extract element form region', settings.region);
41
+ logger.log('extract element from region', settings.region);
42
42
  const region = await driver.element(settings.region).catch(error => logger.log(error));
43
43
  if (!region) {
44
44
  throw new Error('region not found');
@@ -63,7 +63,7 @@ async function extractMobileElementsIntoCheckSettings({ settings, driver, logger
63
63
  if (!settings[`${regionType}Regions`])
64
64
  return obj;
65
65
  obj[`${regionType}Regions`] = (await Promise.all((_b = (_a = settings[`${regionType}Regions`]) === null || _a === void 0 ? void 0 : _a.flatMap(async (reference) => {
66
- logger.log('extract element form region', reference);
66
+ logger.log('extract element from region', reference);
67
67
  const { region } = utils.types.has(reference, 'region') ? reference : { region: reference };
68
68
  const handleRegion = new Set();
69
69
  const elements = await driver.elements(region).catch(error => logger.log(error));
@@ -355,7 +355,7 @@ async function takeNMLScreenshot({ driver, settings, environments, logger, eyes,
355
355
  aggregateCalculatedRegions.push({ regions, selector: reference });
356
356
  }
357
357
  else {
358
- logger.log(`Regions "${reference}" was not found in the screenshot`);
358
+ logger.log(`Regions "${JSON.stringify(reference)}" was not found in the screenshot`);
359
359
  }
360
360
  });
361
361
  if ((_a = baseTarget.dom) === null || _a === void 0 ? void 0 : _a.error) {
@@ -127,45 +127,97 @@ async function runOfflineSnapshots(options) {
127
127
  const environment = await ufgClient.getActualEnvironment({
128
128
  settings: { environment: openSettings.environment.requested },
129
129
  });
130
+ const closeSettings = await getCloseSettings(testPath);
131
+ let resultsGetter;
132
+ if (closeSettings) {
133
+ const targets = await getCheckTargets(testPath, logger);
134
+ const uploadResourcePromise = uploadResources(targets, logger).then(() => logger.log('uploaded resources for test', testPath));
135
+ if (targets.length === 1) {
136
+ logger.log('only one check found for test', testPath);
137
+ await uploadResourcePromise;
138
+ const target = targets[0];
139
+ resultsGetter = await runOpenCheckAndClose({
140
+ ...target,
141
+ settings: {
142
+ ...(0, merge_configs_1.mergeConfigs)((0, merge_configs_1.mergeConfigs)(closeSettings, openSettings), target.settings),
143
+ ...account.eyesServer,
144
+ environment: {
145
+ ...openSettings.environment,
146
+ ...target.settings.environment,
147
+ },
148
+ },
149
+ }, logger, environment);
150
+ logger.log('finished running checks for test', testPath);
151
+ }
152
+ else {
153
+ const eyes = await openEyes(openSettings, environment, logger);
154
+ logger.log('opened eyes for test', testPath);
155
+ await uploadResourcePromise;
156
+ const lastTarget = targets.pop();
157
+ await Promise.all(targets.map((target, index) => runCheck(eyes, target, index, logger)));
158
+ if (lastTarget) {
159
+ lastTarget.settings = (0, merge_configs_1.mergeConfigs)(lastTarget.settings, closeSettings);
160
+ await runCheckAndClose(eyes, lastTarget, targets.length - 1, logger);
161
+ logger.log('finished running checks for test', testPath);
162
+ }
163
+ else {
164
+ logger.log('no checks found for test', testPath);
165
+ // on empty test, `checkAndClose` will not be called so we need to call `close` instead
166
+ await eyes.close({ settings: closeSettings });
167
+ }
168
+ resultsGetter = eyes;
169
+ }
170
+ }
171
+ else {
172
+ logger.log('no close settings found for test - aborting test', testPath);
173
+ resultsGetter = await makeAbortedTest(openSettings, environment, logger);
174
+ }
175
+ logger.log('done running test', testPath);
176
+ return { batchId: openSettings.batch.id, results: (await resultsGetter.getResults({ logger }))[0] };
177
+ }
178
+ async function getCloseSettings(testPath) {
179
+ const closeSettingsPath = path_1.default.resolve(testPath, 'close.json');
180
+ if (fs_1.default.existsSync(closeSettingsPath)) {
181
+ const fileCloseSettings = await fs_1.default.promises.readFile(closeSettingsPath, 'utf-8').then(JSON.parse);
182
+ const closeSettings = (0, merge_configs_1.mergeConfigs)(fileCloseSettings, options.config.close);
183
+ return closeSettings;
184
+ }
185
+ return undefined;
186
+ }
187
+ async function getCheckTargets(testPath, logger) {
188
+ const checkFolders = (await fs_1.default.promises.readdir(testPath)).filter(folderpath => folderpath.startsWith('check-'));
189
+ logger.log('check folders', checkFolders);
190
+ const targets = await Promise.all(checkFolders.map(async (checkFolder) => {
191
+ const snapshot = await fs_1.default.promises
192
+ .readFile(path_1.default.resolve(testPath, checkFolder, 'snapshot.json'), 'utf-8')
193
+ .then(JSON.parse);
194
+ snapshot.settings.environment.environmentId = utils.general.guid();
195
+ return snapshot;
196
+ }));
197
+ return targets;
198
+ }
199
+ async function makeAbortedTest(openSettings, environment, logger) {
200
+ const eyes = await openEyes(openSettings, environment, logger);
201
+ await eyes.abort({
202
+ settings: {
203
+ reason: 'internal',
204
+ },
205
+ });
206
+ return eyes;
207
+ }
208
+ async function openEyes(settings, environment, logger) {
130
209
  const eyes = await core.base.openEyes({
131
210
  settings: {
132
- ...openSettings,
211
+ ...settings,
133
212
  environment: {
134
- ...openSettings.environment,
213
+ ...settings.environment,
135
214
  ...environment,
136
215
  },
137
216
  ...account.eyesServer,
138
217
  },
139
218
  logger,
140
219
  });
141
- const closeSettingsPath = path_1.default.resolve(testPath, 'close.json');
142
- if (fs_1.default.existsSync(closeSettingsPath)) {
143
- const checkFolders = (await fs_1.default.promises.readdir(testPath)).filter(folderpath => folderpath.startsWith('check-'));
144
- logger.log('running checks for test', testPath, ':', checkFolders);
145
- const targets = await Promise.all(checkFolders.map(async (checkFolder) => {
146
- const snapshot = await fs_1.default.promises
147
- .readFile(path_1.default.resolve(testPath, checkFolder, 'snapshot.json'), 'utf-8')
148
- .then(JSON.parse);
149
- snapshot.settings.environment.environmentId = utils.general.guid();
150
- return snapshot;
151
- }));
152
- await uploadResources(targets, logger);
153
- // logger.log('resource hashes for test', testFolder, ':', resourceHashes)
154
- logger.log('uploaded resources for test', testPath);
155
- await Promise.all(targets.map((target, index) => runCheck(eyes, target, index, logger)));
156
- const fileCloseSettings = await fs_1.default.promises.readFile(closeSettingsPath, 'utf-8').then(JSON.parse);
157
- const closeSettings = (0, merge_configs_1.mergeConfigs)(fileCloseSettings, options.config.close);
158
- await eyes.close({ settings: closeSettings });
159
- }
160
- else {
161
- await eyes.abort({
162
- settings: {
163
- reason: 'internal',
164
- },
165
- });
166
- }
167
- logger.log('done running test', testPath);
168
- return { batchId: openSettings.batch.id, results: (await eyes.getResults({ logger }))[0] };
220
+ return eyes;
169
221
  }
170
222
  async function uploadResources(targets, logger) {
171
223
  const uploadLogger = logger.extend({ tags: ['upload-resources'] });
@@ -202,6 +254,53 @@ async function runOfflineSnapshots(options) {
202
254
  async function runCheck(eyes, target, index, logger) {
203
255
  var _a;
204
256
  const checkLogger = logger.extend({ tags: [`check-${index}`] });
257
+ const { mergedCheckSettings, baseTarget } = await render(target, checkLogger);
258
+ (_a = mergedCheckSettings.stepIndex) !== null && _a !== void 0 ? _a : (mergedCheckSettings.stepIndex = index);
259
+ await eyes.check({
260
+ target: { ...baseTarget, isTransformed: true },
261
+ settings: mergedCheckSettings,
262
+ logger: checkLogger,
263
+ });
264
+ logger.log('check finished', mergedCheckSettings);
265
+ return eyes;
266
+ }
267
+ async function runCheckAndClose(eyes, target, index, logger) {
268
+ var _a;
269
+ const checkLogger = logger.extend({ tags: [`check-${index}`] });
270
+ const { mergedCheckSettings, baseTarget } = await render(target, checkLogger);
271
+ (_a = mergedCheckSettings.stepIndex) !== null && _a !== void 0 ? _a : (mergedCheckSettings.stepIndex = index);
272
+ await eyes.checkAndClose({
273
+ target: { ...baseTarget, isTransformed: true },
274
+ settings: mergedCheckSettings,
275
+ logger: checkLogger,
276
+ });
277
+ logger.log('checkAndClose finished', mergedCheckSettings);
278
+ return eyes;
279
+ }
280
+ async function runOpenCheckAndClose(target, logger, actualEnvironment) {
281
+ const checkLogger = logger.extend({ tags: ['open-check-and-close'] });
282
+ const { mergedCheckSettings, baseTarget } = await render(target, checkLogger);
283
+ const settings = (0, merge_configs_1.mergeConfigs)(target.settings, mergedCheckSettings);
284
+ return core.base.openCheckAndCloseEyes({
285
+ target: { ...baseTarget, isTransformed: true },
286
+ settings: {
287
+ ...settings,
288
+ environment: {
289
+ ...settings.environment,
290
+ ...actualEnvironment,
291
+ },
292
+ },
293
+ logger: checkLogger,
294
+ heartbeat: {
295
+ processId: '',
296
+ startPeriodicHeartbeatMessaging(settings) {
297
+ logger.log('heartbeat is not used (offline)', settings);
298
+ },
299
+ },
300
+ });
301
+ }
302
+ async function render(target, logger) {
303
+ var _a;
205
304
  const { elementReferences: selectors, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({
206
305
  settings: target.settings,
207
306
  });
@@ -217,7 +316,7 @@ async function runOfflineSnapshots(options) {
217
316
  uploadUrl: account.uploadUrl,
218
317
  stitchingServiceUrl: account.stitchingServiceUrl,
219
318
  },
220
- logger: checkLogger,
319
+ logger,
221
320
  });
222
321
  const baseSettings = getBaseCheckSettings({
223
322
  calculatedRegions: selectors.calculate.map((_, index) => {
@@ -228,15 +327,11 @@ async function runOfflineSnapshots(options) {
228
327
  }),
229
328
  });
230
329
  baseSettings.renderId = renderId;
231
- baseSettings.stepIndex = index;
330
+ // baseSettings.stepIndex = index
232
331
  baseTarget.source = target.target.source; // TODO verify
233
332
  // baseTarget.name = snapshot.title // TODO figure out
234
333
  const mergedCheckSettings = (0, merge_configs_1.mergeConfigs)(baseSettings, options.config.check);
235
- await eyes.check({
236
- target: { ...baseTarget, isTransformed: true },
237
- settings: mergedCheckSettings,
238
- logger: checkLogger,
239
- });
334
+ return { mergedCheckSettings, baseTarget };
240
335
  }
241
336
  }
242
337
  exports.runOfflineSnapshots = runOfflineSnapshots;
package/dist/ufg/check.js CHANGED
@@ -174,6 +174,12 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
174
174
  },
175
175
  });
176
176
  }
177
+ try {
178
+ logInvalidSettings(logger, settings);
179
+ }
180
+ catch (err) {
181
+ logger.log('Failed to log invalid check settings', err);
182
+ }
177
183
  await baseEyes.check({
178
184
  target: { ...baseTarget, isTransformed: true },
179
185
  settings: baseSettings,
@@ -204,3 +210,14 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
204
210
  };
205
211
  }
206
212
  exports.makeCheck = makeCheck;
213
+ function logInvalidSettings(logger, settings) {
214
+ const invalidKeys = ['overlap', 'scrollRootElement', 'stitchMode'];
215
+ if (!settings)
216
+ return;
217
+ const invalidEntries = Object.entries(settings)
218
+ .filter(([key]) => invalidKeys.includes(key))
219
+ .filter(([_, value]) => value !== undefined);
220
+ if (invalidEntries.length > 0) {
221
+ logger.warn('Warning - Invalid keys in check settings (will be ignored):', { settings, invalidEntries });
222
+ }
223
+ }
@@ -54,36 +54,50 @@ async function takeDomSnapshots({ driver, settings, hooks, provides, logger, })
54
54
  return Array(settings.environments.length).fill(snapshot);
55
55
  }
56
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
- const requiredWidths = await prev;
60
- const requiredWidth = isStrictBreakpoints
61
- ? calculateBreakpoint({ breakpoints: settings.layoutBreakpoints.breakpoints, value: width })
62
- : width;
63
- let environments = requiredWidths.get(requiredWidth);
57
+ const initialViewportSize = await driver.getViewportSize();
58
+ const requiredSizes = await settings.environments.reduce(async (prev, environment, index) => {
59
+ var _a;
60
+ const { name, width, height } = (await extractEnvironmentInfo(environment));
61
+ const requiredSizes = await prev;
62
+ let requiredSize;
63
+ if ((_a = settings.layoutBreakpoints) === null || _a === void 0 ? void 0 : _a.heightBreakpoints) {
64
+ const requiredWidth = settings.layoutBreakpoints.breakpoints ? width : initialViewportSize.width;
65
+ requiredSize = `${requiredWidth},${height}`;
66
+ }
67
+ else {
68
+ const requiredWidth = isStrictBreakpoints
69
+ ? calculateBreakpoint({ breakpoints: settings.layoutBreakpoints.breakpoints, value: width })
70
+ : width;
71
+ requiredSize = `${requiredWidth},${initialViewportSize.height}`;
72
+ }
73
+ let environments = requiredSizes.get(requiredSize);
64
74
  if (!environments)
65
- requiredWidths.set(requiredWidth, (environments = []));
66
- environments.push({ name, width, index });
67
- return requiredWidths;
75
+ requiredSizes.set(requiredSize, (environments = []));
76
+ environments.push({ name, width, height, index });
77
+ return requiredSizes;
68
78
  }, Promise.resolve(new Map()));
69
79
  const smallestBreakpoint = Math.min(...(isStrictBreakpoints ? settings.layoutBreakpoints.breakpoints : []));
70
- if (isStrictBreakpoints && requiredWidths.has(smallestBreakpoint - 1)) {
80
+ const smallestSize = `${smallestBreakpoint - 1},${initialViewportSize.height}`;
81
+ if (isStrictBreakpoints && requiredSizes.has(smallestSize)) {
71
82
  const message = lang.requestedEnvironmentSmallerThenBreakpointWarning({
72
83
  breakpoint: smallestBreakpoint,
73
- browsers: requiredWidths.get(smallestBreakpoint - 1),
84
+ browsers: requiredSizes.get(smallestSize),
74
85
  });
75
86
  logger.console.log(chalk_1.default.yellow(message));
76
87
  }
77
- logger.log(`Taking multiple dom snapshots for the breakpoints`, settings.layoutBreakpoints);
78
- const initialViewportSize = await driver.getViewportSize();
88
+ logger.log(`Taking multiple dom snapshots for the breakpoints`, isStrictBreakpoints ? settings.layoutBreakpoints : requiredSizes);
79
89
  const entries = [];
80
- const initialsBrowsers = requiredWidths.get(initialViewportSize.width);
90
+ const initialSize = `${initialViewportSize.width},${initialViewportSize.height}`;
91
+ const initialsBrowsers = requiredSizes.get(initialSize);
81
92
  if (initialsBrowsers) {
82
93
  logger.log(`The first dom snapshot is going to be taking for initial viewport size`, initialViewportSize);
83
- requiredWidths.delete(initialViewportSize.width);
94
+ requiredSizes.delete(initialSize);
84
95
  entries.push({ browsers: initialsBrowsers });
85
96
  }
86
- requiredWidths.forEach((browsers, requiredWidth) => entries.push({ viewportSize: { width: requiredWidth, height: initialViewportSize.height }, browsers }));
97
+ requiredSizes.forEach((browsers, requiredSize) => {
98
+ const [requiredWidth, requiredHeight] = requiredSize.split(',').map(Number);
99
+ entries.push({ viewportSize: { width: requiredWidth, height: requiredHeight }, browsers });
100
+ });
87
101
  logger.log(`All entries to take dom snapshots for`, entries);
88
102
  // making safe selectors before any resize in order to make sure fallback selectors are created
89
103
  await (0, generate_safe_selectors_1.generateSafeSelectors)({
@@ -70,7 +70,7 @@ exports.extractGitBranch = utils.general.cachify(async function ({ execOptions,
70
70
  return process.env.GITHUB_HEAD_REF;
71
71
  }
72
72
  if (process.env.GITHUB_REF) {
73
- return process.env.GITHUB_REF.split('/')[2]; // refs/heads/<branch_name>
73
+ return process.env.GITHUB_REF.split('/').splice(2).join('/'); // refs/heads/<branch_name>
74
74
  }
75
75
  const result = await executeWithLog('git branch --show-current', { execOptions, logger });
76
76
  if (result.stderr) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/core",
3
- "version": "4.37.0-debug-20250429",
3
+ "version": "4.37.0-debug-20250429-3",
4
4
  "homepage": "https://applitools.com",
5
5
  "bugs": {
6
6
  "url": "https://github.com/applitools/eyes.sdk.javascript1/issues"
@@ -75,7 +75,7 @@
75
75
  }
76
76
  },
77
77
  "dependencies": {
78
- "@applitools/core-base": "1.24.0-debug-20250429",
78
+ "@applitools/core-base": "1.24.0-debug-20250429-1",
79
79
  "@applitools/dom-capture": "11.5.5",
80
80
  "@applitools/dom-snapshot": "4.11.18",
81
81
  "@applitools/driver": "1.21.1",
@@ -1 +1 @@
1
- export declare function mergeConfigs<TBase extends Record<string, any>>(base: TBase, other: Record<string, any>): TBase;
1
+ export declare function mergeConfigs<TBase extends Record<string, any>, TBase2 extends Record<string, any>>(base: TBase, other: TBase2): TBase & TBase2;
@@ -19,6 +19,7 @@ export declare function makeCheckAndClose<TSpec extends SpecType>({ eyes, target
19
19
  disableBrowserFetching?: boolean | undefined;
20
20
  layoutBreakpoints?: {
21
21
  breakpoints: boolean | number[];
22
+ heightBreakpoints?: boolean | undefined;
22
23
  reload?: boolean | undefined;
23
24
  } | undefined;
24
25
  hooks?: {
@@ -54,6 +54,7 @@ export type SnapshotSettings<TSpec extends SpecType> = AutomationCore.CheckSetti
54
54
  disableBrowserFetching?: boolean;
55
55
  layoutBreakpoints?: {
56
56
  breakpoints: number[] | boolean;
57
+ heightBreakpoints?: boolean;
57
58
  reload?: boolean;
58
59
  };
59
60
  hooks?: {
@@ -10,6 +10,7 @@ export type DomSnapshotsSettings<TSpec extends SpecType> = DomSnapshotSettings<T
10
10
  waitBeforeCapture?: number | (() => Promise<void>);
11
11
  layoutBreakpoints?: {
12
12
  breakpoints: number[] | boolean;
13
+ heightBreakpoints?: boolean;
13
14
  reload?: boolean;
14
15
  };
15
16
  lazyLoad?: boolean | LazyLoadOptions;