@testim/testim-cli 3.289.0 → 3.290.0-beta
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/cli.js +22390 -122
- package/cli.js.map +1 -0
- package/npm-shrinkwrap.json +8 -29129
- package/package.json +16 -10
- package/OverrideTestDataBuilder.js +0 -117
- package/agent/routers/cliJsCode/index.js +0 -13
- package/agent/routers/cliJsCode/router.js +0 -63
- package/agent/routers/cliJsCode/service.js +0 -705
- package/agent/routers/codim/router.js +0 -69
- package/agent/routers/codim/router.test.js +0 -60
- package/agent/routers/codim/service.js +0 -193
- package/agent/routers/general/index.js +0 -36
- package/agent/routers/hybrid/registerRoutes.js +0 -81
- package/agent/routers/index.js +0 -56
- package/agent/routers/playground/router.js +0 -77
- package/agent/routers/playground/service.js +0 -96
- package/agent/routers/standalone-browser/registerRoutes.js +0 -47
- package/agent/server.js +0 -150
- package/cdpTestRunner.js +0 -86
- package/chromiumInstaller.js +0 -91
- package/cli/isCiRun.js +0 -10
- package/cli/onExit.js +0 -65
- package/cli/writeStackTrace.js +0 -27
- package/cliAgentMode.js +0 -384
- package/codim/codim-cli.js +0 -91
- package/codim/codim-npm-package/index.ts +0 -427
- package/codim/codim-npm-package/package-lock.json +0 -14
- package/codim/codim-npm-package/package.json +0 -14
- package/codim/hybrid-utils.js +0 -28
- package/codim/measure-perf.js +0 -41
- package/codim/template.js/.idea/workspace.xml +0 -57
- package/codim/template.js/.vscode/launch.json +0 -53
- package/codim/template.ts/.idea/workspace.xml +0 -57
- package/codim/template.ts/.vscode/launch.json +0 -55
- package/commons/AbortError.js +0 -12
- package/commons/SeleniumPerfStats.js +0 -58
- package/commons/chrome-launcher.js +0 -15
- package/commons/chromedriverWrapper.js +0 -70
- package/commons/config.js +0 -39
- package/commons/constants.js +0 -67
- package/commons/detectDebugger.js +0 -19
- package/commons/featureAvailabilityService.js +0 -26
- package/commons/featureFlags.js +0 -132
- package/commons/getSessionPlayerRequire.js +0 -28
- package/commons/httpRequest.js +0 -261
- package/commons/httpRequestCounters.js +0 -98
- package/commons/httpRequestCounters.test.js +0 -38
- package/commons/initializeUserWithAuth.js +0 -55
- package/commons/lazyRequire.js +0 -105
- package/commons/logUtils.js +0 -15
- package/commons/logUtils.test.js +0 -21
- package/commons/logger.js +0 -178
- package/commons/mockNetworkRuleFileSchema.json +0 -140
- package/commons/npmWrapper.js +0 -174
- package/commons/npmWrapper.test.js +0 -374
- package/commons/performance-logger.js +0 -71
- package/commons/preloadTests.js +0 -29
- package/commons/prepareRunner.js +0 -85
- package/commons/prepareRunner.test.js +0 -144
- package/commons/prepareRunnerAndTestimStartUtils.js +0 -198
- package/commons/prepareRunnerAndTestimStartUtils.test.js +0 -73
- package/commons/requireWithFallback.js +0 -25
- package/commons/runnerFileCache.js +0 -204
- package/commons/socket/baseSocketServiceSocketIO.js +0 -197
- package/commons/socket/realDataService.js +0 -59
- package/commons/socket/realDataServiceSocketIO.js +0 -33
- package/commons/socket/remoteStepService.js +0 -55
- package/commons/socket/remoteStepServiceSocketIO.js +0 -61
- package/commons/socket/socketService.js +0 -175
- package/commons/socket/testResultService.js +0 -62
- package/commons/socket/testResultServiceSocketIO.js +0 -64
- package/commons/testimAnalytics.js +0 -40
- package/commons/testimCloudflare.js +0 -83
- package/commons/testimCloudflare.test.js +0 -185
- package/commons/testimCustomToken.js +0 -124
- package/commons/testimDesiredCapabilitiesBuilder.js +0 -647
- package/commons/testimNgrok.js +0 -90
- package/commons/testimNgrok.test.js +0 -140
- package/commons/testimServicesApi.js +0 -631
- package/commons/testimTunnel.js +0 -73
- package/commons/testimTunnel.test.js +0 -172
- package/commons/xhr2.js +0 -897
- package/coverage/SummaryToObjectReport.js +0 -19
- package/coverage/jsCoverage.js +0 -252
- package/credentialsManager.js +0 -142
- package/errors.js +0 -161
- package/executionQueue.js +0 -37
- package/fixLocalBuild.js +0 -24
- package/inputFileUtils.js +0 -103
- package/lib/coralogix-winston.transport.js +0 -99
- package/player/SeleniumProtocolError.js +0 -100
- package/player/WebDriverHttpRequest.js +0 -177
- package/player/WebdriverioWebDriverApi.js +0 -671
- package/player/appiumTestPlayer.js +0 -90
- package/player/chromeLauncherTestPlayer.js +0 -67
- package/player/constants.js +0 -332
- package/player/extensionTestPlayer.js +0 -32
- package/player/findElementStrategy.js +0 -154
- package/player/scripts/isElementDisplayed.js +0 -252
- package/player/seleniumTestPlayer.js +0 -140
- package/player/services/frameLocator.js +0 -170
- package/player/services/mobileFrameLocatorMock.js +0 -32
- package/player/services/playbackTimeoutCalculator.js +0 -175
- package/player/services/portSelector.js +0 -19
- package/player/services/tabService.js +0 -551
- package/player/services/tabServiceMock.js +0 -167
- package/player/services/windowCreationListener.js +0 -8
- package/player/stepActions/RefreshStepAction.js +0 -16
- package/player/stepActions/apiStepAction.js +0 -89
- package/player/stepActions/baseCliJsStepAction.js +0 -51
- package/player/stepActions/baseJsStepAction.js +0 -277
- package/player/stepActions/cliConditionStepAction.js +0 -11
- package/player/stepActions/cliJsStepAction.js +0 -11
- package/player/stepActions/dropFileStepAction.js +0 -34
- package/player/stepActions/evaluateExpressionStepAction.js +0 -52
- package/player/stepActions/extensionOnlyStepAction.js +0 -12
- package/player/stepActions/extractTextStepAction.js +0 -19
- package/player/stepActions/hoverStepAction.js +0 -55
- package/player/stepActions/inputFileStepAction.js +0 -199
- package/player/stepActions/jsCodeStepAction.js +0 -11
- package/player/stepActions/jsConditionStepAction.js +0 -11
- package/player/stepActions/locateStepAction.js +0 -159
- package/player/stepActions/mouseStepAction.js +0 -370
- package/player/stepActions/navigationStepAction.js +0 -29
- package/player/stepActions/nodePackageStepAction.js +0 -47
- package/player/stepActions/pixelValidationStepAction.js +0 -39
- package/player/stepActions/scripts/dispatchEvents.js +0 -282
- package/player/stepActions/scripts/doClick.js +0 -221
- package/player/stepActions/scripts/doDragPath.js +0 -225
- package/player/stepActions/scripts/doubleClick.js +0 -119
- package/player/stepActions/scripts/dropEvent.js +0 -63
- package/player/stepActions/scripts/focusElement.js +0 -46
- package/player/stepActions/scripts/html5dragAction.js +0 -56
- package/player/stepActions/scripts/html5dragActionV2.js +0 -312
- package/player/stepActions/scripts/runCode.js +0 -147
- package/player/stepActions/scripts/scroll.js +0 -90
- package/player/stepActions/scripts/selectOption.js +0 -51
- package/player/stepActions/scripts/setText.js +0 -415
- package/player/stepActions/scripts/wheel.js +0 -61
- package/player/stepActions/scrollStepAction.js +0 -96
- package/player/stepActions/selectOptionStepAction.js +0 -49
- package/player/stepActions/sfdcRecordedStepAction.js +0 -24
- package/player/stepActions/sfdcStepAction.js +0 -28
- package/player/stepActions/sleepStepAction.js +0 -12
- package/player/stepActions/specialKeyStepAction.js +0 -52
- package/player/stepActions/stepAction.js +0 -73
- package/player/stepActions/stepActionRegistrar.js +0 -111
- package/player/stepActions/submitStepAction.js +0 -12
- package/player/stepActions/tdkHybridStepAction.js +0 -18
- package/player/stepActions/textStepAction.js +0 -110
- package/player/stepActions/textValidationStepAction.js +0 -64
- package/player/stepActions/wheelStepAction.js +0 -41
- package/player/utils/cookieUtils.js +0 -39
- package/player/utils/eyeSdkService.js +0 -250
- package/player/utils/imageCaptureUtils.js +0 -267
- package/player/utils/screenshotUtils.js +0 -68
- package/player/utils/stepActionUtils.js +0 -90
- package/player/utils/windowUtils.js +0 -195
- package/player/webDriverUtils.js +0 -40
- package/player/webDriverUtils.test.js +0 -116
- package/player/webdriver.js +0 -976
- package/polyfills/Array.prototype.at.js +0 -13
- package/polyfills/index.js +0 -13
- package/processHandler.js +0 -79
- package/processHandler.test.js +0 -55
- package/reports/chromeReporter.js +0 -17
- package/reports/consoleReporter.js +0 -190
- package/reports/debugReporter.js +0 -82
- package/reports/jsonReporter.js +0 -55
- package/reports/junitReporter.js +0 -183
- package/reports/reporter.js +0 -166
- package/reports/reporterUtils.js +0 -54
- package/reports/teamCityReporter.js +0 -73
- package/runOptions.d.ts +0 -305
- package/runOptions.js +0 -1288
- package/runOptionsAgentFlow.js +0 -87
- package/runOptionsUtils.js +0 -60
- package/runner.js +0 -355
- package/runners/ParallelWorkerManager.js +0 -284
- package/runners/TestPlanRunner.js +0 -419
- package/runners/buildCodeTests.js +0 -159
- package/runners/runnerUtils.js +0 -81
- package/services/analyticsService.js +0 -96
- package/services/branchService.js +0 -29
- package/services/gridService.js +0 -357
- package/services/gridService.test.js +0 -357
- package/services/labFeaturesService.js +0 -64
- package/services/lambdatestService.js +0 -227
- package/services/lambdatestService.test.js +0 -353
- package/services/localRCASaver.js +0 -124
- package/stepPlayers/cliJsStepPlayback.js +0 -40
- package/stepPlayers/hybridStepPlayback.js +0 -140
- package/stepPlayers/nodePackageStepPlayback.js +0 -28
- package/stepPlayers/playwrightHybridStepPlayback.js +0 -61
- package/stepPlayers/puppeteerHybridStepPlayback.js +0 -76
- package/stepPlayers/remoteStepPlayback.js +0 -80
- package/stepPlayers/seleniumHybridStepPlayback.js +0 -84
- package/stepPlayers/tdkHybridStepPlayback.js +0 -112
- package/testRunHandler.js +0 -603
- package/testRunStatus.js +0 -567
- package/testimNpmDriver.js +0 -52
- package/utils/argsUtils.js +0 -91
- package/utils/argsUtils.test.js +0 -32
- package/utils/fsUtils.js +0 -174
- package/utils/index.js +0 -197
- package/utils/promiseUtils.js +0 -85
- package/utils/stringUtils.js +0 -98
- package/utils/stringUtils.test.js +0 -22
- package/utils/timeUtils.js +0 -25
- package/utils/utils.test.js +0 -27
- package/workers/BaseWorker.js +0 -498
- package/workers/BaseWorker.test.js +0 -186
- package/workers/WorkerAppium.js +0 -180
- package/workers/WorkerExtension.js +0 -192
- package/workers/WorkerExtensionSingleBrowser.js +0 -77
- package/workers/WorkerSelenium.js +0 -253
- package/workers/workerUtils.js +0 -20
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const webdriverio = require('webdriverio');
|
|
4
|
-
const TabService = require('./services/tabServiceMock');
|
|
5
|
-
const PortSelector = require('./services/portSelector');
|
|
6
|
-
const StepActionUtils = require('./utils/stepActionUtils');
|
|
7
|
-
const frameLocatorFactory = require('./services/mobileFrameLocatorMock');
|
|
8
|
-
const testResultService = require('../commons/socket/testResultService');
|
|
9
|
-
const windowCreationListener = require('./services/windowCreationListener');
|
|
10
|
-
const PlaybackTimeoutCalculator = require('./services/playbackTimeoutCalculator');
|
|
11
|
-
const { isDebuggerConnected } = require('../commons/detectDebugger');
|
|
12
|
-
const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
|
|
13
|
-
const logger = require('../commons/logger').getLogger('appium-test-player');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AppiumTestPlayer {
|
|
17
|
-
//eslint-disable-next-line default-param-last
|
|
18
|
-
constructor(id, userParamsData, shouldMonitorPerformance, automationMode = 'code', driver = webdriverio, testRetryCount, previousTestResultId) {
|
|
19
|
-
const { sessionPlayer: Player, commonConstants, stepActionFactory: StepActionFactory, MobileLocateElementPlayer } = getSessionPlayer();
|
|
20
|
-
this.driver = driver;
|
|
21
|
-
this.id = id;
|
|
22
|
-
|
|
23
|
-
const stepActionUtils = new StepActionUtils(this.driver);
|
|
24
|
-
this.stepActionFactory = new StepActionFactory(stepActionUtils);
|
|
25
|
-
require('./stepActions/stepActionRegistrar')(this.driver, this.stepActionFactory, 'selenium');
|
|
26
|
-
|
|
27
|
-
this.tabService = new TabService(this.driver);
|
|
28
|
-
this.windowCreationListener = windowCreationListener;
|
|
29
|
-
this.playbackTimeoutCalculator = new PlaybackTimeoutCalculator(isDebuggerConnected());
|
|
30
|
-
|
|
31
|
-
this.tabService.createSesion(id);
|
|
32
|
-
|
|
33
|
-
const FrameLocator = frameLocatorFactory(this.driver);
|
|
34
|
-
|
|
35
|
-
this.sessionPlayer = new Player(
|
|
36
|
-
id,
|
|
37
|
-
this.tabService,
|
|
38
|
-
null,
|
|
39
|
-
null,
|
|
40
|
-
FrameLocator,
|
|
41
|
-
PortSelector,
|
|
42
|
-
MobileLocateElementPlayer,
|
|
43
|
-
null /* Not in use, placeholder for the order of arguments */,
|
|
44
|
-
stepActionUtils,
|
|
45
|
-
this.stepActionFactory,
|
|
46
|
-
this.playbackTimeoutCalculator,
|
|
47
|
-
testResultService.getSocket(),
|
|
48
|
-
automationMode,
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
if (this.sessionPlayer.setShouldMonitorPerformance) {
|
|
52
|
-
this.sessionPlayer.setShouldMonitorPerformance(shouldMonitorPerformance);
|
|
53
|
-
}
|
|
54
|
-
this.sessionPlayer.playbackManager.isRemoteSession = true;
|
|
55
|
-
this.sessionPlayer.playbackManager.isLocalRun = false;
|
|
56
|
-
this.sessionPlayer.playbackManager.testRetryCount = testRetryCount;
|
|
57
|
-
this.sessionPlayer.playbackManager.previousTestResultId = previousTestResultId;
|
|
58
|
-
|
|
59
|
-
this.sessionPlayer.playbackManager.userParamsData = userParamsData || {};
|
|
60
|
-
this.onStepCompleted = this.onStepCompleted.bind(this);
|
|
61
|
-
|
|
62
|
-
this.sessionPlayer.playbackManager.on(commonConstants.playback.RESULT, this.onStepCompleted);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
onStepCompleted(result, testId, resultId, step) {
|
|
66
|
-
//do nothing for now ...
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
async onDone() {
|
|
71
|
-
try {
|
|
72
|
-
await this.driver.activeSession.deleteSession();
|
|
73
|
-
} catch (error) {
|
|
74
|
-
logger.error('error while deleting appium session', { error });
|
|
75
|
-
} finally {
|
|
76
|
-
const { commonConstants } = getSessionPlayer();
|
|
77
|
-
this.sessionPlayer.playbackManager.off(commonConstants.playback.RESULT);
|
|
78
|
-
this.sessionPlayer = null;
|
|
79
|
-
this.tabService = null;
|
|
80
|
-
this.stepActionFactory = null;
|
|
81
|
-
this.driver = null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
getSessionId() {
|
|
86
|
-
return this.driver.activeSession.sessionId;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
module.exports = AppiumTestPlayer;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const launcher = require('chrome-launcher');
|
|
4
|
-
const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
|
|
5
|
-
const utils = require('../utils');
|
|
6
|
-
const { registerExitHook } = require('../processHandler');
|
|
7
|
-
const CDPTestRunner = require('../cdpTestRunner');
|
|
8
|
-
|
|
9
|
-
class LauncherDriver {
|
|
10
|
-
constructor(sessionId) {
|
|
11
|
-
this.sessionId = sessionId;
|
|
12
|
-
this.cdpTestRunner = new CDPTestRunner();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async init(browserOptions, testName, testRunConfig, gridInfo, customExtensionLocalLocation, executionId, testResultId) {
|
|
16
|
-
const capabilities = desiredCapabilitiesBuilder.buildSeleniumOptions(browserOptions, testName, testRunConfig, gridInfo, customExtensionLocalLocation, executionId, testResultId);
|
|
17
|
-
const chromeFlags = [
|
|
18
|
-
...capabilities.desiredCapabilities.chromeOptions.args,
|
|
19
|
-
...launcher.Launcher.defaultFlags().filter(flag => flag !== '--disable-extensions'),
|
|
20
|
-
];
|
|
21
|
-
this.chrome = await launcher.launch({ chromeFlags, startingUrl: undefined, ignoreDefaultFlags: true });
|
|
22
|
-
this.chrome.process.once('exit', () => { this._isAlive = false; });
|
|
23
|
-
this.chrome.process.once('close', () => { this._isAlive = false; });
|
|
24
|
-
this._isAlive = true;
|
|
25
|
-
const webSocketDebuggerUrl = await utils.getCdpAddressForHost(`localhost:${this.chrome.port}`);
|
|
26
|
-
await this.cdpTestRunner.initSession(webSocketDebuggerUrl);
|
|
27
|
-
|
|
28
|
-
registerExitHook(() => this.chrome.kill());
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
isAlive() {
|
|
32
|
-
return this._isAlive;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
start() {
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async stop() {
|
|
39
|
-
await this.cdpTestRunner.stopSession();
|
|
40
|
-
if (this.chrome) {
|
|
41
|
-
await this.chrome.kill();
|
|
42
|
-
}
|
|
43
|
-
this._isAlive = false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
getSessionId() {
|
|
47
|
-
return this.sessionId;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
class ChromeLauncherTestPlayer {
|
|
52
|
-
constructor(id) {
|
|
53
|
-
this.sessionId = utils.guid();
|
|
54
|
-
this.driver = new LauncherDriver(this.sessionId);
|
|
55
|
-
this.id = id;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async onDone() {
|
|
59
|
-
return this.driver.stop();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getSessionId() {
|
|
63
|
-
return this.sessionId;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = ChromeLauncherTestPlayer;
|
package/player/constants.js
DELETED
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
const UNICODE_CHARACTERS = {
|
|
2
|
-
'NULL': '\uE000',
|
|
3
|
-
'Unidentified': '\uE000',
|
|
4
|
-
'Cancel': '\uE001',
|
|
5
|
-
'Help': '\uE002',
|
|
6
|
-
'Back space': '\uE003',
|
|
7
|
-
'Backspace': '\uE003',
|
|
8
|
-
'Tab': '\uE004',
|
|
9
|
-
'Clear': '\uE005',
|
|
10
|
-
'Return': '\uE006',
|
|
11
|
-
'Enter': '\uE007',
|
|
12
|
-
'Shift': '\uE008',
|
|
13
|
-
'Control': '\uE009',
|
|
14
|
-
'Alt': '\uE00A',
|
|
15
|
-
'Pause': '\uE00B',
|
|
16
|
-
'Escape': '\uE00C',
|
|
17
|
-
'Space': '\uE00D',
|
|
18
|
-
' ': '\uE00D',
|
|
19
|
-
'Pageup': '\uE00E',
|
|
20
|
-
'PageUp': '\uE00E',
|
|
21
|
-
'Page_Up': '\uE00E',
|
|
22
|
-
'Pagedown': '\uE00F',
|
|
23
|
-
'PageDown': '\uE00F',
|
|
24
|
-
'Page_Down': '\uE00F',
|
|
25
|
-
'End': '\uE010',
|
|
26
|
-
'Home': '\uE011',
|
|
27
|
-
'Left arrow': '\uE012',
|
|
28
|
-
'Arrow_Left': '\uE012',
|
|
29
|
-
'ArrowLeft': '\uE012',
|
|
30
|
-
'Up arrow': '\uE013',
|
|
31
|
-
'Arrow_Up': '\uE013',
|
|
32
|
-
'ArrowUp': '\uE013',
|
|
33
|
-
'Right arrow': '\uE014',
|
|
34
|
-
'Arrow_Right': '\uE014',
|
|
35
|
-
'ArrowRight': '\uE014',
|
|
36
|
-
'Down arrow': '\uE015',
|
|
37
|
-
'Arrow_Down': '\uE015',
|
|
38
|
-
'ArrowDown': '\uE015',
|
|
39
|
-
'Insert': '\uE016',
|
|
40
|
-
'Delete': '\uE017',
|
|
41
|
-
'Semicolon': '\uE018',
|
|
42
|
-
'Equals': '\uE019',
|
|
43
|
-
'Numpad 0': '\uE01A',
|
|
44
|
-
'Numpad 1': '\uE01B',
|
|
45
|
-
'Numpad 2': '\uE01C',
|
|
46
|
-
'Numpad 3': '\uE01D',
|
|
47
|
-
'Numpad 4': '\uE01E',
|
|
48
|
-
'Numpad 5': '\uE01F',
|
|
49
|
-
'Numpad 6': '\uE020',
|
|
50
|
-
'Numpad 7': '\uE021',
|
|
51
|
-
'Numpad 8': '\uE022',
|
|
52
|
-
'Numpad 9': '\uE023',
|
|
53
|
-
'Multiply': '\uE024',
|
|
54
|
-
'Add': '\uE025',
|
|
55
|
-
'Separator': '\uE026',
|
|
56
|
-
'Subtract': '\uE027',
|
|
57
|
-
'Decimal': '\uE028',
|
|
58
|
-
'Divide': '\uE029',
|
|
59
|
-
'F1': '\uE031',
|
|
60
|
-
'F2': '\uE032',
|
|
61
|
-
'F3': '\uE033',
|
|
62
|
-
'F4': '\uE034',
|
|
63
|
-
'F5': '\uE035',
|
|
64
|
-
'F6': '\uE036',
|
|
65
|
-
'F7': '\uE037',
|
|
66
|
-
'F8': '\uE038',
|
|
67
|
-
'F9': '\uE039',
|
|
68
|
-
'F10': '\uE03A',
|
|
69
|
-
'F11': '\uE03B',
|
|
70
|
-
'F12': '\uE03C',
|
|
71
|
-
'Command': '\uE03D',
|
|
72
|
-
'Meta': '\uE03D',
|
|
73
|
-
'Zenkaku_Hankaku': '\uE040',
|
|
74
|
-
'ZenkakuHankaku': '\uE040'
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const W3C_ELEMENT_ID = 'element-6066-11e4-a52e-4f735466cecf';
|
|
78
|
-
|
|
79
|
-
const BUTTON_ENUM = {
|
|
80
|
-
left: 0,
|
|
81
|
-
middle: 1,
|
|
82
|
-
right: 2
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Webdriver Errors
|
|
87
|
-
*/
|
|
88
|
-
const Unknown = {id: 'Unknown', status: -1, message: 'Remote end send an unknown status code.'};
|
|
89
|
-
const Success = {id: 'Success', status: 0, message: 'The command executed successfully.'};
|
|
90
|
-
const NoSuchDriver = {id: 'NoSuchDriver', status: 6, message: 'A session is either terminated or not started'};
|
|
91
|
-
const NoSuchElement = {
|
|
92
|
-
id: 'NoSuchElement',
|
|
93
|
-
status: 404,
|
|
94
|
-
message: 'An element could not be located on the page using the given search parameters.'
|
|
95
|
-
};
|
|
96
|
-
const NoSuchFrame = {
|
|
97
|
-
id: 'NoSuchFrame',
|
|
98
|
-
status: 400,
|
|
99
|
-
message: 'A request to switch to a frame could not be satisfied because the frame could not be found.'
|
|
100
|
-
};
|
|
101
|
-
const UnknownCommand = {
|
|
102
|
-
id: 'UnknownCommand',
|
|
103
|
-
status: 404,
|
|
104
|
-
message: 'The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource.'
|
|
105
|
-
};
|
|
106
|
-
const StaleElementReference = {
|
|
107
|
-
id: 'StaleElementReference',
|
|
108
|
-
status: 400,
|
|
109
|
-
message: 'An element command failed because the referenced element is no longer attached to the DOM.'
|
|
110
|
-
};
|
|
111
|
-
const ElementNotVisible = {
|
|
112
|
-
id: 'ElementNotVisible',
|
|
113
|
-
status: 11,
|
|
114
|
-
message: 'An element command could not be completed because the element is not visible on the page.'
|
|
115
|
-
};
|
|
116
|
-
const InvalidElementState = {
|
|
117
|
-
id: 'InvalidElementState',
|
|
118
|
-
status: 400,
|
|
119
|
-
message: 'An element command could not be completed because the element is in an invalid state (e.g. attempting to click a disabled element).'
|
|
120
|
-
};
|
|
121
|
-
const UnknownError = {
|
|
122
|
-
id: 'UnknownError',
|
|
123
|
-
status: 500,
|
|
124
|
-
message: 'An unknown server-side error occurred while processing the command.'
|
|
125
|
-
};
|
|
126
|
-
const ElementIsNotSelectable = {
|
|
127
|
-
id: 'ElementIsNotSelectable',
|
|
128
|
-
status: 400,
|
|
129
|
-
message: 'An attempt was made to select an element that cannot be selected.'
|
|
130
|
-
};
|
|
131
|
-
const JavaScriptError = {
|
|
132
|
-
id: 'JavaScriptError',
|
|
133
|
-
status: 500,
|
|
134
|
-
message: 'An error occurred while executing user supplied JavaScript.'
|
|
135
|
-
};
|
|
136
|
-
const XPathLookupError = {
|
|
137
|
-
id: 'XPathLookupError',
|
|
138
|
-
status: 19,
|
|
139
|
-
message: 'An error occurred while searching for an element by XPath.'
|
|
140
|
-
};
|
|
141
|
-
const Timeout = {id: 'Timeout', status: 408, message: 'An operation did not complete before its timeout expired.'};
|
|
142
|
-
const NoSuchWindow = {
|
|
143
|
-
id: 'NoSuchWindow',
|
|
144
|
-
status: 400,
|
|
145
|
-
message: 'A request to switch to a different window could not be satisfied because the window could not be found.'
|
|
146
|
-
};
|
|
147
|
-
const InvalidCookieDomain = {
|
|
148
|
-
id: 'InvalidCookieDomain',
|
|
149
|
-
status: 400,
|
|
150
|
-
message: 'An illegal attempt was made to set a cookie under a different domain than the current page.'
|
|
151
|
-
};
|
|
152
|
-
const UnableToSetCookie = {
|
|
153
|
-
id: 'UnableToSetCookie',
|
|
154
|
-
status: 500,
|
|
155
|
-
message: 'A request to set a cookie\'s value could not be satisfied.'
|
|
156
|
-
};
|
|
157
|
-
const UnexpectedAlertOpen = {
|
|
158
|
-
id: 'UnexpectedAlertOpen',
|
|
159
|
-
status: 500,
|
|
160
|
-
message: 'A modal dialog was open, blocking this operation'
|
|
161
|
-
};
|
|
162
|
-
const NoAlertOpenError = {
|
|
163
|
-
id: 'NoAlertOpenError',
|
|
164
|
-
status: 400,
|
|
165
|
-
message: 'An attempt was made to operate on a modal dialog when one was not open.'
|
|
166
|
-
};
|
|
167
|
-
const ScriptTimeout = {
|
|
168
|
-
id: 'ScriptTimeout',
|
|
169
|
-
status: 408,
|
|
170
|
-
message: 'A script did not complete before its timeout expired.'
|
|
171
|
-
};
|
|
172
|
-
const InvalidElementCoordinates = {
|
|
173
|
-
id: 'InvalidElementCoordinates',
|
|
174
|
-
status: 400,
|
|
175
|
-
message: 'The coordinates provided to an interactions operation are invalid.'
|
|
176
|
-
};
|
|
177
|
-
const IMENotAvailable = {id: 'IMENotAvailable', status: 30, message: 'IME was not available.'}
|
|
178
|
-
const IMEEngineActivationFailed = {
|
|
179
|
-
id: 'IMEEngineActivationFailed',
|
|
180
|
-
status: 31,
|
|
181
|
-
message: 'An IME engine could not be started.'
|
|
182
|
-
};
|
|
183
|
-
const InvalidSelector = {
|
|
184
|
-
id: 'InvalidSelector',
|
|
185
|
-
status: 400,
|
|
186
|
-
message: 'Argument was an invalid selector (e.g. XPath/CSS).'
|
|
187
|
-
};
|
|
188
|
-
const SessionNotCreatedException = {
|
|
189
|
-
id: 'SessionNotCreatedException',
|
|
190
|
-
status: 500,
|
|
191
|
-
message: 'A new session could not be created.'
|
|
192
|
-
};
|
|
193
|
-
const ElementNotScrollable = {id: 'ElementNotScrollable', status: 34, message: 'Element cannot be scrolled into view.'};
|
|
194
|
-
|
|
195
|
-
const SelectorTimeoutError = {
|
|
196
|
-
id: 'SelectorTimeoutError',
|
|
197
|
-
status: 100,
|
|
198
|
-
message: 'Request timed out after the element was still found on the page.'
|
|
199
|
-
};
|
|
200
|
-
const NoSessionIdError = {
|
|
201
|
-
id: 'NoSessionIdError',
|
|
202
|
-
status: 101,
|
|
203
|
-
message: 'A session id is required for this command but wasn\'t found in the response payload'
|
|
204
|
-
};
|
|
205
|
-
const GridApiError = {id: 'GridApiError', status: 102, message: 'A call to the Selenium Grid API failed'};
|
|
206
|
-
|
|
207
|
-
const ElementClickIntercepted = {
|
|
208
|
-
id: 'ElementClickIntercepted',
|
|
209
|
-
status: 400,
|
|
210
|
-
message: 'The Element Click command could not be completed because the element receiving the events is obscuring the element that was requested clicked.'
|
|
211
|
-
};
|
|
212
|
-
const ElementNotInteractable = {
|
|
213
|
-
id: 'ElementNotInteractable',
|
|
214
|
-
status: 400,
|
|
215
|
-
message: 'A command could not be completed because the element is not pointer- or keyboard interactable.'
|
|
216
|
-
};
|
|
217
|
-
const InsecureCertificate = {
|
|
218
|
-
id: 'InsecureCertificate',
|
|
219
|
-
status: 400,
|
|
220
|
-
message: 'Navigation caused the user agent to hit a certificate warning, which is usually the result of an expired or invalid TLS certificate.'
|
|
221
|
-
};
|
|
222
|
-
const InvalidArgument = {
|
|
223
|
-
id: 'InvalidArgument',
|
|
224
|
-
status: 400,
|
|
225
|
-
message: 'The arguments passed to a command are either invalid or malformed.'
|
|
226
|
-
};
|
|
227
|
-
const InvalidSessionId = {
|
|
228
|
-
id: 'InvalidSessionId',
|
|
229
|
-
status: 404,
|
|
230
|
-
message: 'Occurs if the given session id is not in the list of active sessions, meaning the session either does not exist or that it’s not active.'
|
|
231
|
-
};
|
|
232
|
-
const MoveTargetOutOfBounds = {
|
|
233
|
-
id: 'MoveTargetOutOfBounds',
|
|
234
|
-
status: 500,
|
|
235
|
-
message: 'The target for mouse interaction is not in the browser’s viewport and cannot be brought into that viewport.'
|
|
236
|
-
};
|
|
237
|
-
const NoSuchCookie = {
|
|
238
|
-
id: 'NoSuchCookie',
|
|
239
|
-
status: 404,
|
|
240
|
-
message: 'No cookie matching the given path name was found amongst the associated cookies of the current browsing context’s active document.'
|
|
241
|
-
};
|
|
242
|
-
const UnableToCaptureScreen = {
|
|
243
|
-
id: 'UnableToCaptureScreen',
|
|
244
|
-
status: 500,
|
|
245
|
-
message: 'A screen capture was made impossible.'
|
|
246
|
-
};
|
|
247
|
-
const UnknownMethod = {
|
|
248
|
-
id: 'UnknownMethod',
|
|
249
|
-
status: 405,
|
|
250
|
-
message: 'The requested command matched a known URL but did not match an method for that URL.'
|
|
251
|
-
};
|
|
252
|
-
const UnsupportedOperation = {
|
|
253
|
-
id: 'UnsupportedOperation',
|
|
254
|
-
status: 500,
|
|
255
|
-
message: 'Indicates that a command that should have executed properly cannot be supported for some reason.'
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const SELENIUM_STATUS_CODES = {
|
|
259
|
-
'-1': Unknown,
|
|
260
|
-
'0': Success,
|
|
261
|
-
'6': NoSuchDriver,
|
|
262
|
-
'7': NoSuchElement,
|
|
263
|
-
'8': NoSuchFrame,
|
|
264
|
-
'9': UnknownCommand,
|
|
265
|
-
'10': StaleElementReference,
|
|
266
|
-
'11': ElementNotVisible,
|
|
267
|
-
'12': InvalidElementState,
|
|
268
|
-
'13': UnknownError,
|
|
269
|
-
'15': ElementIsNotSelectable,
|
|
270
|
-
'17': JavaScriptError,
|
|
271
|
-
'19': XPathLookupError,
|
|
272
|
-
'21': Timeout,
|
|
273
|
-
'23': NoSuchWindow,
|
|
274
|
-
'24': InvalidCookieDomain,
|
|
275
|
-
'25': UnableToSetCookie,
|
|
276
|
-
'26': UnexpectedAlertOpen,
|
|
277
|
-
'27': NoAlertOpenError,
|
|
278
|
-
'28': ScriptTimeout,
|
|
279
|
-
'29': InvalidElementCoordinates,
|
|
280
|
-
'30': IMENotAvailable,
|
|
281
|
-
'31': IMEEngineActivationFailed,
|
|
282
|
-
'32': InvalidSelector,
|
|
283
|
-
'33': SessionNotCreatedException,
|
|
284
|
-
'34': ElementNotScrollable,
|
|
285
|
-
|
|
286
|
-
// WebdriverIO specific error codes
|
|
287
|
-
'100': SelectorTimeoutError,
|
|
288
|
-
'101': NoSessionIdError,
|
|
289
|
-
'102': GridApiError,
|
|
290
|
-
|
|
291
|
-
// W3C Webdriver errors
|
|
292
|
-
'element click intercepted': ElementClickIntercepted,
|
|
293
|
-
'element not selectable': ElementIsNotSelectable,
|
|
294
|
-
'element not interactable': ElementNotInteractable,
|
|
295
|
-
'insecure certificate': InsecureCertificate,
|
|
296
|
-
'invalid argument': InvalidArgument,
|
|
297
|
-
'invalid cookie domain': InvalidCookieDomain,
|
|
298
|
-
'invalid coordinates': InvalidElementCoordinates,
|
|
299
|
-
'invalid element state': InvalidElementState,
|
|
300
|
-
'invalid selector': InvalidSelector,
|
|
301
|
-
'invalid session id': InvalidSessionId,
|
|
302
|
-
'javascript error': JavaScriptError,
|
|
303
|
-
'move target out of bounds': MoveTargetOutOfBounds,
|
|
304
|
-
'no such alert': NoAlertOpenError,
|
|
305
|
-
'no such cookie': NoSuchCookie,
|
|
306
|
-
'no such element': NoSuchElement,
|
|
307
|
-
'no such frame': NoSuchFrame,
|
|
308
|
-
'no such window': NoSuchWindow,
|
|
309
|
-
'script timeout': ScriptTimeout,
|
|
310
|
-
'session not created': SessionNotCreatedException,
|
|
311
|
-
'stale element reference': StaleElementReference,
|
|
312
|
-
'timeout': Timeout,
|
|
313
|
-
'unable to set cookie': UnableToSetCookie,
|
|
314
|
-
'unable to capture screen': UnableToCaptureScreen,
|
|
315
|
-
'unexpected alert open': UnexpectedAlertOpen,
|
|
316
|
-
'unknown command': UnknownCommand,
|
|
317
|
-
'unknown error': UnknownError,
|
|
318
|
-
'unknown method': UnknownMethod,
|
|
319
|
-
'unsupported operation': UnsupportedOperation
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
const EDGE_LAST_VERSION = 44;
|
|
323
|
-
const EDGE_CHROMIUM_MIN_VERSION = 79;
|
|
324
|
-
|
|
325
|
-
module.exports = {
|
|
326
|
-
EDGE_LAST_VERSION,
|
|
327
|
-
EDGE_CHROMIUM_MIN_VERSION,
|
|
328
|
-
UNICODE_CHARACTERS,
|
|
329
|
-
W3C_ELEMENT_ID,
|
|
330
|
-
BUTTON_ENUM,
|
|
331
|
-
SELENIUM_STATUS_CODES
|
|
332
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const utils = require('../utils');
|
|
4
|
-
const WebDriver = require('./webdriver');
|
|
5
|
-
|
|
6
|
-
class ExtensionTestPlayer {
|
|
7
|
-
constructor(id) {
|
|
8
|
-
this.driver = new WebDriver();
|
|
9
|
-
this.id = id;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
onDone() {
|
|
13
|
-
const END_DRIVER_TIMEOUT = 1000 * 60 * 2;
|
|
14
|
-
return utils.promiseTimeout(this.driver.end(), END_DRIVER_TIMEOUT)
|
|
15
|
-
.catch((error) => {
|
|
16
|
-
if (error instanceof utils.TimeoutError) {
|
|
17
|
-
return this.driver.forceEnd();
|
|
18
|
-
}
|
|
19
|
-
throw error;
|
|
20
|
-
})
|
|
21
|
-
.catch(() => {})
|
|
22
|
-
.then(() => {
|
|
23
|
-
this.driver = null;
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getSessionId() {
|
|
28
|
-
return this.driver.getSessionId();
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
module.exports = ExtensionTestPlayer;
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
const DEFAULT_SELECTOR = 'css selector';
|
|
2
|
-
const DIRECT_SELECTOR_REGEXP = /^(id|css selector|xpath|link text|partial link text|name|tag name|class name|-android uiautomator|-ios uiautomation|-ios predicate string|-ios class chain|accessibility id):(.+)/;
|
|
3
|
-
|
|
4
|
-
module.exports = function (...args) {
|
|
5
|
-
let value = args[0];
|
|
6
|
-
let relative = (args.length > 1 ? args[1] : false);
|
|
7
|
-
let xpathPrefix = relative ? './/' : '//';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* set default selector
|
|
11
|
-
*/
|
|
12
|
-
let using = DEFAULT_SELECTOR;
|
|
13
|
-
|
|
14
|
-
if (typeof value !== 'string') {
|
|
15
|
-
throw new Error('selector needs to be typeof `string`');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (args.length === 3) {
|
|
19
|
-
return {
|
|
20
|
-
using: args[0],
|
|
21
|
-
value: args[1]
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* check if user has specified locator strategy directly
|
|
27
|
-
*/
|
|
28
|
-
const match = value.match(DIRECT_SELECTOR_REGEXP);
|
|
29
|
-
if (match) {
|
|
30
|
-
return {
|
|
31
|
-
using: match[1],
|
|
32
|
-
value: match[2]
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// check value type
|
|
37
|
-
// use css selector for hash instead of by.id
|
|
38
|
-
// https://github.com/webdriverio/webdriverio/issues/2780
|
|
39
|
-
if (value.search(/^#-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/) > -1) {
|
|
40
|
-
using = 'css selector';
|
|
41
|
-
|
|
42
|
-
// use xPath strategy if value starts with //
|
|
43
|
-
} else if (value.indexOf('/') === 0 || value.indexOf('(') === 0 ||
|
|
44
|
-
value.indexOf('../') === 0 || value.indexOf('./') === 0 ||
|
|
45
|
-
value.indexOf('*/') === 0) {
|
|
46
|
-
using = 'xpath';
|
|
47
|
-
|
|
48
|
-
// use link text strategy if value startes with =
|
|
49
|
-
} else if (value.indexOf('=') === 0) {
|
|
50
|
-
using = 'link text';
|
|
51
|
-
value = value.slice(1);
|
|
52
|
-
|
|
53
|
-
// use partial link text strategy if value startes with *=
|
|
54
|
-
} else if (value.indexOf('*=') === 0) {
|
|
55
|
-
using = 'partial link text';
|
|
56
|
-
value = value.slice(2);
|
|
57
|
-
|
|
58
|
-
// recursive element search using the UiAutomator library (Android only)
|
|
59
|
-
} else if (value.indexOf('android=') === 0) {
|
|
60
|
-
using = '-android uiautomator';
|
|
61
|
-
value = value.slice(8);
|
|
62
|
-
|
|
63
|
-
// recursive element search using the UIAutomation or XCUITest library (iOS-only)
|
|
64
|
-
} else if (value.indexOf('ios=') === 0) {
|
|
65
|
-
value = value.slice(4);
|
|
66
|
-
|
|
67
|
-
if (value.indexOf('predicate=') === 0) {
|
|
68
|
-
// Using 'ios=predicate=' (iOS 10+ only)
|
|
69
|
-
using = '-ios predicate string';
|
|
70
|
-
value = value.slice(10);
|
|
71
|
-
} else if (value.indexOf('chain=') === 0) {
|
|
72
|
-
// Using 'ios=chain=' (iOS 10+ only)
|
|
73
|
-
using = '-ios class chain';
|
|
74
|
-
value = value.slice(6);
|
|
75
|
-
} else {
|
|
76
|
-
// Legacy iOS (<= 9.3) UIAutomation library
|
|
77
|
-
using = '-ios uiautomation';
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// recursive element search using accessibility id
|
|
81
|
-
} else if (value.indexOf('~') === 0) {
|
|
82
|
-
using = 'accessibility id';
|
|
83
|
-
value = value.slice(1);
|
|
84
|
-
|
|
85
|
-
// class name mobile selector
|
|
86
|
-
// for iOS = UIA...
|
|
87
|
-
// for Android = android.widget
|
|
88
|
-
} else if (value.slice(0, 3) === 'UIA' || value.slice(0, 15) === 'XCUIElementType' || value.slice(0, 14).toLowerCase() === 'android.widget') {
|
|
89
|
-
using = 'class name';
|
|
90
|
-
|
|
91
|
-
// use tag name strategy if value contains a tag
|
|
92
|
-
// e.g. "<div>" or "<div />"
|
|
93
|
-
} else if (value.search(/<[a-zA-Z-]+( \/)*>/g) >= 0) {
|
|
94
|
-
using = 'tag name';
|
|
95
|
-
value = value.replace(/<|>|\/|\s/g, '');
|
|
96
|
-
|
|
97
|
-
// use name strategy if value queries elements with name attributes
|
|
98
|
-
// e.g. "[name='myName']" or '[name="myName"]'
|
|
99
|
-
} else if (value.search(/^\[name=("|')([a-zA-z0-9\-_. ]+)("|')]$/) >= 0) {
|
|
100
|
-
using = 'name';
|
|
101
|
-
value = value.match(/^\[name=("|')([a-zA-z0-9\-_. ]+)("|')]$/)[2];
|
|
102
|
-
|
|
103
|
-
// allow to move up to the parent or select current element
|
|
104
|
-
} else if (value === '..' || value === '.') {
|
|
105
|
-
using = 'xpath';
|
|
106
|
-
|
|
107
|
-
// any element with given class, id, or attribute and content
|
|
108
|
-
// e.g. h1.header=Welcome or [data-name=table-row]=Item or #content*=Intro
|
|
109
|
-
} else {
|
|
110
|
-
const match = value.match(new RegExp([
|
|
111
|
-
// HTML tag
|
|
112
|
-
/^([a-z0-9]*)/,
|
|
113
|
-
// optional . or # + class or id
|
|
114
|
-
/(?:(\.|#)(-?[_a-zA-Z]+[_a-zA-Z0-9-]*))?/,
|
|
115
|
-
// optional [attribute-name="attribute-value"]
|
|
116
|
-
/(?:\[(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)(?:=(?:"|')([a-zA-z0-9\-_. ]+)(?:"|'))?\])?/,
|
|
117
|
-
// *=query or =query
|
|
118
|
-
/(\*)?=(.+)$/
|
|
119
|
-
].map(rx => rx.source).join('')));
|
|
120
|
-
|
|
121
|
-
if (match) {
|
|
122
|
-
const PREFIX_NAME = {'.': 'class', '#': 'id'};
|
|
123
|
-
const conditions = [];
|
|
124
|
-
const [
|
|
125
|
-
tag,
|
|
126
|
-
prefix, name,
|
|
127
|
-
attrName, attrValue,
|
|
128
|
-
partial, query
|
|
129
|
-
] = match.slice(1);
|
|
130
|
-
|
|
131
|
-
if (prefix) {
|
|
132
|
-
conditions.push(`contains(@${PREFIX_NAME[prefix]}, "${name}")`);
|
|
133
|
-
}
|
|
134
|
-
if (attrName) {
|
|
135
|
-
conditions.push(
|
|
136
|
-
attrValue ? `contains(@${attrName}, "${attrValue}")` : `@${attrName}`
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
if (partial) {
|
|
140
|
-
conditions.push(`contains(., "${query}")`);
|
|
141
|
-
} else {
|
|
142
|
-
conditions.push(`normalize-space() = "${query}"`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
using = 'xpath';
|
|
146
|
-
value = `${xpathPrefix}${tag || '*'}[${conditions.join(' and ')}]`;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
using,
|
|
152
|
-
value
|
|
153
|
-
};
|
|
154
|
-
};
|