expect-webdriverio 4.5.1 → 4.6.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.
Files changed (44) hide show
  1. package/lib/constants.js +2 -0
  2. package/lib/matchers/browser/toHaveClipboardText.js +37 -0
  3. package/lib/matchers/browser/toHaveTitle.js +22 -4
  4. package/lib/matchers/browser/toHaveUrl.js +22 -4
  5. package/lib/matchers/element/toBeClickable.js +12 -2
  6. package/lib/matchers/element/toBeDisabled.js +12 -2
  7. package/lib/matchers/element/toBeDisplayed.js +11 -1
  8. package/lib/matchers/element/toBeDisplayedInViewport.js +12 -2
  9. package/lib/matchers/element/toBeEnabled.js +12 -2
  10. package/lib/matchers/element/toBeExisting.js +12 -2
  11. package/lib/matchers/element/toBeFocused.js +12 -2
  12. package/lib/matchers/element/toBeSelected.js +24 -4
  13. package/lib/matchers/element/toHaveAttribute.js +25 -9
  14. package/lib/matchers/element/toHaveChildren.js +17 -5
  15. package/lib/matchers/element/toHaveClass.js +29 -7
  16. package/lib/matchers/element/toHaveComputedLabel.js +23 -5
  17. package/lib/matchers/element/toHaveComputedRole.js +23 -5
  18. package/lib/matchers/element/toHaveElementProperty.js +14 -2
  19. package/lib/matchers/element/toHaveHTML.js +22 -4
  20. package/lib/matchers/element/toHaveHeight.js +17 -5
  21. package/lib/matchers/element/toHaveHref.js +22 -3
  22. package/lib/matchers/element/toHaveId.js +15 -3
  23. package/lib/matchers/element/toHaveSize.js +17 -5
  24. package/lib/matchers/element/toHaveStyle.js +16 -4
  25. package/lib/matchers/element/toHaveText.js +22 -4
  26. package/lib/matchers/element/toHaveValue.js +6 -0
  27. package/lib/matchers/element/toHaveWidth.js +17 -5
  28. package/lib/matchers/elements/toBeElementsArrayOfSize.js +18 -6
  29. package/lib/matchers/mock/toBeRequested.js +1 -1
  30. package/lib/matchers/mock/toBeRequestedTimes.js +18 -6
  31. package/lib/matchers/mock/toBeRequestedWith.js +23 -11
  32. package/lib/matchers.js +4 -14
  33. package/package.json +11 -10
  34. package/types/expect-webdriverio.d.ts +74 -5
  35. package/lib/matchers/browser/toHaveTitleContaining.js +0 -7
  36. package/lib/matchers/browser/toHaveUrlContaining.js +0 -7
  37. package/lib/matchers/element/toHaveAttributeContaining.js +0 -8
  38. package/lib/matchers/element/toHaveClassContaining.js +0 -10
  39. package/lib/matchers/element/toHaveComputedLabelContaining.js +0 -7
  40. package/lib/matchers/element/toHaveComputedRoleContaining.js +0 -7
  41. package/lib/matchers/element/toHaveHTMLContaining.js +0 -7
  42. package/lib/matchers/element/toHaveHrefContaining.js +0 -8
  43. package/lib/matchers/element/toHaveTextContaining.js +0 -7
  44. package/lib/matchers/element/toHaveValueContaining.js +0 -7
package/lib/constants.js CHANGED
@@ -1,4 +1,6 @@
1
1
  export const DEFAULT_OPTIONS = {
2
2
  wait: 2000,
3
3
  interval: 100,
4
+ beforeAssertion: async () => { },
5
+ afterAssertion: async () => { },
4
6
  };
@@ -0,0 +1,37 @@
1
+ import { waitUntil, enhanceError, compareText } from '../../utils.js';
2
+ import logger from '@wdio/logger';
3
+ const log = logger('expect-webdriverio');
4
+ export async function toHaveClipboardText(browser, expectedValue, options = {}) {
5
+ const isNot = this.isNot;
6
+ const { expectation = 'clipboard text', verb = 'have' } = this;
7
+ await options.beforeAssertion?.({
8
+ matcherName: 'toHaveClipboardText',
9
+ expectedValue,
10
+ options,
11
+ });
12
+ let actual;
13
+ const pass = await waitUntil(async () => {
14
+ await browser.setPermissions({ name: 'clipboard-read' }, 'granted')
15
+ .catch((err) => log.warn(`Couldn't set clipboard permissions: ${err}`));
16
+ actual = await browser.execute(() => window.navigator.clipboard.readText());
17
+ return compareText(actual, expectedValue, options).result;
18
+ }, isNot, options);
19
+ const message = enhanceError('browser', expectedValue, actual, this, verb, expectation, '', options);
20
+ const result = {
21
+ pass,
22
+ message: () => message
23
+ };
24
+ await options.afterAssertion?.({
25
+ matcherName: 'toHaveClipboardText',
26
+ expectedValue,
27
+ options,
28
+ result
29
+ });
30
+ return result;
31
+ }
32
+ export function toHaveClipboardTextContaining(browser, clipboardText, options = {}) {
33
+ return toHaveClipboardText.call(this, browser, clipboardText, {
34
+ ...options,
35
+ containing: true
36
+ });
37
+ }
@@ -1,15 +1,33 @@
1
1
  import { waitUntil, enhanceError, compareText } from '../../utils.js';
2
- export async function toHaveTitle(browser, title, options = {}) {
2
+ export async function toHaveTitle(browser, expectedValue, options = {}) {
3
3
  const isNot = this.isNot;
4
4
  const { expectation = 'title', verb = 'have' } = this;
5
+ await options.beforeAssertion?.({
6
+ matcherName: 'toHaveTitle',
7
+ expectedValue,
8
+ options,
9
+ });
5
10
  let actual;
6
11
  const pass = await waitUntil(async () => {
7
12
  actual = await browser.getTitle();
8
- return compareText(actual, title, options).result;
13
+ return compareText(actual, expectedValue, options).result;
9
14
  }, isNot, options);
10
- const message = enhanceError('window', title, actual, this, verb, expectation, '', options);
11
- return {
15
+ const message = enhanceError('window', expectedValue, actual, this, verb, expectation, '', options);
16
+ const result = {
12
17
  pass,
13
18
  message: () => message
14
19
  };
20
+ await options.afterAssertion?.({
21
+ matcherName: 'toHaveTitle',
22
+ expectedValue,
23
+ options,
24
+ result
25
+ });
26
+ return result;
27
+ }
28
+ export function toHaveTitleContaining(browser, title, options = {}) {
29
+ return toHaveTitle.call(this, browser, title, {
30
+ ...options,
31
+ containing: true
32
+ });
15
33
  }
@@ -1,15 +1,33 @@
1
1
  import { waitUntil, enhanceError, compareText } from '../../utils.js';
2
- export async function toHaveUrl(browser, url, options = {}) {
2
+ export async function toHaveUrl(browser, expectedValue, options = {}) {
3
3
  const isNot = this.isNot;
4
4
  const { expectation = 'url', verb = 'have' } = this;
5
+ await options.beforeAssertion?.({
6
+ matcherName: 'toHaveUrl',
7
+ expectedValue,
8
+ options,
9
+ });
5
10
  let actual;
6
11
  const pass = await waitUntil(async () => {
7
12
  actual = await browser.getUrl();
8
- return compareText(actual, url, options).result;
13
+ return compareText(actual, expectedValue, options).result;
9
14
  }, isNot, options);
10
- const message = enhanceError('window', url, actual, this, verb, expectation, '', options);
11
- return {
15
+ const message = enhanceError('window', expectedValue, actual, this, verb, expectation, '', options);
16
+ const result = {
12
17
  pass,
13
18
  message: () => message
14
19
  };
20
+ await options.afterAssertion?.({
21
+ matcherName: 'toHaveUrl',
22
+ expectedValue,
23
+ options,
24
+ result
25
+ });
26
+ return result;
27
+ }
28
+ export function toHaveUrlContaining(browser, url, options = {}) {
29
+ return toHaveUrl.call(this, browser, url, {
30
+ ...options,
31
+ containing: true
32
+ });
15
33
  }
@@ -1,7 +1,11 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeClickable(received, options = {}) {
2
+ export async function toBeClickable(received, options = {}) {
3
3
  this.expectation = this.expectation || 'clickable';
4
- return executeCommandBe.call(this, received, async (el) => {
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeClickable',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, async (el) => {
5
9
  try {
6
10
  return el.isClickable();
7
11
  }
@@ -9,4 +13,10 @@ export function toBeClickable(received, options = {}) {
9
13
  return false;
10
14
  }
11
15
  }, options);
16
+ await options.afterAssertion?.({
17
+ matcherName: 'toBeClickable',
18
+ options,
19
+ result
20
+ });
21
+ return result;
12
22
  }
@@ -1,5 +1,15 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeDisabled(received, options = {}) {
2
+ export async function toBeDisabled(received, options = {}) {
3
3
  this.expectation = this.expectation || 'disabled';
4
- return executeCommandBe.call(this, received, async (el) => !await el.isEnabled(), options);
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeDisabled',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, async (el) => !await el.isEnabled(), options);
9
+ await options.afterAssertion?.({
10
+ matcherName: 'toBeDisabled',
11
+ options,
12
+ result
13
+ });
14
+ return result;
5
15
  }
@@ -1,7 +1,11 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
2
  export async function toBeDisplayed(received, options = {}) {
3
3
  this.expectation = this.expectation || 'displayed';
4
- return executeCommandBe.call(this, received, async (el) => {
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeDisplayed',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, async (el) => {
5
9
  try {
6
10
  return el.isDisplayed();
7
11
  }
@@ -9,4 +13,10 @@ export async function toBeDisplayed(received, options = {}) {
9
13
  return false;
10
14
  }
11
15
  }, options);
16
+ await options.afterAssertion?.({
17
+ matcherName: 'toBeDisplayed',
18
+ options,
19
+ result
20
+ });
21
+ return result;
12
22
  }
@@ -1,7 +1,11 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeDisplayedInViewport(received, options = {}) {
2
+ export async function toBeDisplayedInViewport(received, options = {}) {
3
3
  this.expectation = this.expectation || 'displayed in viewport';
4
- return executeCommandBe.call(this, received, async (el) => {
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeDisplayedInViewport',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, async (el) => {
5
9
  try {
6
10
  return el.isDisplayedInViewport();
7
11
  }
@@ -9,4 +13,10 @@ export function toBeDisplayedInViewport(received, options = {}) {
9
13
  return false;
10
14
  }
11
15
  }, options);
16
+ await options.afterAssertion?.({
17
+ matcherName: 'toBeDisplayedInViewport',
18
+ options,
19
+ result
20
+ });
21
+ return result;
12
22
  }
@@ -1,5 +1,15 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeEnabled(received, options = {}) {
2
+ export async function toBeEnabled(received, options = {}) {
3
3
  this.expectation = this.expectation || 'enabled';
4
- return executeCommandBe.call(this, received, el => el.isEnabled(), options);
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeEnabled',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, el => el.isEnabled(), options);
9
+ await options.afterAssertion?.({
10
+ matcherName: 'toBeEnabled',
11
+ options,
12
+ result
13
+ });
14
+ return result;
5
15
  }
@@ -1,8 +1,12 @@
1
1
  import { executeCommandBe, aliasFn } from '../../utils.js';
2
- export function toExist(received, options = {}) {
2
+ export async function toExist(received, options = {}) {
3
3
  this.expectation = this.expectation || 'exist';
4
4
  this.verb = this.verb || '';
5
- return executeCommandBe.call(this, received, async (el) => {
5
+ await options.beforeAssertion?.({
6
+ matcherName: 'toExist',
7
+ options,
8
+ });
9
+ const result = await executeCommandBe.call(this, received, async (el) => {
6
10
  try {
7
11
  return el.isExisting();
8
12
  }
@@ -10,6 +14,12 @@ export function toExist(received, options = {}) {
10
14
  return false;
11
15
  }
12
16
  }, options);
17
+ await options.afterAssertion?.({
18
+ matcherName: 'toExist',
19
+ options,
20
+ result
21
+ });
22
+ return result;
13
23
  }
14
24
  export function toBeExisting(el, options) {
15
25
  return aliasFn.call(this, toExist, { verb: 'be', expectation: 'existing' }, el, options);
@@ -1,5 +1,15 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeFocused(received, options = {}) {
2
+ export async function toBeFocused(received, options = {}) {
3
3
  this.expectation = this.expectation || 'focused';
4
- return executeCommandBe.call(this, received, el => el.isFocused(), options);
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeFocused',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, el => el.isFocused(), options);
9
+ await options.afterAssertion?.({
10
+ matcherName: 'toBeFocused',
11
+ options,
12
+ result
13
+ });
14
+ return result;
5
15
  }
@@ -1,9 +1,29 @@
1
1
  import { executeCommandBe } from '../../utils.js';
2
- export function toBeSelected(received, options = {}) {
2
+ export async function toBeSelected(received, options = {}) {
3
3
  this.expectation = this.expectation || 'selected';
4
- return executeCommandBe.call(this, received, el => el.isSelected(), options);
4
+ await options.beforeAssertion?.({
5
+ matcherName: 'toBeSelected',
6
+ options,
7
+ });
8
+ const result = await executeCommandBe.call(this, received, el => el.isSelected(), options);
9
+ await options.afterAssertion?.({
10
+ matcherName: 'toBeSelected',
11
+ options,
12
+ result
13
+ });
14
+ return result;
5
15
  }
6
- export function toBeChecked(el, options) {
16
+ export async function toBeChecked(el, options = {}) {
7
17
  this.expectation = 'checked';
8
- return toBeSelected.call(this, el, options);
18
+ await options.beforeAssertion?.({
19
+ matcherName: 'toBeChecked',
20
+ options,
21
+ });
22
+ const result = await toBeSelected.call(this, el, options);
23
+ await options.afterAssertion?.({
24
+ matcherName: 'toBeChecked',
25
+ options,
26
+ result
27
+ });
28
+ return result;
9
29
  }
@@ -15,7 +15,7 @@ async function conditionAttrAndValue(el, attribute, value, options) {
15
15
  }
16
16
  return compareText(attr, value, options);
17
17
  }
18
- export async function toHaveAttributeAndValueFn(received, attribute, value, options = {}) {
18
+ export async function toHaveAttributeAndValue(received, attribute, value, options = {}) {
19
19
  const isNot = this.isNot;
20
20
  const { expectation = 'attribute', verb = 'have' } = this;
21
21
  let el = await received;
@@ -34,7 +34,7 @@ export async function toHaveAttributeAndValueFn(received, attribute, value, opti
34
34
  message: () => message
35
35
  };
36
36
  }
37
- export async function toHaveAttributeFn(received, attribute) {
37
+ async function toHaveAttributeFn(received, attribute) {
38
38
  const isNot = this.isNot;
39
39
  const { expectation = 'attribute', verb = 'have' } = this;
40
40
  let el = await received;
@@ -50,12 +50,28 @@ export async function toHaveAttributeFn(received, attribute) {
50
50
  message: () => message
51
51
  };
52
52
  }
53
- export function toHaveAttribute(...args) {
54
- if (args.length === 3 || args.length === 4) {
55
- return toHaveAttributeAndValueFn.call(this, ...args);
56
- }
57
- else {
58
- return toHaveAttributeFn.call(this, ...args);
59
- }
53
+ export async function toHaveAttribute(received, attribute, value, options = {}) {
54
+ await options.beforeAssertion?.({
55
+ matcherName: 'toHaveAttribute',
56
+ expectedValue: [attribute, value],
57
+ options,
58
+ });
59
+ const result = typeof value !== 'undefined'
60
+ ? await toHaveAttributeAndValue.call(this, received, attribute, value, options)
61
+ : await toHaveAttributeFn.call(this, received, attribute);
62
+ await options.afterAssertion?.({
63
+ matcherName: 'toHaveAttribute',
64
+ expectedValue: [attribute, value],
65
+ options,
66
+ result
67
+ });
68
+ return result;
69
+ }
70
+ export function toHaveAttributeContaining(el, attribute, value, options = {}) {
71
+ return toHaveAttributeAndValue.call(this, el, attribute, value, {
72
+ ...options,
73
+ containing: true
74
+ });
60
75
  }
76
+ export const toHaveAttrContaining = toHaveAttributeContaining;
61
77
  export const toHaveAttr = toHaveAttribute;
@@ -14,12 +14,17 @@ async function condition(el, options) {
14
14
  value: children?.length
15
15
  };
16
16
  }
17
- export async function toHaveChildren(received, expected, options = {}) {
17
+ export async function toHaveChildren(received, expectedValue, options = {}) {
18
18
  const isNot = this.isNot;
19
19
  const { expectation = 'children', verb = 'have' } = this;
20
- const numberOptions = typeof expected === 'number'
21
- ? { eq: expected }
22
- : expected || {};
20
+ await options.beforeAssertion?.({
21
+ matcherName: 'toHaveChildren',
22
+ expectedValue,
23
+ options,
24
+ });
25
+ const numberOptions = typeof expectedValue === 'number'
26
+ ? { eq: expectedValue }
27
+ : expectedValue || {};
23
28
  let el = await received;
24
29
  let children;
25
30
  const pass = await waitUntil(async () => {
@@ -32,8 +37,15 @@ export async function toHaveChildren(received, expected, options = {}) {
32
37
  const error = numberError(numberOptions);
33
38
  const expectedArray = wrapExpectedWithArray(el, children, error);
34
39
  const message = enhanceError(el, expectedArray, children, this, verb, expectation, '', numberOptions);
35
- return {
40
+ const result = {
36
41
  pass,
37
42
  message: () => message
38
43
  };
44
+ await options.afterAssertion?.({
45
+ matcherName: 'toHaveChildren',
46
+ expectedValue,
47
+ options,
48
+ result
49
+ });
50
+ return result;
39
51
  }
@@ -1,3 +1,4 @@
1
+ import { toHaveAttributeAndValue } from './toHaveAttribute.js';
1
2
  import { waitUntil, enhanceError, executeCommand, wrapExpectedWithArray, updateElementsArray, compareText } from '../../utils.js';
2
3
  async function condition(el, attribute, value, options) {
3
4
  const { ignoreCase = false, trim = false, containing = false } = options;
@@ -20,32 +21,53 @@ async function condition(el, attribute, value, options) {
20
21
  ? !!t.match(value)
21
22
  : containing && typeof value === 'string'
22
23
  ? t.includes(value)
23
- : compareText(t, value, options);
24
+ : compareText(t, value, options).result;
24
25
  });
25
26
  return {
26
27
  value: attr,
27
28
  result: valueInClasses
28
29
  };
29
30
  }
30
- export function toHaveElementClass(...args) {
31
- return toHaveClass.call(this || {}, ...args);
31
+ export function toHaveClass(...args) {
32
+ return toHaveElementClass.call(this || {}, ...args);
32
33
  }
33
- export async function toHaveClass(received, className, options = {}) {
34
+ export async function toHaveElementClass(received, expectedValue, options = {}) {
34
35
  const isNot = this.isNot;
35
36
  const { expectation = 'class', verb = 'have' } = this;
37
+ await options.beforeAssertion?.({
38
+ matcherName: 'toHaveElementClass',
39
+ expectedValue,
40
+ options,
41
+ });
36
42
  const attribute = 'class';
37
43
  let el = await received;
38
44
  let attr;
39
45
  const pass = await waitUntil(async () => {
40
- const result = await executeCommand.call(this, el, condition, options, [attribute, className, options]);
46
+ const result = await executeCommand.call(this, el, condition, options, [attribute, expectedValue, options]);
41
47
  el = result.el;
42
48
  attr = result.values;
43
49
  return result.success;
44
50
  }, isNot, options);
45
51
  updateElementsArray(pass, received, el);
46
- const message = enhanceError(el, wrapExpectedWithArray(el, attr, className), attr, this, verb, expectation, '', options);
47
- return {
52
+ const message = enhanceError(el, wrapExpectedWithArray(el, attr, expectedValue), attr, this, verb, expectation, '', options);
53
+ const result = {
48
54
  pass,
49
55
  message: () => message
50
56
  };
57
+ await options.afterAssertion?.({
58
+ matcherName: 'toHaveElementClass',
59
+ expectedValue,
60
+ options,
61
+ result
62
+ });
63
+ return result;
64
+ }
65
+ export function toHaveElementClassContaining(...args) {
66
+ return toHaveClassContaining.call(this, ...args);
67
+ }
68
+ export function toHaveClassContaining(el, className, options = {}) {
69
+ return toHaveAttributeAndValue.call(this, el, 'class', className, {
70
+ ...options,
71
+ containing: true
72
+ });
51
73
  }
@@ -6,21 +6,39 @@ async function condition(el, label, options) {
6
6
  }
7
7
  return compareText(actualLabel, label, options);
8
8
  }
9
- export async function toHaveComputedLabel(received, label, options = {}) {
9
+ export async function toHaveComputedLabel(received, expectedValue, options = {}) {
10
10
  const isNot = this.isNot;
11
11
  const { expectation = 'computed label', verb = 'have' } = this;
12
+ await options.beforeAssertion?.({
13
+ matcherName: 'toHaveComputedLabel',
14
+ expectedValue,
15
+ options,
16
+ });
12
17
  let el = await received;
13
18
  let actualLabel;
14
19
  const pass = await waitUntil(async () => {
15
- const result = await executeCommand.call(this, el, condition, options, [label, options]);
20
+ const result = await executeCommand.call(this, el, condition, options, [expectedValue, options]);
16
21
  el = result.el;
17
22
  actualLabel = result.values;
18
23
  return result.success;
19
24
  }, isNot, options);
20
25
  updateElementsArray(pass, received, el);
21
- const message = enhanceError(el, wrapExpectedWithArray(el, actualLabel, label), actualLabel, this, verb, expectation, '', options);
22
- return {
26
+ const message = enhanceError(el, wrapExpectedWithArray(el, actualLabel, expectedValue), actualLabel, this, verb, expectation, '', options);
27
+ const result = {
23
28
  pass,
24
- message: () => message,
29
+ message: () => message
25
30
  };
31
+ await options.afterAssertion?.({
32
+ matcherName: 'toHaveComputedLabel',
33
+ expectedValue,
34
+ options,
35
+ result
36
+ });
37
+ return result;
38
+ }
39
+ export function toHaveComputedLabelContaining(el, label, options = {}) {
40
+ return toHaveComputedLabel.call(this, el, label, {
41
+ ...options,
42
+ containing: true
43
+ });
26
44
  }
@@ -6,21 +6,39 @@ async function condition(el, role, options) {
6
6
  }
7
7
  return compareText(actualRole, role, options);
8
8
  }
9
- export async function toHaveComputedRole(received, role, options = {}) {
9
+ export async function toHaveComputedRole(received, expectedValue, options = {}) {
10
10
  const isNot = this.isNot;
11
11
  const { expectation = 'computed role', verb = 'have' } = this;
12
+ await options.beforeAssertion?.({
13
+ matcherName: 'toHaveComputedRole',
14
+ expectedValue,
15
+ options,
16
+ });
12
17
  let el = await received;
13
18
  let actualRole;
14
19
  const pass = await waitUntil(async () => {
15
- const result = await executeCommand.call(this, el, condition, options, [role, options]);
20
+ const result = await executeCommand.call(this, el, condition, options, [expectedValue, options]);
16
21
  el = result.el;
17
22
  actualRole = result.values;
18
23
  return result.success;
19
24
  }, isNot, options);
20
25
  updateElementsArray(pass, received, el);
21
- const message = enhanceError(el, wrapExpectedWithArray(el, actualRole, role), actualRole, this, verb, expectation, '', options);
22
- return {
26
+ const message = enhanceError(el, wrapExpectedWithArray(el, actualRole, expectedValue), actualRole, this, verb, expectation, '', options);
27
+ const result = {
23
28
  pass,
24
- message: () => message,
29
+ message: () => message
25
30
  };
31
+ await options.afterAssertion?.({
32
+ matcherName: 'toHaveComputedRole',
33
+ expectedValue,
34
+ options,
35
+ result
36
+ });
37
+ return result;
38
+ }
39
+ export function toHaveComputedRoleContaining(el, role, options = {}) {
40
+ return toHaveComputedRole.call(this, el, role, {
41
+ ...options,
42
+ containing: true
43
+ });
26
44
  }
@@ -17,6 +17,11 @@ async function condition(el, property, value, options = {}) {
17
17
  export async function toHaveElementProperty(received, property, value, options = {}) {
18
18
  const isNot = this.isNot;
19
19
  const { expectation = 'property', verb = 'have' } = this;
20
+ await options.beforeAssertion?.({
21
+ matcherName: 'toHaveElementProperty',
22
+ expectedValue: [property, value],
23
+ options,
24
+ });
20
25
  let el = await received;
21
26
  let prop;
22
27
  const pass = await waitUntil(async () => {
@@ -34,8 +39,15 @@ export async function toHaveElementProperty(received, property, value, options =
34
39
  const expected = wrapExpectedWithArray(el, prop, value);
35
40
  message = enhanceError(el, expected, prop, this, verb, expectation, property, options);
36
41
  }
37
- return {
42
+ const result = {
38
43
  pass,
39
- message: () => message,
44
+ message: () => message
40
45
  };
46
+ await options.afterAssertion?.({
47
+ matcherName: 'toHaveElementProperty',
48
+ expectedValue: [property, value],
49
+ options,
50
+ result
51
+ });
52
+ return result;
41
53
  }
@@ -6,21 +6,39 @@ async function condition(el, html, options) {
6
6
  }
7
7
  return compareText(actualHTML, html, options);
8
8
  }
9
- export async function toHaveHTML(received, html, options = {}) {
9
+ export async function toHaveHTML(received, expectedValue, options = {}) {
10
10
  const isNot = this.isNot;
11
11
  const { expectation = 'HTML', verb = 'have' } = this;
12
+ await options.beforeAssertion?.({
13
+ matcherName: 'toHaveHTML',
14
+ expectedValue,
15
+ options,
16
+ });
12
17
  let el = await received;
13
18
  let actualHTML;
14
19
  const pass = await waitUntil(async () => {
15
- const result = await executeCommand.call(this, el, condition, options, [html, options]);
20
+ const result = await executeCommand.call(this, el, condition, options, [expectedValue, options]);
16
21
  el = result.el;
17
22
  actualHTML = result.values;
18
23
  return result.success;
19
24
  }, isNot, options);
20
25
  updateElementsArray(pass, received, el);
21
- const message = enhanceError(el, wrapExpectedWithArray(el, actualHTML, html), actualHTML, this, verb, expectation, '', options);
22
- return {
26
+ const message = enhanceError(el, wrapExpectedWithArray(el, actualHTML, expectedValue), actualHTML, this, verb, expectation, '', options);
27
+ const result = {
23
28
  pass,
24
29
  message: () => message
25
30
  };
31
+ await options.afterAssertion?.({
32
+ matcherName: 'toHaveHTML',
33
+ expectedValue,
34
+ options,
35
+ result
36
+ });
37
+ return result;
38
+ }
39
+ export function toHaveHTMLContaining(el, html, options = {}) {
40
+ return toHaveHTML.call(this, el, html, {
41
+ ...options,
42
+ containing: true
43
+ });
26
44
  }