@serenity-js/assertions 3.0.0-rc.9 → 3.0.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 (125) hide show
  1. package/CHANGELOG.md +83 -1891
  2. package/README.md +21 -21
  3. package/lib/Ensure.d.ts +75 -84
  4. package/lib/Ensure.d.ts.map +1 -0
  5. package/lib/Ensure.js +103 -123
  6. package/lib/Ensure.js.map +1 -1
  7. package/lib/EnsureEventually.d.ts +97 -0
  8. package/lib/EnsureEventually.d.ts.map +1 -0
  9. package/lib/EnsureEventually.js +143 -0
  10. package/lib/EnsureEventually.js.map +1 -0
  11. package/lib/expectations/and.d.ts +22 -1
  12. package/lib/expectations/and.d.ts.map +1 -0
  13. package/lib/expectations/and.js +30 -5
  14. package/lib/expectations/and.js.map +1 -1
  15. package/lib/expectations/contain.d.ts +27 -2
  16. package/lib/expectations/contain.d.ts.map +1 -0
  17. package/lib/expectations/contain.js +25 -5
  18. package/lib/expectations/contain.js.map +1 -1
  19. package/lib/expectations/containAtLeastOneItemThat.d.ts +23 -1
  20. package/lib/expectations/containAtLeastOneItemThat.d.ts.map +1 -0
  21. package/lib/expectations/containAtLeastOneItemThat.js +29 -7
  22. package/lib/expectations/containAtLeastOneItemThat.js.map +1 -1
  23. package/lib/expectations/containItemsWhereEachItem.d.ts +22 -0
  24. package/lib/expectations/containItemsWhereEachItem.d.ts.map +1 -0
  25. package/lib/expectations/containItemsWhereEachItem.js +29 -7
  26. package/lib/expectations/containItemsWhereEachItem.js.map +1 -1
  27. package/lib/expectations/endsWith.d.ts +22 -2
  28. package/lib/expectations/endsWith.d.ts.map +1 -0
  29. package/lib/expectations/endsWith.js +20 -5
  30. package/lib/expectations/endsWith.js.map +1 -1
  31. package/lib/expectations/equals.d.ts +28 -2
  32. package/lib/expectations/equals.d.ts.map +1 -0
  33. package/lib/expectations/equals.js +26 -5
  34. package/lib/expectations/equals.js.map +1 -1
  35. package/lib/expectations/includes.d.ts +22 -2
  36. package/lib/expectations/includes.d.ts.map +1 -0
  37. package/lib/expectations/includes.js +20 -5
  38. package/lib/expectations/includes.js.map +1 -1
  39. package/lib/expectations/index.d.ts +3 -0
  40. package/lib/expectations/index.d.ts.map +1 -0
  41. package/lib/expectations/index.js +7 -1
  42. package/lib/expectations/index.js.map +1 -1
  43. package/lib/expectations/isAfter.d.ts +42 -2
  44. package/lib/expectations/isAfter.d.ts.map +1 -0
  45. package/lib/expectations/isAfter.js +40 -5
  46. package/lib/expectations/isAfter.js.map +1 -1
  47. package/lib/expectations/isBefore.d.ts +42 -2
  48. package/lib/expectations/isBefore.d.ts.map +1 -0
  49. package/lib/expectations/isBefore.js +40 -5
  50. package/lib/expectations/isBefore.js.map +1 -1
  51. package/lib/expectations/isCloseTo.d.ts +24 -0
  52. package/lib/expectations/isCloseTo.d.ts.map +1 -0
  53. package/lib/expectations/isCloseTo.js +37 -0
  54. package/lib/expectations/isCloseTo.js.map +1 -0
  55. package/lib/expectations/isFalse.d.ts +19 -0
  56. package/lib/expectations/isFalse.d.ts.map +1 -0
  57. package/lib/expectations/isFalse.js +18 -0
  58. package/lib/expectations/isFalse.js.map +1 -1
  59. package/lib/expectations/isGreaterThan.d.ts +45 -2
  60. package/lib/expectations/isGreaterThan.d.ts.map +1 -0
  61. package/lib/expectations/isGreaterThan.js +43 -5
  62. package/lib/expectations/isGreaterThan.js.map +1 -1
  63. package/lib/expectations/isLessThan.d.ts +45 -2
  64. package/lib/expectations/isLessThan.d.ts.map +1 -0
  65. package/lib/expectations/isLessThan.js +43 -5
  66. package/lib/expectations/isLessThan.js.map +1 -1
  67. package/lib/expectations/isPresent.d.ts +58 -8
  68. package/lib/expectations/isPresent.d.ts.map +1 -0
  69. package/lib/expectations/isPresent.js +60 -11
  70. package/lib/expectations/isPresent.js.map +1 -1
  71. package/lib/expectations/isTrue.d.ts +19 -0
  72. package/lib/expectations/isTrue.d.ts.map +1 -0
  73. package/lib/expectations/isTrue.js +18 -0
  74. package/lib/expectations/isTrue.js.map +1 -1
  75. package/lib/expectations/matches.d.ts +22 -2
  76. package/lib/expectations/matches.d.ts.map +1 -0
  77. package/lib/expectations/matches.js +20 -5
  78. package/lib/expectations/matches.js.map +1 -1
  79. package/lib/expectations/not.d.ts +23 -1
  80. package/lib/expectations/not.d.ts.map +1 -0
  81. package/lib/expectations/not.js +32 -10
  82. package/lib/expectations/not.js.map +1 -1
  83. package/lib/expectations/or.d.ts +22 -1
  84. package/lib/expectations/or.d.ts.map +1 -0
  85. package/lib/expectations/or.js +29 -9
  86. package/lib/expectations/or.js.map +1 -1
  87. package/lib/expectations/property.d.ts +62 -0
  88. package/lib/expectations/property.d.ts.map +1 -0
  89. package/lib/expectations/property.js +85 -0
  90. package/lib/expectations/property.js.map +1 -0
  91. package/lib/expectations/startsWith.d.ts +22 -2
  92. package/lib/expectations/startsWith.d.ts.map +1 -0
  93. package/lib/expectations/startsWith.js +20 -5
  94. package/lib/expectations/startsWith.js.map +1 -1
  95. package/lib/index.d.ts +2 -1
  96. package/lib/index.d.ts.map +1 -0
  97. package/lib/index.js +6 -5
  98. package/lib/index.js.map +1 -1
  99. package/package.json +19 -42
  100. package/src/Ensure.ts +110 -136
  101. package/src/EnsureEventually.ts +173 -0
  102. package/src/expectations/and.ts +38 -14
  103. package/src/expectations/contain.ts +30 -5
  104. package/src/expectations/containAtLeastOneItemThat.ts +40 -10
  105. package/src/expectations/containItemsWhereEachItem.ts +35 -5
  106. package/src/expectations/endsWith.ts +25 -5
  107. package/src/expectations/equals.ts +31 -5
  108. package/src/expectations/includes.ts +25 -5
  109. package/src/expectations/index.ts +2 -0
  110. package/src/expectations/isAfter.ts +45 -5
  111. package/src/expectations/isBefore.ts +45 -5
  112. package/src/expectations/isCloseTo.ts +40 -0
  113. package/src/expectations/isFalse.ts +19 -1
  114. package/src/expectations/isGreaterThan.ts +48 -5
  115. package/src/expectations/isLessThan.ts +48 -5
  116. package/src/expectations/isPresent.ts +62 -13
  117. package/src/expectations/isTrue.ts +19 -1
  118. package/src/expectations/matches.ts +25 -5
  119. package/src/expectations/not.ts +28 -5
  120. package/src/expectations/or.ts +28 -6
  121. package/src/expectations/property.ts +93 -0
  122. package/src/expectations/startsWith.ts +25 -5
  123. package/src/index.ts +1 -1
  124. package/tsconfig.build.json +10 -0
  125. package/tsconfig.eslint.json +0 -10
@@ -1,5 +1,26 @@
1
- import { Answerable, AnswersQuestions, d, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
1
+ import { Answerable, AnswersQuestions, d, Expectation, ExpectationDetails, ExpectationMet, ExpectationNotMet, ExpectationOutcome, Unanswered } from '@serenity-js/core';
2
2
 
3
+ /**
4
+ * Produces an {@apilink Expectation|expectation} that is met when all the items of the actual array of `Item[]`
5
+ * meet the `expectation`.
6
+ *
7
+ * ## Ensuring that all the items in an array meet the expectation
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, containItemsWhereEachItem, endsWith } from '@serenity-js/assertions'
12
+ *
13
+ * const items = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ]
14
+ *
15
+ * await actorCalled('Ester').attemptsTo(
16
+ * Ensure.that(items, containItemsWhereEachItem(endsWith('day'))),
17
+ * )
18
+ * ```
19
+ *
20
+ * @param expectation
21
+ *
22
+ * @group Expectations
23
+ */
3
24
  export function containItemsWhereEachItem<Actual>(expectation: Expectation<Actual>): Expectation<Actual[]> {
4
25
  return new ContainItemsWhereEachItemMeetsExpectation(expectation);
5
26
  }
@@ -15,20 +36,23 @@ class ContainItemsWhereEachItemMeetsExpectation<Actual> extends Expectation<Actu
15
36
 
16
37
  constructor(private readonly expectation: Expectation<Actual>) {
17
38
  super(
39
+ 'containItemsWhereEachItem',
18
40
  ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
19
41
  async (actor: AnswersQuestions, actual: Answerable<Actual[]>) => {
20
42
 
21
43
  const items: Actual[] = await actor.answer(actual);
22
44
 
23
45
  if (! items || items.length === 0) {
46
+ const unanswered = new Unanswered();
24
47
  return new ExpectationNotMet(
25
48
  ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
26
- undefined,
49
+ ExpectationDetails.of('containItemsWhereEachItem', unanswered),
50
+ unanswered,
27
51
  items,
28
52
  );
29
53
  }
30
54
 
31
- let outcome: ExpectationOutcome<unknown, Actual>;
55
+ let outcome: ExpectationOutcome;
32
56
 
33
57
  for (const item of items) {
34
58
 
@@ -37,13 +61,19 @@ class ContainItemsWhereEachItemMeetsExpectation<Actual> extends Expectation<Actu
37
61
  if (outcome instanceof ExpectationNotMet) {
38
62
  return new ExpectationNotMet(
39
63
  ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
64
+ ExpectationDetails.of('containItemsWhereEachItem', outcome.expectation),
40
65
  outcome.expected,
41
- items
66
+ items,
42
67
  );
43
68
  }
44
69
  }
45
70
 
46
- return new ExpectationMet(ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation), outcome.expected, items);
71
+ return new ExpectationMet(
72
+ ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
73
+ ExpectationDetails.of('containItemsWhereEachItem', outcome.expectation),
74
+ outcome.expected,
75
+ items,
76
+ );
47
77
  }
48
78
  );
49
79
  }
@@ -1,6 +1,26 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function endsWith(expected: Answerable<string>): Expectation<string> {
4
- return Expectation.thatActualShould<string, string>('end with', expected)
5
- .soThat((actualValue, expectedValue) => actualValue.endsWith(expectedValue));
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual `string` value
5
+ * ends with the resolved value of `expected`.
6
+ *
7
+ * ## Ensuring that a given string ends with an expected substring
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, endsWith } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that('Hello World!', endsWith('!')),
15
+ * )
16
+ * ```
17
+ *
18
+ * @param expected
19
+ *
20
+ * @group Expectations
21
+ */
22
+ export const endsWith = Expectation.define(
23
+ 'endsWith', 'end with',
24
+ (actual: string, expected: string) =>
25
+ actual.endsWith(expected)
26
+ )
@@ -1,7 +1,33 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
  import { equal } from 'tiny-types/lib/objects';
3
3
 
4
- export function equals<Expected>(expectedValue: Answerable<Expected>): Expectation<Expected> {
5
- return Expectation.thatActualShould<Expected, Expected>('equal', expectedValue)
6
- .soThat((actual, expected) => equal(actual, expected));
7
- }
4
+ /**
5
+ * Produces an {@apilink Expectation|expectation} that is met when the actual value
6
+ * is equal to the resolved value of `expectedValue`.
7
+ *
8
+ * Note that the equality check performs comparison **by value**
9
+ * using [TinyTypes `equal`](https://github.com/jan-molak/tiny-types/blob/master/src/objects/equal.ts).
10
+ *
11
+ * ## Ensuring that the actual value equals expected value
12
+ *
13
+ * ```ts
14
+ * import { actorCalled } from '@serenity-js/core'
15
+ * import { Ensure, equals } from '@serenity-js/assertions'
16
+ *
17
+ * const actual = { name: 'apples' }
18
+ * const expected = { name: 'apples' }
19
+ *
20
+ * await actorCalled('Ester').attemptsTo(
21
+ * Ensure.that(actual, equals(expected)),
22
+ * )
23
+ * ```
24
+ *
25
+ * @param expectedValue
26
+ *
27
+ * @group Expectations
28
+ */
29
+ export const equals = Expectation.define(
30
+ 'equals', 'equal',
31
+ <T>(actual: T, expected: T) =>
32
+ equal(actual, expected),
33
+ );
@@ -1,6 +1,26 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function includes(expected: Answerable<string>): Expectation<string> {
4
- return Expectation.thatActualShould<string, string>('include', expected)
5
- .soThat((actualValue, expectedValue) => actualValue.includes(expectedValue));
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual `string` value
5
+ * includes a substring of `expected`.
6
+ *
7
+ * ## Ensuring that a given string includes the expected substring
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, includes } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that('Hello World!', includes('World')),
15
+ * )
16
+ * ```
17
+ *
18
+ * @param expected
19
+ *
20
+ * @group Expectations
21
+ */
22
+ export const includes = Expectation.define(
23
+ 'includes', 'include',
24
+ (actual: string, expected: string) =>
25
+ actual.includes(expected)
26
+ );
@@ -7,6 +7,7 @@ export * from './equals';
7
7
  export * from './includes';
8
8
  export * from './isAfter';
9
9
  export * from './isBefore';
10
+ export * from './isCloseTo';
10
11
  export * from './isFalse';
11
12
  export * from './isGreaterThan';
12
13
  export * from './isLessThan';
@@ -15,4 +16,5 @@ export * from './isTrue';
15
16
  export * from './matches';
16
17
  export * from './not';
17
18
  export * from './or';
19
+ export * from './property';
18
20
  export * from './startsWith';
@@ -1,6 +1,46 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function isAfter(expected: Answerable<Date>): Expectation<Date> {
4
- return Expectation.thatActualShould<Date, Date>('have value that is after', expected)
5
- .soThat((actualValue, expectedValue) => actualValue.getTime() > expectedValue.getTime());
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual value of type `Date`
5
+ * is after the expected `Date`.
6
+ *
7
+ * ## Ensuring that a given date is after the expected date
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, isAfter } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that(new Date('2022-01-01'), isAfter(new Date('1995-01-01'))),
15
+ * )
16
+ * ```
17
+ *
18
+ * ## Ensuring that a given date is within the expected date range
19
+ *
20
+ * ```ts
21
+ * import { actorCalled, Expectation, d } from '@serenity-js/core'
22
+ * import { Ensure, and, isAfter, isBefore } from '@serenity-js/assertions'
23
+ *
24
+ * const isWithinDateRange = (lowerBound: Answerable<Date>, upperBound: Answerable<Date>) =>
25
+ * Expectation.to(d`have value that is between ${ lowerBound } and ${ upperBound }`)
26
+ * .soThatActual(
27
+ * and(isAfter(lowerBound), isBefore(upperBound))
28
+ * ),
29
+ *
30
+ * await actorCalled('Ester').attemptsTo(
31
+ * Ensure.that(
32
+ * new Date('2022-01-01'),
33
+ * isWithinDateRange(new Date('1995-01-01'), new Date('2025-01-01'))
34
+ * ),
35
+ * )
36
+ * ```
37
+ *
38
+ * @param expected
39
+ *
40
+ * @group Expectations
41
+ */
42
+ export const isAfter = Expectation.define(
43
+ 'isAfter', 'have value that is after',
44
+ (actual: Date, expected: Date) =>
45
+ actual.getTime() > expected.getTime()
46
+ );
@@ -1,6 +1,46 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function isBefore(expected: Answerable<Date>): Expectation<Date> {
4
- return Expectation.thatActualShould<Date, Date>('have value that is before', expected)
5
- .soThat((actualValue, expectedValue) => actualValue.getTime() < expectedValue.getTime());
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual value of type `Date`
5
+ * is before the expected `Date`.
6
+ *
7
+ * ## Ensuring that a given date is after the expected date
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, isBefore } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that(new Date('1995-01-01'), isBefore(new Date('2022-01-01'))),
15
+ * )
16
+ * ```
17
+ *
18
+ * ## Ensuring that a given date is within the expected date range
19
+ *
20
+ * ```ts
21
+ * import { actorCalled, Expectation, d } from '@serenity-js/core'
22
+ * import { Ensure, and, isAfter, isBefore } from '@serenity-js/assertions'
23
+ *
24
+ * const isWithinDateRange = (lowerBound: Answerable<Date>, upperBound: Answerable<Date>) =>
25
+ * Expectation.to(d`have value that is between ${ lowerBound } and ${ upperBound }`)
26
+ * .soThatActual(
27
+ * and(isAfter(lowerBound), isBefore(upperBound))
28
+ * ),
29
+ *
30
+ * await actorCalled('Ester').attemptsTo(
31
+ * Ensure.that(
32
+ * new Date('2022-01-01'),
33
+ * isWithinDateRange(new Date('1995-01-01'), new Date('2025-01-01'))
34
+ * ),
35
+ * )
36
+ * ```
37
+ *
38
+ * @param expected
39
+ *
40
+ * @group Expectations
41
+ */
42
+ export const isBefore = Expectation.define(
43
+ 'isBefore', 'have value that is before',
44
+ (actual: Date, expected: Date) =>
45
+ actual.getTime() < expected.getTime()
46
+ );
@@ -0,0 +1,40 @@
1
+ import { d, Expectation } from '@serenity-js/core';
2
+
3
+ /**
4
+ * Produces an {@apilink Expectation|expectation} that is met when the actual value
5
+ * is within a given ± `absoluteTolerance` range of the `expected` value.
6
+ *
7
+ * ## Ensuring that a given floating point number is close to the expected number
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, isCloseTo } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Iris').attemptsTo(
14
+ * Ensure.that(10.123, isCloseTo(10, 0.2))
15
+ * )
16
+ * ```
17
+ *
18
+ * @param expected
19
+ * @param [absoluteTolerance=1e-9]
20
+ * Absolute ± tolerance range, defaults to `1e-9`
21
+ *
22
+ * @group Expectations
23
+ */
24
+ export const isCloseTo = Expectation.define(
25
+ 'isCloseTo', (expected, absoluteTolerance = 1e-9) => d`have value close to ${ expected } ±${ absoluteTolerance }`,
26
+ (actual: number, expected: number, absoluteTolerance = 1e-9) => {
27
+ // short-circuit exact equality
28
+ if (actual === expected) {
29
+ return true;
30
+ }
31
+
32
+ if (! (Number.isFinite(actual) && Number.isFinite(expected))) {
33
+ return false;
34
+ }
35
+
36
+ const difference = Math.abs(actual - expected)
37
+
38
+ return difference <= absoluteTolerance;
39
+ }
40
+ )
@@ -2,6 +2,24 @@ import { Expectation } from '@serenity-js/core';
2
2
 
3
3
  import { equals } from './equals';
4
4
 
5
+ /**
6
+ * Creates an {@apilink Expectation|expectation} that is met when the actual `boolean` value
7
+ * is `false`.
8
+ *
9
+ * ## Ensuring that a given value is false
10
+ *
11
+ * ```ts
12
+ * import { actorCalled } from '@serenity-js/core'
13
+ * import { Ensure, isFalse } from '@serenity-js/assertions'
14
+ * import { Cookie } from '@serenity-js/web'
15
+ *
16
+ * await actorCalled('Ester').attemptsTo(
17
+ * Ensure.that(Cookie.called('example-regular-cookie').isSecure(), isFalse()),
18
+ * )
19
+ * ```
20
+ *
21
+ * @group Expectations
22
+ */
5
23
  export function isFalse(): Expectation<boolean> {
6
- return Expectation.to<never, boolean>(`equal false`).soThatActual(equals(false));
24
+ return Expectation.to<boolean>(`equal false`).soThatActual(equals(false));
7
25
  }
@@ -1,6 +1,49 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function isGreaterThan(expected: Answerable<number>): Expectation<number> {
4
- return Expectation.thatActualShould<number, number>('have value greater than', expected)
5
- .soThat((actualValue, expectedValue) => actualValue > expectedValue);
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual value of type `number`
5
+ * is greater than the expected `number`.
6
+ *
7
+ * ## Ensuring that a given number is greater than the expected number
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, isGreaterThan } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that(10, isGreaterThan(5)),
15
+ * )
16
+ * ```
17
+ *
18
+ * ## Ensuring that a given number is within the expected range
19
+ *
20
+ * ```ts
21
+ * import { actorCalled, Expectation, d } from '@serenity-js/core'
22
+ * import { Ensure, and, equals, isGreaterThan, isLessThan, or } from '@serenity-js/assertions'
23
+ *
24
+ * const isWithinRange = (lowerBound: Answerable<number>, upperBound: Answerable<number>) =>
25
+ * Expectation.to(d`have value that is between ${ lowerBound } and ${ upperBound }`)
26
+ * .soThatActual(
27
+ * and(
28
+ * or(equals(lowerBound), isGreaterThan(lowerBound)),
29
+ * or(equals(upperBound), isLessThan(upperBound)),
30
+ * )
31
+ * ),
32
+ *
33
+ * await actorCalled('Ester').attemptsTo(
34
+ * Ensure.that(
35
+ * 7,
36
+ * isWithinRange(5, 10)
37
+ * ),
38
+ * )
39
+ * ```
40
+ *
41
+ * @param expected
42
+ *
43
+ * @group Expectations
44
+ */
45
+ export const isGreaterThan = Expectation.define(
46
+ 'isGreaterThan', 'have value greater than',
47
+ (actual: number, expected: number) =>
48
+ actual > expected,
49
+ )
@@ -1,6 +1,49 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function isLessThan(expected: Answerable<number>): Expectation<number> {
4
- return Expectation.thatActualShould<number, number>(`have value that's less than`, expected)
5
- .soThat((actualValue, expectedValue) => actualValue < expectedValue);
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual value of type `number`
5
+ * is less than the expected `number`.
6
+ *
7
+ * ## Ensuring that a given number is less than the expected number
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, isLessThan } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that(5, isLessThan(10)),
15
+ * )
16
+ * ```
17
+ *
18
+ * ## Ensuring that a given number is within the expected range
19
+ *
20
+ * ```ts
21
+ * import { actorCalled, Expectation, d } from '@serenity-js/core'
22
+ * import { Ensure, and, equals, isGreaterThan, isLessThan, or } from '@serenity-js/assertions'
23
+ *
24
+ * const isWithinRange = (lowerBound: Answerable<number>, upperBound: Answerable<number>) =>
25
+ * Expectation.to(d`have value that is between ${ lowerBound } and ${ upperBound }`)
26
+ * .soThatActual(
27
+ * and(
28
+ * or(equals(lowerBound), isGreaterThan(lowerBound)),
29
+ * or(equals(upperBound), isLessThan(upperBound)),
30
+ * )
31
+ * ),
32
+ *
33
+ * await actorCalled('Ester').attemptsTo(
34
+ * Ensure.that(
35
+ * 7,
36
+ * isWithinRange(5, 10)
37
+ * ),
38
+ * )
39
+ * ```
40
+ *
41
+ * @param expected
42
+ *
43
+ * @group Expectations
44
+ */
45
+ export const isLessThan = Expectation.define(
46
+ 'isLessThan', `have value that's less than`,
47
+ (actual: number, expected: number) =>
48
+ actual < expected,
49
+ );
@@ -1,16 +1,65 @@
1
- import { Answerable, AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, Optional } from '@serenity-js/core';
1
+ import { Answerable, AnswersQuestions, Expectation, ExpectationDetails, ExpectationMet, ExpectationNotMet, Optional } from '@serenity-js/core';
2
2
 
3
3
  /**
4
- * @desc
5
- * Expectation that the `actual` is not undefined or null.
6
- * Also, for `actual` implementing {@link @serenity-js/core/lib/screenplay~Optional}, that `Optional.isPresent()` returns an {@link @serenity-js/core/lib/screenplay~Answerable}
7
- * that resolves to `true`
4
+ * Creates an {@apilink Expectation|expectation} that is met when the `actual` value is not undefined or null.
8
5
  *
9
- * @returns {@serenity-js/core/lib/screenplay/questions~Expectation<Answerable<boolean>, Optional>}
6
+ * Also, when the `actual` implements {@apilink Optional}, the expectation is met when calling {@apilink Optional.isPresent()}
7
+ * returns an {@apilink Answerable} that resolves to `true`
10
8
  *
11
- * @see {@link @serenity-js/assertions~Ensure}
12
- * @see {@link @serenity-js/core/lib/screenplay/questions~Check}
13
- * @see {@link Wait}
9
+ * ## Ensuring that a value is defined
10
+ *
11
+ * ```ts
12
+ * import { actorCalled } from '@serenity-js/core'
13
+ * import { CallAnApi, Send, GetRequest, LastResponse } from '@serenity-js/rest'
14
+ * import { Ensure, isPresent } from '@serenity-js/assertions'
15
+ *
16
+ * interface Product {
17
+ * name: string;
18
+ * }
19
+ *
20
+ * interface ProductsResponse {
21
+ * products: Product[];
22
+ * }
23
+ *
24
+ * await actorCalled('Apisitt')
25
+ * .whoCan(CallAnApi.at('https://api.example.org'))
26
+ * .attemptsTo(
27
+ * Send.a(GetRequest.to('/products')),
28
+ * Ensure.that(LastResponse.body<ProductsResponse>().products[0], isPresent()),
29
+ * )
30
+ * ```
31
+ *
32
+ * ## Checking if a PageElement is present
33
+ *
34
+ * ```ts
35
+ * import { actorCalled, Check } from '@serenity-js/core';
36
+ * import { BrowseTheWebWithPlaywright } from '@serenity-js/playwright';
37
+ * import { By, Click, Navigate, PageElement } from '@serenity-js/web';
38
+ * import { Browser, chromium } from 'playwright';
39
+ *
40
+ * class NewsletterSubscription {
41
+ * static modal = () =>
42
+ * PageElement.located(By.id('newsletter-subscription'))
43
+ * .describedAs('newsletter subscription modal')
44
+ *
45
+ * static closeButton = () =>
46
+ * PageElement.located(By.class('.close'))
47
+ * .of(NewsletterSubscription.modal())
48
+ * .describedAs('close button')
49
+ * }
50
+ *
51
+ * const browser = await chromium.launch({ headless: true });
52
+ *
53
+ * await actorCalled('Isabela')
54
+ * .whoCan(BrowseTheWebWithPlaywright.using(browser))
55
+ * .attemptsTo(
56
+ * Navigate.to(`https://example.org`),
57
+ * Check.whether(NewsletterSubscription.modal(), isPresent())
58
+ * .andIfSo(Click.on(NewsletterSubscription.closeButton())),
59
+ * )
60
+ * ```
61
+ *
62
+ * @group Expectations
14
63
  */
15
64
  export function isPresent<Actual>(): Expectation<Actual> {
16
65
  return new IsPresent<Actual>();
@@ -42,16 +91,16 @@ class IsPresent<Actual> extends Expectation<Actual> {
42
91
 
43
92
  constructor() {
44
93
  super(
94
+ 'isPresent',
45
95
  'become present',
46
96
  async (actor: AnswersQuestions, actual: Answerable<Actual>) => {
47
97
 
48
- const value = await IsPresent.valueToCheck(actual, actor);
49
-
98
+ const value = await IsPresent.valueToCheck(actual, actor);
50
99
  const result = await IsPresent.isPresent(value, actor);
51
100
 
52
101
  return result
53
- ? new ExpectationMet('become present', undefined, undefined)
54
- : new ExpectationNotMet('become present', undefined, undefined);
102
+ ? new ExpectationMet('become present', ExpectationDetails.of('isPresent'), true, actual)
103
+ : new ExpectationNotMet('become present', ExpectationDetails.of('isPresent'), true, actual);
55
104
  }
56
105
  );
57
106
  }
@@ -2,6 +2,24 @@ import { Expectation } from '@serenity-js/core';
2
2
 
3
3
  import { equals } from './equals';
4
4
 
5
+ /**
6
+ * Creates an {@apilink Expectation|expectation} that is met when the actual `boolean` value
7
+ * is `true`.
8
+ *
9
+ * ## Ensuring that a given value is true
10
+ *
11
+ * ```ts
12
+ * import { actorCalled } from '@serenity-js/core'
13
+ * import { Ensure, isTrue } from '@serenity-js/assertions'
14
+ * import { Cookie } from '@serenity-js/web'
15
+ *
16
+ * await actorCalled('Ester').attemptsTo(
17
+ * Ensure.that(Cookie.called('example-secure-cookie').isSecure(), isTrue()),
18
+ * )
19
+ * ```
20
+ *
21
+ * @group Expectations
22
+ */
5
23
  export function isTrue(): Expectation<boolean> {
6
- return Expectation.to<never, boolean>(`equal true`).soThatActual(equals(true));
24
+ return Expectation.to<boolean>(`equal true`).soThatActual(equals(true));
7
25
  }
@@ -1,6 +1,26 @@
1
- import { Answerable, Expectation } from '@serenity-js/core';
1
+ import { Expectation } from '@serenity-js/core';
2
2
 
3
- export function matches(expected: Answerable<RegExp>): Expectation<string> {
4
- return Expectation.thatActualShould<RegExp, string>('match', expected)
5
- .soThat((actualValue, expectedValue) => expectedValue.test(actualValue));
6
- }
3
+ /**
4
+ * Creates an {@apilink Expectation|expectation} that is met when the actual `string` value
5
+ * matches the `expected` regular expression.
6
+ *
7
+ * ## Ensuring that a given string matches a regular expression
8
+ *
9
+ * ```ts
10
+ * import { actorCalled } from '@serenity-js/core'
11
+ * import { Ensure, includes } from '@serenity-js/assertions'
12
+ *
13
+ * await actorCalled('Ester').attemptsTo(
14
+ * Ensure.that('Hello World!', matches(/[Ww]orld/)),
15
+ * )
16
+ * ```
17
+ *
18
+ * @param expected
19
+ *
20
+ * @group Expectations
21
+ */
22
+ export const matches = Expectation.define(
23
+ 'matches', 'match',
24
+ (actual: string, expected: RegExp) =>
25
+ expected.test(actual),
26
+ );