expect-webdriverio 7.0.0 → 8.0.0-alpha.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/README.md +7 -3
- package/jasmine-wdio-expect-async.d.ts +1 -1
- package/lib/constants.js +0 -6
- package/lib/index.js +1 -13
- package/lib/jasmineUtils.js +2 -2
- package/lib/matchers/asymmetrics/oneOf.js +2 -2
- package/lib/matchers/browser/toHaveClipboardText.js +7 -3
- package/lib/matchers/browser/toHaveLocalStorageItem.js +1 -11
- package/lib/matchers/element/toBeClickable.js +3 -2
- package/lib/matchers/element/toBeDisabled.js +3 -2
- package/lib/matchers/element/toBeDisplayed.js +3 -2
- package/lib/matchers/element/toBeDisplayedInViewport.js +3 -2
- package/lib/matchers/element/toBeEnabled.js +3 -2
- package/lib/matchers/element/toBeExisting.js +5 -2
- package/lib/matchers/element/toBeFocused.js +3 -2
- package/lib/matchers/element/toBeSelected.js +4 -4
- package/lib/matchers/element/toHaveAttribute.js +2 -14
- package/lib/matchers/element/toHaveChildren.js +7 -13
- package/lib/matchers/element/toHaveComputedLabel.js +0 -2
- package/lib/matchers/element/toHaveComputedRole.js +0 -2
- package/lib/matchers/element/toHaveElementClass.js +3 -8
- package/lib/matchers/element/toHaveElementProperty.js +0 -5
- package/lib/matchers/element/toHaveHTML.js +3 -5
- package/lib/matchers/element/toHaveHeight.js +4 -5
- package/lib/matchers/element/toHaveHref.js +6 -3
- package/lib/matchers/element/toHaveId.js +3 -2
- package/lib/matchers/element/toHaveSize.js +0 -1
- package/lib/matchers/element/toHaveStyle.js +0 -1
- package/lib/matchers/element/toHaveText.js +2 -5
- package/lib/matchers/element/toHaveValue.js +1 -1
- package/lib/matchers/element/toHaveWidth.js +4 -5
- package/lib/matchers/elements/toBeElementsArrayOfSize.js +9 -11
- package/lib/matchers/mock/toBeRequested.js +1 -1
- package/lib/matchers/mock/toBeRequestedTimes.js +6 -6
- package/lib/matchers/mock/toBeRequestedWith.js +0 -3
- package/lib/matchers.js +32 -32
- package/lib/snapshot.js +1 -8
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/util/elementsUtil.js +3 -2
- package/lib/util/executeBrowserCommand.js +2 -2
- package/lib/util/executeCommand.js +2 -41
- package/lib/util/formatMessage.js +4 -4
- package/lib/util/multiRemoteUtils.js +9 -1
- package/lib/util/numberOptionsUtil.js +15 -26
- package/lib/utils.js +10 -110
- package/package.json +36 -39
- package/types/expect-global.d.ts +1 -2
- package/types/expect-webdriverio.d.ts +31 -222
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# expect-webdriverio [](https://github.com/webdriverio/expect-webdriverio/actions/workflows/test.yml)
|
|
2
2
|
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> This branch is v8, in development for WebdriverIO v10. Its docs are not released yet.
|
|
5
|
+
> For the latest release (v7, WebdriverIO v9), see the [v7 README](https://github.com/webdriverio/expect-webdriverio/blob/v7/README.md).
|
|
6
|
+
|
|
3
7
|
###### [API](docs/API.md) | [Multiple Elements](docs/MultipleElements.md) | [Multi-remote](docs/MultiRemote.md) | [TypeScript / JS Autocomplete](docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](docs/CustomMatchers.md)
|
|
4
8
|
|
|
5
9
|
> [WebdriverIO](https://webdriver.io/) assertion library inspired by [expect](https://www.npmjs.com/package/expect)
|
|
@@ -31,7 +35,7 @@
|
|
|
31
35
|
If you run your tests through the [WDIO testrunner](https://webdriver.io/docs/clioptions), no additional setup is needed. WebdriverIO initializes `expect-webdriverio` and makes `expect` available in the global scope so you can use it directly in your tests:
|
|
32
36
|
|
|
33
37
|
```js
|
|
34
|
-
await expect($('
|
|
38
|
+
await expect($('#submit')).toBeDisplayed()
|
|
35
39
|
await expect($$('buttons')).toBeDisplayed()
|
|
36
40
|
```
|
|
37
41
|
|
|
@@ -46,7 +50,7 @@ await expect(multiRemoteBrowser).toHaveTitle('WebdriverIO')
|
|
|
46
50
|
await expect(multiRemoteBrowser.$('h1')).toHaveText(expect.multiRemote({ chrome: 'Welcome', firefox: 'Bienvenue' }))
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
Some
|
|
53
|
+
Some WebdriverIO environment variables are recommended, see [Multi-remote Support](docs/MultiRemote.md#requirements--configuration).
|
|
50
54
|
|
|
51
55
|
#### Local & Browser Runners
|
|
52
56
|
- **Local Runner**: Fully compatible. You can leverage your test framework adapter as mentioned above.
|
|
@@ -69,7 +73,7 @@ import { expect } from 'expect-webdriverio'
|
|
|
69
73
|
|
|
70
74
|
await browser.url('https://webdriver.io')
|
|
71
75
|
|
|
72
|
-
const $button = await browser.$('
|
|
76
|
+
const $button = await browser.$('.DocSearch-Button')
|
|
73
77
|
await expect($button).toBeDisplayed()
|
|
74
78
|
|
|
75
79
|
await browser.deleteSession()
|
|
@@ -80,7 +80,7 @@ declare namespace ExpectWebdriverIO {
|
|
|
80
80
|
* Under `@wdio/jasmine-framework`, the global `expect` is overridden to use Jasmine's `expectAsync`.
|
|
81
81
|
* It contains custom WebdriverIO matchers as well as Jasmine's built-in async & sync matchers but not the basic Jest's expect library matchers.
|
|
82
82
|
*/
|
|
83
|
-
// @ts-expect-error:
|
|
83
|
+
// @ts-expect-error: the Jasmine `expect` is always loaded with this entry, so the two declarations conflict
|
|
84
84
|
declare const expect: ExpectWebdriverIO.JasmineExpect
|
|
85
85
|
declare namespace NodeJS {
|
|
86
86
|
interface Global {
|
package/lib/constants.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { getGlobalSingleton } from './util/globalSingleton.js';
|
|
2
2
|
function createSharedConstants() {
|
|
3
|
-
const DEFAULT_FEATURE_FLAGS = {
|
|
4
|
-
useToHaveTextStrictMultiElementsCompareStrategy: false
|
|
5
|
-
};
|
|
6
3
|
const DEFAULT_OPTIONS = {
|
|
7
4
|
wait: 2000,
|
|
8
5
|
interval: 100,
|
|
9
6
|
beforeAssertion: async () => { },
|
|
10
7
|
afterAssertion: async () => { },
|
|
11
|
-
featureFlags: DEFAULT_FEATURE_FLAGS
|
|
12
8
|
};
|
|
13
9
|
const DEFAULT_OPTIONS_TO_BE_DISPLAYED = {
|
|
14
10
|
...DEFAULT_OPTIONS,
|
|
@@ -18,14 +14,12 @@ function createSharedConstants() {
|
|
|
18
14
|
visibilityProperty: true
|
|
19
15
|
};
|
|
20
16
|
return {
|
|
21
|
-
DEFAULT_FEATURE_FLAGS,
|
|
22
17
|
DEFAULT_OPTIONS,
|
|
23
18
|
DEFAULT_OPTIONS_TO_BE_DISPLAYED,
|
|
24
19
|
defaultOptionsList: [DEFAULT_OPTIONS, DEFAULT_OPTIONS_TO_BE_DISPLAYED]
|
|
25
20
|
};
|
|
26
21
|
}
|
|
27
22
|
const shared = getGlobalSingleton('constants', createSharedConstants);
|
|
28
|
-
export const DEFAULT_FEATURE_FLAGS = shared.DEFAULT_FEATURE_FLAGS;
|
|
29
23
|
export const DEFAULT_OPTIONS = shared.DEFAULT_OPTIONS;
|
|
30
24
|
export const DEFAULT_OPTIONS_TO_BE_DISPLAYED = shared.DEFAULT_OPTIONS_TO_BE_DISPLAYED;
|
|
31
25
|
export const defaultOptionsList = shared.defaultOptionsList;
|
package/lib/index.js
CHANGED
|
@@ -8,7 +8,6 @@ import { multiRemote } from './matchers/asymmetrics/multiRemote.js';
|
|
|
8
8
|
import { getGlobalSingleton } from './util/globalSingleton.js';
|
|
9
9
|
function createSharedExpectSetup() {
|
|
10
10
|
const wdioCustomMatchers = {};
|
|
11
|
-
const matchers = new Map();
|
|
12
11
|
const extend = expectLib.extend;
|
|
13
12
|
expectLib.extend = (extendedMatchers) => {
|
|
14
13
|
if (!extendedMatchers || typeof extendedMatchers !== 'object') {
|
|
@@ -16,7 +15,6 @@ function createSharedExpectSetup() {
|
|
|
16
15
|
}
|
|
17
16
|
Object.entries(extendedMatchers).forEach(([name, matcher]) => {
|
|
18
17
|
wdioCustomMatchers[name] = matcher;
|
|
19
|
-
matchers.set(name, matcher);
|
|
20
18
|
});
|
|
21
19
|
return extend(extendedMatchers);
|
|
22
20
|
};
|
|
@@ -46,11 +44,10 @@ function createSharedExpectSetup() {
|
|
|
46
44
|
configurable: true,
|
|
47
45
|
value: (testId) => SoftAssertService.getInstance().clearFailures(testId)
|
|
48
46
|
});
|
|
49
|
-
return { wdioExpect, wdioCustomMatchers
|
|
47
|
+
return { wdioExpect, wdioCustomMatchers };
|
|
50
48
|
}
|
|
51
49
|
const sharedExpectSetup = getGlobalSingleton('expect', createSharedExpectSetup);
|
|
52
50
|
export const wdioCustomMatchers = sharedExpectSetup.wdioCustomMatchers;
|
|
53
|
-
export const matchers = sharedExpectSetup.matchers;
|
|
54
51
|
export const expect = sharedExpectSetup.wdioExpect;
|
|
55
52
|
export const getDefaultOptions = () => DEFAULT_OPTIONS;
|
|
56
53
|
export const setDefaultOptions = (options) => {
|
|
@@ -62,15 +59,6 @@ export const setDefaultOptions = (options) => {
|
|
|
62
59
|
});
|
|
63
60
|
});
|
|
64
61
|
};
|
|
65
|
-
export const setFeatureFlags = (featureFlags) => {
|
|
66
|
-
Object.entries(featureFlags).forEach(([ffName, ffValue]) => {
|
|
67
|
-
defaultOptionsList.forEach((option) => {
|
|
68
|
-
option.featureFlags[ffName] = ffValue;
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
export const setOptions = setDefaultOptions;
|
|
73
|
-
export const getConfig = getDefaultOptions;
|
|
74
62
|
export { SnapshotService } from './snapshot.js';
|
|
75
63
|
export { SoftAssertService } from './softAssert.js';
|
|
76
64
|
export { SoftAssertionService } from './softAssertService.js';
|
package/lib/jasmineUtils.js
CHANGED
|
@@ -11,10 +11,10 @@ function asymmetricMatch(a, b) {
|
|
|
11
11
|
if (asymmetricA && asymmetricB) {
|
|
12
12
|
return undefined;
|
|
13
13
|
}
|
|
14
|
-
const matchersUtil = {
|
|
14
|
+
const matchersUtil = Object.assign([], {
|
|
15
15
|
equals,
|
|
16
16
|
contains: (actual, expected) => actual.some(value => equals(value, expected)),
|
|
17
|
-
};
|
|
17
|
+
});
|
|
18
18
|
if (asymmetricA) {
|
|
19
19
|
return a.asymmetricMatch(b, matchersUtil);
|
|
20
20
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compareText } from '../../utils.js';
|
|
2
2
|
import { WdioAsymmetricMatchers } from './asymmetricsUtils.js';
|
|
3
3
|
const ONE_OF_TAG = 'expect-webdriverio.oneOf';
|
|
4
4
|
const ONE_OF_SYMBOL = Symbol.for(ONE_OF_TAG);
|
|
@@ -19,7 +19,7 @@ export class OneOfMatcher extends WdioAsymmetricMatchers {
|
|
|
19
19
|
else if (typeof actual !== 'string') {
|
|
20
20
|
return false;
|
|
21
21
|
}
|
|
22
|
-
return
|
|
22
|
+
return this.sample.some((expected) => expected !== null && compareText(actual, expected, this.options).success);
|
|
23
23
|
}
|
|
24
24
|
withOptions(options) {
|
|
25
25
|
return new OneOfMatcher(...this.sample).setOptions(options);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import logger from '@wdio/logger';
|
|
2
1
|
import { waitUntil, enhanceError, compareTextOrOneOf } from '../../utils.js';
|
|
3
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
4
3
|
import { executeBrowserCommand } from '../../util/executeBrowserCommand.js';
|
|
5
4
|
import { buildWdioAsymmetricMatchersWithOptions } from '../asymmetrics/asymmetricsUtils.js';
|
|
6
|
-
|
|
5
|
+
let permissionWarningLogged = false;
|
|
7
6
|
export async function toHaveClipboardText(browser, expectedValue, options = DEFAULT_OPTIONS) {
|
|
8
7
|
const { expectation = 'clipboard text', verb = 'have', isNot, matcherName = 'toHaveClipboardText' } = this;
|
|
9
8
|
await options.beforeAssertion?.({
|
|
@@ -35,7 +34,12 @@ export async function toHaveClipboardText(browser, expectedValue, options = DEFA
|
|
|
35
34
|
}
|
|
36
35
|
const compareClipboardText = async (browser, expectedValue, options) => {
|
|
37
36
|
await browser.setPermissions({ name: 'clipboard-read' }, 'granted')
|
|
38
|
-
.catch((err) =>
|
|
37
|
+
.catch((err) => {
|
|
38
|
+
if (!permissionWarningLogged) {
|
|
39
|
+
permissionWarningLogged = true;
|
|
40
|
+
console.warn(`expect-webdriverio: Couldn't set clipboard permissions: ${err}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
39
43
|
const actual = await browser.execute(() => window.navigator.clipboard.readText());
|
|
40
44
|
return compareTextOrOneOf(actual, expectedValue, options);
|
|
41
45
|
};
|
|
@@ -10,17 +10,7 @@ export async function toHaveLocalStorageItem(browser, key, expectedValue, option
|
|
|
10
10
|
expectedValue: expectedValue ? [key, expectedValue] : key,
|
|
11
11
|
options,
|
|
12
12
|
});
|
|
13
|
-
const
|
|
14
|
-
let expected;
|
|
15
|
-
if (expectedValue === undefined) {
|
|
16
|
-
if (paramsCount > 2) {
|
|
17
|
-
console.warn('[DEPRECATION] Using toHaveLocalStorageItem with undefined is deprecated in favor of expect.anything().');
|
|
18
|
-
}
|
|
19
|
-
expected = expect.anything();
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
expected = expectedValue;
|
|
23
|
-
}
|
|
13
|
+
const expected = expectedValue ?? expect.anything();
|
|
24
14
|
const expectedWithOptions = buildWdioAsymmetricMatchersWithOptions(expected, options);
|
|
25
15
|
const { actual, success: pass, subject, expected: expectedValues } = await waitUntil(async () => {
|
|
26
16
|
return await executeBrowserCommand({
|
|
@@ -2,13 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeClickable(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'clickable';
|
|
5
|
+
const { matcherName = 'toBeClickable' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await executeCommandBe.call(this, received, el => el?.isClickable(), options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
options,
|
|
13
14
|
result
|
|
14
15
|
});
|
|
@@ -2,13 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeDisabled(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'disabled';
|
|
5
|
+
const { matcherName = 'toBeDisabled' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await executeCommandBe.call(this, received, async (el) => !await el.isEnabled(), options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
options,
|
|
13
14
|
result
|
|
14
15
|
});
|
|
@@ -2,8 +2,9 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS_TO_BE_DISPLAYED } from '../../constants.js';
|
|
3
3
|
export async function toBeDisplayed(received, options = DEFAULT_OPTIONS_TO_BE_DISPLAYED) {
|
|
4
4
|
this.expectation = this.expectation || 'displayed';
|
|
5
|
+
const { matcherName = 'toBeDisplayed' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const { withinViewport, contentVisibilityAuto, opacityProperty, visibilityProperty, ...commandOptions } = { ...DEFAULT_OPTIONS_TO_BE_DISPLAYED, ...options };
|
|
@@ -14,7 +15,7 @@ export async function toBeDisplayed(received, options = DEFAULT_OPTIONS_TO_BE_DI
|
|
|
14
15
|
visibilityProperty
|
|
15
16
|
}), commandOptions);
|
|
16
17
|
await options.afterAssertion?.({
|
|
17
|
-
matcherName
|
|
18
|
+
matcherName,
|
|
18
19
|
options,
|
|
19
20
|
result
|
|
20
21
|
});
|
|
@@ -2,13 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeDisplayedInViewport(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'displayed in viewport';
|
|
5
|
+
const { matcherName = 'toBeDisplayedInViewport' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await executeCommandBe.call(this, received, el => el?.isDisplayed({ withinViewport: true }), options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
options,
|
|
13
14
|
result
|
|
14
15
|
});
|
|
@@ -2,13 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeEnabled(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'enabled';
|
|
5
|
+
const { matcherName = 'toBeEnabled' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await executeCommandBe.call(this, received, el => el?.isEnabled(), options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
options,
|
|
13
14
|
result
|
|
14
15
|
});
|
|
@@ -4,13 +4,14 @@ export async function toExist(received, options = DEFAULT_OPTIONS) {
|
|
|
4
4
|
this.expectation = this.expectation || 'exist';
|
|
5
5
|
this.verb = this.verb || '';
|
|
6
6
|
this.allowEmptyElements = true;
|
|
7
|
+
const { matcherName = 'toExist' } = this;
|
|
7
8
|
await options.beforeAssertion?.({
|
|
8
|
-
matcherName
|
|
9
|
+
matcherName,
|
|
9
10
|
options,
|
|
10
11
|
});
|
|
11
12
|
const result = await executeCommandBe.call(this, received, el => el?.isExisting(), options);
|
|
12
13
|
await options.afterAssertion?.({
|
|
13
|
-
matcherName
|
|
14
|
+
matcherName,
|
|
14
15
|
options,
|
|
15
16
|
result
|
|
16
17
|
});
|
|
@@ -19,10 +20,12 @@ export async function toExist(received, options = DEFAULT_OPTIONS) {
|
|
|
19
20
|
export function toBeExisting(el, options) {
|
|
20
21
|
this.expectation = 'existing';
|
|
21
22
|
this.verb = 'be';
|
|
23
|
+
this.matcherName ??= 'toBeExisting';
|
|
22
24
|
return toExist.call(this, el, options);
|
|
23
25
|
}
|
|
24
26
|
export function toBePresent(el, options) {
|
|
25
27
|
this.expectation = 'present';
|
|
26
28
|
this.verb = 'be';
|
|
29
|
+
this.matcherName ??= 'toBePresent';
|
|
27
30
|
return toExist.call(this, el, options);
|
|
28
31
|
}
|
|
@@ -2,13 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeFocused(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'focused';
|
|
5
|
+
const { matcherName = 'toBeFocused' } = this;
|
|
5
6
|
await options.beforeAssertion?.({
|
|
6
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await executeCommandBe.call(this, received, el => el?.isFocused(), options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
options,
|
|
13
14
|
result
|
|
14
15
|
});
|
|
@@ -2,14 +2,14 @@ import { executeCommandBe } from '../../utils.js';
|
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toBeSelected(received, options = DEFAULT_OPTIONS) {
|
|
4
4
|
this.expectation = this.expectation || 'selected';
|
|
5
|
-
|
|
5
|
+
const { matcherName = 'toBeSelected' } = this;
|
|
6
6
|
await options.beforeAssertion?.({
|
|
7
|
-
matcherName
|
|
7
|
+
matcherName,
|
|
8
8
|
options,
|
|
9
9
|
});
|
|
10
10
|
const result = await executeCommandBe.call(this, received, el => el?.isSelected(), options);
|
|
11
11
|
await options.afterAssertion?.({
|
|
12
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
13
13
|
options,
|
|
14
14
|
result
|
|
15
15
|
});
|
|
@@ -17,7 +17,7 @@ export async function toBeSelected(received, options = DEFAULT_OPTIONS) {
|
|
|
17
17
|
}
|
|
18
18
|
export async function toBeChecked(received, options = DEFAULT_OPTIONS) {
|
|
19
19
|
this.expectation = 'checked';
|
|
20
|
-
this.matcherName
|
|
20
|
+
this.matcherName ??= 'toBeChecked';
|
|
21
21
|
const result = await toBeSelected.call(this, received, options);
|
|
22
22
|
return result;
|
|
23
23
|
}
|
|
@@ -29,7 +29,6 @@ export async function toHaveAttributeAndValue(received, attribute, expectedValue
|
|
|
29
29
|
return conditionAttributeValueMatchWithExpected(element, attribute, values, options);
|
|
30
30
|
},
|
|
31
31
|
context: { isNot, iteration },
|
|
32
|
-
strategy: 'NewStrictMultipleElements',
|
|
33
32
|
});
|
|
34
33
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
35
34
|
const expected = expectedValues ?? wrapExpectedWithArray(el, attr, expectedValue);
|
|
@@ -40,23 +39,13 @@ export async function toHaveAttributeAndValue(received, attribute, expectedValue
|
|
|
40
39
|
};
|
|
41
40
|
}
|
|
42
41
|
export async function toHaveAttribute(received, attribute, value, options = DEFAULT_OPTIONS) {
|
|
43
|
-
const matcherName = 'toHaveAttribute';
|
|
44
|
-
const paramsCount = arguments.length;
|
|
42
|
+
const { matcherName = 'toHaveAttribute' } = this;
|
|
45
43
|
await options.beforeAssertion?.({
|
|
46
44
|
matcherName,
|
|
47
45
|
expectedValue: [attribute, value],
|
|
48
46
|
options,
|
|
49
47
|
});
|
|
50
|
-
|
|
51
|
-
if (value === undefined) {
|
|
52
|
-
if (paramsCount > 2) {
|
|
53
|
-
console.warn('Using undefined or null as value for toHaveAttribute is deprecated and will be removed in v6.0.0. Please omit the third argument entirely or use toHaveAttribute(el, attribute, wdioExpect.anything(), options).');
|
|
54
|
-
}
|
|
55
|
-
expectedValue = expect.anything();
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
expectedValue = value;
|
|
59
|
-
}
|
|
48
|
+
const expectedValue = value ?? expect.anything();
|
|
60
49
|
const result = await toHaveAttributeAndValue.call(this, received, attribute, expectedValue, options);
|
|
61
50
|
await options.afterAssertion?.({
|
|
62
51
|
matcherName,
|
|
@@ -66,4 +55,3 @@ export async function toHaveAttribute(received, attribute, value, options = DEFA
|
|
|
66
55
|
});
|
|
67
56
|
return result;
|
|
68
57
|
}
|
|
69
|
-
export const toHaveAttr = toHaveAttribute;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
2
2
|
import { executeCommandWithStrategy } from '../../util/executeCommand.js';
|
|
3
|
-
import {
|
|
4
|
-
import { isMultiRemoteMatcher } from '../../util/multiRemoteUtils.js';
|
|
3
|
+
import { validateNumberMatcherArray } from '../../util/numberOptionsUtil.js';
|
|
5
4
|
import { enhanceError, waitUntil, wrapExpectedWithArray } from '../../utils.js';
|
|
6
5
|
async function condition(el, expectedValue) {
|
|
7
6
|
const children = await el.$$('./*').getElements();
|
|
@@ -13,36 +12,31 @@ async function condition(el, expectedValue) {
|
|
|
13
12
|
actual: children?.length
|
|
14
13
|
};
|
|
15
14
|
}
|
|
16
|
-
export async function toHaveChildren(received,
|
|
15
|
+
export async function toHaveChildren(received, expectedValue, options = DEFAULT_OPTIONS) {
|
|
17
16
|
const { expectation = 'children', verb = 'have', isNot, matcherName = 'toHaveChildren' } = this;
|
|
18
|
-
const paramsCount = arguments.length;
|
|
19
|
-
if (paramsCount > 1 && (expectedValueOrOptions === undefined || (isEmptyOrLegacyNumberOptions(expectedValueOrOptions) && !isMultiRemoteMatcher(expectedValueOrOptions)))) {
|
|
20
|
-
console.warn('Passing undefined or NumberOptions as the second argument to toHaveChildren is deprecated. Use a NumberMatcher instead. For example, `expect(el).toHaveChildren({ gte: 1 }, options)`');
|
|
21
|
-
}
|
|
22
17
|
await options.beforeAssertion?.({
|
|
23
18
|
matcherName,
|
|
24
|
-
expectedValue
|
|
19
|
+
expectedValue,
|
|
25
20
|
options,
|
|
26
21
|
});
|
|
27
|
-
const
|
|
22
|
+
const expectedNumber = validateNumberMatcherArray(expectedValue, { supportDefaultAsGteThen1: true });
|
|
28
23
|
const { success: pass, actual: children, subject, context: { isSome } = {}, expected } = await waitUntil(async (iteration) => {
|
|
29
24
|
return await executeCommandWithStrategy({
|
|
30
25
|
unresolvedElements: received,
|
|
31
26
|
expectedValues: expectedNumber,
|
|
32
27
|
singleElementCompare: (element, expectedValue) => condition(element, expectedValue),
|
|
33
28
|
context: { isNot, iteration },
|
|
34
|
-
strategy: 'NewStrictMultipleElements',
|
|
35
29
|
});
|
|
36
|
-
}, isNot, { wait:
|
|
30
|
+
}, isNot, { wait: options.wait, interval: options.interval });
|
|
37
31
|
const expectedArray = expected ?? wrapExpectedWithArray(subject, children, expectedNumber);
|
|
38
|
-
const message = enhanceError(subject, expectedArray, children, { isNot, isSome }, verb, expectation, '',
|
|
32
|
+
const message = enhanceError(subject, expectedArray, children, { isNot, isSome }, verb, expectation, '', options);
|
|
39
33
|
const result = {
|
|
40
34
|
pass,
|
|
41
35
|
message: () => message
|
|
42
36
|
};
|
|
43
37
|
await options.afterAssertion?.({
|
|
44
38
|
matcherName,
|
|
45
|
-
expectedValue
|
|
39
|
+
expectedValue,
|
|
46
40
|
options,
|
|
47
41
|
result
|
|
48
42
|
});
|
|
@@ -21,8 +21,6 @@ export async function toHaveComputedLabel(received, expectedValue, options = DEF
|
|
|
21
21
|
expectedValues: expectedValue,
|
|
22
22
|
singleElementCompare: (element, expectedValue) => singleElementCompare(element, expectedValue, options),
|
|
23
23
|
context: { isNot, iteration },
|
|
24
|
-
strategy: 'NewStrictMultipleElements',
|
|
25
|
-
strictConfiguration: { allowArrayWithSingleElement: true }
|
|
26
24
|
});
|
|
27
25
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
28
26
|
const message = enhanceError(el, expected ?? wrapExpectedWithArray(el, actualLabel, expectedValue), actualLabel, { isNot, isSome }, verb, expectation, '', options);
|
|
@@ -21,8 +21,6 @@ export async function toHaveComputedRole(received, expectedValue, options = DEFA
|
|
|
21
21
|
expectedValues: expectedValue,
|
|
22
22
|
singleElementCompare: (element, expectedValue) => singleElementCompare(element, expectedValue, options),
|
|
23
23
|
context: { isNot, iteration },
|
|
24
|
-
strategy: 'NewStrictMultipleElements',
|
|
25
|
-
strictConfiguration: { allowArrayWithSingleElement: true }
|
|
26
24
|
});
|
|
27
25
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
28
26
|
const message = enhanceError(el, expected ?? wrapExpectedWithArray(el, actualRole, expectedValue), actualRole, { isNot, isSome }, verb, expectation, '', options);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
2
2
|
import { executeCommandWithStrategy } from '../../util/executeCommand.js';
|
|
3
|
-
import { compareText,
|
|
3
|
+
import { compareText, enhanceError, isAsymmetricMatcher, waitUntil, wrapExpectedWithArray } from '../../utils.js';
|
|
4
4
|
async function singleElementCompare(el, attribute, value, options) {
|
|
5
5
|
const actualClass = await el.getAttribute(attribute);
|
|
6
6
|
if (value === undefined) {
|
|
@@ -13,17 +13,13 @@ async function singleElementCompare(el, attribute, value, options) {
|
|
|
13
13
|
return compareText(actualClass, value, options);
|
|
14
14
|
}
|
|
15
15
|
const classes = actualClass.split(' ');
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
});
|
|
16
|
+
const values = Array.isArray(value) ? value : [value];
|
|
17
|
+
const isValueInClasses = classes.some((clazz) => values.some((expected) => compareText(clazz, expected, options).success));
|
|
19
18
|
return {
|
|
20
19
|
success: isValueInClasses,
|
|
21
20
|
actual: actualClass
|
|
22
21
|
};
|
|
23
22
|
}
|
|
24
|
-
export function toHaveClass(...args) {
|
|
25
|
-
return toHaveElementClass.call(this || {}, ...args);
|
|
26
|
-
}
|
|
27
23
|
export async function toHaveElementClass(received, expectedValue, options = DEFAULT_OPTIONS) {
|
|
28
24
|
const { expectation = 'class', verb = 'have', isNot, matcherName = 'toHaveElementClass' } = this;
|
|
29
25
|
await options.beforeAssertion?.({
|
|
@@ -39,7 +35,6 @@ export async function toHaveElementClass(received, expectedValue, options = DEFA
|
|
|
39
35
|
expectedValues: expectedValue,
|
|
40
36
|
singleElementCompare: (element, expectedValue) => singleElementCompare(element, attribute, expectedValue, options),
|
|
41
37
|
context: { isNot, iteration },
|
|
42
|
-
strategy: 'NewStrictMultipleElements',
|
|
43
38
|
strictConfiguration: { allowArrayWithSingleElement: true }
|
|
44
39
|
});
|
|
45
40
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
@@ -21,11 +21,7 @@ async function condition(el, property, expectedValue, options = DEFAULT_OPTIONS)
|
|
|
21
21
|
}
|
|
22
22
|
export async function toHaveElementProperty(received, property, value, options = DEFAULT_OPTIONS) {
|
|
23
23
|
const { expectation = 'property', verb = 'have', isNot, matcherName = 'toHaveElementProperty', allowObjectExpectedValue = true } = this;
|
|
24
|
-
const paramsCount = arguments.length;
|
|
25
24
|
if (value === undefined || value === null) {
|
|
26
|
-
if (paramsCount > 2) {
|
|
27
|
-
console.warn('Using undefined or null as value for toHaveElementProperty is deprecated and will be removed in v6.0.0. Please omit the third argument entirely or use toHaveElementProperty(el, property, object.anything(), options).');
|
|
28
|
-
}
|
|
29
25
|
value = expect.anything();
|
|
30
26
|
}
|
|
31
27
|
await options.beforeAssertion?.({
|
|
@@ -43,7 +39,6 @@ export async function toHaveElementProperty(received, property, value, options =
|
|
|
43
39
|
return condition(element, property, expectedValue, options);
|
|
44
40
|
},
|
|
45
41
|
context: { isNot, iteration },
|
|
46
|
-
strategy: 'NewStrictMultipleElements',
|
|
47
42
|
strictConfiguration: { allowArrayWithSingleElement: false, allowObjectExpectedValue }
|
|
48
43
|
});
|
|
49
44
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
@@ -8,25 +8,23 @@ async function singleElementCompare(el, html, options) {
|
|
|
8
8
|
}
|
|
9
9
|
export async function toHaveHTML(received, expectedValue, options = DEFAULT_OPTIONS) {
|
|
10
10
|
const { expectation = 'HTML', verb = 'have', isNot, matcherName = 'toHaveHTML' } = this;
|
|
11
|
-
expectedValue = buildWdioAsymmetricMatchersWithOptions(expectedValue, options);
|
|
12
11
|
await options.beforeAssertion?.({
|
|
13
12
|
matcherName,
|
|
14
13
|
expectedValue,
|
|
15
14
|
options,
|
|
16
15
|
});
|
|
16
|
+
const expectedWithOptions = buildWdioAsymmetricMatchersWithOptions(expectedValue, options);
|
|
17
17
|
const { success: pass, actual: actualHTML, subject: elements, context: { isSome } = {}, expected } = await waitUntil(async (iteration) => {
|
|
18
18
|
const result = await executeCommandWithStrategy({
|
|
19
19
|
unresolvedElements: received,
|
|
20
20
|
supportsArrayContaining: true,
|
|
21
|
-
expectedValues:
|
|
21
|
+
expectedValues: expectedWithOptions,
|
|
22
22
|
singleElementCompare: (element, expectedValue) => singleElementCompare(element, expectedValue, options),
|
|
23
23
|
context: { isNot, iteration },
|
|
24
|
-
strategy: 'NewStrictMultipleElements',
|
|
25
|
-
strictConfiguration: { allowArrayWithSingleElement: true }
|
|
26
24
|
});
|
|
27
25
|
return result;
|
|
28
26
|
}, isNot, { wait: options.wait, interval: options.interval });
|
|
29
|
-
const expectedValues = expected ?? wrapExpectedWithArray(elements, actualHTML,
|
|
27
|
+
const expectedValues = expected ?? wrapExpectedWithArray(elements, actualHTML, expectedWithOptions);
|
|
30
28
|
const message = enhanceError(elements, expectedValues, actualHTML, { isNot, isSome }, verb, expectation, '', options);
|
|
31
29
|
const result = {
|
|
32
30
|
pass,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
2
2
|
import { wrapExpectedWithArray } from '../../util/elementsUtil.js';
|
|
3
3
|
import { executeCommandWithStrategy } from '../../util/executeCommand.js';
|
|
4
|
-
import {
|
|
4
|
+
import { validateNumberMatcherArray } from '../../util/numberOptionsUtil.js';
|
|
5
5
|
import { enhanceError, waitUntil, } from '../../utils.js';
|
|
6
6
|
async function condition(el, expectedNumber) {
|
|
7
7
|
const actualHeight = await el.getSize('height');
|
|
@@ -17,19 +17,18 @@ export async function toHaveHeight(received, expectedValue, options = DEFAULT_OP
|
|
|
17
17
|
expectedValue,
|
|
18
18
|
options,
|
|
19
19
|
});
|
|
20
|
-
const
|
|
20
|
+
const expectedNumber = validateNumberMatcherArray(expectedValue);
|
|
21
21
|
const { success: pass, actual: actualHeight, subject: elements, context: { isSome } = {}, expected } = await waitUntil(async (iteration) => {
|
|
22
22
|
return await executeCommandWithStrategy({
|
|
23
23
|
unresolvedElements: received,
|
|
24
24
|
expectedValues: expectedNumber,
|
|
25
25
|
singleElementCompare: (element, expectedNumber) => condition(element, expectedNumber),
|
|
26
26
|
context: { isNot, iteration },
|
|
27
|
-
strategy: 'NewStrictMultipleElements',
|
|
28
27
|
strictConfiguration: { allowArrayWithSingleElement: false }
|
|
29
28
|
});
|
|
30
|
-
}, isNot, { wait:
|
|
29
|
+
}, isNot, { wait: options.wait, interval: options.interval });
|
|
31
30
|
const expectedValues = expected ?? wrapExpectedWithArray(elements, actualHeight, expectedNumber);
|
|
32
|
-
const message = enhanceError(elements, expectedValues, actualHeight, { isNot, isSome }, verb, expectation, '',
|
|
31
|
+
const message = enhanceError(elements, expectedValues, actualHeight, { isNot, isSome }, verb, expectation, '', options);
|
|
33
32
|
const result = {
|
|
34
33
|
pass,
|
|
35
34
|
message: () => message
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { toHaveAttributeAndValue } from './toHaveAttribute.js';
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toHaveHref(el, expectedValue, options = DEFAULT_OPTIONS) {
|
|
4
|
+
const { matcherName = 'toHaveHref' } = this;
|
|
4
5
|
await options.beforeAssertion?.({
|
|
5
|
-
matcherName
|
|
6
|
+
matcherName,
|
|
6
7
|
expectedValue,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await toHaveAttributeAndValue.call(this, el, 'href', expectedValue, options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
expectedValue,
|
|
13
14
|
options,
|
|
14
15
|
result
|
|
15
16
|
});
|
|
16
17
|
return result;
|
|
17
18
|
}
|
|
18
|
-
export const toHaveLink =
|
|
19
|
+
export const toHaveLink = function toHaveLink(...args) {
|
|
20
|
+
return toHaveHref.call({ matcherName: 'toHaveLink', ...this }, ...args);
|
|
21
|
+
};
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { toHaveAttributeAndValue } from './toHaveAttribute.js';
|
|
2
2
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
3
3
|
export async function toHaveId(el, expectedValue, options = DEFAULT_OPTIONS) {
|
|
4
|
+
const { matcherName = 'toHaveId' } = this;
|
|
4
5
|
await options.beforeAssertion?.({
|
|
5
|
-
matcherName
|
|
6
|
+
matcherName,
|
|
6
7
|
expectedValue,
|
|
7
8
|
options,
|
|
8
9
|
});
|
|
9
10
|
const result = await toHaveAttributeAndValue.call(this, el, 'id', expectedValue, options);
|
|
10
11
|
await options.afterAssertion?.({
|
|
11
|
-
matcherName
|
|
12
|
+
matcherName,
|
|
12
13
|
expectedValue,
|
|
13
14
|
options,
|
|
14
15
|
result
|