expect-webdriverio 5.6.1 → 5.6.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.
Files changed (49) hide show
  1. package/lib/{matchers → src/matchers}/browser/toHaveClipboardText.js +1 -2
  2. package/lib/{matchers → src/matchers}/browser/toHaveTitle.js +1 -2
  3. package/lib/{matchers → src/matchers}/browser/toHaveUrl.js +1 -2
  4. package/lib/src/matchers/element/toBeDisplayed.js +29 -0
  5. package/lib/{matchers → src/matchers}/element/toHaveAttribute.js +6 -8
  6. package/lib/{matchers → src/matchers}/element/toHaveChildren.js +1 -2
  7. package/lib/{matchers → src/matchers}/element/toHaveClass.js +1 -2
  8. package/lib/{matchers → src/matchers}/element/toHaveComputedLabel.js +1 -2
  9. package/lib/{matchers → src/matchers}/element/toHaveComputedRole.js +1 -2
  10. package/lib/{matchers → src/matchers}/element/toHaveElementProperty.js +2 -3
  11. package/lib/{matchers → src/matchers}/element/toHaveHTML.js +1 -2
  12. package/lib/{matchers → src/matchers}/element/toHaveHeight.js +1 -2
  13. package/lib/{matchers → src/matchers}/element/toHaveSize.js +1 -2
  14. package/lib/{matchers → src/matchers}/element/toHaveStyle.js +1 -2
  15. package/lib/{matchers → src/matchers}/element/toHaveText.js +1 -2
  16. package/lib/{matchers → src/matchers}/element/toHaveWidth.js +1 -2
  17. package/lib/{matchers → src/matchers}/elements/toBeElementsArrayOfSize.js +1 -2
  18. package/lib/{matchers → src/matchers}/mock/toBeRequestedTimes.js +1 -2
  19. package/lib/{matchers → src/matchers}/mock/toBeRequestedWith.js +2 -3
  20. package/lib/{softAssert.js → src/softAssert.js} +9 -18
  21. package/lib/{util → src/util}/elementsUtil.js +3 -0
  22. package/lib/{util → src/util}/formatMessage.js +4 -3
  23. package/lib/src/util/refetchElements.js +9 -0
  24. package/lib/{utils.js → src/utils.js} +19 -31
  25. package/package.json +2 -1
  26. package/types/expect-webdriverio.d.ts +36 -7
  27. package/lib/matchers/element/toBeDisplayed.js +0 -16
  28. package/lib/util/refetchElements.js +0 -9
  29. /package/lib/{constants.js → src/constants.js} +0 -0
  30. /package/lib/{index.js → src/index.js} +0 -0
  31. /package/lib/{jasmineUtils.js → src/jasmineUtils.js} +0 -0
  32. /package/lib/{matchers → src/matchers}/element/toBeClickable.js +0 -0
  33. /package/lib/{matchers → src/matchers}/element/toBeDisabled.js +0 -0
  34. /package/lib/{matchers → src/matchers}/element/toBeDisplayedInViewport.js +0 -0
  35. /package/lib/{matchers → src/matchers}/element/toBeEnabled.js +0 -0
  36. /package/lib/{matchers → src/matchers}/element/toBeExisting.js +0 -0
  37. /package/lib/{matchers → src/matchers}/element/toBeFocused.js +0 -0
  38. /package/lib/{matchers → src/matchers}/element/toBeSelected.js +0 -0
  39. /package/lib/{matchers → src/matchers}/element/toHaveHref.js +0 -0
  40. /package/lib/{matchers → src/matchers}/element/toHaveId.js +0 -0
  41. /package/lib/{matchers → src/matchers}/element/toHaveValue.js +0 -0
  42. /package/lib/{matchers → src/matchers}/mock/toBeRequested.js +0 -0
  43. /package/lib/{matchers → src/matchers}/snapshot.js +0 -0
  44. /package/lib/{matchers.js → src/matchers.js} +0 -0
  45. /package/lib/{snapshot.js → src/snapshot.js} +0 -0
  46. /package/lib/{softAssertService.js → src/softAssertService.js} +0 -0
  47. /package/lib/{softExpect.js → src/softExpect.js} +0 -0
  48. /package/lib/{types.js → src/types.js} +0 -0
  49. /package/lib/{util → src/util}/executeCommand.js +0 -0
@@ -3,7 +3,6 @@ import { waitUntil, enhanceError, compareText } from '../../utils.js';
3
3
  import { DEFAULT_OPTIONS } from '../../constants.js';
4
4
  const log = logger('expect-webdriverio');
5
5
  export async function toHaveClipboardText(browser, expectedValue, options = DEFAULT_OPTIONS) {
6
- const isNot = this.isNot;
7
6
  const { expectation = 'clipboard text', verb = 'have' } = this;
8
7
  await options.beforeAssertion?.({
9
8
  matcherName: 'toHaveClipboardText',
@@ -16,7 +15,7 @@ export async function toHaveClipboardText(browser, expectedValue, options = DEFA
16
15
  .catch((err) => log.warn(`Couldn't set clipboard permissions: ${err}`));
17
16
  actual = await browser.execute(() => window.navigator.clipboard.readText());
18
17
  return compareText(actual, expectedValue, options).result;
19
- }, isNot, options);
18
+ }, options);
20
19
  const message = enhanceError('browser', expectedValue, actual, this, verb, expectation, '', options);
21
20
  const result = {
22
21
  pass,
@@ -1,7 +1,6 @@
1
1
  import { waitUntil, enhanceError, compareText } from '../../utils.js';
2
2
  import { DEFAULT_OPTIONS } from '../../constants.js';
3
3
  export async function toHaveTitle(browser, expectedValue, options = DEFAULT_OPTIONS) {
4
- const isNot = this.isNot;
5
4
  const { expectation = 'title', verb = 'have' } = this;
6
5
  await options.beforeAssertion?.({
7
6
  matcherName: 'toHaveTitle',
@@ -12,7 +11,7 @@ export async function toHaveTitle(browser, expectedValue, options = DEFAULT_OPTI
12
11
  const pass = await waitUntil(async () => {
13
12
  actual = await browser.getTitle();
14
13
  return compareText(actual, expectedValue, options).result;
15
- }, isNot, options);
14
+ }, options);
16
15
  const message = enhanceError('window', expectedValue, actual, this, verb, expectation, '', options);
17
16
  const result = {
18
17
  pass,
@@ -1,7 +1,6 @@
1
1
  import { waitUntil, enhanceError, compareText } from '../../utils.js';
2
2
  import { DEFAULT_OPTIONS } from '../../constants.js';
3
3
  export async function toHaveUrl(browser, expectedValue, options = DEFAULT_OPTIONS) {
4
- const isNot = this.isNot;
5
4
  const { expectation = 'url', verb = 'have' } = this;
6
5
  await options.beforeAssertion?.({
7
6
  matcherName: 'toHaveUrl',
@@ -12,7 +11,7 @@ export async function toHaveUrl(browser, expectedValue, options = DEFAULT_OPTION
12
11
  const pass = await waitUntil(async () => {
13
12
  actual = await browser.getUrl();
14
13
  return compareText(actual, expectedValue, options).result;
15
- }, isNot, options);
14
+ }, options);
16
15
  const message = enhanceError('window', expectedValue, actual, this, verb, expectation, '', options);
17
16
  const result = {
18
17
  pass,
@@ -0,0 +1,29 @@
1
+ import { executeCommandBe } from '../../utils.js';
2
+ import { DEFAULT_OPTIONS } from '../../constants.js';
3
+ const DEFAULT_OPTIONS_DISPLAYED = {
4
+ ...DEFAULT_OPTIONS,
5
+ withinViewport: false,
6
+ contentVisibilityAuto: true,
7
+ opacityProperty: true,
8
+ visibilityProperty: true
9
+ };
10
+ export async function toBeDisplayed(received, options = DEFAULT_OPTIONS_DISPLAYED) {
11
+ this.expectation = this.expectation || 'displayed';
12
+ await options.beforeAssertion?.({
13
+ matcherName: 'toBeDisplayed',
14
+ options,
15
+ });
16
+ const { withinViewport, contentVisibilityAuto, opacityProperty, visibilityProperty, ...commandOptions } = { ...DEFAULT_OPTIONS_DISPLAYED, ...options };
17
+ const result = await executeCommandBe.call(this, received, el => el?.isDisplayed({
18
+ withinViewport,
19
+ contentVisibilityAuto,
20
+ opacityProperty,
21
+ visibilityProperty
22
+ }), commandOptions);
23
+ await options.afterAssertion?.({
24
+ matcherName: 'toBeDisplayed',
25
+ options,
26
+ result
27
+ });
28
+ return result;
29
+ }
@@ -15,7 +15,6 @@ async function conditionAttrAndValue(el, attribute, value, options) {
15
15
  return compareText(attr, value, options);
16
16
  }
17
17
  export async function toHaveAttributeAndValue(received, attribute, value, options = DEFAULT_OPTIONS) {
18
- const isNot = this.isNot;
19
18
  const { expectation = 'attribute', verb = 'have' } = this;
20
19
  let el = await received?.getElement();
21
20
  let attr;
@@ -24,7 +23,7 @@ export async function toHaveAttributeAndValue(received, attribute, value, option
24
23
  el = result.el;
25
24
  attr = result.values;
26
25
  return result.success;
27
- }, isNot, options);
26
+ }, options);
28
27
  const expected = wrapExpectedWithArray(el, attr, value);
29
28
  const message = enhanceError(el, expected, attr, this, verb, expectation, attribute, options);
30
29
  return {
@@ -32,16 +31,15 @@ export async function toHaveAttributeAndValue(received, attribute, value, option
32
31
  message: () => message
33
32
  };
34
33
  }
35
- async function toHaveAttributeFn(received, attribute) {
36
- const isNot = this.isNot;
37
- const { expectation = 'attribute', verb = 'have' } = this;
34
+ async function toHaveAttributeFn(received, attribute, options) {
35
+ const { expectation = 'attribute', verb = 'have', isNot } = this;
38
36
  let el = await received?.getElement();
39
37
  const pass = await waitUntil(async () => {
40
38
  const result = await executeCommand.call(this, el, conditionAttr, {}, [attribute]);
41
39
  el = result.el;
42
40
  return result.success;
43
- }, isNot, {});
44
- const message = enhanceError(el, !isNot, pass, this, verb, expectation, attribute, {});
41
+ }, options);
42
+ const message = enhanceError(el, !isNot, pass, this, verb, expectation, attribute, options);
45
43
  return {
46
44
  pass,
47
45
  message: () => message
@@ -55,7 +53,7 @@ export async function toHaveAttribute(received, attribute, value, options = DEFA
55
53
  });
56
54
  const result = value !== undefined
57
55
  ? await toHaveAttributeAndValue.call(this, received, attribute, value, options)
58
- : await toHaveAttributeFn.call(this, received, attribute);
56
+ : await toHaveAttributeFn.call(this, received, attribute, options);
59
57
  await options.afterAssertion?.({
60
58
  matcherName: 'toHaveAttribute',
61
59
  expectedValue: [attribute, value],
@@ -16,7 +16,6 @@ async function condition(el, options) {
16
16
  };
17
17
  }
18
18
  export async function toHaveChildren(received, expectedValue, options = DEFAULT_OPTIONS) {
19
- const isNot = this.isNot;
20
19
  const { expectation = 'children', verb = 'have' } = this;
21
20
  await options.beforeAssertion?.({
22
21
  matcherName: 'toHaveChildren',
@@ -33,7 +32,7 @@ export async function toHaveChildren(received, expectedValue, options = DEFAULT_
33
32
  el = result.el;
34
33
  children = result.values;
35
34
  return result.success;
36
- }, isNot, { ...numberOptions, ...options });
35
+ }, { ...numberOptions, ...options });
37
36
  const error = numberError(numberOptions);
38
37
  const expectedArray = wrapExpectedWithArray(el, children, error);
39
38
  const message = enhanceError(el, expectedArray, children, this, verb, expectation, '', numberOptions);
@@ -24,7 +24,6 @@ export function toHaveClass(...args) {
24
24
  return toHaveElementClass.call(this || {}, ...args);
25
25
  }
26
26
  export async function toHaveElementClass(received, expectedValue, options = DEFAULT_OPTIONS) {
27
- const isNot = this.isNot;
28
27
  const { expectation = 'class', verb = 'have' } = this;
29
28
  await options.beforeAssertion?.({
30
29
  matcherName: 'toHaveElementClass',
@@ -39,7 +38,7 @@ export async function toHaveElementClass(received, expectedValue, options = DEFA
39
38
  el = result.el;
40
39
  attr = result.values;
41
40
  return result.success;
42
- }, isNot, options);
41
+ }, options);
43
42
  const message = enhanceError(el, wrapExpectedWithArray(el, attr, expectedValue), attr, this, verb, expectation, '', options);
44
43
  const result = {
45
44
  pass,
@@ -8,7 +8,6 @@ async function condition(el, label, options) {
8
8
  return compareText(actualLabel, label, options);
9
9
  }
10
10
  export async function toHaveComputedLabel(received, expectedValue, options = DEFAULT_OPTIONS) {
11
- const isNot = this.isNot;
12
11
  const { expectation = 'computed label', verb = 'have' } = this;
13
12
  await options.beforeAssertion?.({
14
13
  matcherName: 'toHaveComputedLabel',
@@ -22,7 +21,7 @@ export async function toHaveComputedLabel(received, expectedValue, options = DEF
22
21
  el = result.el;
23
22
  actualLabel = result.values;
24
23
  return result.success;
25
- }, isNot, options);
24
+ }, options);
26
25
  const message = enhanceError(el, wrapExpectedWithArray(el, actualLabel, expectedValue), actualLabel, this, verb, expectation, '', options);
27
26
  const result = {
28
27
  pass,
@@ -8,7 +8,6 @@ async function condition(el, role, options) {
8
8
  return compareText(actualRole, role, options);
9
9
  }
10
10
  export async function toHaveComputedRole(received, expectedValue, options = DEFAULT_OPTIONS) {
11
- const isNot = this.isNot;
12
11
  const { expectation = 'computed role', verb = 'have' } = this;
13
12
  await options.beforeAssertion?.({
14
13
  matcherName: 'toHaveComputedRole',
@@ -22,7 +21,7 @@ export async function toHaveComputedRole(received, expectedValue, options = DEFA
22
21
  el = result.el;
23
22
  actualRole = result.values;
24
23
  return result.success;
25
- }, isNot, options);
24
+ }, options);
26
25
  const message = enhanceError(el, wrapExpectedWithArray(el, actualRole, expectedValue), actualRole, this, verb, expectation, '', options);
27
26
  const result = {
28
27
  pass,
@@ -16,8 +16,7 @@ async function condition(el, property, value, options = DEFAULT_OPTIONS) {
16
16
  return compareText(prop, value, options);
17
17
  }
18
18
  export async function toHaveElementProperty(received, property, value, options = DEFAULT_OPTIONS) {
19
- const isNot = this.isNot;
20
- const { expectation = 'property', verb = 'have' } = this;
19
+ const { expectation = 'property', verb = 'have', isNot } = this;
21
20
  await options.beforeAssertion?.({
22
21
  matcherName: 'toHaveElementProperty',
23
22
  expectedValue: [property, value],
@@ -30,7 +29,7 @@ export async function toHaveElementProperty(received, property, value, options =
30
29
  el = result.el;
31
30
  prop = result.values;
32
31
  return result.success;
33
- }, isNot, options);
32
+ }, options);
34
33
  let message;
35
34
  if (value === undefined) {
36
35
  message = enhanceError(el, !isNot, pass, this, verb, expectation, property, options);
@@ -8,7 +8,6 @@ async function condition(el, html, options) {
8
8
  return compareText(actualHTML, html, options);
9
9
  }
10
10
  export async function toHaveHTML(received, expectedValue, options = DEFAULT_OPTIONS) {
11
- const isNot = this.isNot;
12
11
  const { expectation = 'HTML', verb = 'have' } = this;
13
12
  await options.beforeAssertion?.({
14
13
  matcherName: 'toHaveHTML',
@@ -26,7 +25,7 @@ export async function toHaveHTML(received, expectedValue, options = DEFAULT_OPTI
26
25
  el = result.el;
27
26
  actualHTML = result.values;
28
27
  return result.success;
29
- }, isNot, options);
28
+ }, options);
30
29
  const message = enhanceError(el, wrapExpectedWithArray(el, actualHTML, expectedValue), actualHTML, this, verb, expectation, '', options);
31
30
  const result = {
32
31
  pass,
@@ -8,7 +8,6 @@ async function condition(el, height, options) {
8
8
  };
9
9
  }
10
10
  export async function toHaveHeight(received, expectedValue, options = DEFAULT_OPTIONS) {
11
- const isNot = this.isNot;
12
11
  const { expectation = 'height', verb = 'have' } = this;
13
12
  await options.beforeAssertion?.({
14
13
  matcherName: 'toHaveHeight',
@@ -32,7 +31,7 @@ export async function toHaveHeight(received, expectedValue, options = DEFAULT_OP
32
31
  el = result.el;
33
32
  actualHeight = result.values;
34
33
  return result.success;
35
- }, isNot, { ...numberOptions, ...options });
34
+ }, { ...numberOptions, ...options });
36
35
  const error = numberError(numberOptions);
37
36
  const message = enhanceError(el, error, actualHeight, this, verb, expectation, '', options);
38
37
  const result = {
@@ -5,7 +5,6 @@ async function condition(el, size) {
5
5
  return compareObject(actualSize, size);
6
6
  }
7
7
  export async function toHaveSize(received, expectedValue, options = DEFAULT_OPTIONS) {
8
- const isNot = this.isNot;
9
8
  const { expectation = 'size', verb = 'have' } = this;
10
9
  await options.beforeAssertion?.({
11
10
  matcherName: 'toHaveSize',
@@ -19,7 +18,7 @@ export async function toHaveSize(received, expectedValue, options = DEFAULT_OPTI
19
18
  el = result.el;
20
19
  actualSize = result.values;
21
20
  return result.success;
22
- }, isNot, options);
21
+ }, options);
23
22
  const message = enhanceError(el, wrapExpectedWithArray(el, actualSize, expectedValue), actualSize, this, verb, expectation, '', options);
24
23
  const result = {
25
24
  pass,
@@ -4,7 +4,6 @@ async function condition(el, style, options) {
4
4
  return compareStyle(el, style, options);
5
5
  }
6
6
  export async function toHaveStyle(received, expectedValue, options = DEFAULT_OPTIONS) {
7
- const isNot = this.isNot;
8
7
  const { expectation = 'style', verb = 'have' } = this;
9
8
  await options.beforeAssertion?.({
10
9
  matcherName: 'toHaveStyle',
@@ -18,7 +17,7 @@ export async function toHaveStyle(received, expectedValue, options = DEFAULT_OPT
18
17
  el = result.el;
19
18
  actualStyle = result.values;
20
19
  return result.success;
21
- }, isNot, options);
20
+ }, options);
22
21
  const message = enhanceError(el, wrapExpectedWithArray(el, actualStyle, expectedValue), actualStyle, this, verb, expectation, '', options);
23
22
  const result = {
24
23
  pass,
@@ -28,7 +28,6 @@ async function condition(el, text, options) {
28
28
  };
29
29
  }
30
30
  export async function toHaveText(received, expectedValue, options = DEFAULT_OPTIONS) {
31
- const isNot = this.isNot;
32
31
  const { expectation = 'text', verb = 'have' } = this;
33
32
  await options.beforeAssertion?.({
34
33
  matcherName: 'toHaveText',
@@ -46,7 +45,7 @@ export async function toHaveText(received, expectedValue, options = DEFAULT_OPTI
46
45
  el = result.el;
47
46
  actualText = result.values;
48
47
  return result.success;
49
- }, isNot, options);
48
+ }, options);
50
49
  const message = enhanceError(el, wrapExpectedWithArray(el, actualText, expectedValue), actualText, this, verb, expectation, '', options);
51
50
  const result = {
52
51
  pass,
@@ -8,7 +8,6 @@ async function condition(el, width, options) {
8
8
  };
9
9
  }
10
10
  export async function toHaveWidth(received, expectedValue, options = DEFAULT_OPTIONS) {
11
- const isNot = this.isNot;
12
11
  const { expectation = 'width', verb = 'have' } = this;
13
12
  await options.beforeAssertion?.({
14
13
  matcherName: 'toHaveWidth',
@@ -32,7 +31,7 @@ export async function toHaveWidth(received, expectedValue, options = DEFAULT_OPT
32
31
  el = result.el;
33
32
  actualWidth = result.values;
34
33
  return result.success;
35
- }, isNot, { ...numberOptions, ...options });
34
+ }, { ...numberOptions, ...options });
36
35
  const error = numberError(numberOptions);
37
36
  const message = enhanceError(el, error, actualWidth, this, verb, expectation, '', options);
38
37
  const result = {
@@ -2,7 +2,6 @@ import { waitUntil, enhanceError, compareNumbers, numberError } from '../../util
2
2
  import { refetchElements } from '../../util/refetchElements.js';
3
3
  import { DEFAULT_OPTIONS } from '../../constants.js';
4
4
  export async function toBeElementsArrayOfSize(received, expectedValue, options = DEFAULT_OPTIONS) {
5
- const isNot = this.isNot;
6
5
  const { expectation = 'elements array of size', verb = 'be' } = this;
7
6
  await options.beforeAssertion?.({
8
7
  matcherName: 'toBeElementsArrayOfSize',
@@ -28,7 +27,7 @@ export async function toBeElementsArrayOfSize(received, expectedValue, options =
28
27
  }
29
28
  elements = await refetchElements(elements, numberOptions.wait, true);
30
29
  return false;
31
- }, isNot, { ...numberOptions, ...options });
30
+ }, { ...numberOptions, ...options });
32
31
  if (Array.isArray(received) && pass) {
33
32
  for (let index = originalLength; index < elements.length; index++) {
34
33
  received.push(elements[index]);
@@ -2,7 +2,6 @@ import { waitUntil, enhanceError, compareNumbers } from '../../utils.js';
2
2
  import { numberError } from '../../util/formatMessage.js';
3
3
  import { DEFAULT_OPTIONS } from '../../constants.js';
4
4
  export async function toBeRequestedTimes(received, expectedValue = {}, options = DEFAULT_OPTIONS) {
5
- const isNot = this.isNot || false;
6
5
  const { expectation = `called${typeof expectedValue === 'number' ? ' ' + expectedValue : ''} time${expectedValue !== 1 ? 's' : ''}`, verb = 'be' } = this;
7
6
  await options.beforeAssertion?.({
8
7
  matcherName: 'toBeRequestedTimes',
@@ -16,7 +15,7 @@ export async function toBeRequestedTimes(received, expectedValue = {}, options =
16
15
  const pass = await waitUntil(async () => {
17
16
  actual = received.calls.length;
18
17
  return compareNumbers(actual, numberOptions);
19
- }, isNot, { ...numberOptions, ...options });
18
+ }, { ...numberOptions, ...options });
20
19
  const error = numberError(numberOptions);
21
20
  const message = enhanceError('mock', error, actual, this, verb, expectation, '', numberOptions);
22
21
  const result = {
@@ -10,8 +10,7 @@ function reduceHeaders(headers) {
10
10
  }, {});
11
11
  }
12
12
  export async function toBeRequestedWith(received, expectedValue = {}, options = DEFAULT_OPTIONS) {
13
- const isNot = this.isNot || false;
14
- const { expectation = 'called with', verb = 'be' } = this;
13
+ const { expectation = 'called with', verb = 'be', isNot } = this;
15
14
  await options.beforeAssertion?.({
16
15
  matcherName: 'toBeRequestedWith',
17
16
  expectedValue,
@@ -30,7 +29,7 @@ export async function toBeRequestedWith(received, expectedValue = {}, options =
30
29
  }
31
30
  }
32
31
  return false;
33
- }, isNot, { ...options, wait: isNot ? 0 : options.wait });
32
+ }, { ...options, wait: isNot ? 0 : options.wait });
34
33
  const message = enhanceError('mock', minifyRequestedWith(expectedValue), minifyRequestMock(actual, expectedValue) || 'was not called', this, verb, expectation, '', options);
35
34
  const result = {
36
35
  pass,
@@ -1,5 +1,6 @@
1
1
  export class SoftAssertService {
2
2
  static instance;
3
+ static GLOBAL_TEST_ID = '__global_soft_assert_context__';
3
4
  failureMap = new Map();
4
5
  currentTest = null;
5
6
  constructor() { }
@@ -22,9 +23,9 @@ export class SoftAssertService {
22
23
  return this.currentTest?.id || null;
23
24
  }
24
25
  addFailure(error, matcherName) {
25
- const testId = this.getCurrentTestId();
26
- if (!testId) {
27
- throw error;
26
+ const testId = this.getCurrentTestId() || SoftAssertService.GLOBAL_TEST_ID;
27
+ if (!this.failureMap.has(testId)) {
28
+ this.failureMap.set(testId, []);
28
29
  }
29
30
  const stackLines = error.stack?.split('\n') || [];
30
31
  let location = '';
@@ -34,28 +35,18 @@ export class SoftAssertService {
34
35
  break;
35
36
  }
36
37
  }
37
- const failures = this.failureMap.get(testId) || [];
38
- failures.push({ error, matcherName, location });
39
- this.failureMap.set(testId, failures);
38
+ this.failureMap.get(testId).push({ error, matcherName, location });
40
39
  }
41
40
  getFailures(testId) {
42
- const id = testId || this.getCurrentTestId();
43
- if (!id) {
44
- return [];
45
- }
41
+ const id = testId || this.getCurrentTestId() || SoftAssertService.GLOBAL_TEST_ID;
46
42
  return this.failureMap.get(id) || [];
47
43
  }
48
44
  clearFailures(testId) {
49
- const id = testId || this.getCurrentTestId();
50
- if (id) {
51
- this.failureMap.delete(id);
52
- }
45
+ const id = testId || this.getCurrentTestId() || SoftAssertService.GLOBAL_TEST_ID;
46
+ this.failureMap.delete(id);
53
47
  }
54
48
  assertNoFailures(testId) {
55
- const id = testId || this.getCurrentTestId();
56
- if (!id) {
57
- return;
58
- }
49
+ const id = testId || this.getCurrentTestId() || SoftAssertService.GLOBAL_TEST_ID;
59
50
  const failures = this.getFailures(id);
60
51
  if (failures.length === 0) {
61
52
  return;
@@ -4,3 +4,6 @@ export const wrapExpectedWithArray = (el, actual, expected) => {
4
4
  }
5
5
  return expected;
6
6
  };
7
+ export const isElementArray = (obj) => {
8
+ return obj !== null && typeof obj === 'object' && 'selector' in obj && 'foundWith' in obj && 'parent' in obj;
9
+ };
@@ -1,5 +1,6 @@
1
1
  import { printDiffOrStringify, printExpected, printReceived } from 'jest-matcher-utils';
2
2
  import { equals } from '../jasmineUtils.js';
3
+ import { isElementArray } from './elementsUtil.js';
3
4
  const EXPECTED_LABEL = 'Expected';
4
5
  const RECEIVED_LABEL = 'Received';
5
6
  const NOT_SUFFIX = ' [not]';
@@ -14,11 +15,11 @@ export const getSelector = (el) => {
14
15
  export const getSelectors = (el) => {
15
16
  const selectors = [];
16
17
  let parent;
17
- if (Array.isArray(el)) {
18
- selectors.push(`${el.foundWith}(\`${getSelector(el)}\`)`);
18
+ if (isElementArray(el)) {
19
+ selectors.push(`${(el).foundWith}(\`${getSelector(el)}\`)`);
19
20
  parent = el.parent;
20
21
  }
21
- else {
22
+ else if (!Array.isArray(el)) {
22
23
  parent = el;
23
24
  }
24
25
  while (parent && 'selector' in parent) {
@@ -0,0 +1,9 @@
1
+ import { DEFAULT_OPTIONS } from '../constants.js';
2
+ import { isElementArray } from './elementsUtil.js';
3
+ export const refetchElements = async (elements, wait = DEFAULT_OPTIONS.wait, full = false) => {
4
+ if (elements && wait > 0 && (elements.length === 0 || full) && isElementArray(elements) && elements.parent && elements.foundWith && elements.foundWith in elements.parent) {
5
+ const fetchFunction = elements.parent[elements.foundWith];
6
+ elements = await fetchFunction(elements.selector, ...elements.props);
7
+ }
8
+ return elements;
9
+ };
@@ -19,50 +19,38 @@ export function isAsymmetricMatcher(expected) {
19
19
  function isStringContainingMatcher(expected) {
20
20
  return isAsymmetricMatcher(expected) && ['StringContaining', 'StringNotContaining'].includes(expected.toString());
21
21
  }
22
- const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait, interval = DEFAULT_OPTIONS.interval } = {}) => {
23
- if (wait === 0) {
24
- return await condition();
25
- }
22
+ const waitUntil = async (condition, { wait = DEFAULT_OPTIONS.wait, interval = DEFAULT_OPTIONS.interval } = {}) => {
23
+ const start = Date.now();
26
24
  let error;
27
- try {
28
- const start = Date.now();
29
- while (true) {
30
- if (Date.now() - start > wait) {
31
- throw new Error('timeout');
32
- }
33
- try {
34
- const result = isNot !== (await condition());
35
- error = undefined;
36
- if (result) {
37
- break;
38
- }
39
- await sleep(interval);
40
- }
41
- catch (err) {
42
- error = err;
43
- await sleep(interval);
25
+ let result = false;
26
+ do {
27
+ try {
28
+ result = await condition();
29
+ error = undefined;
30
+ if (result) {
31
+ break;
44
32
  }
45
33
  }
46
- if (error) {
47
- throw error;
34
+ catch (err) {
35
+ error = err;
48
36
  }
49
- return !isNot;
50
- }
51
- catch {
52
- if (error) {
53
- throw error;
37
+ if (Date.now() - start < wait) {
38
+ await sleep(interval);
54
39
  }
55
- return isNot;
40
+ } while (Date.now() - start < wait);
41
+ if (error) {
42
+ throw error;
56
43
  }
44
+ return result;
57
45
  };
58
46
  async function executeCommandBe(received, command, options) {
59
- const { isNot, expectation, verb = 'be' } = this;
47
+ const { expectation, verb = 'be' } = this;
60
48
  let el = await received?.getElement();
61
49
  const pass = await waitUntil(async () => {
62
50
  const result = await executeCommand.call(this, el, async (element) => ({ result: await command(element) }), options);
63
51
  el = result.el;
64
52
  return result.success;
65
- }, isNot, options);
53
+ }, options);
66
54
  const message = enhanceErrorBe(el, pass, this, verb, expectation, options);
67
55
  return {
68
56
  pass,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expect-webdriverio",
3
- "version": "5.6.1",
3
+ "version": "5.6.2",
4
4
  "author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
5
5
  "description": "WebdriverIO Assertion Library",
6
6
  "license": "MIT",
@@ -63,6 +63,7 @@
63
63
  "ts:mocha": "cd test-types/mocha && tsc --project ./tsconfig.json",
64
64
  "ts:jasmine": "cd test-types/jasmine && tsc --project ./tsconfig.json",
65
65
  "ts:jasmine-async": "cd test-types/jasmine-async && tsc --project ./tsconfig.json",
66
+ "checks:all": "npm run build && npm run compile && npm run tsc:root-types && npm run test && npm run ts",
66
67
  "watch": "npm run compile -- --watch",
67
68
  "prepare": "husky install"
68
69
  },
@@ -54,7 +54,7 @@ type WdioOnlyMaybePromiseLike = ElementPromise | ElementArrayPromise | Chainable
54
54
  */
55
55
  type ElementOrArrayLike = ElementLike | ElementArrayLike
56
56
  type ElementLike = WebdriverIO.Element | ChainablePromiseElement
57
- type ElementArrayLike = WebdriverIO.ElementArray | ChainablePromiseArray
57
+ type ElementArrayLike = WebdriverIO.ElementArray | ChainablePromiseArray | WebdriverIO.Element[]
58
58
  type MockPromise = Promise<WebdriverIO.Mock>
59
59
 
60
60
  /**
@@ -122,7 +122,7 @@ interface WdioElementOrArrayMatchers<_R, ActualT = unknown> {
122
122
  /**
123
123
  * `WebdriverIO.Element` -> `isDisplayed`
124
124
  */
125
- toBeDisplayed: FnWhenElementOrArrayLike<ActualT, (options?: ExpectWebdriverIO.CommandOptions) => Promise<void>>
125
+ toBeDisplayed: FnWhenElementOrArrayLike<ActualT, (options?: ExpectWebdriverIO.ToBeDisplayedOptions) => Promise<void>>
126
126
 
127
127
  /**
128
128
  * `WebdriverIO.Element` -> `isExisting`
@@ -188,11 +188,14 @@ interface WdioElementOrArrayMatchers<_R, ActualT = unknown> {
188
188
  /**
189
189
  * `WebdriverIO.Element` -> `getProperty`
190
190
  */
191
- toHaveElementProperty: FnWhenElementOrArrayLike<ActualT, (
192
- property: string | RegExp | ExpectWebdriverIO.PartialMatcher<string>,
193
- value?: unknown,
194
- options?: ExpectWebdriverIO.StringOptions
195
- ) => Promise<void>>
191
+ toHaveElementProperty: FnWhenElementOrArrayLike<
192
+ ActualT,
193
+ (
194
+ property: string,
195
+ value?: string | RegExp | WdioAsymmetricMatcher<string> | null,
196
+ options?: ExpectWebdriverIO.StringOptions,
197
+ ) => Promise<void>
198
+ >
196
199
 
197
200
  /**
198
201
  * `WebdriverIO.Element` -> `getProperty` value
@@ -702,6 +705,32 @@ declare namespace ExpectWebdriverIO {
702
705
  gte?: number
703
706
  }
704
707
 
708
+ interface ToBeDisplayedOptions extends CommandOptions {
709
+ /**
710
+ * `true` to check if the element is within the viewport. false by default.
711
+ */
712
+ withinViewport?: boolean
713
+
714
+ /**
715
+ * `true` to check if the element content-visibility property has (or inherits) the value auto,
716
+ * and it is currently skipping its rendering. `true` by default.
717
+ * @default true
718
+ */
719
+ contentVisibilityAuto?: boolean
720
+
721
+ /**
722
+ * `true` to check if the element opacity property has (or inherits) a value of 0. `true` by default.
723
+ * @default true
724
+ */
725
+ opacityProperty?: boolean
726
+
727
+ /**
728
+ * `true` to check if the element is invisible due to the value of its visibility property. `true` by default.
729
+ * @default true
730
+ */
731
+ visibilityProperty?: boolean
732
+ }
733
+
705
734
  type RequestedWith = {
706
735
  url?: string | ExpectWebdriverIO.PartialMatcher<string>| ((url: string) => boolean)
707
736
  method?: string | Array<string>
@@ -1,16 +0,0 @@
1
- import { executeCommandBe } from '../../utils.js';
2
- import { DEFAULT_OPTIONS } from '../../constants.js';
3
- export async function toBeDisplayed(received, { withinViewport = false, contentVisibilityAuto = true, opacityProperty = true, visibilityProperty = true } = {}, options = DEFAULT_OPTIONS) {
4
- this.expectation = this.expectation || 'displayed';
5
- await options.beforeAssertion?.({
6
- matcherName: 'toBeDisplayed',
7
- options,
8
- });
9
- const result = await executeCommandBe.call(this, received, el => el?.isDisplayed({ withinViewport, contentVisibilityAuto, opacityProperty, visibilityProperty }), options);
10
- await options.afterAssertion?.({
11
- matcherName: 'toBeDisplayed',
12
- options,
13
- result
14
- });
15
- return result;
16
- }
@@ -1,9 +0,0 @@
1
- import { DEFAULT_OPTIONS } from '../constants.js';
2
- export const refetchElements = async (elements, wait = DEFAULT_OPTIONS.wait, full = false) => {
3
- if (elements) {
4
- if (wait > 0 && (elements.length === 0 || full)) {
5
- elements = await elements.parent[elements.foundWith](elements.selector, ...elements.props);
6
- }
7
- }
8
- return elements;
9
- };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes