@applitools/core 4.31.4 → 4.32.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 +13 -0
- package/dist/offline/run-offline-snapshots.js +64 -30
- package/dist/open-eyes.js +20 -10
- package/dist/ufg/open-eyes.js +11 -1
- package/dist/ufg/take-snapshots.js +22 -3
- package/dist/ufg/utils/filterStaleElements.js +40 -0
- package/dist/ufg/utils/verify-environment-info.js +89 -0
- package/package.json +1 -1
- package/types/automation/types.d.ts +1 -0
- package/types/ufg/utils/filterStaleElements.d.ts +22 -0
- package/types/ufg/utils/verify-environment-info.d.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.32.0](https://github.com/Applitools-Dev/sdk/compare/js/core@4.31.4...js/core@4.32.0) (2025-03-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* limit offline console logs ([#2813](https://github.com/Applitools-Dev/sdk/issues/2813)) ([9bec38b](https://github.com/Applitools-Dev/sdk/commit/9bec38b39cd7a35e574b667e8efa5016d3cf8fb3))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* abort offline corrupt tests ([#2827](https://github.com/Applitools-Dev/sdk/issues/2827)) ([eabca07](https://github.com/Applitools-Dev/sdk/commit/eabca07c7575433fb97f63762412ddbb492dd665))
|
|
14
|
+
* stale elements for webdriver sdks ([#2798](https://github.com/Applitools-Dev/sdk/issues/2798)) ([03e5fac](https://github.com/Applitools-Dev/sdk/commit/03e5fac2d3929ebe615293fd899b7e21443fb062))
|
|
15
|
+
|
|
3
16
|
## [4.31.4](https://github.com/Applitools-Dev/sdk/compare/js/core@4.31.3...js/core@4.31.4) (2025-02-26)
|
|
4
17
|
|
|
5
18
|
|
|
@@ -37,8 +37,13 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
37
37
|
const utils = __importStar(require("@applitools/utils"));
|
|
38
38
|
const merge_configs_1 = require("./merge-configs");
|
|
39
39
|
const format_results_1 = require("../utils/format-results");
|
|
40
|
+
function getConsoleLogLimit() {
|
|
41
|
+
var _a;
|
|
42
|
+
return (_a = utils.general.getEnvValue('OFFLINE_LOG_LIMIT', 'number')) !== null && _a !== void 0 ? _a : 20;
|
|
43
|
+
}
|
|
40
44
|
async function runOfflineSnapshots(options) {
|
|
41
45
|
var _a;
|
|
46
|
+
const limitConsoleLogs = getConsoleLogLimit();
|
|
42
47
|
if (!options.offlineLocationPath)
|
|
43
48
|
throw new Error('offlineLocationPath is required');
|
|
44
49
|
const offlineLocationPath = path_1.default.resolve(options.offlineLocationPath);
|
|
@@ -80,14 +85,26 @@ async function runOfflineSnapshots(options) {
|
|
|
80
85
|
return allTestResults;
|
|
81
86
|
async function runTests(testFolders) {
|
|
82
87
|
logger.log('running tests', testFolders);
|
|
83
|
-
const
|
|
88
|
+
const messages = [];
|
|
89
|
+
const testPromises = testFolders.map(async (testFolder) => {
|
|
84
90
|
const testLogger = logger.extend({ tags: [testFolder] });
|
|
85
91
|
const testPath = path_1.default.join(offlineLocationPath, testFolder);
|
|
86
92
|
const fileOpenSettings = await fs_1.default.promises
|
|
87
93
|
.readFile(path_1.default.join(testPath, 'settings.json'), 'utf-8')
|
|
88
94
|
.then(JSON.parse);
|
|
89
95
|
const openSettings = (0, merge_configs_1.mergeConfigs)(fileOpenSettings, options.config.open);
|
|
90
|
-
|
|
96
|
+
messages.push(`Running test: ${openSettings.testName} (${formatEnvironment(openSettings.environment)})`);
|
|
97
|
+
return { testPath, openSettings, testLogger };
|
|
98
|
+
});
|
|
99
|
+
const preparedTests = await Promise.all(testPromises);
|
|
100
|
+
if (messages.length > limitConsoleLogs) {
|
|
101
|
+
const slice = messages.slice(0, limitConsoleLogs);
|
|
102
|
+
logger.console.log(slice.join('\n') + `\n... ${messages.length - limitConsoleLogs} more tests`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
logger.console.log(messages.join('\n'));
|
|
106
|
+
}
|
|
107
|
+
const results = await Promise.all(preparedTests.map(async ({ testPath, openSettings, testLogger }) => {
|
|
91
108
|
return runTest(testPath, openSettings, testLogger);
|
|
92
109
|
}));
|
|
93
110
|
const batchIds = [...new Set(results.map(t => t.batchId))];
|
|
@@ -115,23 +132,29 @@ async function runOfflineSnapshots(options) {
|
|
|
115
132
|
},
|
|
116
133
|
logger,
|
|
117
134
|
});
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
const closeSettingsPath = path_1.default.resolve(testPath, 'close.json');
|
|
136
|
+
if (fs_1.default.existsSync(closeSettingsPath)) {
|
|
137
|
+
const checkFolders = (await fs_1.default.promises.readdir(testPath)).filter(folderpath => folderpath.startsWith('check-'));
|
|
138
|
+
logger.log('running checks for test', testPath, ':', checkFolders);
|
|
139
|
+
const targets = await Promise.all(checkFolders.map(async (checkFolder) => {
|
|
140
|
+
const snapshot = await fs_1.default.promises
|
|
141
|
+
.readFile(path_1.default.resolve(testPath, checkFolder, 'snapshot.json'), 'utf-8')
|
|
142
|
+
.then(JSON.parse);
|
|
143
|
+
snapshot.settings.environment.environmentId = utils.general.guid();
|
|
144
|
+
return snapshot;
|
|
145
|
+
}));
|
|
146
|
+
await uploadResources(targets, logger);
|
|
147
|
+
// logger.log('resource hashes for test', testFolder, ':', resourceHashes)
|
|
148
|
+
logger.log('uploaded resources for test', testPath);
|
|
149
|
+
await Promise.all(targets.map((target, index) => runCheck(eyes, target, index, logger)));
|
|
150
|
+
const fileCloseSettings = await fs_1.default.promises.readFile(closeSettingsPath, 'utf-8').then(JSON.parse);
|
|
151
|
+
const closeSettings = (0, merge_configs_1.mergeConfigs)(fileCloseSettings, options.config.close);
|
|
152
|
+
await eyes.close({ settings: closeSettings });
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
await eyes.abort();
|
|
156
|
+
}
|
|
157
|
+
logger.log('done running test', testPath);
|
|
135
158
|
return { batchId: openSettings.batch.id, results: (await eyes.getResults({ logger }))[0] };
|
|
136
159
|
}
|
|
137
160
|
async function uploadResources(targets, logger) {
|
|
@@ -235,16 +258,16 @@ function processResults({ testResults, totalTime, saveNewTests = true, failOnDif
|
|
|
235
258
|
}
|
|
236
259
|
outputStr += '[EYES: TEST RESULTS]:\n\n';
|
|
237
260
|
if (passedOrNew.length > 0) {
|
|
238
|
-
outputStr += testResultsOutput(passedOrNew, warnForUnsavedNewTests);
|
|
261
|
+
outputStr += testResultsOutput(passedOrNew, warnForUnsavedNewTests, 'Passed');
|
|
239
262
|
}
|
|
240
263
|
if (failedTests.length > 0) {
|
|
241
|
-
outputStr += testResultsOutput(failedTests, warnForUnsavedNewTests);
|
|
264
|
+
outputStr += testResultsOutput(failedTests, warnForUnsavedNewTests, 'Failed');
|
|
242
265
|
}
|
|
243
266
|
if (unresolved.length > 0) {
|
|
244
|
-
outputStr += testResultsOutput(unresolved, warnForUnsavedNewTests);
|
|
267
|
+
outputStr += testResultsOutput(unresolved, warnForUnsavedNewTests, 'Unresolved');
|
|
245
268
|
}
|
|
246
269
|
if (aborted.length > 0) {
|
|
247
|
-
outputStr += testResultsOutput(aborted, warnForUnsavedNewTests);
|
|
270
|
+
outputStr += testResultsOutput(aborted, warnForUnsavedNewTests, 'Aborted');
|
|
248
271
|
}
|
|
249
272
|
if (errors.length) {
|
|
250
273
|
const sortedErrors = errors.sort((a, b) => a.title.localeCompare(b.title));
|
|
@@ -308,28 +331,39 @@ function processResults({ testResults, totalTime, saveNewTests = true, failOnDif
|
|
|
308
331
|
isSuccess,
|
|
309
332
|
};
|
|
310
333
|
}
|
|
311
|
-
function testResultsOutput(results, warnForUnsavedNewTests) {
|
|
312
|
-
|
|
334
|
+
function testResultsOutput(results, warnForUnsavedNewTests, tag) {
|
|
335
|
+
const limitConsoleLogs = getConsoleLogLimit();
|
|
336
|
+
const truncated = [];
|
|
337
|
+
let limitCount = 0;
|
|
313
338
|
const sortedTestResults = results.sort((a, b) => a.name.localeCompare(b.name));
|
|
314
339
|
sortedTestResults.forEach(result => {
|
|
315
340
|
const testTitle = `${result.name} [${result.hostApp}] [${result.hostDisplaySize.width}x${result.hostDisplaySize.height}] - `;
|
|
316
341
|
if (result.isAborted) {
|
|
317
|
-
|
|
342
|
+
const str = `${testTitle}${chalk_1.default.keyword('red')(`Aborted`)}\n`;
|
|
343
|
+
truncated.push(str);
|
|
318
344
|
}
|
|
319
345
|
else if (result.isNew) {
|
|
320
346
|
const newResColor = warnForUnsavedNewTests ? 'orange' : 'blue';
|
|
321
|
-
|
|
347
|
+
const str = `${testTitle}${chalk_1.default.keyword(newResColor)('New')}\n`;
|
|
348
|
+
truncated.push(str);
|
|
322
349
|
}
|
|
323
350
|
else if (result.status === 'Passed') {
|
|
324
|
-
|
|
351
|
+
const str = `${testTitle}${chalk_1.default.green('Passed')}\n`;
|
|
352
|
+
truncated.push(str);
|
|
325
353
|
}
|
|
326
354
|
else if (result.status === 'Failed') {
|
|
327
|
-
|
|
355
|
+
const str = `${testTitle}${chalk_1.default.keyword('red')('Failed')}\n`;
|
|
356
|
+
truncated.push(str);
|
|
328
357
|
}
|
|
329
358
|
else {
|
|
330
|
-
|
|
359
|
+
const str = `${testTitle}${chalk_1.default.keyword('orange')(`Unresolved`)}\n`;
|
|
360
|
+
truncated.push(str);
|
|
331
361
|
}
|
|
362
|
+
if (limitCount < limitConsoleLogs)
|
|
363
|
+
limitCount++;
|
|
332
364
|
});
|
|
365
|
+
let outputStr = truncated.slice(0, limitConsoleLogs).join('');
|
|
366
|
+
outputStr += results.length - limitCount > 0 ? `... ${results.length - limitCount} more ${tag} tests` : '';
|
|
333
367
|
outputStr += '\n';
|
|
334
368
|
return outputStr;
|
|
335
369
|
}
|
package/dist/open-eyes.js
CHANGED
|
@@ -39,20 +39,20 @@ const core_base_1 = require("@applitools/core-base");
|
|
|
39
39
|
const extract_git_info_1 = require("./utils/extract-git-info");
|
|
40
40
|
function makeOpenEyes({ type: defaultType = 'classic', clients, batch, removeDuplicateTests, core, cores, spec, environment, logger: mainLogger, asyncCache, cwd = process.cwd(), }) {
|
|
41
41
|
return async function openEyes({ type = defaultType, settings: openSettings, config, target, logger = mainLogger, }) {
|
|
42
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
43
|
-
var
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
43
|
+
var _z, _0, _1, _2, _3;
|
|
44
44
|
logger = logger.extend(mainLogger, { tags: [`eyes-${type}-${utils.general.shortid()}`] });
|
|
45
|
-
const settings = { ...config === null || config === void 0 ? void 0 : config.open, ...openSettings };
|
|
45
|
+
const settings = { environments: config === null || config === void 0 ? void 0 : config.check.environments, ...config === null || config === void 0 ? void 0 : config.open, ...openSettings };
|
|
46
46
|
const eyesServerSettings = (0, populate_eyes_server_settings_1.populateEyesServerSettings)(settings);
|
|
47
47
|
logger.mask(eyesServerSettings.apiKey);
|
|
48
48
|
logger.mask(eyesServerSettings.eyesServerUrl);
|
|
49
49
|
(_a = settings.userTestId) !== null && _a !== void 0 ? _a : (settings.userTestId = `${settings.testName}--${utils.general.guid()}`);
|
|
50
50
|
settings.batch = { ...batch, ...settings.batch };
|
|
51
|
-
(_b = (
|
|
52
|
-
(_d = (
|
|
53
|
-
(_e = (
|
|
54
|
-
(_f = (
|
|
55
|
-
(_g = (
|
|
51
|
+
(_b = (_z = settings.batch).id) !== null && _b !== void 0 ? _b : (_z.id = (_c = utils.general.getEnvValue('BATCH_ID')) !== null && _c !== void 0 ? _c : `generated-${utils.general.guid()}`);
|
|
52
|
+
(_d = (_0 = settings.batch).buildId) !== null && _d !== void 0 ? _d : (_0.buildId = utils.general.getEnvValue('BATCH_BUILD_ID'));
|
|
53
|
+
(_e = (_1 = settings.batch).name) !== null && _e !== void 0 ? _e : (_1.name = utils.general.getEnvValue('BATCH_NAME'));
|
|
54
|
+
(_f = (_2 = settings.batch).sequenceName) !== null && _f !== void 0 ? _f : (_2.sequenceName = utils.general.getEnvValue('BATCH_SEQUENCE'));
|
|
55
|
+
(_g = (_3 = settings.batch).notifyOnCompletion) !== null && _g !== void 0 ? _g : (_3.notifyOnCompletion = utils.general.getEnvValue('BATCH_NOTIFY', 'boolean'));
|
|
56
56
|
(_h = settings.keepBatchOpen) !== null && _h !== void 0 ? _h : (settings.keepBatchOpen = utils.general.getEnvValue('DONT_CLOSE_BATCHES', 'boolean'));
|
|
57
57
|
(_j = settings.branchName) !== null && _j !== void 0 ? _j : (settings.branchName = utils.general.getEnvValue('BRANCH'));
|
|
58
58
|
(_k = settings.parentBranchName) !== null && _k !== void 0 ? _k : (settings.parentBranchName = utils.general.getEnvValue('PARENT_BRANCH'));
|
|
@@ -92,6 +92,15 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, removeDup
|
|
|
92
92
|
const driver = target && (await (0, driver_1.makeDriver)({ spec, driver: target, logger, customConfig: settings }));
|
|
93
93
|
const driverEnvironment = await (driver === null || driver === void 0 ? void 0 : driver.getEnvironment());
|
|
94
94
|
const driverUrl = await (driver === null || driver === void 0 ? void 0 : driver.getDriverUrl());
|
|
95
|
+
const multiDeviceTargets = [];
|
|
96
|
+
for (const checkEnv of (_u = settings.environments) !== null && _u !== void 0 ? _u : []) {
|
|
97
|
+
if (utils.types.has(checkEnv, 'iosDeviceInfo') && ((_v = driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.applitoolsLib) === null || _v === void 0 ? void 0 : _v.instrumented)) {
|
|
98
|
+
multiDeviceTargets.push({
|
|
99
|
+
deviceInfo: checkEnv.iosDeviceInfo.deviceName,
|
|
100
|
+
orientation: (_w = checkEnv.iosDeviceInfo.screenOrientation) !== null && _w !== void 0 ? _w : 'portrait',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
95
104
|
void core.logEvent({
|
|
96
105
|
settings: {
|
|
97
106
|
...settings,
|
|
@@ -99,7 +108,7 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, removeDup
|
|
|
99
108
|
event: {
|
|
100
109
|
type: 'openEyes',
|
|
101
110
|
userTestId: settings.userTestId,
|
|
102
|
-
concurrency: (
|
|
111
|
+
concurrency: (_x = cores === null || cores === void 0 ? void 0 : cores[type].concurrency) !== null && _x !== void 0 ? _x : core.concurrency,
|
|
103
112
|
environment,
|
|
104
113
|
driver: {
|
|
105
114
|
deviceName: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.deviceName,
|
|
@@ -107,10 +116,11 @@ function makeOpenEyes({ type: defaultType = 'classic', clients, batch, removeDup
|
|
|
107
116
|
browserVersion: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.browserVersion,
|
|
108
117
|
platformName: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.platformName,
|
|
109
118
|
platformVersion: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.platformVersion,
|
|
110
|
-
isApplitoolsLib: (
|
|
119
|
+
isApplitoolsLib: (_y = driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.applitoolsLib) === null || _y === void 0 ? void 0 : _y.instrumented,
|
|
111
120
|
isEC: driverEnvironment === null || driverEnvironment === void 0 ? void 0 : driverEnvironment.isEC,
|
|
112
121
|
},
|
|
113
122
|
driverUrl,
|
|
123
|
+
multiDeviceTargets,
|
|
114
124
|
},
|
|
115
125
|
},
|
|
116
126
|
logger,
|
package/dist/ufg/open-eyes.js
CHANGED
|
@@ -32,11 +32,12 @@ const close_1 = require("../automation/close");
|
|
|
32
32
|
const abort_1 = require("../automation/abort");
|
|
33
33
|
const get_results_1 = require("../automation/get-results");
|
|
34
34
|
const extract_default_environment_1 = require("./utils/extract-default-environment");
|
|
35
|
+
const verify_environment_info_1 = require("./utils/verify-environment-info");
|
|
35
36
|
const abort_controller_1 = require("abort-controller");
|
|
36
37
|
const utils = __importStar(require("@applitools/utils"));
|
|
37
38
|
function makeOpenEyes({ core, spec, logger: mainLogger }) {
|
|
38
39
|
return async function openEyes({ target, settings, storage = new Map(), logger = mainLogger, }) {
|
|
39
|
-
var _a, _b, _c;
|
|
40
|
+
var _a, _b, _c, _d;
|
|
40
41
|
logger = logger.extend(mainLogger);
|
|
41
42
|
logger.log(`Command "openEyes" is called with ${target ? 'default driver' : ''}`, ...(settings ? ['and settings', settings] : []), storage.size > 0 ? 'and default eyes storage' : '');
|
|
42
43
|
const driver = target && (await (0, driver_1.makeDriver)({ spec, driver: target, logger }));
|
|
@@ -54,6 +55,15 @@ function makeOpenEyes({ core, spec, logger: mainLogger }) {
|
|
|
54
55
|
const controller = new abort_controller_1.AbortController();
|
|
55
56
|
const { signal } = controller;
|
|
56
57
|
const account = await core.getAccountInfo({ settings, logger });
|
|
58
|
+
const ufgClient = await core.getUFGClient({
|
|
59
|
+
settings: {
|
|
60
|
+
...account.ufgServer,
|
|
61
|
+
eyesServerUrl: account.eyesServer.eyesServerUrl,
|
|
62
|
+
apiKey: account.eyesServer.apiKey,
|
|
63
|
+
},
|
|
64
|
+
logger,
|
|
65
|
+
});
|
|
66
|
+
await (0, verify_environment_info_1.verifyEnvironmentsInfo)({ environments: (_d = settings.environments) !== null && _d !== void 0 ? _d : [], ufgClient });
|
|
57
67
|
return utils.general.extend({}, eyes => {
|
|
58
68
|
var _a, _b, _c, _d;
|
|
59
69
|
return {
|
|
@@ -6,9 +6,10 @@ const take_dom_snapshots_1 = require("./utils/take-dom-snapshots");
|
|
|
6
6
|
const to_safe_check_settings_1 = require("./utils/to-safe-check-settings");
|
|
7
7
|
const to_generated_selectors_1 = require("./utils/to-generated-selectors");
|
|
8
8
|
const abort_error_1 = require("../errors/abort-error");
|
|
9
|
+
const filterStaleElements_1 = require("./utils/filterStaleElements");
|
|
9
10
|
function makeTakeSnapshots({ core, spec, signal, logger: mainLogger }) {
|
|
10
11
|
return async function takeSnapshots({ driver, settings = {}, account, logger = mainLogger, }) {
|
|
11
|
-
var _a;
|
|
12
|
+
var _a, _b;
|
|
12
13
|
logger = logger.extend(mainLogger);
|
|
13
14
|
logger.log('Command "takeSnapshots" is called with settings', settings);
|
|
14
15
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
@@ -38,7 +39,7 @@ function makeTakeSnapshots({ core, spec, signal, logger: mainLogger }) {
|
|
|
38
39
|
},
|
|
39
40
|
logger,
|
|
40
41
|
});
|
|
41
|
-
|
|
42
|
+
const takeSnapshotsSettings = {
|
|
42
43
|
driver,
|
|
43
44
|
settings: {
|
|
44
45
|
waitBeforeCapture: settings.waitBeforeCapture,
|
|
@@ -54,7 +55,25 @@ function makeTakeSnapshots({ core, spec, signal, logger: mainLogger }) {
|
|
|
54
55
|
getIOSDevices: ufgClient.getIOSDevices,
|
|
55
56
|
},
|
|
56
57
|
logger,
|
|
57
|
-
}
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
snapshots = await (0, take_dom_snapshots_1.takeDomSnapshots)(takeSnapshotsSettings);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if ((_b = err === null || err === void 0 ? void 0 : err.message) === null || _b === void 0 ? void 0 : _b.includes('stale element')) {
|
|
64
|
+
snapshots = await (0, take_dom_snapshots_1.takeDomSnapshots)({
|
|
65
|
+
...takeSnapshotsSettings,
|
|
66
|
+
settings: await (0, filterStaleElements_1.removeStaleElementsFromDomSnapshotsSettings)({
|
|
67
|
+
settings: takeSnapshotsSettings.settings,
|
|
68
|
+
context: currentContext,
|
|
69
|
+
targetElement: elementReferences.target,
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
58
77
|
}
|
|
59
78
|
else {
|
|
60
79
|
// dead code - used for NMG
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeStaleElementsFromDomSnapshotsSettings = exports.filterStaleElements = exports.isStale = void 0;
|
|
4
|
+
async function isStale({ context, element, }) {
|
|
5
|
+
try {
|
|
6
|
+
await context.execute('return arguments[0]', element);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
exports.isStale = isStale;
|
|
14
|
+
async function filterStaleElements({ context, elementReferences, }) {
|
|
15
|
+
if (!elementReferences)
|
|
16
|
+
return [];
|
|
17
|
+
const validElements = [];
|
|
18
|
+
for (const element of elementReferences) {
|
|
19
|
+
if (!(await isStale({ context, element }))) {
|
|
20
|
+
validElements.push(element);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return validElements;
|
|
24
|
+
}
|
|
25
|
+
exports.filterStaleElements = filterStaleElements;
|
|
26
|
+
async function removeStaleElementsFromDomSnapshotsSettings({ context, settings, targetElement, }) {
|
|
27
|
+
// if one of the stale elements is the target element, we can't recover from it
|
|
28
|
+
if (await isStale({ context, element: targetElement })) {
|
|
29
|
+
throw new Error('Target element is stale - please make sure the element is not detached from the DOM tree. Failed to recover from stale element');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// remove other stale elements from the array
|
|
33
|
+
settings.elementReferences = await filterStaleElements({
|
|
34
|
+
context,
|
|
35
|
+
elementReferences: settings.elementReferences,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return settings;
|
|
39
|
+
}
|
|
40
|
+
exports.removeStaleElementsFromDomSnapshotsSettings = removeStaleElementsFromDomSnapshotsSettings;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.verifyEnvironmentsInfo = void 0;
|
|
27
|
+
const utils = __importStar(require("@applitools/utils"));
|
|
28
|
+
const ufg_client_1 = require("@applitools/ufg-client");
|
|
29
|
+
async function verifyEnvironmentsInfo({ environments, ufgClient, }) {
|
|
30
|
+
const invalid = [];
|
|
31
|
+
await Promise.all(environments.map(async (environment) => {
|
|
32
|
+
if (utils.types.has(environment, ['width', 'height'])) {
|
|
33
|
+
const browserName = environment.name || '';
|
|
34
|
+
if (!getAllBrowserNames().includes(browserName)) {
|
|
35
|
+
invalid.push(browserName);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (utils.types.has(environment, 'chromeEmulationInfo')) {
|
|
39
|
+
const devices = await ufgClient.getChromeEmulationDevices();
|
|
40
|
+
const deviceName = environment.chromeEmulationInfo.deviceName;
|
|
41
|
+
if (!devices[deviceName]) {
|
|
42
|
+
invalid.push(deviceName);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (utils.types.has(environment, 'iosDeviceInfo')) {
|
|
46
|
+
const devices = await ufgClient.getIOSDevices();
|
|
47
|
+
const deviceName = environment.iosDeviceInfo.deviceName;
|
|
48
|
+
if (!devices[deviceName]) {
|
|
49
|
+
invalid.push(deviceName);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}));
|
|
53
|
+
if (invalid.length > 0) {
|
|
54
|
+
throw new Error(`The specified UFG environment(s): ${invalid
|
|
55
|
+
.map(item => `"${item}"`)
|
|
56
|
+
.join(', ')} are either invalid or no longer supported. \nRefer to our current list of supported devices and browsers at: https://applitools.com/tutorials/concepts/test-execution/ultrafast-grid-devices-browsers \nIf you continue to experience issues, ensure that your SDK is updated to the latest version.`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.verifyEnvironmentsInfo = verifyEnvironmentsInfo;
|
|
60
|
+
function getAllBrowserNames() {
|
|
61
|
+
/*
|
|
62
|
+
Some of the browser names are not part of the enum because they are not user facing. We support them for backward compatibility.
|
|
63
|
+
do not add them to the enum.
|
|
64
|
+
*/
|
|
65
|
+
return [
|
|
66
|
+
...Object.values(ufg_client_1.BrowserNameEnum),
|
|
67
|
+
'chrome-1',
|
|
68
|
+
'firefox-1',
|
|
69
|
+
'edgechromium-1',
|
|
70
|
+
'safari-1',
|
|
71
|
+
'chrome-2',
|
|
72
|
+
'firefox-2',
|
|
73
|
+
'edgechromium-2',
|
|
74
|
+
'safari-2',
|
|
75
|
+
'chrome-canary',
|
|
76
|
+
'firefox-canary',
|
|
77
|
+
'edgechromium-canary',
|
|
78
|
+
'safari-canary',
|
|
79
|
+
'chrome-one-versions-back',
|
|
80
|
+
'firefox-one-versions-back',
|
|
81
|
+
'edgechromium-one-versions-back',
|
|
82
|
+
'safari-one-versions-back',
|
|
83
|
+
'chrome-two-version-back',
|
|
84
|
+
'firefox-two-version-back',
|
|
85
|
+
'edgechromium-two-version-back',
|
|
86
|
+
'safari-two-version-back',
|
|
87
|
+
'ie11',
|
|
88
|
+
];
|
|
89
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Context, ElementReference, SpecType } from '@applitools/driver';
|
|
2
|
+
import { DomSnapshotsSettings } from './take-dom-snapshots';
|
|
3
|
+
export declare function isStale<TSpec extends SpecType>({ context, element, }: {
|
|
4
|
+
context: Context<TSpec>;
|
|
5
|
+
element: ElementReference<TSpec>;
|
|
6
|
+
}): Promise<boolean>;
|
|
7
|
+
export declare function filterStaleElements<TSpec extends SpecType>({ context, elementReferences, }: {
|
|
8
|
+
context: Context<TSpec>;
|
|
9
|
+
elementReferences: ElementReference<TSpec>[] | undefined;
|
|
10
|
+
}): Promise<(string | TSpec["element"] | TSpec["secondary"]["element"] | TSpec["selector"] | TSpec["secondary"]["selector"] | {
|
|
11
|
+
selector: string | TSpec["selector"] | TSpec["secondary"]["selector"];
|
|
12
|
+
type?: string | undefined;
|
|
13
|
+
child?: TSpec["selector"] | TSpec["secondary"]["selector"] | import("@applitools/driver").CommonSelector<TSpec["selector"] | TSpec["secondary"]["selector"]> | undefined;
|
|
14
|
+
shadow?: TSpec["selector"] | TSpec["secondary"]["selector"] | import("@applitools/driver").CommonSelector<TSpec["selector"] | TSpec["secondary"]["selector"]> | undefined;
|
|
15
|
+
frame?: TSpec["selector"] | TSpec["secondary"]["selector"] | import("@applitools/driver").CommonSelector<TSpec["selector"] | TSpec["secondary"]["selector"]> | undefined;
|
|
16
|
+
fallback?: TSpec["selector"] | TSpec["secondary"]["selector"] | import("@applitools/driver").CommonSelector<TSpec["selector"] | TSpec["secondary"]["selector"]> | undefined;
|
|
17
|
+
})[]>;
|
|
18
|
+
export declare function removeStaleElementsFromDomSnapshotsSettings<TSpec extends SpecType>({ context, settings, targetElement, }: {
|
|
19
|
+
context: Context<TSpec>;
|
|
20
|
+
settings: DomSnapshotsSettings<TSpec>;
|
|
21
|
+
targetElement: ElementReference<TSpec>;
|
|
22
|
+
}): Promise<DomSnapshotsSettings<TSpec>>;
|