@appium/base-driver 10.7.0 → 10.7.2
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/README.md +2 -2
- package/build/lib/basedriver/capabilities.d.ts +1 -1
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +4 -8
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/bidi.d.ts.map +1 -1
- package/build/lib/basedriver/commands/bidi.js +1 -3
- package/build/lib/basedriver/commands/bidi.js.map +1 -1
- package/build/lib/basedriver/commands/event.d.ts.map +1 -1
- package/build/lib/basedriver/commands/event.js.map +1 -1
- package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
- package/build/lib/basedriver/commands/execute.js +1 -1
- package/build/lib/basedriver/commands/execute.js.map +1 -1
- package/build/lib/basedriver/commands/find.d.ts.map +1 -1
- package/build/lib/basedriver/commands/find.js.map +1 -1
- package/build/lib/basedriver/commands/log.d.ts.map +1 -1
- package/build/lib/basedriver/commands/log.js +1 -2
- package/build/lib/basedriver/commands/log.js.map +1 -1
- package/build/lib/basedriver/commands/mixin.d.ts.map +1 -1
- package/build/lib/basedriver/commands/mixin.js.map +1 -1
- package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
- package/build/lib/basedriver/commands/timeout.js +1 -1
- package/build/lib/basedriver/commands/timeout.js.map +1 -1
- package/build/lib/basedriver/core.d.ts +1 -2
- package/build/lib/basedriver/core.d.ts.map +1 -1
- package/build/lib/basedriver/core.js +6 -10
- package/build/lib/basedriver/core.js.map +1 -1
- package/build/lib/basedriver/device-settings.d.ts +1 -1
- package/build/lib/basedriver/device-settings.d.ts.map +1 -1
- package/build/lib/basedriver/device-settings.js +2 -3
- package/build/lib/basedriver/device-settings.js.map +1 -1
- package/build/lib/basedriver/driver.d.ts +1 -2
- package/build/lib/basedriver/driver.d.ts.map +1 -1
- package/build/lib/basedriver/driver.js +6 -11
- package/build/lib/basedriver/driver.js.map +1 -1
- package/build/lib/basedriver/extension-core.d.ts.map +1 -1
- package/build/lib/basedriver/extension-core.js +1 -1
- package/build/lib/basedriver/extension-core.js.map +1 -1
- package/build/lib/basedriver/helpers.d.ts.map +1 -1
- package/build/lib/basedriver/helpers.js +6 -11
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/basedriver/ipc.d.ts +1 -1
- package/build/lib/basedriver/ipc.d.ts.map +1 -1
- package/build/lib/basedriver/ipc.js +3 -5
- package/build/lib/basedriver/ipc.js.map +1 -1
- package/build/lib/basedriver/validation.d.ts.map +1 -1
- package/build/lib/basedriver/validation.js +1 -2
- package/build/lib/basedriver/validation.js.map +1 -1
- package/build/lib/express/express-logging.d.ts.map +1 -1
- package/build/lib/express/express-logging.js +4 -2
- package/build/lib/express/express-logging.js.map +1 -1
- package/build/lib/express/idempotency.d.ts +1 -1
- package/build/lib/express/idempotency.d.ts.map +1 -1
- package/build/lib/express/idempotency.js +6 -9
- package/build/lib/express/idempotency.js.map +1 -1
- package/build/lib/express/middleware.d.ts +1 -1
- package/build/lib/express/middleware.d.ts.map +1 -1
- package/build/lib/express/middleware.js +1 -1
- package/build/lib/express/middleware.js.map +1 -1
- package/build/lib/express/server.d.ts +2 -2
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js +8 -9
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/express/websocket.d.ts.map +1 -1
- package/build/lib/express/websocket.js.map +1 -1
- package/build/lib/helpers/capabilities.d.ts +1 -1
- package/build/lib/helpers/capabilities.d.ts.map +1 -1
- package/build/lib/helpers/capabilities.js.map +1 -1
- package/build/lib/helpers/extension-command-name.d.ts.map +1 -1
- package/build/lib/helpers/extension-command-name.js.map +1 -1
- package/build/lib/helpers/levenshtein-match.d.ts.map +1 -1
- package/build/lib/helpers/levenshtein-match.js +1 -4
- package/build/lib/helpers/levenshtein-match.js.map +1 -1
- package/build/lib/index.d.ts +21 -18
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +9 -12
- package/build/lib/index.js.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.js +6 -15
- package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts +3 -3
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js +17 -19
- package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
- package/build/lib/jsonwp-status/status.d.ts.map +1 -1
- package/build/lib/jsonwp-status/status.js.map +1 -1
- package/build/lib/protocol/errors.d.ts +1 -1
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/errors.js +11 -28
- package/build/lib/protocol/errors.js.map +1 -1
- package/build/lib/protocol/helpers.d.ts.map +1 -1
- package/build/lib/protocol/helpers.js.map +1 -1
- package/build/lib/protocol/index.d.ts +4 -4
- package/build/lib/protocol/index.d.ts.map +1 -1
- package/build/lib/protocol/index.js +12 -12
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/protocol/protocol.d.ts +1 -1
- package/build/lib/protocol/protocol.d.ts.map +1 -1
- package/build/lib/protocol/protocol.js +16 -30
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.d.ts +1 -1
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +5 -15
- package/build/lib/protocol/routes.js.map +1 -1
- package/build/lib/test-pages/handlers.d.ts.map +1 -1
- package/build/lib/test-pages/handlers.js +2 -2
- package/build/lib/test-pages/handlers.js.map +1 -1
- package/build/lib/test-pages/index.d.ts +1 -1
- package/build/lib/test-pages/index.d.ts.map +1 -1
- package/build/lib/test-pages/index.js +4 -4
- package/build/lib/test-pages/index.js.map +1 -1
- package/build/lib/test-pages/static-dir.d.ts.map +1 -1
- package/build/lib/test-pages/static-dir.js +5 -6
- package/build/lib/test-pages/static-dir.js.map +1 -1
- package/build/lib/test-pages/template.d.ts.map +1 -1
- package/build/lib/test-pages/template.js.map +1 -1
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js.map +1 -1
- package/lib/basedriver/capabilities.ts +14 -37
- package/lib/basedriver/commands/bidi.ts +4 -14
- package/lib/basedriver/commands/event.ts +9 -15
- package/lib/basedriver/commands/execute.ts +5 -14
- package/lib/basedriver/commands/find.ts +3 -10
- package/lib/basedriver/commands/log.ts +2 -2
- package/lib/basedriver/commands/mixin.ts +1 -0
- package/lib/basedriver/commands/timeout.ts +5 -9
- package/lib/basedriver/core.ts +9 -15
- package/lib/basedriver/device-settings.ts +6 -9
- package/lib/basedriver/driver.ts +24 -48
- package/lib/basedriver/extension-core.ts +7 -12
- package/lib/basedriver/helpers.ts +18 -45
- package/lib/basedriver/ipc.ts +13 -18
- package/lib/basedriver/validation.ts +6 -16
- package/lib/express/express-logging.ts +11 -11
- package/lib/express/idempotency.ts +10 -19
- package/lib/express/middleware.ts +10 -18
- package/lib/express/server.ts +29 -38
- package/lib/express/websocket.ts +7 -13
- package/lib/helpers/capabilities.ts +2 -3
- package/lib/helpers/extension-command-name.ts +2 -4
- package/lib/helpers/levenshtein-match.ts +2 -7
- package/lib/{index.js → index.ts} +7 -9
- package/lib/jsonwp-proxy/protocol-converter.ts +24 -88
- package/lib/jsonwp-proxy/proxy.ts +34 -62
- package/lib/jsonwp-status/status.ts +5 -10
- package/lib/protocol/errors.ts +24 -70
- package/lib/protocol/helpers.ts +1 -0
- package/lib/protocol/index.ts +20 -26
- package/lib/protocol/protocol.ts +38 -82
- package/lib/protocol/routes.ts +8 -21
- package/lib/test-pages/handlers.ts +4 -2
- package/lib/test-pages/index.ts +5 -3
- package/lib/test-pages/static-dir.ts +6 -6
- package/lib/test-pages/template.ts +1 -3
- package/lib/utils.ts +1 -4
- package/package.json +29 -32
- package/tsconfig.json +14 -9
- package/LICENSE +0 -201
- package/index.js +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import type {Constraints, Element, IFindCommands} from '@appium/types';
|
|
3
|
+
|
|
3
4
|
import {errors} from '../../protocol';
|
|
4
5
|
import type {BaseDriver} from '../driver';
|
|
5
6
|
import {mixin} from './mixin';
|
|
@@ -71,19 +72,11 @@ async function findElOrElsWithProcessing<C extends Constraints>(
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
const FindCommands: IFindCommands = {
|
|
74
|
-
async findElement<C extends Constraints>(
|
|
75
|
-
this: BaseDriver<C>,
|
|
76
|
-
strategy: string,
|
|
77
|
-
selector: string,
|
|
78
|
-
) {
|
|
75
|
+
async findElement<C extends Constraints>(this: BaseDriver<C>, strategy: string, selector: string) {
|
|
79
76
|
return await this.findElOrElsWithProcessing(strategy, selector, false);
|
|
80
77
|
},
|
|
81
78
|
|
|
82
|
-
async findElements<C extends Constraints>(
|
|
83
|
-
this: BaseDriver<C>,
|
|
84
|
-
strategy: string,
|
|
85
|
-
selector: string,
|
|
86
|
-
) {
|
|
79
|
+
async findElements<C extends Constraints>(this: BaseDriver<C>, strategy: string, selector: string) {
|
|
87
80
|
return await this.findElOrElsWithProcessing(strategy, selector, true);
|
|
88
81
|
},
|
|
89
82
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {Constraints, Driver, ILogCommands} from '@appium/types';
|
|
2
|
+
|
|
2
3
|
import type {BaseDriver} from '../driver';
|
|
3
4
|
import {mixin} from './mixin';
|
|
4
5
|
|
|
@@ -23,8 +24,7 @@ const LogCommands: ILogCommands = {
|
|
|
23
24
|
Object.entries(this.supportedLogTypes).map(([key, value]) => [key, value.description]),
|
|
24
25
|
);
|
|
25
26
|
throw new Error(
|
|
26
|
-
`Unsupported log type '${String(logType)}'. ` +
|
|
27
|
-
`Supported types: ${JSON.stringify(logsTypesWithDescriptions)}`,
|
|
27
|
+
`Unsupported log type '${String(logType)}'. ` + `Supported types: ${JSON.stringify(logsTypesWithDescriptions)}`,
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {waitForCondition} from 'asyncbox';
|
|
2
1
|
import {util} from '@appium/support';
|
|
2
|
+
import type {Constraints, ITimeoutCommands} from '@appium/types';
|
|
3
|
+
import {waitForCondition} from 'asyncbox';
|
|
4
|
+
|
|
3
5
|
import {errors} from '../../protocol';
|
|
4
6
|
import type {BaseDriver} from '../driver';
|
|
5
|
-
import type {Constraints, ITimeoutCommands} from '@appium/types';
|
|
6
7
|
import {mixin} from './mixin';
|
|
7
8
|
|
|
8
9
|
declare module '../driver' {
|
|
@@ -40,9 +41,7 @@ const TimeoutCommands: ITimeoutCommands = {
|
|
|
40
41
|
|
|
41
42
|
this.log.debug(`W3C timeout argument: ${JSON.stringify({script, pageLoad, implicit})}}`);
|
|
42
43
|
if ([script, pageLoad, implicit].every((value) => value == null)) {
|
|
43
|
-
throw new errors.InvalidArgumentError(
|
|
44
|
-
'W3C protocol expects any of script, pageLoad or implicit to be set',
|
|
45
|
-
);
|
|
44
|
+
throw new errors.InvalidArgumentError('W3C protocol expects any of script, pageLoad or implicit to be set');
|
|
46
45
|
}
|
|
47
46
|
if (util.hasValue(script)) {
|
|
48
47
|
await this.scriptTimeoutW3C(script);
|
|
@@ -110,10 +109,7 @@ const TimeoutCommands: ITimeoutCommands = {
|
|
|
110
109
|
}
|
|
111
110
|
},
|
|
112
111
|
|
|
113
|
-
async implicitWaitForCondition<C extends Constraints>(
|
|
114
|
-
this: BaseDriver<C>,
|
|
115
|
-
condFn: (...args: any[]) => Promise<any>,
|
|
116
|
-
) {
|
|
112
|
+
async implicitWaitForCondition<C extends Constraints>(this: BaseDriver<C>, condFn: (...args: any[]) => Promise<any>) {
|
|
117
113
|
this.log.debug(`Waiting up to ${this.implicitWaitMs} ms for condition`);
|
|
118
114
|
const wrappedCondFn = async (...args: any[]) => {
|
|
119
115
|
// reset command timeout
|
package/lib/basedriver/core.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
|
|
3
|
+
import {util} from '@appium/support';
|
|
1
4
|
import type {
|
|
2
5
|
AppiumLogger,
|
|
3
6
|
Constraints,
|
|
@@ -12,13 +15,12 @@ import type {
|
|
|
12
15
|
StringRecord,
|
|
13
16
|
} from '@appium/types';
|
|
14
17
|
import AsyncLock from 'async-lock';
|
|
15
|
-
|
|
16
|
-
import os from 'node:os';
|
|
18
|
+
|
|
17
19
|
import {DEFAULT_BASE_PATH, PROTOCOLS} from '../constants';
|
|
18
20
|
import {errors} from '../protocol';
|
|
19
21
|
import {DeviceSettings} from './device-settings';
|
|
20
|
-
import * as helpers from './helpers';
|
|
21
22
|
import {ExtensionCore} from './extension-core';
|
|
23
|
+
import * as helpers from './helpers';
|
|
22
24
|
|
|
23
25
|
const NEW_COMMAND_TIMEOUT_MS = 60 * 1000;
|
|
24
26
|
|
|
@@ -113,7 +115,7 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
|
|
113
115
|
this.shouldValidateCaps = shouldValidateCaps;
|
|
114
116
|
|
|
115
117
|
// keeping track of initial opts
|
|
116
|
-
this.initialOpts =
|
|
118
|
+
this.initialOpts = {...opts};
|
|
117
119
|
|
|
118
120
|
this.sessionId = null;
|
|
119
121
|
this.helpers = helpers;
|
|
@@ -275,17 +277,12 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
|
|
275
277
|
`the feature name split by a colon. Got '${fullName}' instead`,
|
|
276
278
|
);
|
|
277
279
|
}
|
|
278
|
-
return [
|
|
279
|
-
fullName.substring(0, separatorPos).toLowerCase(),
|
|
280
|
-
fullName.substring(separatorPos + 1),
|
|
281
|
-
];
|
|
280
|
+
return [fullName.substring(0, separatorPos).toLowerCase(), fullName.substring(separatorPos + 1)];
|
|
282
281
|
};
|
|
283
282
|
const parseFullNames = (fullNames: string[]) => fullNames.map(parseFullName);
|
|
284
283
|
const matches = (pair: string[]) => {
|
|
285
284
|
const [automationName, featureName] = pair;
|
|
286
|
-
return (
|
|
287
|
-
[currentAutomationName, ALL_DRIVERS_MATCH].includes(automationName) && featureName === name
|
|
288
|
-
);
|
|
285
|
+
return [currentAutomationName, ALL_DRIVERS_MATCH].includes(automationName) && featureName === name;
|
|
289
286
|
};
|
|
290
287
|
|
|
291
288
|
// if we have explicitly denied this feature, return false immediately
|
|
@@ -334,9 +331,7 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
|
|
334
331
|
}
|
|
335
332
|
|
|
336
333
|
if (!validStrategies.includes(strategy)) {
|
|
337
|
-
throw new errors.InvalidSelectorError(
|
|
338
|
-
`Locator Strategy '${strategy}' is not supported for this session`,
|
|
339
|
-
);
|
|
334
|
+
throw new errors.InvalidSelectorError(`Locator Strategy '${strategy}' is not supported for this session`);
|
|
340
335
|
}
|
|
341
336
|
}
|
|
342
337
|
|
|
@@ -390,7 +385,6 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
|
|
390
385
|
}
|
|
391
386
|
|
|
392
387
|
/**
|
|
393
|
-
*
|
|
394
388
|
* @param {Driver} driver
|
|
395
389
|
*/
|
|
396
390
|
addManagedDriver(driver: Driver) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {node, util} from '@appium/support';
|
|
2
|
+
import type {IDeviceSettings, SettingsUpdateListener, StringRecord} from '@appium/types';
|
|
3
|
+
|
|
3
4
|
import {errors} from '../protocol/errors';
|
|
4
|
-
import
|
|
5
|
+
import {log} from './logger';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Maximum size (in bytes) of a given driver's settings object (which is internal to {@linkcode DeviceSettings}).
|
|
@@ -21,10 +22,7 @@ export class DeviceSettings<T extends StringRecord = StringRecord> implements ID
|
|
|
21
22
|
* @param defaultSettings - Initial settings (shallow-copied).
|
|
22
23
|
* @param onSettingsUpdate - Called when a setting is changed; receives (prop, newValue, curValue).
|
|
23
24
|
*/
|
|
24
|
-
constructor(
|
|
25
|
-
defaultSettings: T = {} as T,
|
|
26
|
-
onSettingsUpdate: SettingsUpdateListener<T> = async () => {},
|
|
27
|
-
) {
|
|
25
|
+
constructor(defaultSettings: T = {} as T, onSettingsUpdate: SettingsUpdateListener<T> = async () => {}) {
|
|
28
26
|
this._settings = {...defaultSettings};
|
|
29
27
|
this._onSettingsUpdate = onSettingsUpdate;
|
|
30
28
|
}
|
|
@@ -37,8 +35,7 @@ export class DeviceSettings<T extends StringRecord = StringRecord> implements ID
|
|
|
37
35
|
async update(newSettings: T): Promise<void> {
|
|
38
36
|
if (!util.isPlainObject(newSettings)) {
|
|
39
37
|
throw new errors.InvalidArgumentError(
|
|
40
|
-
`Settings update should be called with valid JSON. Got ` +
|
|
41
|
-
`${JSON.stringify(newSettings)} instead`,
|
|
38
|
+
`Settings update should be called with valid JSON. Got ` + `${JSON.stringify(newSettings)} instead`,
|
|
42
39
|
);
|
|
43
40
|
}
|
|
44
41
|
|
package/lib/basedriver/driver.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import type AsyncLock from 'async-lock';
|
|
2
1
|
import {util} from '@appium/support';
|
|
3
2
|
import {
|
|
4
|
-
BASE_DESIRED_CAP_CONSTRAINTS,
|
|
5
3
|
type AppiumServer,
|
|
4
|
+
BASE_DESIRED_CAP_CONSTRAINTS,
|
|
6
5
|
type BaseDriverCapConstraints,
|
|
7
6
|
type Capabilities,
|
|
8
7
|
type Constraints,
|
|
9
8
|
type DefaultCreateSessionResult,
|
|
9
|
+
type DefaultDeleteSessionResult,
|
|
10
10
|
type Driver,
|
|
11
11
|
type DriverCaps,
|
|
12
12
|
type DriverData,
|
|
13
|
+
type InitialOpts,
|
|
13
14
|
type ServerArgs,
|
|
15
|
+
type SessionCapabilities,
|
|
16
|
+
type SingularSessionData,
|
|
14
17
|
type StringRecord,
|
|
15
18
|
type W3CDriverCaps,
|
|
16
|
-
type InitialOpts,
|
|
17
|
-
type DefaultDeleteSessionResult,
|
|
18
|
-
type SingularSessionData,
|
|
19
|
-
type SessionCapabilities,
|
|
20
19
|
} from '@appium/types';
|
|
20
|
+
import type AsyncLock from 'async-lock';
|
|
21
|
+
|
|
21
22
|
import {fixCaps, isW3cCaps} from '../helpers/capabilities';
|
|
23
|
+
import {resolveExecuteExtensionName} from '../helpers/extension-command-name';
|
|
22
24
|
import {getLevenshteinSuggestion} from '../helpers/levenshtein-match';
|
|
23
25
|
import {calcSignature} from '../helpers/session';
|
|
24
26
|
import {DELETE_SESSION_COMMAND, determineProtocol, errors} from '../protocol';
|
|
27
|
+
import {mergePlainObjects} from '../utils';
|
|
25
28
|
import {processCapabilities, validateCaps} from './capabilities';
|
|
26
29
|
import {DriverCore} from './core';
|
|
27
30
|
import * as helpers from './helpers';
|
|
28
|
-
import {mergePlainObjects} from '../utils';
|
|
29
|
-
import {resolveExecuteExtensionName} from '../helpers/extension-command-name';
|
|
30
31
|
|
|
31
|
-
type CommandInvoker<C extends Constraints> = BaseDriver<C> &
|
|
32
|
-
Record<string, ((...args: any[]) => any) | undefined>;
|
|
32
|
+
type CommandInvoker<C extends Constraints> = BaseDriver<C> & Record<string, ((...args: any[]) => any) | undefined>;
|
|
33
33
|
|
|
34
34
|
const EVENT_SESSION_INIT = 'newSessionRequested';
|
|
35
35
|
const EVENT_SESSION_START = 'newSessionStarted';
|
|
@@ -73,11 +73,7 @@ export class BaseDriver<
|
|
|
73
73
|
*/
|
|
74
74
|
protected get _desiredCapConstraints(): Readonly<BaseDriverCapConstraints & C> {
|
|
75
75
|
return Object.freeze(
|
|
76
|
-
mergePlainObjects(
|
|
77
|
-
{},
|
|
78
|
-
BASE_DESIRED_CAP_CONSTRAINTS,
|
|
79
|
-
this.desiredCapConstraints,
|
|
80
|
-
) as BaseDriverCapConstraints & C,
|
|
76
|
+
mergePlainObjects({}, BASE_DESIRED_CAP_CONSTRAINTS, this.desiredCapConstraints) as BaseDriverCapConstraints & C,
|
|
81
77
|
);
|
|
82
78
|
}
|
|
83
79
|
|
|
@@ -149,11 +145,7 @@ export class BaseDriver<
|
|
|
149
145
|
// automatic session deletion in this.onCommandTimeout. Of course we don't
|
|
150
146
|
// want to trigger the timer when the user is shutting down the session
|
|
151
147
|
// intentionally
|
|
152
|
-
if (
|
|
153
|
-
!wasSessionShutdownUnexpectedly &&
|
|
154
|
-
this.isCommandsQueueEnabled &&
|
|
155
|
-
cmd !== DELETE_SESSION_COMMAND
|
|
156
|
-
) {
|
|
148
|
+
if (!wasSessionShutdownUnexpectedly && this.isCommandsQueueEnabled && cmd !== DELETE_SESSION_COMMAND) {
|
|
157
149
|
// resetting existing timeout
|
|
158
150
|
await this.startNewCommandTimeout();
|
|
159
151
|
}
|
|
@@ -205,9 +197,7 @@ export class BaseDriver<
|
|
|
205
197
|
return cmd;
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
async startUnexpectedShutdown(
|
|
209
|
-
err: Error = new errors.NoSuchDriverError('The driver was unexpectedly shut down!'),
|
|
210
|
-
) {
|
|
200
|
+
async startUnexpectedShutdown(err: Error = new errors.NoSuchDriverError('The driver was unexpectedly shut down!')) {
|
|
211
201
|
this.eventEmitter.emit(ON_UNEXPECTED_SHUTDOWN_EVENT, err); // allow others to listen for this
|
|
212
202
|
this.shutdownUnexpectedly = true;
|
|
213
203
|
try {
|
|
@@ -227,10 +217,7 @@ export class BaseDriver<
|
|
|
227
217
|
if (!this.newCommandTimeoutMs) return; // eslint-disable-line curly
|
|
228
218
|
|
|
229
219
|
this.noCommandTimer = setTimeout(async () => {
|
|
230
|
-
this.log.warn(
|
|
231
|
-
`Shutting down because we waited ` +
|
|
232
|
-
`${this.newCommandTimeoutMs / 1000.0} seconds for a command`,
|
|
233
|
-
);
|
|
220
|
+
this.log.warn(`Shutting down because we waited ` + `${this.newCommandTimeoutMs / 1000.0} seconds for a command`);
|
|
234
221
|
const errorMessage =
|
|
235
222
|
`New Command Timeout of ` +
|
|
236
223
|
`${this.newCommandTimeoutMs / 1000.0} seconds ` +
|
|
@@ -277,7 +264,6 @@ export class BaseDriver<
|
|
|
277
264
|
}
|
|
278
265
|
|
|
279
266
|
/**
|
|
280
|
-
*
|
|
281
267
|
* Historically the first two arguments were reserved for JSONWP capabilities.
|
|
282
268
|
* Appium 2 has dropped the support of these, so now we only accept capability
|
|
283
269
|
* objects in W3C format and thus allow any of the three arguments to represent
|
|
@@ -291,16 +277,12 @@ export class BaseDriver<
|
|
|
291
277
|
driverData?: DriverData[],
|
|
292
278
|
): Promise<CreateResult> {
|
|
293
279
|
if (this.sessionId !== null) {
|
|
294
|
-
throw new errors.SessionNotCreatedError(
|
|
295
|
-
'Cannot create a new session while one is in progress',
|
|
296
|
-
);
|
|
280
|
+
throw new errors.SessionNotCreatedError('Cannot create a new session while one is in progress');
|
|
297
281
|
}
|
|
298
282
|
|
|
299
283
|
this.log.debug();
|
|
300
284
|
|
|
301
|
-
const originalCaps = structuredClone(
|
|
302
|
-
[w3cCapabilities, w3cCapabilities1, w3cCapabilities2].find(isW3cCaps),
|
|
303
|
-
);
|
|
285
|
+
const originalCaps = structuredClone([w3cCapabilities, w3cCapabilities1, w3cCapabilities2].find(isW3cCaps));
|
|
304
286
|
if (!originalCaps) {
|
|
305
287
|
throw new errors.SessionNotCreatedError(
|
|
306
288
|
'Appium only supports W3C-style capability objects. ' +
|
|
@@ -311,17 +293,11 @@ export class BaseDriver<
|
|
|
311
293
|
this.setProtocolW3C();
|
|
312
294
|
|
|
313
295
|
this.originalCaps = originalCaps;
|
|
314
|
-
this.log.debug(
|
|
315
|
-
`Creating session with W3C capabilities: ${JSON.stringify(originalCaps, null, 2)}`,
|
|
316
|
-
);
|
|
296
|
+
this.log.debug(`Creating session with W3C capabilities: ${JSON.stringify(originalCaps, null, 2)}`);
|
|
317
297
|
|
|
318
298
|
let caps: DriverCaps<C>;
|
|
319
299
|
try {
|
|
320
|
-
caps = processCapabilities(
|
|
321
|
-
originalCaps,
|
|
322
|
-
this._desiredCapConstraints,
|
|
323
|
-
this.shouldValidateCaps,
|
|
324
|
-
) as DriverCaps<C>;
|
|
300
|
+
caps = processCapabilities(originalCaps, this._desiredCapConstraints, this.shouldValidateCaps) as DriverCaps<C>;
|
|
325
301
|
caps = fixCaps(caps, this._desiredCapConstraints, this.log) as DriverCaps<C>;
|
|
326
302
|
} catch (e) {
|
|
327
303
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -334,7 +310,7 @@ export class BaseDriver<
|
|
|
334
310
|
this.sessionCreationTimestampMs = Date.now();
|
|
335
311
|
this.caps = caps;
|
|
336
312
|
// merge caps onto opts so we don't need to worry about what's where
|
|
337
|
-
this.opts = {...
|
|
313
|
+
this.opts = {...this.initialOpts, ...this.caps};
|
|
338
314
|
|
|
339
315
|
// deal with resets
|
|
340
316
|
// some people like to do weird things by setting noReset and fullReset
|
|
@@ -382,9 +358,10 @@ export class BaseDriver<
|
|
|
382
358
|
* Use {@linkcode EventCommands.getLogEvents} instead to get the event history.
|
|
383
359
|
*/
|
|
384
360
|
async getSession() {
|
|
385
|
-
return (
|
|
386
|
-
|
|
387
|
-
|
|
361
|
+
return (this.caps.eventTimings ? {...this.caps, events: this.eventHistory} : this.caps) as SingularSessionData<
|
|
362
|
+
C,
|
|
363
|
+
SessionData
|
|
364
|
+
>;
|
|
388
365
|
}
|
|
389
366
|
|
|
390
367
|
/**
|
|
@@ -432,8 +409,7 @@ export class BaseDriver<
|
|
|
432
409
|
const capError = e instanceof Error ? e : new Error(String(e));
|
|
433
410
|
throw this.log.errorWithException(
|
|
434
411
|
new errors.SessionNotCreatedError(
|
|
435
|
-
`Session capabilities were not valid for the ` +
|
|
436
|
-
`following reason(s): ${capError.message}`,
|
|
412
|
+
`Session capabilities were not valid for the ` + `following reason(s): ${capError.message}`,
|
|
437
413
|
capError,
|
|
438
414
|
),
|
|
439
415
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {logger, util} from '@appium/support';
|
|
2
1
|
import {EventEmitter} from 'node:events';
|
|
2
|
+
|
|
3
|
+
import {logger, util} from '@appium/support';
|
|
3
4
|
import type {
|
|
4
5
|
AppiumLogger,
|
|
5
6
|
BidiModuleMap,
|
|
@@ -9,6 +10,7 @@ import type {
|
|
|
9
10
|
IpcData,
|
|
10
11
|
StringRecord,
|
|
11
12
|
} from '@appium/types';
|
|
13
|
+
|
|
12
14
|
import {MAX_LOG_BODY_LENGTH} from '../constants';
|
|
13
15
|
import {errors} from '../protocol';
|
|
14
16
|
import {BIDI_COMMANDS} from '../protocol/bidi-commands';
|
|
@@ -43,9 +45,7 @@ export class ExtensionCore {
|
|
|
43
45
|
updateBidiCommands(cmds: BidiModuleMap): void {
|
|
44
46
|
const overlappingKeys = Object.keys(cmds).filter((key) => key in this.bidiCommands);
|
|
45
47
|
if (overlappingKeys.length) {
|
|
46
|
-
this.log.warn(
|
|
47
|
-
`Overwriting existing bidi modules: ${JSON.stringify(overlappingKeys)}. This may not be intended!`,
|
|
48
|
-
);
|
|
48
|
+
this.log.warn(`Overwriting existing bidi modules: ${JSON.stringify(overlappingKeys)}. This may not be intended!`);
|
|
49
49
|
}
|
|
50
50
|
this.bidiCommands = {
|
|
51
51
|
...this.bidiCommands,
|
|
@@ -107,9 +107,7 @@ export class ExtensionCore {
|
|
|
107
107
|
if (params?.required?.length) {
|
|
108
108
|
for (const requiredParam of params.required) {
|
|
109
109
|
if (bidiParams[requiredParam] === undefined) {
|
|
110
|
-
throw new errors.InvalidArgumentError(
|
|
111
|
-
`The ${requiredParam} parameter was required but you omitted it`,
|
|
112
|
-
);
|
|
110
|
+
throw new errors.InvalidArgumentError(`The ${requiredParam} parameter was required but you omitted it`);
|
|
113
111
|
}
|
|
114
112
|
args.push(bidiParams[requiredParam]);
|
|
115
113
|
}
|
|
@@ -127,15 +125,12 @@ export class ExtensionCore {
|
|
|
127
125
|
`method '${command}'`,
|
|
128
126
|
);
|
|
129
127
|
// call the handler with the signature appropriate to extension type (plugin or driver)
|
|
130
|
-
const commandHandler = (
|
|
131
|
-
this as unknown as Record<string, (...handlerArgs: any[]) => Promise<unknown>>
|
|
132
|
-
)[command];
|
|
128
|
+
const commandHandler = (this as unknown as Record<string, (...handlerArgs: any[]) => Promise<unknown>>)[command];
|
|
133
129
|
const response =
|
|
134
130
|
next && driver
|
|
135
131
|
? await commandHandler.call(this, next, driver, ...args)
|
|
136
132
|
: await commandHandler.call(this, ...args);
|
|
137
|
-
const finalResponse: BiDiResultData =
|
|
138
|
-
response === undefined ? {} : (response as BiDiResultData);
|
|
133
|
+
const finalResponse: BiDiResultData = response === undefined ? {} : (response as BiDiResultData);
|
|
139
134
|
this.log.debug(
|
|
140
135
|
`Responding to bidi command '${bidiCmd}' with ` +
|
|
141
136
|
`${util.truncateString(JSON.stringify(finalResponse), {length: MAX_LOG_BODY_LENGTH})}`,
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import nodeFs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
3
|
+
import type {Readable} from 'node:stream';
|
|
4
|
+
|
|
5
|
+
import {fs, node, tempDir, timing, util} from '@appium/support';
|
|
6
|
+
import type {CachedAppInfo, ConfigureAppOptions, DriverHelpers, HTTPHeaders, PostProcessOptions} from '@appium/types';
|
|
6
7
|
import AsyncLock from 'async-lock';
|
|
7
8
|
import axios from 'axios';
|
|
8
|
-
import type {
|
|
9
|
-
ConfigureAppOptions,
|
|
10
|
-
CachedAppInfo,
|
|
11
|
-
PostProcessOptions,
|
|
12
|
-
HTTPHeaders,
|
|
13
|
-
DriverHelpers,
|
|
14
|
-
} from '@appium/types';
|
|
15
9
|
import type {AxiosResponseHeaders, RawAxiosRequestHeaders} from 'axios';
|
|
16
|
-
import
|
|
10
|
+
import {LRUCache} from 'lru-cache';
|
|
17
11
|
import type {PackageJson} from 'type-fest';
|
|
18
12
|
|
|
13
|
+
import {log as logger} from './logger';
|
|
14
|
+
|
|
19
15
|
// for compat with running tests transpiled and in-place
|
|
20
16
|
export const BASEDRIVER_VER = readBaseDriverVersion();
|
|
21
17
|
|
|
@@ -31,10 +27,7 @@ const APPLICATIONS_CACHE = new LRUCache<string, CachedAppInfoEntry>({
|
|
|
31
27
|
ttl: CACHED_APPS_MAX_AGE_MS, // expire after 24 hours
|
|
32
28
|
updateAgeOnGet: true,
|
|
33
29
|
dispose: ({fullPath}, app) => {
|
|
34
|
-
logger.info(
|
|
35
|
-
`The application '${app}' cached at '${fullPath}' has ` +
|
|
36
|
-
`expired after ${CACHED_APPS_MAX_AGE_MS}ms`,
|
|
37
|
-
);
|
|
30
|
+
logger.info(`The application '${app}' cached at '${fullPath}' has ` + `expired after ${CACHED_APPS_MAX_AGE_MS}ms`);
|
|
38
31
|
if (fullPath) {
|
|
39
32
|
void fs.rimraf(fullPath);
|
|
40
33
|
}
|
|
@@ -52,9 +45,7 @@ process.on('exit', () => {
|
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
const appPaths = [...APPLICATIONS_CACHE.values()].map(({fullPath}) => fullPath);
|
|
55
|
-
logger.debug(
|
|
56
|
-
`Performing cleanup of ${util.pluralize('cached application', appPaths.length, true)}`,
|
|
57
|
-
);
|
|
48
|
+
logger.debug(`Performing cleanup of ${util.pluralize('cached application', appPaths.length, true)}`);
|
|
58
49
|
for (const appPath of appPaths) {
|
|
59
50
|
if (!appPath) {
|
|
60
51
|
continue;
|
|
@@ -285,8 +276,7 @@ export async function configureApp(
|
|
|
285
276
|
}
|
|
286
277
|
|
|
287
278
|
verifyAppExtension(newApp, supportedAppExtensions);
|
|
288
|
-
return appCacheKey !== toCacheKey(newApp) &&
|
|
289
|
-
(packageHash || Object.values(remoteAppProps).some(Boolean))
|
|
279
|
+
return appCacheKey !== toCacheKey(newApp) && (packageHash || Object.values(remoteAppProps).some(Boolean))
|
|
290
280
|
? await storeAppInCache(newApp)
|
|
291
281
|
: newApp;
|
|
292
282
|
});
|
|
@@ -386,9 +376,7 @@ export function generateDriverLogPrefix(obj: object | null, _sessionId?: string
|
|
|
386
376
|
|
|
387
377
|
// #region Private helpers
|
|
388
378
|
|
|
389
|
-
function parseAppLink(
|
|
390
|
-
appLink: string,
|
|
391
|
-
): URL | {protocol?: string; pathname?: string; href?: string; search?: string} {
|
|
379
|
+
function parseAppLink(appLink: string): URL | {protocol?: string; pathname?: string; href?: string; search?: string} {
|
|
392
380
|
try {
|
|
393
381
|
return new URL(appLink);
|
|
394
382
|
} catch {
|
|
@@ -438,10 +426,7 @@ function toCacheKey(app: string): string {
|
|
|
438
426
|
return app;
|
|
439
427
|
}
|
|
440
428
|
|
|
441
|
-
async function queryAppLink(
|
|
442
|
-
appLink: string,
|
|
443
|
-
reqHeaders: RawAxiosRequestHeaders,
|
|
444
|
-
): Promise<RemoteAppData> {
|
|
429
|
+
async function queryAppLink(appLink: string, reqHeaders: RawAxiosRequestHeaders): Promise<RemoteAppData> {
|
|
445
430
|
const url = new URL(appLink);
|
|
446
431
|
// Extract credentials, then remove them from the URL for axios
|
|
447
432
|
const {username, password} = url;
|
|
@@ -454,8 +439,7 @@ async function queryAppLink(
|
|
|
454
439
|
auth: axiosAuth,
|
|
455
440
|
responseType: 'stream' as const,
|
|
456
441
|
timeout: APP_DOWNLOAD_TIMEOUT_MS,
|
|
457
|
-
validateStatus: (status: number) =>
|
|
458
|
-
(status >= 200 && status < 300) || status === HTTP_STATUS_NOT_MODIFIED,
|
|
442
|
+
validateStatus: (status: number) => (status >= 200 && status < 300) || status === HTTP_STATUS_NOT_MODIFIED,
|
|
459
443
|
headers: reqHeaders,
|
|
460
444
|
};
|
|
461
445
|
try {
|
|
@@ -510,10 +494,7 @@ function determineFilename(
|
|
|
510
494
|
replacement: SANITIZE_REPLACEMENT,
|
|
511
495
|
});
|
|
512
496
|
const extname = path.extname(basename);
|
|
513
|
-
if (
|
|
514
|
-
headers['content-disposition'] &&
|
|
515
|
-
/^attachment/i.test(String(headers['content-disposition']))
|
|
516
|
-
) {
|
|
497
|
+
if (headers['content-disposition'] && /^attachment/i.test(String(headers['content-disposition']))) {
|
|
517
498
|
logger.debug(`Content-Disposition: ${headers['content-disposition']}`);
|
|
518
499
|
const match = /filename="([^"]+)/i.exec(String(headers['content-disposition']));
|
|
519
500
|
if (match) {
|
|
@@ -522,13 +503,9 @@ function determineFilename(
|
|
|
522
503
|
}
|
|
523
504
|
|
|
524
505
|
// assign the default file name and the extension if none has been detected
|
|
525
|
-
const resultingName = basename
|
|
526
|
-
? basename.substring(0, basename.length - extname.length)
|
|
527
|
-
: DEFAULT_BASENAME;
|
|
506
|
+
const resultingName = basename ? basename.substring(0, basename.length - extname.length) : DEFAULT_BASENAME;
|
|
528
507
|
let resultingExt = extname;
|
|
529
|
-
if (
|
|
530
|
-
!supportedAppExtensions.map((ext) => ext.toLowerCase()).includes(resultingExt.toLowerCase())
|
|
531
|
-
) {
|
|
508
|
+
if (!supportedAppExtensions.map((ext) => ext.toLowerCase()).includes(resultingExt.toLowerCase())) {
|
|
532
509
|
logger.info(
|
|
533
510
|
`The current file extension '${resultingExt}' is not supported. ` +
|
|
534
511
|
`Defaulting to '${supportedAppExtensions[0]}'`,
|
|
@@ -539,9 +516,7 @@ function determineFilename(
|
|
|
539
516
|
}
|
|
540
517
|
|
|
541
518
|
function verifyAppExtension(app: string, supportedAppExtensions: string[]): string {
|
|
542
|
-
if (
|
|
543
|
-
supportedAppExtensions.map((ext) => ext.toLowerCase()).includes(path.extname(app).toLowerCase())
|
|
544
|
-
) {
|
|
519
|
+
if (supportedAppExtensions.map((ext) => ext.toLowerCase()).includes(path.extname(app).toLowerCase())) {
|
|
545
520
|
return app;
|
|
546
521
|
}
|
|
547
522
|
throw new Error(
|
|
@@ -592,9 +567,7 @@ function readBaseDriverVersion(): string {
|
|
|
592
567
|
if (!pkgRoot) {
|
|
593
568
|
throw new Error('Cannot find the @appium/base-driver package root');
|
|
594
569
|
}
|
|
595
|
-
const pkg = JSON.parse(
|
|
596
|
-
nodeFs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8'),
|
|
597
|
-
) as PackageJson;
|
|
570
|
+
const pkg = JSON.parse(nodeFs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8')) as PackageJson;
|
|
598
571
|
if (typeof pkg.version !== 'string') {
|
|
599
572
|
throw new Error('Invalid `package.json` for @appium/base-driver');
|
|
600
573
|
}
|
package/lib/basedriver/ipc.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import EventEmitter from 'node:events';
|
|
2
|
+
|
|
3
|
+
import {node} from '@appium/support';
|
|
2
4
|
import type {
|
|
3
|
-
StringRecord,
|
|
4
|
-
IIpcSubscription,
|
|
5
|
-
IAppiumIpc,
|
|
6
|
-
IpcMessage,
|
|
7
|
-
IpcEvent,
|
|
8
5
|
AppiumLogger,
|
|
6
|
+
IAppiumIpc,
|
|
7
|
+
IIpcSubscription,
|
|
9
8
|
IpcData,
|
|
9
|
+
IpcEvent,
|
|
10
|
+
IpcMessage,
|
|
11
|
+
StringRecord,
|
|
10
12
|
} from '@appium/types';
|
|
11
|
-
import EventEmitter from 'node:events';
|
|
12
13
|
import {sleep} from 'asyncbox';
|
|
13
|
-
|
|
14
|
+
|
|
15
|
+
import {log} from './logger';
|
|
14
16
|
|
|
15
17
|
const DEF_MAX_OBJ_SIZE_BYTES = 1024 * 1024; // 1mb seems like plenty for any plugin to pass a message
|
|
16
18
|
const DEF_MAX_TOPICS = 1000;
|
|
@@ -26,10 +28,7 @@ export type AppiumIpcOpts = {
|
|
|
26
28
|
|
|
27
29
|
const ASYNC_ITERATOR_STOP = Symbol('asyncIteratorStop');
|
|
28
30
|
|
|
29
|
-
export class IpcSubscription<T extends IpcData>
|
|
30
|
-
extends EventEmitter<IpcEvent<T>>
|
|
31
|
-
implements IIpcSubscription<T>
|
|
32
|
-
{
|
|
31
|
+
export class IpcSubscription<T extends IpcData> extends EventEmitter<IpcEvent<T>> implements IIpcSubscription<T> {
|
|
33
32
|
constructor(
|
|
34
33
|
public readonly subscriber: string,
|
|
35
34
|
public readonly topic: string,
|
|
@@ -110,9 +109,7 @@ export class AppiumIpc implements IAppiumIpc {
|
|
|
110
109
|
subscribe<T extends IpcData>(topic: string, subscriber: string): IpcSubscription<T> {
|
|
111
110
|
this.log.info(`Subscribing ${subscriber} to topic '${topic}'`);
|
|
112
111
|
if (this.subscriptionExists(topic, subscriber)) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Subscription already exists for topic "${topic}" and subscriber "${subscriber}"`,
|
|
115
|
-
);
|
|
112
|
+
throw new Error(`Subscription already exists for topic "${topic}" and subscriber "${subscriber}"`);
|
|
116
113
|
}
|
|
117
114
|
|
|
118
115
|
this.ensureTopic(topic);
|
|
@@ -157,9 +154,7 @@ export class AppiumIpc implements IAppiumIpc {
|
|
|
157
154
|
|
|
158
155
|
this.messageByTopic[topic] = message;
|
|
159
156
|
|
|
160
|
-
const subs = this.subs[topic]
|
|
161
|
-
? this.subs[topic].filter((sub) => sub.subscriber !== publisher)
|
|
162
|
-
: [];
|
|
157
|
+
const subs = this.subs[topic] ? this.subs[topic].filter((sub) => sub.subscriber !== publisher) : [];
|
|
163
158
|
|
|
164
159
|
for (const sub of subs) {
|
|
165
160
|
sub.emit(EVT_MESSAGE, structuredClone(message));
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import type {Constraint} from '@appium/types';
|
|
2
1
|
import {util} from '@appium/support';
|
|
2
|
+
import type {Constraint} from '@appium/types';
|
|
3
|
+
|
|
3
4
|
import {log} from './logger';
|
|
4
5
|
|
|
5
6
|
export class Validator {
|
|
6
|
-
private readonly _validators: Record<
|
|
7
|
-
keyof Constraint,
|
|
8
|
-
(value: any, options?: any, key?: string) => string | null
|
|
9
|
-
> = {
|
|
7
|
+
private readonly _validators: Record<keyof Constraint, (value: any, options?: any, key?: string) => string | null> = {
|
|
10
8
|
isString: (value: any, options?: any): string | null => {
|
|
11
9
|
if (value === undefined || options == null) {
|
|
12
10
|
return null;
|
|
@@ -108,8 +106,7 @@ export class Validator {
|
|
|
108
106
|
}
|
|
109
107
|
if (
|
|
110
108
|
!options?.allowEmpty &&
|
|
111
|
-
((value !== undefined && util.isEmpty(value)) ||
|
|
112
|
-
(typeof value === 'string' && !value.trim()))
|
|
109
|
+
((value !== undefined && util.isEmpty(value)) || (typeof value === 'string' && !value.trim()))
|
|
113
110
|
) {
|
|
114
111
|
return 'must not be empty or blank';
|
|
115
112
|
}
|
|
@@ -117,10 +114,7 @@ export class Validator {
|
|
|
117
114
|
},
|
|
118
115
|
};
|
|
119
116
|
|
|
120
|
-
validate(
|
|
121
|
-
values: Record<string, any>,
|
|
122
|
-
constraints: Record<string, Constraint>,
|
|
123
|
-
): Record<string, string[]> | null {
|
|
117
|
+
validate(values: Record<string, any>, constraints: Record<string, Constraint>): Record<string, string[]> | null {
|
|
124
118
|
const result: Record<string, string[]> = {};
|
|
125
119
|
for (const [key, constraint] of Object.entries(constraints)) {
|
|
126
120
|
const value = values[key];
|
|
@@ -129,11 +123,7 @@ export class Validator {
|
|
|
129
123
|
continue;
|
|
130
124
|
}
|
|
131
125
|
|
|
132
|
-
const validationError = this._validators[validatorName as keyof Constraint](
|
|
133
|
-
value,
|
|
134
|
-
options,
|
|
135
|
-
key,
|
|
136
|
-
);
|
|
126
|
+
const validationError = this._validators[validatorName as keyof Constraint](value, options, key);
|
|
137
127
|
if (validationError == null) {
|
|
138
128
|
continue;
|
|
139
129
|
}
|