@testim/testim-cli 3.253.0 → 3.254.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/OverrideTestDataBuilder.js +1 -1
- package/agent/routers/cliJsCode/index.js +4 -4
- package/agent/routers/cliJsCode/router.js +46 -42
- package/agent/routers/cliJsCode/service.js +18 -13
- package/agent/routers/codim/router.js +14 -17
- package/agent/routers/codim/router.test.js +15 -14
- package/agent/routers/codim/service.js +1 -1
- package/agent/routers/general/index.js +4 -8
- package/agent/routers/hybrid/registerRoutes.js +18 -18
- package/agent/routers/index.js +7 -7
- package/agent/routers/playground/router.js +11 -10
- package/agent/routers/playground/service.js +19 -18
- package/agent/routers/standalone-browser/registerRoutes.js +10 -10
- package/cdpTestRunner.js +4 -3
- package/chromiumInstaller.js +4 -5
- package/cli/onExit.js +2 -2
- package/cli.js +7 -6
- package/cliAgentMode.js +4 -5
- package/codim/codim-cli.js +11 -10
- package/codim/hybrid-utils.js +1 -1
- package/codim/measure-perf.js +9 -6
- package/codim/template.js/tests/examples/01-simple-text-validation.test.js +6 -6
- package/codim/template.js/tests/examples/02-using-locators.test.js +13 -15
- package/codim/template.js/tests/examples/03-using-hooks.test.js +17 -19
- package/codim/template.js/tests/examples/04-skip-and-only.test.js +16 -17
- package/codim/template.js/tests/examples/05-multiple-windows.test.js +16 -17
- package/codim/template.js/webpack.config.js +1 -1
- package/codim/template.ts/webpack.config.js +3 -3
- package/commons/AbortError.js +4 -4
- package/commons/detectDebugger.js +4 -2
- package/commons/lazyRequire.js +10 -9
- package/commons/logger.js +4 -4
- package/commons/performance-logger.js +14 -8
- package/commons/prepareRunnerAndTestimStartUtils.js +6 -7
- package/commons/socket/baseSocketServiceSocketIO.js +32 -34
- package/commons/socket/realDataService.js +6 -5
- package/commons/socket/realDataServiceSocketIO.js +4 -4
- package/commons/socket/remoteStepService.js +4 -3
- package/commons/socket/remoteStepServiceSocketIO.js +11 -12
- package/commons/socket/socketService.js +50 -52
- package/commons/socket/testResultServiceSocketIO.js +11 -11
- package/commons/testimDesiredCapabilitiesBuilder.js +3 -2
- package/commons/testimNgrok.js +2 -2
- package/commons/testimNgrok.test.js +1 -1
- package/commons/testimServicesApi.js +27 -20
- package/commons/xhr2.js +97 -100
- package/errors.js +5 -0
- package/fixLocalBuild.js +2 -0
- package/npm-shrinkwrap.json +2515 -1256
- package/package.json +6 -6
- package/player/appiumTestPlayer.js +1 -1
- package/player/chromeLauncherTestPlayer.js +0 -1
- package/player/services/tabServiceMock.js +166 -0
- package/player/stepActions/navigationStepAction.js +11 -10
- package/player/stepActions/sleepStepAction.js +4 -5
- package/player/stepActions/textStepAction.js +4 -11
- package/player/utils/windowUtils.js +4 -3
- package/player/webdriver.js +1 -1
- package/processHandler.js +3 -3
- package/processHandler.test.js +1 -1
- package/reports/consoleReporter.js +3 -2
- package/reports/junitReporter.js +1 -2
- package/runOptions.js +6 -6
- package/runner.js +13 -0
- package/runners/TestPlanRunner.js +142 -74
- package/runners/buildCodeTests.js +38 -37
- package/runners/runnerUtils.js +3 -3
- package/services/lambdatestService.js +3 -5
- package/stepPlayers/cliJsStepPlayback.js +22 -17
- package/testRunHandler.js +8 -0
- package/testRunStatus.js +1 -1
- package/{utils.js → utils/index.js} +25 -117
- package/utils/promiseUtils.js +78 -0
- package/utils/stringUtils.js +96 -0
- package/{utils.test.js → utils/utils.test.js} +2 -2
- package/workers/BaseWorker.js +16 -14
- package/workers/WorkerAppium.js +1 -1
- package/workers/WorkerExtensionSingleBrowser.js +4 -4
- package/workers/WorkerSelenium.js +5 -2
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
4
|
const util = require('util');
|
|
5
5
|
const writeFileAsync = util.promisify(require('fs').writeFile);
|
|
6
6
|
const path = require('path');
|
|
7
|
-
const {fork} = require('child_process');
|
|
7
|
+
const { fork } = require('child_process');
|
|
8
8
|
const os = require('os');
|
|
9
|
-
const {ClientError, PlaygroundCodeError} = require('../../../errors');
|
|
9
|
+
const { ClientError, PlaygroundCodeError } = require('../../../errors');
|
|
10
|
+
|
|
10
11
|
const CODE_TYPES = ['playwright', 'selenium', 'puppeteer'];
|
|
11
12
|
|
|
12
13
|
const runForks = {};
|
|
@@ -21,28 +22,28 @@ const forkAsync = (fileFullPath) => {
|
|
|
21
22
|
let gotResolved;
|
|
22
23
|
const promise = new Promise(resolve => gotResolved = resolve);
|
|
23
24
|
|
|
24
|
-
const child = fork(fileFullPath, {stdio: [
|
|
25
|
+
const child = fork(fileFullPath, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'] });
|
|
25
26
|
promise.child = child;
|
|
26
27
|
child.on('message', (message) => {
|
|
27
|
-
if(!message) {
|
|
28
|
+
if (!message) {
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
|
-
const {type, error} = message;
|
|
31
|
-
if(error && ['uncaughtException', 'unhandledRejection'].includes(type)) {
|
|
32
|
-
return gotResolved({error: Object.assign(new PlaygroundCodeError(), {innerStack: message.error.stack})})
|
|
31
|
+
const { type, error } = message;
|
|
32
|
+
if (error && ['uncaughtException', 'unhandledRejection'].includes(type)) {
|
|
33
|
+
return gotResolved({ error: Object.assign(new PlaygroundCodeError(), { innerStack: message.error.stack }) });
|
|
33
34
|
}
|
|
34
35
|
});
|
|
35
36
|
child.on('error', (error) => {
|
|
36
|
-
gotResolved({error});
|
|
37
|
+
gotResolved({ error });
|
|
37
38
|
});
|
|
38
39
|
child.on('exit', (exitCode) => {
|
|
39
|
-
gotResolved({exitCode});
|
|
40
|
+
gotResolved({ exitCode });
|
|
40
41
|
});
|
|
41
42
|
|
|
42
43
|
return promise;
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
async function runCodeLocally({code}) {
|
|
46
|
+
async function runCodeLocally({ code }) {
|
|
46
47
|
const forkId = Date.now();
|
|
47
48
|
try {
|
|
48
49
|
const codeWithExtra = `
|
|
@@ -60,25 +61,25 @@ async function runCodeLocally({code}) {
|
|
|
60
61
|
const fileFullPath = await createTempFile(`tst-playground-${Date.now()}.js`, codeWithExtra);
|
|
61
62
|
const promiseExec = forkAsync(fileFullPath);
|
|
62
63
|
runForks[forkId] = promiseExec.child;
|
|
63
|
-
const {error, exitCode} = await promiseExec;
|
|
64
|
-
if(error) {
|
|
64
|
+
const { error, exitCode } = await promiseExec;
|
|
65
|
+
if (error) {
|
|
65
66
|
throw error;
|
|
66
67
|
}
|
|
67
|
-
if(exitCode !== 0) {
|
|
68
|
+
if (exitCode !== 0) {
|
|
68
69
|
throw new Error(`Process exited with exit code: ${exitCode}`);
|
|
69
70
|
}
|
|
70
71
|
return undefined;
|
|
71
72
|
} finally {
|
|
72
|
-
if(runForks[forkId]) {
|
|
73
|
+
if (runForks[forkId]) {
|
|
73
74
|
runForks[forkId].kill();
|
|
74
75
|
delete runForks[forkId];
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
async function runPlaygroundTest({code, type}) {
|
|
80
|
-
if(['playwright', 'puppeteer', 'selenium'].includes(type)) {
|
|
81
|
-
return runCodeLocally({code});
|
|
80
|
+
async function runPlaygroundTest({ code, type }) {
|
|
81
|
+
if (['playwright', 'puppeteer', 'selenium'].includes(type)) {
|
|
82
|
+
return runCodeLocally({ code });
|
|
82
83
|
}
|
|
83
84
|
throw new ClientError();
|
|
84
85
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
3
4
|
|
|
4
5
|
const express = require('express');
|
|
5
6
|
|
|
6
7
|
module.exports = {
|
|
7
|
-
standaloneBrowserRoutes
|
|
8
|
-
}
|
|
8
|
+
standaloneBrowserRoutes,
|
|
9
|
+
};
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* @param {{
|
|
@@ -13,33 +14,32 @@ module.exports = {
|
|
|
13
14
|
}} [testimStandaloneBrowser]
|
|
14
15
|
*/
|
|
15
16
|
function standaloneBrowserRoutes(testimStandaloneBrowser) {
|
|
16
|
-
|
|
17
17
|
const router = express.Router();
|
|
18
18
|
|
|
19
|
-
router.get(
|
|
19
|
+
router.get('/cdp-url', (req, res) => {
|
|
20
20
|
if (!testimStandaloneBrowser) {
|
|
21
21
|
res.status(503).send({
|
|
22
|
-
error:
|
|
22
|
+
error: 'Testim standalone browser is not running',
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
res.status(200).send({
|
|
29
|
-
url: testimStandaloneBrowser.webdriverApi.cdpUrl
|
|
29
|
+
url: testimStandaloneBrowser.webdriverApi.cdpUrl,
|
|
30
30
|
});
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
router.get(
|
|
33
|
+
router.get('/status', (req, res) => {
|
|
34
34
|
if (!testimStandaloneBrowser) {
|
|
35
35
|
res.status(503).send({
|
|
36
|
-
ok: false
|
|
36
|
+
ok: false,
|
|
37
37
|
});
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
res.status(200).send({
|
|
42
|
-
ok: true
|
|
42
|
+
ok: true,
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
|
package/cdpTestRunner.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const WebSocket = require('ws');
|
|
2
2
|
const Promise = require('bluebird');
|
|
3
|
+
const { promiseFromCallback } = require('./utils');
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class CDPTestRunner {
|
|
@@ -20,11 +21,11 @@ class CDPTestRunner {
|
|
|
20
21
|
}
|
|
21
22
|
const websocket = new WebSocket(this._cdpUrl, { timeout });
|
|
22
23
|
|
|
23
|
-
const openPromise =
|
|
24
|
+
const openPromise = promiseFromCallback((cb) => {
|
|
24
25
|
websocket.once('open', cb);
|
|
25
26
|
});
|
|
26
27
|
|
|
27
|
-
const errorPromise =
|
|
28
|
+
const errorPromise = promiseFromCallback((cb) => {
|
|
28
29
|
websocket.once('error', cb);
|
|
29
30
|
}).catch(() => {
|
|
30
31
|
websocket.close();
|
|
@@ -46,7 +47,7 @@ class CDPTestRunner {
|
|
|
46
47
|
this._cdpCallbacks.delete(object.id);
|
|
47
48
|
if (object.error) {
|
|
48
49
|
callback.reject(new Error(object.error));
|
|
49
|
-
} else if (object.result.exceptionDetails
|
|
50
|
+
} else if (object.result.exceptionDetails?.exception) {
|
|
50
51
|
callback.reject(new Error(object.result.exceptionDetails.exception.description));
|
|
51
52
|
} else {
|
|
52
53
|
callback.resolve(object.result);
|
package/chromiumInstaller.js
CHANGED
|
@@ -2,8 +2,7 @@ const path = require('path');
|
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const { ArgError } = require('./errors');
|
|
5
|
-
const { unzipFile } = require('./utils');
|
|
6
|
-
const { downloadAndSave, TESTIM_BROWSER_DIR } = require('./utils');
|
|
5
|
+
const { downloadAndSave, unzipFile, TESTIM_BROWSER_DIR } = require('./utils');
|
|
7
6
|
const ora = require('ora');
|
|
8
7
|
|
|
9
8
|
|
|
@@ -30,7 +29,7 @@ async function downloadAndInstallChromium() {
|
|
|
30
29
|
const platformFolder = {
|
|
31
30
|
linux: 'Linux_x64',
|
|
32
31
|
mac: 'Mac',
|
|
33
|
-
mac_arm: 'Mac_Arm',
|
|
32
|
+
mac_arm: 'Mac_Arm', // eslint-disable-line camelcase
|
|
34
33
|
win32: 'Win',
|
|
35
34
|
win64: 'Win_x64',
|
|
36
35
|
};
|
|
@@ -42,14 +41,14 @@ async function downloadAndInstallChromium() {
|
|
|
42
41
|
const platformArchiveName = {
|
|
43
42
|
linux: 'chrome-linux',
|
|
44
43
|
mac: 'chrome-mac',
|
|
45
|
-
mac_arm: 'chrome-mac',
|
|
44
|
+
mac_arm: 'chrome-mac', // eslint-disable-line camelcase
|
|
46
45
|
win32: winArchiveName,
|
|
47
46
|
win64: winArchiveName,
|
|
48
47
|
};
|
|
49
48
|
const binaryPaths = {
|
|
50
49
|
linux: 'chrome',
|
|
51
50
|
mac: 'Chromium.app/Contents/MacOS/Chromium',
|
|
52
|
-
mac_arm: 'Chromium.app/Contents/MacOS/Chromium',
|
|
51
|
+
mac_arm: 'Chromium.app/Contents/MacOS/Chromium', // eslint-disable-line camelcase
|
|
53
52
|
win32: 'chrome.exe',
|
|
54
53
|
win64: 'chrome.exe',
|
|
55
54
|
};
|
package/cli/onExit.js
CHANGED
|
@@ -48,12 +48,12 @@ module.exports.ignoreFailingTestsInExitCode = function () {
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
module.exports.onExit = async function onExit(exitValue) {
|
|
51
|
-
if (exitValue
|
|
51
|
+
if (exitValue?.stack) {
|
|
52
52
|
if (!isCi) {
|
|
53
53
|
writeStackTrace(exitValue);
|
|
54
54
|
} else {
|
|
55
55
|
// eslint-disable-next-line no-console
|
|
56
|
-
console.error(exitValue, exitValue
|
|
56
|
+
console.error(exitValue, exitValue.stack);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
package/cli.js
CHANGED
|
@@ -35,15 +35,16 @@ async function checkNodeVersion() {
|
|
|
35
35
|
throw new ArgError(`Required node version ${version} not satisfied with current version ${process.version}`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
const
|
|
38
|
+
const minimalNodeVersion = 16;
|
|
39
|
+
const majorVersion = Number(process.versions.node.split('.')[0]);
|
|
40
|
+
const dateHasPassed = new Date('2023-04-30T00:00:00.000Z') <= new Date();
|
|
40
41
|
|
|
41
|
-
if (majorVersion <
|
|
42
|
-
throw new ArgError(
|
|
42
|
+
if (majorVersion < minimalNodeVersion && dateHasPassed) {
|
|
43
|
+
throw new ArgError(`Testim.io CLI supports Node.js ${minimalNodeVersion} and above, please upgrade to a newer Node.js version`);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
if (majorVersion <
|
|
46
|
-
console.log('\x1b[33m%s\x1b[0m',
|
|
46
|
+
if (majorVersion < minimalNodeVersion) {
|
|
47
|
+
console.log('\x1b[33m%s\x1b[0m', `Testim.io CLI will stop supporting Node.js < ${minimalNodeVersion} on April 30 2023, please upgrade to a newer Node.js version`);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
package/cliAgentMode.js
CHANGED
|
@@ -7,13 +7,12 @@ const path = require('path');
|
|
|
7
7
|
const fs = require('fs-extra');
|
|
8
8
|
const ms = require('ms');
|
|
9
9
|
const WebSocket = require('ws');
|
|
10
|
-
const Bluebird = require('bluebird');
|
|
11
10
|
const ChromeLauncher = require('chrome-launcher');
|
|
12
11
|
const config = require('./commons/config');
|
|
13
12
|
const { ArgError } = require('./errors');
|
|
14
13
|
const lazyRequire = require('./commons/lazyRequire');
|
|
15
14
|
const prepareUtils = require('./commons/prepareRunnerAndTestimStartUtils');
|
|
16
|
-
const { downloadAndSave, unzipFile, getCdpAddressForHost, TESTIM_BROWSER_DIR } = require('./utils');
|
|
15
|
+
const { downloadAndSave, unzipFile, getCdpAddressForHost, TESTIM_BROWSER_DIR, promiseFromCallback } = require('./utils');
|
|
17
16
|
const ora = require('ora');
|
|
18
17
|
const { downloadAndInstallChromium, CHROMIUM_VERSION } = require('./chromiumInstaller');
|
|
19
18
|
|
|
@@ -361,7 +360,7 @@ async function readAndValidateChromedriverDevToolsActivePortFile() {
|
|
|
361
360
|
async function tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl, timeout = 100) {
|
|
362
361
|
const websocketConnection = await wsConnectAndOpen(webSocketDebuggerUrl, timeout);
|
|
363
362
|
|
|
364
|
-
return
|
|
363
|
+
return promiseFromCallback(cb => {
|
|
365
364
|
websocketConnection.send(JSON.stringify({
|
|
366
365
|
id: 0,
|
|
367
366
|
method: 'Browser.close',
|
|
@@ -376,13 +375,13 @@ async function tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl, timeout = 100)
|
|
|
376
375
|
async function wsConnectAndOpen(webSocketDebuggerUrl, timeout = 100) {
|
|
377
376
|
const websocket = new WebSocket(webSocketDebuggerUrl, { timeout });
|
|
378
377
|
|
|
379
|
-
const openPromise =
|
|
378
|
+
const openPromise = promiseFromCallback((cb) => {
|
|
380
379
|
websocket.once('open', cb);
|
|
381
380
|
}).then(() => {
|
|
382
381
|
websocket.removeAllListeners();
|
|
383
382
|
});
|
|
384
383
|
|
|
385
|
-
const errorPromise =
|
|
384
|
+
const errorPromise = promiseFromCallback((cb) => {
|
|
386
385
|
websocket.once('error', cb);
|
|
387
386
|
}).catch(() => {
|
|
388
387
|
websocket.close();
|
package/codim/codim-cli.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
2
4
|
|
|
3
5
|
const { promisifyAll } = require('bluebird');
|
|
4
6
|
const fse = require('fs-extra');
|
|
5
7
|
const exec = promisifyAll(require('child_process')).execAsync;
|
|
6
8
|
const path = require('path');
|
|
7
|
-
const validateNpmPackageName = require(
|
|
9
|
+
const validateNpmPackageName = require('validate-npm-package-name');
|
|
8
10
|
const ArgError = require('../errors.js').ArgError;
|
|
9
11
|
|
|
10
12
|
module.exports.init = async function init(name) {
|
|
@@ -16,19 +18,19 @@ module.exports.init = async function init(name) {
|
|
|
16
18
|
type: 'text',
|
|
17
19
|
name: 'project',
|
|
18
20
|
message: 'Please enter Project name',
|
|
19
|
-
validate: value => String(value).length > 3
|
|
21
|
+
validate: value => String(value).length > 3,
|
|
20
22
|
});
|
|
21
23
|
name = response.project;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
const
|
|
26
|
+
const fullPath = path.resolve(name);
|
|
25
27
|
|
|
26
|
-
if (fse.existsSync(
|
|
27
|
-
console.log(`${
|
|
28
|
+
if (fse.existsSync(fullPath) && fse.readdirSync(fullPath).length !== 0) {
|
|
29
|
+
console.log(`${fullPath} is not empty. Quitting...`);
|
|
28
30
|
process.exit(1);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
const packageName =
|
|
33
|
+
const packageName = fullPath.substr(Math.max(fullPath.lastIndexOf('/'), fullPath.lastIndexOf('\\')) + 1);
|
|
32
34
|
|
|
33
35
|
const nameValidity = validateNpmPackageName(packageName);
|
|
34
36
|
|
|
@@ -36,7 +38,7 @@ module.exports.init = async function init(name) {
|
|
|
36
38
|
if (nameValidity.errors) nameValidity.errors.forEach((e) => console.log(e));
|
|
37
39
|
if (nameValidity.warnings) nameValidity.warnings.forEach((e) => console.log(e));
|
|
38
40
|
|
|
39
|
-
throw new ArgError(
|
|
41
|
+
throw new ArgError('Package name is not valid');
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
const response = await prompts({
|
|
@@ -45,7 +47,7 @@ module.exports.init = async function init(name) {
|
|
|
45
47
|
message: 'Add support for TypeScript?',
|
|
46
48
|
initial: true,
|
|
47
49
|
active: 'no',
|
|
48
|
-
inactive: 'yes'
|
|
50
|
+
inactive: 'yes',
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
const sourceFolder = response.isJs ? 'template.js' : 'template.ts';
|
|
@@ -77,5 +79,4 @@ module.exports.init = async function init(name) {
|
|
|
77
79
|
spinner.succeed();
|
|
78
80
|
|
|
79
81
|
console.log(`Testim Dev Kit project folder successfully created in ${dest}.`);
|
|
80
|
-
|
|
81
82
|
};
|
package/codim/hybrid-utils.js
CHANGED
|
@@ -4,7 +4,7 @@ module.exports.getArgumentsFromContext = async function getArgumentsFromContext(
|
|
|
4
4
|
step,
|
|
5
5
|
context,
|
|
6
6
|
locatorStrategy
|
|
7
|
-
)
|
|
7
|
+
) {
|
|
8
8
|
const argsInCorrectOrder = fixArgsOrdering(step.parameterNames.map(p => p.displayName), context.incomingParams.as);
|
|
9
9
|
|
|
10
10
|
return await Promise.all(argsInCorrectOrder.map(arg => {
|
package/codim/measure-perf.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
const startTime = Date.now();
|
|
2
3
|
let last = 0;
|
|
3
4
|
global.log = function time(message) {
|
|
4
|
-
|
|
5
|
-
console.log(time, time - last
|
|
5
|
+
const time = Date.now() - startTime;
|
|
6
|
+
console.log(time, time - last, message);
|
|
6
7
|
last = time;
|
|
7
8
|
};
|
|
8
9
|
global.perf = function perf(fn) {
|
|
@@ -12,22 +13,24 @@ global.perf = function perf(fn) {
|
|
|
12
13
|
} finally {
|
|
13
14
|
console.log(fn.name, 'took', Date.now() - start);
|
|
14
15
|
}
|
|
15
|
-
}
|
|
16
|
+
};
|
|
16
17
|
|
|
17
18
|
require('bluebird').prototype.log = function log(message) {
|
|
18
19
|
return this.tap(() => global.log(message));
|
|
19
|
-
}
|
|
20
|
+
};
|
|
20
21
|
|
|
21
22
|
global.measureRequireTimes = () => {
|
|
22
23
|
'use strict';
|
|
24
|
+
|
|
23
25
|
const {
|
|
24
26
|
performance,
|
|
25
|
-
PerformanceObserver
|
|
27
|
+
PerformanceObserver,
|
|
26
28
|
} = require('perf_hooks');
|
|
27
29
|
const mod = require('module');
|
|
28
30
|
|
|
29
31
|
// Monkey patch the require function
|
|
30
32
|
mod.Module.prototype.require = performance.timerify(mod.Module.prototype.require);
|
|
33
|
+
// eslint-disable-next-line no-global-assign
|
|
31
34
|
require = performance.timerify(require);
|
|
32
35
|
|
|
33
36
|
// Activate the observer
|
|
@@ -39,4 +42,4 @@ global.measureRequireTimes = () => {
|
|
|
39
42
|
obs.disconnect();
|
|
40
43
|
});
|
|
41
44
|
obs.observe({ entryTypes: ['function'], buffered: true });
|
|
42
|
-
}
|
|
45
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
// Import Testim Dev Kit methods
|
|
4
4
|
const { go, text, test, l, Locator } = require('testim');
|
|
@@ -10,12 +10,12 @@ const { expect } = require('chai');
|
|
|
10
10
|
Locator.set(require('./locators/locators.js'));
|
|
11
11
|
|
|
12
12
|
test('Simple text validation', async () => {
|
|
13
|
-
|
|
13
|
+
await go('http://demo.testim.io');
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Grab the title text and store it in a const
|
|
16
|
+
const title = await text(l('SPACE_&_BEYOND'));
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// Use Chai to assert the title text is correct
|
|
19
|
+
expect(title).to.eq('Space & Beyond');
|
|
20
20
|
}); // end of test
|
|
21
21
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
// Import Testim Dev Kit methods
|
|
4
4
|
const { go, waitForText, scrollToElement, click, test, l, Locator } = require('testim');
|
|
@@ -7,24 +7,22 @@ const { go, waitForText, scrollToElement, click, test, l, Locator } = require('t
|
|
|
7
7
|
Locator.set(require('./locators/locators.js'));
|
|
8
8
|
|
|
9
9
|
test('Using locators', async () => {
|
|
10
|
+
await go('http://demo.testim.io');
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
// Load the SELECT DESTINATION button smart locator. This locator
|
|
13
|
+
// can now be used by any method that accepts a smart locator as
|
|
14
|
+
// as argument.
|
|
15
|
+
//
|
|
16
|
+
// You can read more about the advantages of working with smart
|
|
17
|
+
// locators in the Testim documentation:
|
|
18
|
+
// https://help.testim.io/docs/working-with-locators
|
|
19
|
+
const selectDestButton = l('SELECT_DESTINATION');
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
// can now be used by any method that accepts a smart locator as
|
|
15
|
-
// as argument.
|
|
16
|
-
//
|
|
17
|
-
// You can read more about the advantages of working with smart
|
|
18
|
-
// locators in the Testim documentation:
|
|
19
|
-
// https://help.testim.io/docs/working-with-locators
|
|
20
|
-
const selectDestButton = l("SELECT_DESTINATION");
|
|
21
|
+
await waitForText(selectDestButton, 'Select Destination');
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await scrollToElement(selectDestButton);
|
|
25
|
-
|
|
26
|
-
await click(selectDestButton);
|
|
23
|
+
await scrollToElement(selectDestButton);
|
|
27
24
|
|
|
25
|
+
await click(selectDestButton);
|
|
28
26
|
}); // end of test
|
|
29
27
|
|
|
30
28
|
|
|
@@ -7,30 +7,28 @@ const { go, test, describe, before, beforeEach, afterEach, after, text } = requi
|
|
|
7
7
|
const { expect } = require('chai');
|
|
8
8
|
|
|
9
9
|
describe('Using hooks', () => {
|
|
10
|
+
before(() => {
|
|
11
|
+
// runs before all tests in this block
|
|
12
|
+
});
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
// runs before each test in this block
|
|
16
|
+
await go('http://demo.testim.io');
|
|
17
|
+
});
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
// runs before each test in this block
|
|
17
|
-
await go('http://demo.testim.io');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
afterEach(function() {
|
|
19
|
+
afterEach(() => {
|
|
21
20
|
// runs after each test in this block
|
|
22
|
-
|
|
21
|
+
});
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
after(() => {
|
|
25
24
|
// runs after all tests in this block
|
|
26
|
-
|
|
25
|
+
});
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
test('finds text element', async () => {
|
|
29
28
|
// Find an element using a vanilla CSS selector and extract its text
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const title = await text('.theme__title___35Wsy');
|
|
30
|
+
|
|
31
|
+
// Validate the extracted text
|
|
32
|
+
expect(title).to.eq('Madan');
|
|
33
|
+
});
|
|
36
34
|
});
|
|
@@ -8,25 +8,24 @@ const { expect } = require('chai');
|
|
|
8
8
|
|
|
9
9
|
// Using `.only()`
|
|
10
10
|
describe.only('Test suite', () => {
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
await go('http://demo.testim.io');
|
|
13
|
+
});
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
test('finds text element', async () => {
|
|
16
|
+
const title = await text('.theme__title___35Wsy');
|
|
17
|
+
expect(title).to.eq('Madan');
|
|
18
|
+
});
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
test.skip('skips this test', async () => {
|
|
23
|
-
// this test will not be run
|
|
24
|
-
const title = await text('.Gallery__headline-1___2lHj5');
|
|
25
|
-
expect(title).to.eq('Your next destination');
|
|
26
|
-
});
|
|
20
|
+
// Using `skip()`
|
|
21
|
+
test.skip('skips this test', async () => {
|
|
22
|
+
// this test will not be run
|
|
23
|
+
const title = await text('.Gallery__headline-1___2lHj5');
|
|
24
|
+
expect(title).to.eq('Your next destination');
|
|
25
|
+
});
|
|
27
26
|
});
|
|
28
27
|
|
|
29
|
-
describe('Just another test', async() => {
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
describe('Just another test', async () => {
|
|
29
|
+
// this describe will not be run since the first describe
|
|
30
|
+
// above is using `.only()`
|
|
32
31
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
// Import Testim Dev Kit methods
|
|
4
4
|
const { go, click, waitForText, withContext, test, l, Locator } = require('testim');
|
|
@@ -7,26 +7,25 @@ const { go, click, waitForText, withContext, test, l, Locator } = require('testi
|
|
|
7
7
|
Locator.set(require('./locators/locators.js'));
|
|
8
8
|
|
|
9
9
|
test('Working with multiple windows', async () => {
|
|
10
|
-
|
|
10
|
+
await go('https://the-internet.herokuapp.com/');
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
await click(l('Multiple_Windows'));
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// Open a new tab
|
|
15
|
+
await click(l('Click_Here'));
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Import a `waitForText` method in the context of the newly opened tab
|
|
21
|
-
// using the `withContext` method (@see https://help.testim.io/docs/with-context)
|
|
22
|
-
// Please note we're using an alias since we've already imported `waitForText`
|
|
23
|
-
// to be used in the context of the main tab.
|
|
24
|
-
const { waitForText: waitForTextForTab } = withContext({
|
|
25
|
-
tabUrl: 'https://the-internet.herokuapp.com/windows/new'
|
|
26
|
-
});
|
|
17
|
+
// Run validation on the main tab
|
|
18
|
+
await waitForText(l('Opening_a_new_window'), 'Opening a new window');
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
// Import a `waitForText` method in the context of the newly opened tab
|
|
21
|
+
// using the `withContext` method (@see https://help.testim.io/docs/with-context)
|
|
22
|
+
// Please note we're using an alias since we've already imported `waitForText`
|
|
23
|
+
// to be used in the context of the main tab.
|
|
24
|
+
const { waitForText: waitForTextForTab } = withContext({
|
|
25
|
+
tabUrl: 'https://the-internet.herokuapp.com/windows/new',
|
|
26
|
+
});
|
|
30
27
|
|
|
28
|
+
// Run validation on the newly opened tab
|
|
29
|
+
await waitForTextForTab(l('New_Window'), 'New Window');
|
|
31
30
|
}); // end of test
|
|
32
31
|
|
package/commons/AbortError.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
class AbortError extends Error {
|
|
4
|
-
constructor(message =
|
|
4
|
+
constructor(message = 'aborted') {
|
|
5
5
|
super(message);
|
|
6
|
-
this.name =
|
|
6
|
+
this.name = 'AbortError';
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
AbortError
|
|
12
|
-
}
|
|
11
|
+
AbortError,
|
|
12
|
+
};
|