@applitools/core 4.18.2 → 4.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/autonomous/core.js +1 -1
  3. package/dist/autonomous/create-render-target.js +2 -15
  4. package/dist/autonomous/take-snapshots.js +6 -2
  5. package/dist/classic/core.js +2 -2
  6. package/dist/classic/utils/take-dom-capture.js +1 -0
  7. package/dist/cli/cli.js +20 -0
  8. package/dist/core.js +6 -3
  9. package/dist/make-manager.js +4 -3
  10. package/dist/open-eyes.js +61 -1
  11. package/dist/run-offline-snapshots.js +346 -0
  12. package/dist/ufg/check.js +40 -96
  13. package/dist/ufg/core.js +4 -3
  14. package/dist/ufg/create-render-target-from-snapshot.js +21 -0
  15. package/dist/ufg/get-ufg-client.js +2 -2
  16. package/dist/ufg/take-snapshots.js +4 -6
  17. package/dist/ufg/utils/generate-safe-selectors.js +18 -18
  18. package/dist/ufg/utils/take-dom-snapshots.js +13 -14
  19. package/dist/{log-event.js → utils/ensure-offline-folder.js} +15 -11
  20. package/package.json +13 -12
  21. package/types/autonomous/create-render-target.d.ts +2 -2
  22. package/types/autonomous/start-renders.d.ts +2 -2
  23. package/types/autonomous/take-snapshots.d.ts +3 -2
  24. package/types/autonomous/types.d.ts +5 -5
  25. package/types/classic/core.d.ts +2 -1
  26. package/types/classic/utils/take-dom-capture.d.ts +8 -0
  27. package/types/make-manager.d.ts +2 -1
  28. package/types/run-offline-snapshots.d.ts +5 -0
  29. package/types/ufg/core.d.ts +2 -1
  30. package/types/ufg/create-render-target-from-snapshot.d.ts +8 -0
  31. package/types/ufg/get-ufg-client.d.ts +2 -1
  32. package/types/ufg/take-snapshots.d.ts +4 -6
  33. package/types/ufg/types.d.ts +3 -3
  34. package/types/ufg/utils/generate-safe-selectors.d.ts +18 -12
  35. package/types/utils/ensure-offline-folder.d.ts +1 -0
  36. package/types/log-event.d.ts +0 -12
@@ -0,0 +1,346 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.runOfflineSnapshots = void 0;
30
+ const fs_1 = __importDefault(require("fs"));
31
+ const path_1 = __importDefault(require("path"));
32
+ const tar = __importStar(require("tar"));
33
+ const core_1 = require("./core");
34
+ const get_ufg_client_1 = require("./ufg/get-ufg-client");
35
+ const logger_1 = require("@applitools/logger");
36
+ const to_base_check_settings_1 = require("./automation/utils/to-base-check-settings");
37
+ const chalk_1 = __importDefault(require("chalk"));
38
+ const utils = __importStar(require("@applitools/utils"));
39
+ async function runOfflineSnapshots(options) {
40
+ if (!options.offlineLocationPath)
41
+ throw new Error('offlineLocationPath is required');
42
+ const startTime = Date.now();
43
+ const logger = (0, logger_1.makeLogger)({ format: { label: 'offline-exec' } });
44
+ const core = (0, core_1.makeCore)();
45
+ const account = await core.getAccountInfo({ settings: options });
46
+ const ufgClient = await (0, get_ufg_client_1.makeGetUFGClient)({ logger })({
47
+ settings: { ...account.eyesServer, ...account.ufgServer },
48
+ });
49
+ const executionFiles = (await fs_1.default.promises.readdir(options.offlineLocationPath)).filter(filename => filename.endsWith('.tar.gz'));
50
+ if (executionFiles.length === 1) {
51
+ logger.console.log(`Running execution ${executionFiles[0]} from folder ${path_1.default.resolve(options.offlineLocationPath)}`);
52
+ }
53
+ else if (executionFiles.length === 0) {
54
+ logger.console.log('No execution artifacts were found at', options.offlineLocationPath);
55
+ }
56
+ else {
57
+ logger.console.log(`Running the following executions from folder ${options.offlineLocationPath} :\n ${executionFiles.join('\n ')}`);
58
+ }
59
+ if (executionFiles.length === 0) {
60
+ throw new Error(`Unable to find offline executions in ${options.offlineLocationPath}`);
61
+ }
62
+ const allTestResults = (await Promise.all(executionFiles.map(runExecution))).flat();
63
+ const { exitCode, outputStr } = processResults({ testResults: allTestResults, totalTime: Date.now() - startTime });
64
+ if (exitCode) {
65
+ throw new Error(outputStr);
66
+ }
67
+ else {
68
+ logger.console.log(outputStr);
69
+ }
70
+ async function runExecution(executionFile) {
71
+ const executionName = executionFile.replace('.tar.gz', '');
72
+ const executionLogger = logger.extend({ tags: [executionName] });
73
+ executionLogger.log('unpacking execution', executionFile);
74
+ await tar.extract({
75
+ file: path_1.default.resolve(options.offlineLocationPath, executionFile),
76
+ gzip: true,
77
+ C: options.offlineLocationPath,
78
+ });
79
+ const executionPath = path_1.default.resolve(options.offlineLocationPath, executionName);
80
+ executionLogger.log('handling execution', executionPath);
81
+ const testFolders = (await fs_1.default.promises.readdir(executionPath)).filter(foldername => foldername.startsWith('test-'));
82
+ executionLogger.log('running tests', testFolders);
83
+ const results = await Promise.all(testFolders.map(async (testFolder) => {
84
+ const testLogger = logger.extend({ tags: [testFolder] });
85
+ const testPath = path_1.default.resolve(executionPath, testFolder);
86
+ const openSettings = (await fs_1.default.promises
87
+ .readFile(path_1.default.resolve(testPath, 'settings.json'), 'utf-8')
88
+ .then(JSON.parse));
89
+ logger.console.log(`Running test: ${openSettings.testName} (${formatEnvironment(openSettings.environment)})`);
90
+ return runTest(executionPath, testPath, openSettings, testLogger);
91
+ }));
92
+ const batchIds = [...new Set(results.map(t => t.batchId))];
93
+ const allTestResults = results.map(t => t.results);
94
+ executionLogger.log('done running all tests', allTestResults);
95
+ // @ts-expect-error // we use node v12 types, therefore it's not aware of the existence of `fs.promises.rm`
96
+ await fs_1.default.promises.rm(executionPath, { recursive: true });
97
+ await core.closeBatch({ settings: batchIds.map(batchId => ({ batchId, ...account.eyesServer })) });
98
+ executionLogger.log('one execution', executionFile);
99
+ return allTestResults;
100
+ }
101
+ async function runTest(executionPath, testPath, openSettings, logger) {
102
+ const environment = await ufgClient.getActualEnvironment({
103
+ settings: { environment: openSettings.environment.requested },
104
+ });
105
+ const eyes = await core.base.openEyes({
106
+ settings: {
107
+ ...openSettings,
108
+ environment: {
109
+ ...openSettings.environment,
110
+ ...environment,
111
+ },
112
+ ...account.eyesServer,
113
+ },
114
+ logger,
115
+ });
116
+ const checkFolders = (await fs_1.default.promises.readdir(testPath)).filter(folderpath => folderpath.startsWith('check-'));
117
+ logger.log('running checks for test', testPath, ':', checkFolders);
118
+ const targets = (await Promise.all(checkFolders.map(checkFolder => fs_1.default.promises.readFile(path_1.default.resolve(testPath, checkFolder, 'snapshot.json'), 'utf-8').then(JSON.parse))));
119
+ await uploadResources(executionPath, targets, logger);
120
+ // logger.log('resource hashes for test', testFolder, ':', resourceHashes)
121
+ logger.log('uploaded resources for test', testPath);
122
+ await Promise.all(targets.map((target, index) => runCheck(eyes, target, index, logger)));
123
+ await eyes.close({
124
+ settings: await fs_1.default.promises.readFile(path_1.default.resolve(testPath, 'close.json'), 'utf-8').then(JSON.parse),
125
+ });
126
+ logger.log('done running test', logger);
127
+ return { batchId: openSettings.batch.id, results: (await eyes.getResults({ logger }))[0] };
128
+ }
129
+ async function uploadResources(executionPath, targets, logger) {
130
+ const uploadLogger = logger.extend({ tags: ['upload-resources'] });
131
+ const promises = targets.map(async ({ target }) => {
132
+ let resourcePromises = Object.values(target.resources)
133
+ .filter(isHashedResource)
134
+ .map(async (resource) => {
135
+ const contentfuleResource = {
136
+ id: '',
137
+ url: '',
138
+ value: await fs_1.default.promises.readFile(path_1.default.resolve(executionPath, 'resources', resource.hash)),
139
+ contentType: resource.contentType,
140
+ hash: resource,
141
+ };
142
+ return ufgClient.uploadResource({ resource: contentfuleResource, logger: uploadLogger });
143
+ });
144
+ resourcePromises = resourcePromises.concat(ufgClient.uploadResource({
145
+ resource: {
146
+ id: '',
147
+ url: '',
148
+ value: await fs_1.default.promises.readFile(path_1.default.resolve(executionPath, 'resources', target.snapshot.hash)),
149
+ contentType: target.snapshot.contentType,
150
+ hash: target.snapshot,
151
+ },
152
+ logger: uploadLogger,
153
+ }));
154
+ return Promise.all(resourcePromises);
155
+ });
156
+ await Promise.all(promises);
157
+ function isHashedResource(resource) {
158
+ return 'hash' in resource;
159
+ }
160
+ }
161
+ async function runCheck(eyes, target, index, logger) {
162
+ var _a;
163
+ const checkLogger = logger.extend({ tags: [`check-${index}`] });
164
+ const { elementReferences: selectors, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({
165
+ settings: target.settings,
166
+ });
167
+ const { renderId, selectorRegions, ...baseTarget } = await ufgClient.render({
168
+ target: target.target,
169
+ settings: {
170
+ ...target.settings,
171
+ region: (_a = selectors.target) !== null && _a !== void 0 ? _a : target.settings.region,
172
+ scrollRootElement: selectors.scrolling,
173
+ selectorsToCalculate: selectors.calculate,
174
+ includeFullPageSize: Boolean(target.settings.pageId),
175
+ environment: target.settings.environment,
176
+ uploadUrl: account.uploadUrl,
177
+ stitchingServiceUrl: account.stitchingServiceUrl,
178
+ },
179
+ logger: checkLogger,
180
+ });
181
+ const baseSettings = getBaseCheckSettings({
182
+ calculatedRegions: selectors.calculate.map((_, index) => {
183
+ var _a;
184
+ return ({
185
+ regions: (_a = selectorRegions === null || selectorRegions === void 0 ? void 0 : selectorRegions[index]) !== null && _a !== void 0 ? _a : [],
186
+ });
187
+ }),
188
+ });
189
+ baseSettings.renderId = renderId;
190
+ baseSettings.stepIndex = index;
191
+ baseTarget.source = target.target.source; // TODO verify
192
+ // baseTarget.name = snapshot.title // TODO figure out
193
+ await eyes.check({
194
+ target: { ...baseTarget, isTransformed: true },
195
+ settings: baseSettings,
196
+ logger: checkLogger,
197
+ });
198
+ }
199
+ }
200
+ exports.runOfflineSnapshots = runOfflineSnapshots;
201
+ function uniq(arr) {
202
+ return [...new Set(arr)];
203
+ }
204
+ function processResults({ testResults, totalTime, saveNewTests = true, failOnDiff = true, }) {
205
+ let outputStr = '\n';
206
+ const pluralize = utils.general.pluralize;
207
+ const testResultsWithErrors = testResults.filter(r => r && r.reason);
208
+ const unresolved = testResults.filter(r => r.isDifferent && !r.isAborted);
209
+ const passedOrNew = testResults.filter(r => r.status === 'Passed' || (r.isNew && !r.isAborted));
210
+ const aborted = testResults.filter(r => r.isAborted);
211
+ const newTests = testResults.filter(r => r.isNew && !r.isAborted);
212
+ const failedTests = testResults.filter(r => !r.reason && !r.isNew && !r.isAborted && !r.isDifferent && r.status === 'Failed');
213
+ const newTestsSize = newTests.length;
214
+ const warnForUnsavedNewTests = !!(!saveNewTests && newTestsSize);
215
+ const errMessagesToExclude = ['detected differences', 'Please approve the new baseline', 'is failed! See details at'];
216
+ const errors = testResultsWithErrors
217
+ .filter(r => !errMessagesToExclude.some(msg => { var _a, _b; return (_b = (_a = r.reason) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.includes(msg); }))
218
+ .map(r => ({
219
+ error: r.reason,
220
+ title: r.name,
221
+ }));
222
+ const hasResults = unresolved.length || passedOrNew.length || aborted.length;
223
+ const seeDetailsStr = hasResults && `See details at ${(passedOrNew[0] || unresolved[0] || aborted[0]).appUrls.batch}`;
224
+ if (hasResults) {
225
+ outputStr += `${seeDetailsStr}\n\n`;
226
+ }
227
+ outputStr += '[EYES: TEST RESULTS]:\n\n';
228
+ if (passedOrNew.length > 0) {
229
+ outputStr += testResultsOutput(passedOrNew, warnForUnsavedNewTests);
230
+ }
231
+ if (failedTests.length > 0) {
232
+ outputStr += testResultsOutput(failedTests, warnForUnsavedNewTests);
233
+ }
234
+ if (unresolved.length > 0) {
235
+ outputStr += testResultsOutput(unresolved, warnForUnsavedNewTests);
236
+ }
237
+ if (aborted.length > 0) {
238
+ outputStr += testResultsOutput(aborted, warnForUnsavedNewTests);
239
+ }
240
+ if (errors.length) {
241
+ const sortedErrors = errors.sort((a, b) => a.title.localeCompare(b.title));
242
+ outputStr += uniq(sortedErrors.map(({ title, error }) => `${title} - ${chalk_1.default.red('Failed')}. ${error.message || error.toString()}`)).join('\n');
243
+ outputStr += '\n';
244
+ }
245
+ if (!errors.length && !hasResults) {
246
+ outputStr += 'Test is finished but no results returned.\n';
247
+ }
248
+ const unresolvedOrFailed = unresolved.concat(failedTests);
249
+ if (errors.length && !unresolvedOrFailed.length) {
250
+ outputStr += chalk_1.default.red(`\nA total of ${errors.length} test${pluralize(errors.length)} failed for unexpected error${pluralize(errors.length)}.`);
251
+ }
252
+ else if (unresolvedOrFailed.length && !errors.length) {
253
+ outputStr += chalk_1.default.keyword(failedTests.length ? 'red' : 'orange')(`\nA total of ${unresolvedOrFailed.length} difference${pluralize(unresolvedOrFailed.length, [
254
+ 's were',
255
+ ' was',
256
+ ])} found.`);
257
+ }
258
+ else if (unresolvedOrFailed.length || errors.length) {
259
+ outputStr += chalk_1.default.red(`\nA total of ${unresolvedOrFailed.length} difference${pluralize(unresolvedOrFailed.length, [
260
+ 's were',
261
+ ' was',
262
+ ])} found and ${errors.length} test${pluralize(errors.length)} failed for ${pluralize(errors.length, [
263
+ '',
264
+ 'an ',
265
+ ])}unexpected error${pluralize(errors.length)}.`);
266
+ }
267
+ else if (warnForUnsavedNewTests) {
268
+ const countText = newTestsSize > 1 ? `are ${newTestsSize} new tests` : `is a new test: '${newTests[0].name}'`;
269
+ outputStr += chalk_1.default.red(`\n'saveNewTests' was set to false and there ${countText}. Please approve ${pluralize(newTestsSize, [
270
+ 'their',
271
+ 'its',
272
+ ])} baseline${pluralize(newTestsSize)} in Eyes dashboard.\n`);
273
+ }
274
+ else if (passedOrNew.length) {
275
+ outputStr += chalk_1.default.green(`\nNo differences were found!`);
276
+ }
277
+ if (hasResults) {
278
+ outputStr += `\n${seeDetailsStr}\nTotal time: ${Math.round(totalTime / 1000)} seconds\n`;
279
+ }
280
+ // if (Number(testConcurrency) === 5) {
281
+ // outputStr += `\n${concurrencyMsg}\n`
282
+ // }
283
+ let exitCode;
284
+ if (errors.length) {
285
+ exitCode = 1;
286
+ }
287
+ else if (failOnDiff) {
288
+ exitCode = !warnForUnsavedNewTests && passedOrNew.length && !unresolvedOrFailed.length ? 0 : 1;
289
+ }
290
+ else {
291
+ exitCode = 0;
292
+ }
293
+ return {
294
+ outputStr,
295
+ exitCode,
296
+ };
297
+ }
298
+ function testResultsOutput(results, warnForUnsavedNewTests) {
299
+ let outputStr = '';
300
+ const sortedTestResults = results.sort((a, b) => a.name.localeCompare(b.name));
301
+ sortedTestResults.forEach(result => {
302
+ const testTitle = `${result.name} [${result.hostApp}] [${result.hostDisplaySize.width}x${result.hostDisplaySize.height}] - `;
303
+ if (result.isAborted) {
304
+ outputStr += `${testTitle}${chalk_1.default.keyword('red')(`Aborted`)}\n`;
305
+ }
306
+ else if (result.isNew) {
307
+ const newResColor = warnForUnsavedNewTests ? 'orange' : 'blue';
308
+ outputStr += `${testTitle}${chalk_1.default.keyword(newResColor)('New')}\n`;
309
+ }
310
+ else if (result.status === 'Passed') {
311
+ outputStr += `${testTitle}${chalk_1.default.green('Passed')}\n`;
312
+ }
313
+ else if (result.status === 'Failed') {
314
+ outputStr += `${testTitle}${chalk_1.default.keyword('red')('Failed')}\n`;
315
+ }
316
+ else {
317
+ outputStr += `${testTitle}${chalk_1.default.keyword('orange')(`Unresolved`)}\n`;
318
+ }
319
+ });
320
+ outputStr += '\n';
321
+ return outputStr;
322
+ }
323
+ function formatEnvironment(environment) {
324
+ const env = environment.requested;
325
+ if (isChromeEmulation(env)) {
326
+ return `${env.chromeEmulationInfo.deviceName}${env.chromeEmulationInfo.screenOrientation ? ` [${env.chromeEmulationInfo.screenOrientation}]` : ''}`;
327
+ }
328
+ else if (isIOSDevice(env)) {
329
+ return `${env.iosDeviceInfo.deviceName}${env.iosDeviceInfo.screenOrientation ? ` [${env.iosDeviceInfo.screenOrientation}]` : ''}`;
330
+ }
331
+ else if (isAndroidDevice(env)) {
332
+ return `${env.androidDeviceInfo.deviceName}${env.androidDeviceInfo.screenOrientation ? ` [${env.androidDeviceInfo.screenOrientation}]` : ''}`;
333
+ }
334
+ else {
335
+ return `${env.name} [${env.width}x${env.height}]`;
336
+ }
337
+ function isChromeEmulation(env) {
338
+ return env.chromeEmulationInfo;
339
+ }
340
+ function isIOSDevice(env) {
341
+ return env.iosDeviceInfo;
342
+ }
343
+ function isAndroidDevice(env) {
344
+ return env.androidDeviceInfo;
345
+ }
346
+ }
package/dist/ufg/check.js CHANGED
@@ -28,29 +28,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.makeCheck = void 0;
30
30
  const driver_1 = require("@applitools/driver");
31
- const take_dom_snapshots_1 = require("./utils/take-dom-snapshots");
32
- const to_base_check_settings_1 = require("../automation/utils/to-base-check-settings");
33
- const to_generated_selectors_1 = require("./utils/to-generated-selectors");
34
31
  const uniquify_environments_1 = require("../automation/utils/uniquify-environments");
35
32
  const to_environment_key_1 = require("../automation/utils/to-environment-key");
36
33
  const abort_error_1 = require("../errors/abort-error");
37
34
  const utils = __importStar(require("@applitools/utils"));
38
35
  const lang = __importStar(require("../lang"));
39
36
  const chalk_1 = __importDefault(require("chalk"));
37
+ const take_snapshots_1 = require("./take-snapshots");
38
+ const create_render_target_from_snapshot_1 = require("./create-render-target-from-snapshot");
39
+ const to_base_check_settings_1 = require("../automation/utils/to-base-check-settings");
40
40
  function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironments = [], spec, signal, logger: mainLogger, }) {
41
41
  return async function check({ target = defaultTarget, settings = {}, logger = mainLogger, } = {}) {
42
- var _a, _b;
42
+ var _a;
43
43
  logger = logger.extend(mainLogger);
44
44
  logger.log('Command "check" is called with settings', settings);
45
45
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
46
46
  logger.warn('Command "check" was called after test was already aborted');
47
47
  throw new abort_error_1.AbortError('Command "check" was called after test was already aborted');
48
48
  }
49
- const { elementReferences, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({ settings });
50
- const { elementReferencesToMark, getGeneratedSelectors } = (0, to_generated_selectors_1.toGeneratedSelectors)({
51
- elementReferences,
52
- 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; },
53
- });
54
49
  const uniqueEnvironments = (0, uniquify_environments_1.uniquifyEnvironments)((_a = settings.environments) !== null && _a !== void 0 ? _a : defaultEnvironments);
55
50
  const ufgClient = await eyes.core.getUFGClient({
56
51
  settings: {
@@ -61,66 +56,27 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
61
56
  logger,
62
57
  });
63
58
  let snapshots;
64
- let snapshotUrl;
65
- let snapshotTitle;
66
- let userAgent;
67
- const driver = spec && (0, driver_1.isDriver)(target, spec)
68
- ? await (0, driver_1.makeDriver)({ spec, driver: target, reset: target === defaultTarget, logger })
69
- : undefined;
70
- if (driver) {
71
- const environment = await driver.getEnvironment();
72
- const currentContext = driver.currentContext;
73
- await currentContext.setScrollingElement((_b = settings.scrollRootElement) !== null && _b !== void 0 ? _b : null);
74
- if (environment.isWeb) {
75
- userAgent = await driver.getUserAgentLegacy();
76
- snapshots = await (0, take_dom_snapshots_1.takeDomSnapshots)({
77
- driver,
78
- settings: {
79
- ...eyes.test.eyesServer,
80
- waitBeforeCapture: settings.waitBeforeCapture,
81
- disableBrowserFetching: settings.disableBrowserFetching,
82
- layoutBreakpoints: settings.layoutBreakpoints,
83
- environments: uniqueEnvironments,
84
- skipResources: ufgClient.getCachedResourceUrls(),
85
- lazyLoad: settings.lazyLoad,
86
- elementReferences: elementReferencesToMark,
87
- },
88
- provides: {
89
- getChromeEmulationDevices: ufgClient.getChromeEmulationDevices,
90
- getIOSDevices: ufgClient.getIOSDevices,
91
- },
92
- logger,
93
- });
94
- }
95
- else {
96
- const nmlClient = await eyes.core.getNMLClient({
97
- driver,
98
- settings: { ...eyes.test.eyesServer, supportedEnvironmentsUrl: eyes.test.supportedEnvironmentsUrl },
99
- logger,
100
- });
101
- snapshots = (await nmlClient.takeSnapshots({
102
- settings: {
103
- ...eyes.test.eyesServer,
104
- waitBeforeCapture: settings.waitBeforeCapture,
105
- environments: uniqueEnvironments,
106
- },
107
- logger,
108
- }));
109
- }
110
- await currentContext.focus();
111
- snapshotUrl = await driver.getUrl();
112
- snapshotTitle = await driver.getTitle();
59
+ let driver;
60
+ if (spec && (0, driver_1.isDriver)(target, spec)) {
61
+ const takeSnapshots = (0, take_snapshots_1.makeTakeSnapshots)({ core: eyes.core, spec, signal, logger });
62
+ driver = await (0, driver_1.makeDriver)({ spec, driver: target, logger });
63
+ snapshots = await takeSnapshots({
64
+ driver,
65
+ account: eyes.test.account,
66
+ settings: { ...settings, environments: uniqueEnvironments },
67
+ logger,
68
+ });
113
69
  }
114
70
  else {
71
+ // TODO (amit)
115
72
  snapshots = !utils.types.isArray(target) ? Array(uniqueEnvironments.length).fill(target) : target;
116
- snapshotUrl = utils.types.has(snapshots[0], 'url') ? snapshots[0].url : undefined;
117
73
  }
118
- const generatedSelectors = snapshots.map(snapshot => getGeneratedSelectors(utils.types.has(snapshot, 'generatedSelectors') ? snapshot.generatedSelectors : undefined));
119
- const promises = uniqueEnvironments.map(async (environment, index) => {
74
+ const promises = snapshots.map(async (snapshot, i) => {
120
75
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
121
76
  const environmentLogger = logger.extend({ tags: [`environment-${utils.general.shortid()}`] });
122
- const ufgEnvironment = environment;
123
- if (utils.types.has(ufgEnvironment, 'name') && ufgEnvironment.name === 'edge') {
77
+ const { target } = snapshot;
78
+ const environment = uniqueEnvironments[i];
79
+ if (utils.types.has(environment, 'name') && environment.name === 'edge') {
124
80
  environmentLogger.console.log(chalk_1.default.yellow(lang.edgeUfgEnvironmentDeprecatedWarning));
125
81
  }
126
82
  try {
@@ -128,26 +84,10 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
128
84
  environmentLogger.warn('Command "check" was aborted before rendering');
129
85
  throw new abort_error_1.AbortError('Command "check" was aborted before rendering');
130
86
  }
131
- const { cookies, ...snapshot } = snapshots[index];
132
- const selectors = generatedSelectors[index];
133
- if (utils.types.has(ufgEnvironment, 'iosDeviceInfo') || utils.types.has(ufgEnvironment, 'androidDeviceInfo')) {
134
- ufgEnvironment.type = utils.types.has(snapshot, 'cdt') ? 'web' : 'native';
87
+ if (utils.types.has(environment, 'iosDeviceInfo') || utils.types.has(environment, 'androidDeviceInfo')) {
88
+ environment.type = utils.types.has(target, 'cdt') ? 'web' : 'native';
135
89
  }
136
- const renderTargetPromise = ufgClient.createRenderTarget({
137
- snapshot,
138
- settings: {
139
- environment: ufgEnvironment,
140
- cookies,
141
- headers: {
142
- Referer: snapshotUrl,
143
- 'User-Agent': userAgent,
144
- ...settings.headers,
145
- },
146
- proxy: eyes.test.eyesServer.proxy,
147
- autProxy: settings.autProxy,
148
- },
149
- logger: environmentLogger,
150
- });
90
+ const renderTargetPromise = (0, create_render_target_from_snapshot_1.createRenderTargetFromSnapshot)({ ufgClient, snapshot, logger: environmentLogger });
151
91
  const baseEyes = await eyes.getBaseEyes({ settings: { environment, driver }, logger: environmentLogger });
152
92
  try {
153
93
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
@@ -167,31 +107,35 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
167
107
  environmentLogger.warn(`Render on environment with id "${(_c = baseEyes.test.environment) === null || _c === void 0 ? void 0 : _c.environmentId}" was aborted during one of the previous steps`);
168
108
  throw new abort_error_1.AbortError(`Render on environment with id "${(_d = baseEyes.test.environment) === null || _d === void 0 ? void 0 : _d.environmentId}" was aborted during one of the previous steps`);
169
109
  }
110
+ const { elementReferences: selectors, getBaseCheckSettings } = (0, to_base_check_settings_1.toBaseCheckSettings)({
111
+ settings: snapshot.settings,
112
+ });
170
113
  const { renderId, selectorRegions, ...baseTarget } = await ufgClient.render({
171
114
  target: renderTarget,
172
115
  settings: {
173
- ...settings,
174
- region: (_e = selectors.target) !== null && _e !== void 0 ? _e : settings.region,
116
+ ...snapshot.settings,
117
+ region: (_e = selectors.target) !== null && _e !== void 0 ? _e : snapshot.settings.region,
175
118
  scrollRootElement: selectors.scrolling,
176
- selectorsToCalculate: selectors.calculate.flatMap(({ safeSelector }) => safeSelector !== null && safeSelector !== void 0 ? safeSelector : []),
177
- includeFullPageSize: Boolean(settings.pageId),
178
- environment: { ...ufgEnvironment, environmentId: baseEyes.test.environment.environmentId },
119
+ selectorsToCalculate: selectors.calculate,
120
+ includeFullPageSize: Boolean(snapshot.settings.pageId),
121
+ environment: { ...environment, environmentId: baseEyes.test.environment.environmentId },
179
122
  uploadUrl: baseEyes.test.uploadUrl,
180
123
  stitchingServiceUrl: baseEyes.test.stitchingServiceUrl,
181
124
  },
182
125
  signal,
183
126
  logger: environmentLogger,
184
127
  });
185
- let offset = 0;
186
128
  const baseSettings = getBaseCheckSettings({
187
- calculatedRegions: selectors.calculate.map(({ originalSelector, safeSelector }) => ({
188
- selector: originalSelector !== null && originalSelector !== void 0 ? originalSelector : undefined,
189
- regions: safeSelector ? selectorRegions[offset++] : [],
190
- })),
129
+ calculatedRegions: selectors.calculate.map((_, index) => {
130
+ var _a;
131
+ return ({
132
+ regions: (_a = selectorRegions === null || selectorRegions === void 0 ? void 0 : selectorRegions[index]) !== null && _a !== void 0 ? _a : [],
133
+ });
134
+ }),
191
135
  });
192
136
  baseSettings.renderId = renderId;
193
- baseTarget.source = snapshotUrl;
194
- baseTarget.name = snapshotTitle;
137
+ baseTarget.source = snapshot.url;
138
+ baseTarget.name = snapshot.title;
195
139
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
196
140
  environmentLogger.warn('Command "check" was aborted after rendering');
197
141
  throw new abort_error_1.AbortError('Command "check" was aborted after rendering');
@@ -238,8 +182,8 @@ function makeCheck({ eyes, target: defaultTarget, environments: defaultEnvironme
238
182
  }
239
183
  }
240
184
  catch (error) {
241
- environmentLogger.error(`Environment with id ${ufgEnvironment.environmentId} failed before rendering started due to an error`, error);
242
- error.info = { ...error.info, userTestId: eyes.test.userTestId, environment: ufgEnvironment };
185
+ environmentLogger.error(`Environment with id ${environment.environmentId} failed before rendering started due to an error`, error);
186
+ error.info = { ...error.info, userTestId: eyes.test.userTestId, environment };
243
187
  throw error;
244
188
  }
245
189
  });
package/dist/ufg/core.js CHANGED
@@ -36,10 +36,11 @@ const take_snapshots_1 = require("./take-snapshots");
36
36
  const get_ufg_client_1 = require("./get-ufg-client");
37
37
  const open_eyes_1 = require("./open-eyes");
38
38
  const utils = __importStar(require("@applitools/utils"));
39
- function makeCore({ spec, clients, base: defaultBase, asyncCache, concurrency, fetchConcurrency, agentId = 'core-ufg', cwd = process.cwd(), logger: defaultLogger, }) {
39
+ function makeCore({ spec, clients, base: defaultBase, asyncCache, concurrency, offlineLocationPath, fetchConcurrency, agentId = 'core-ufg', cwd = process.cwd(), logger: defaultLogger, }) {
40
40
  const logger = (0, logger_1.makeLogger)({ logger: defaultLogger, format: { label: 'core-ufg' } });
41
41
  logger.log(`Core ufg is initialized ${defaultBase ? 'with' : 'without'} custom base core`);
42
- const base = defaultBase !== null && defaultBase !== void 0 ? defaultBase : (0, core_base_1.makeCore)({ agentId, concurrency, cwd, logger });
42
+ const base = defaultBase !== null && defaultBase !== void 0 ? defaultBase : (0, core_base_1.makeCore)({ agentId, concurrency, cwd, logger, offlineLocationPath });
43
+ const ufgClient = clients === null || clients === void 0 ? void 0 : clients.ufg;
43
44
  return utils.general.extend(base, core => {
44
45
  return {
45
46
  type: 'ufg',
@@ -50,7 +51,7 @@ function makeCore({ spec, clients, base: defaultBase, asyncCache, concurrency, f
50
51
  locate: (0, locate_1.makeLocate)({ spec, core, logger }),
51
52
  locateText: (0, locate_text_1.makeLocateText)({ spec, core, logger }),
52
53
  extractText: (0, extract_text_1.makeExtractText)({ spec, core, logger }),
53
- getUFGClient: (0, get_ufg_client_1.makeGetUFGClient)({ client: clients === null || clients === void 0 ? void 0 : clients.ufg, fetchConcurrency, asyncCache, logger }),
54
+ getUFGClient: (0, get_ufg_client_1.makeGetUFGClient)({ client: ufgClient, fetchConcurrency, asyncCache, offlineLocationPath, logger }),
54
55
  ...(0, get_nml_client_1.makeGetNMLClient)({ client: clients === null || clients === void 0 ? void 0 : clients.nml, logger }),
55
56
  openEyes: (0, open_eyes_1.makeOpenEyes)({ spec, core, logger }),
56
57
  };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRenderTargetFromSnapshot = void 0;
4
+ async function createRenderTargetFromSnapshot({ ufgClient, snapshot, logger, }) {
5
+ return await ufgClient.createRenderTarget({
6
+ snapshot: snapshot.target,
7
+ settings: {
8
+ environment: snapshot.environment,
9
+ cookies: snapshot.target.cookies,
10
+ headers: {
11
+ Referer: snapshot.url,
12
+ 'User-Agent': snapshot.userAgent,
13
+ ...snapshot.settings.headers,
14
+ },
15
+ proxy: snapshot.account.eyesServer.proxy,
16
+ autProxy: snapshot.settings.autProxy,
17
+ },
18
+ logger,
19
+ });
20
+ }
21
+ exports.createRenderTargetFromSnapshot = createRenderTargetFromSnapshot;
@@ -26,7 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.makeGetUFGClient = void 0;
27
27
  const ufg_client_1 = require("@applitools/ufg-client");
28
28
  const utils = __importStar(require("@applitools/utils"));
29
- function makeGetUFGClient({ client, fetchConcurrency, logger: mainLogger, asyncCache }) {
29
+ function makeGetUFGClient({ client, fetchConcurrency, offlineLocationPath, logger: mainLogger, asyncCache, }) {
30
30
  // we are caching by the server config, therefor if the user creates another Runner / manager with the same server config but different
31
31
  // fetchConcurrency, it will not take any affect.
32
32
  const getUFGClientWithCache = utils.general.cachify(getUFGClient, ([options]) => client ? 'default' : [{ ...options.settings, fetchConcurrency: undefined }]);
@@ -39,7 +39,7 @@ function makeGetUFGClient({ client, fetchConcurrency, logger: mainLogger, asyncC
39
39
  ? utils.general.getEnvValue('TUNNEL_IDS')
40
40
  : undefined;
41
41
  return (0, ufg_client_1.makeUFGClient)({
42
- settings: { ...settings, fetchConcurrency, tunnelIds, asyncCache },
42
+ settings: { ...settings, fetchConcurrency, offlineLocationPath, tunnelIds, asyncCache },
43
43
  logger,
44
44
  });
45
45
  }
@@ -28,25 +28,23 @@ const driver_1 = require("@applitools/driver");
28
28
  const take_dom_snapshots_1 = require("./utils/take-dom-snapshots");
29
29
  const to_safe_check_settings_1 = require("./utils/to-safe-check-settings");
30
30
  const to_generated_selectors_1 = require("./utils/to-generated-selectors");
31
- const uniquify_environments_1 = require("../automation/utils/uniquify-environments");
32
31
  const abort_error_1 = require("../errors/abort-error");
33
32
  const utils = __importStar(require("@applitools/utils"));
34
33
  function makeTakeSnapshots({ core, spec, signal, logger: mainLogger }) {
35
- return async function takeSnapshots({ target, settings = {}, environments: defaultEnvironments = [], account, logger = mainLogger, }) {
36
- var _a, _b;
34
+ return async function takeSnapshots({ driver, settings = {}, account, logger = mainLogger, }) {
35
+ var _a;
37
36
  logger = logger.extend(mainLogger);
38
37
  logger.log('Command "takeSnapshots" is called with settings', settings);
39
38
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
40
39
  logger.warn('Command "takeSnapshots" was called after test was already aborted');
41
40
  throw new abort_error_1.AbortError('Command "takeSnapshots" was called after test was already aborted');
42
41
  }
43
- const uniqueEnvironments = (0, uniquify_environments_1.uniquifyEnvironments)((_a = settings.environments) !== null && _a !== void 0 ? _a : defaultEnvironments);
44
- const driver = spec && target ? await (0, driver_1.makeDriver)({ spec, driver: target, logger }) : null;
42
+ const uniqueEnvironments = settings.environments;
45
43
  if (!driver)
46
44
  throw new Error('Cannot create check snapshot without a driver');
47
45
  const environment = await driver.getEnvironment();
48
46
  const currentContext = driver.currentContext;
49
- await currentContext.setScrollingElement((_b = settings.scrollRootElement) !== null && _b !== void 0 ? _b : null);
47
+ await currentContext.setScrollingElement((_a = settings.scrollRootElement) !== null && _a !== void 0 ? _a : null);
50
48
  const { elementReferences, getSafeCheckSettings } = (0, to_safe_check_settings_1.toSafeCheckSettings)({ settings });
51
49
  const { elementReferencesToMark, getGeneratedSelectors } = (0, to_generated_selectors_1.toGeneratedSelectors)({
52
50
  elementReferences,