@serenity-js/assertions 3.0.0-rc.4 → 3.0.0-rc.40
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/CHANGELOG.md +63 -1850
- package/README.md +10 -8
- package/lib/Ensure.d.ts +56 -77
- package/lib/Ensure.d.ts.map +1 -0
- package/lib/Ensure.js +72 -95
- package/lib/Ensure.js.map +1 -1
- package/lib/expectations/and.d.ts +22 -1
- package/lib/expectations/and.d.ts.map +1 -0
- package/lib/expectations/and.js +26 -6
- package/lib/expectations/and.js.map +1 -1
- package/lib/expectations/contain.d.ts +26 -1
- package/lib/expectations/contain.d.ts.map +1 -0
- package/lib/expectations/contain.js +25 -1
- package/lib/expectations/contain.js.map +1 -1
- package/lib/expectations/containAtLeastOneItemThat.d.ts +23 -1
- package/lib/expectations/containAtLeastOneItemThat.d.ts.map +1 -0
- package/lib/expectations/containAtLeastOneItemThat.js +38 -10
- package/lib/expectations/containAtLeastOneItemThat.js.map +1 -1
- package/lib/expectations/containItemsWhereEachItem.d.ts +23 -1
- package/lib/expectations/containItemsWhereEachItem.d.ts.map +1 -0
- package/lib/expectations/containItemsWhereEachItem.js +38 -10
- package/lib/expectations/containItemsWhereEachItem.js.map +1 -1
- package/lib/expectations/endsWith.d.ts +20 -0
- package/lib/expectations/endsWith.d.ts.map +1 -0
- package/lib/expectations/endsWith.js +19 -0
- package/lib/expectations/endsWith.js.map +1 -1
- package/lib/expectations/equals.d.ts +26 -0
- package/lib/expectations/equals.d.ts.map +1 -0
- package/lib/expectations/equals.js +25 -0
- package/lib/expectations/equals.js.map +1 -1
- package/lib/expectations/includes.d.ts +20 -0
- package/lib/expectations/includes.d.ts.map +1 -0
- package/lib/expectations/includes.js +19 -0
- package/lib/expectations/includes.js.map +1 -1
- package/lib/expectations/index.d.ts +3 -0
- package/lib/expectations/index.d.ts.map +1 -0
- package/lib/expectations/index.js +7 -1
- package/lib/expectations/index.js.map +1 -1
- package/lib/expectations/isAfter.d.ts +40 -0
- package/lib/expectations/isAfter.d.ts.map +1 -0
- package/lib/expectations/isAfter.js +39 -0
- package/lib/expectations/isAfter.js.map +1 -1
- package/lib/expectations/isBefore.d.ts +40 -0
- package/lib/expectations/isBefore.d.ts.map +1 -0
- package/lib/expectations/isBefore.js +39 -0
- package/lib/expectations/isBefore.js.map +1 -1
- package/lib/expectations/isCloseTo.d.ts +24 -0
- package/lib/expectations/isCloseTo.d.ts.map +1 -0
- package/lib/expectations/isCloseTo.js +57 -0
- package/lib/expectations/isCloseTo.js.map +1 -0
- package/lib/expectations/isFalse.d.ts +19 -0
- package/lib/expectations/isFalse.d.ts.map +1 -0
- package/lib/expectations/isFalse.js +18 -0
- package/lib/expectations/isFalse.js.map +1 -1
- package/lib/expectations/isGreaterThan.d.ts +43 -0
- package/lib/expectations/isGreaterThan.d.ts.map +1 -0
- package/lib/expectations/isGreaterThan.js +42 -0
- package/lib/expectations/isGreaterThan.js.map +1 -1
- package/lib/expectations/isLessThan.d.ts +43 -0
- package/lib/expectations/isLessThan.d.ts.map +1 -0
- package/lib/expectations/isLessThan.js +42 -0
- package/lib/expectations/isLessThan.js.map +1 -1
- package/lib/expectations/isPresent.d.ts +64 -0
- package/lib/expectations/isPresent.d.ts.map +1 -0
- package/lib/expectations/isPresent.js +99 -0
- package/lib/expectations/isPresent.js.map +1 -0
- package/lib/expectations/isTrue.d.ts +19 -0
- package/lib/expectations/isTrue.d.ts.map +1 -0
- package/lib/expectations/isTrue.js +18 -0
- package/lib/expectations/isTrue.js.map +1 -1
- package/lib/expectations/matches.d.ts +21 -1
- package/lib/expectations/matches.d.ts.map +1 -0
- package/lib/expectations/matches.js +19 -0
- package/lib/expectations/matches.js.map +1 -1
- package/lib/expectations/not.d.ts +23 -1
- package/lib/expectations/not.d.ts.map +1 -0
- package/lib/expectations/not.js +32 -12
- package/lib/expectations/not.js.map +1 -1
- package/lib/expectations/or.d.ts +22 -1
- package/lib/expectations/or.d.ts.map +1 -0
- package/lib/expectations/or.js +40 -15
- package/lib/expectations/or.js.map +1 -1
- package/lib/expectations/property.d.ts +61 -1
- package/lib/expectations/property.d.ts.map +1 -0
- package/lib/expectations/property.js +66 -10
- package/lib/expectations/property.js.map +1 -1
- package/lib/expectations/startsWith.d.ts +20 -0
- package/lib/expectations/startsWith.d.ts.map +1 -0
- package/lib/expectations/startsWith.js +19 -0
- package/lib/expectations/startsWith.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +5 -5
- package/lib/index.js.map +1 -1
- package/package.json +17 -41
- package/src/Ensure.ts +81 -101
- package/src/expectations/and.ts +39 -18
- package/src/expectations/contain.ts +26 -2
- package/src/expectations/containAtLeastOneItemThat.ts +59 -14
- package/src/expectations/containItemsWhereEachItem.ts +59 -14
- package/src/expectations/endsWith.ts +19 -0
- package/src/expectations/equals.ts +25 -0
- package/src/expectations/includes.ts +19 -0
- package/src/expectations/index.ts +2 -0
- package/src/expectations/isAfter.ts +39 -0
- package/src/expectations/isBefore.ts +39 -0
- package/src/expectations/isCloseTo.ts +66 -0
- package/src/expectations/isFalse.ts +19 -1
- package/src/expectations/isGreaterThan.ts +42 -0
- package/src/expectations/isLessThan.ts +42 -0
- package/src/expectations/isPresent.ts +107 -0
- package/src/expectations/isTrue.ts +19 -1
- package/src/expectations/matches.ts +20 -1
- package/src/expectations/not.ts +36 -15
- package/src/expectations/or.ts +49 -26
- package/src/expectations/property.ts +78 -21
- package/src/expectations/startsWith.ts +19 -0
- package/src/index.ts +0 -1
- package/tsconfig.build.json +10 -0
- package/tsconfig.eslint.json +0 -10
package/src/Ensure.ts
CHANGED
|
@@ -1,173 +1,153 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Activity,
|
|
2
3
|
Answerable,
|
|
3
4
|
AnswersQuestions,
|
|
4
5
|
AssertionError,
|
|
5
6
|
CollectsArtifacts,
|
|
7
|
+
d,
|
|
6
8
|
Expectation,
|
|
7
9
|
ExpectationMet,
|
|
8
10
|
ExpectationNotMet,
|
|
9
11
|
ExpectationOutcome,
|
|
12
|
+
f,
|
|
10
13
|
Interaction,
|
|
11
14
|
LogicError,
|
|
12
15
|
RuntimeError,
|
|
13
16
|
UsesAbilities,
|
|
14
17
|
} from '@serenity-js/core';
|
|
15
|
-
import {
|
|
18
|
+
import { FileSystemLocation } from '@serenity-js/core/lib/io';
|
|
16
19
|
import { inspected } from '@serenity-js/core/lib/io/inspected';
|
|
17
20
|
import { Artifact, AssertionReport, Name } from '@serenity-js/core/lib/model';
|
|
18
21
|
import { match } from 'tiny-types';
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
|
-
* @
|
|
22
|
-
*
|
|
24
|
+
* The {@apilink Interaction|interaction} to `Ensure`
|
|
25
|
+
* verifies if the resolved value of the provided {@apilink Answerable}
|
|
26
|
+
* meets the specified {@apilink Expectation}.
|
|
27
|
+
* If not, it throws an {@apilink AssertionError}.
|
|
23
28
|
*
|
|
24
|
-
*
|
|
25
|
-
* state and ensures that its value meets the {@link @serenity-js/core/lib/screenplay/questions~Expectation}s provided.
|
|
29
|
+
* Use `Ensure` to verify the state of the system under test.
|
|
26
30
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
31
|
+
* ## Basic usage with static values
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { actorCalled } from '@serenity-js/core'
|
|
34
|
+
* import { Ensure, equals } from '@serenity-js/assertions'
|
|
30
35
|
*
|
|
31
|
-
*
|
|
36
|
+
* await actorCalled('Erica').attemptsTo(
|
|
37
|
+
* Ensure.that('Hello world!', equals('Hello world!'))
|
|
38
|
+
* )
|
|
39
|
+
* ```
|
|
32
40
|
*
|
|
33
|
-
*
|
|
34
|
-
* Ensure.that('Hello world!', equals('Hello world!'))
|
|
35
|
-
* );
|
|
41
|
+
* ## Composing expectations with `and`
|
|
36
42
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { actorCalled } from '@serenity-js/core'
|
|
45
|
+
* import { and, Ensure, startsWith, endsWith } from '@serenity-js/assertions'
|
|
40
46
|
*
|
|
41
|
-
*
|
|
47
|
+
* await actorCalled('Erica').attemptsTo(
|
|
48
|
+
* Ensure.that('Hello world!', and(startsWith('Hello'), endsWith('!'))
|
|
49
|
+
* )
|
|
50
|
+
* ```
|
|
42
51
|
*
|
|
43
|
-
*
|
|
44
|
-
* Ensure.that('Hello world!', and(startsWith('Hello'), endsWith('!'))
|
|
45
|
-
* );
|
|
52
|
+
* ## Overriding the type of Error thrown upon assertion failure
|
|
46
53
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { actorCalled, TestCompromisedError } from '@serenity-js/core'
|
|
56
|
+
* import { and, Ensure, startsWith, endsWith } from '@serenity-js/assertions'
|
|
57
|
+
* import { CallAnApi, GetRequest, LastResponse, Send } from '@serenity-js/rest'
|
|
51
58
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
59
|
+
* await actorCalled('Erica')
|
|
60
|
+
* .whoCan(CallAnApi.at('https://example.com'))
|
|
61
|
+
* .attemptsTo(
|
|
62
|
+
* Send.a(GetRequest.to('/api/health')),
|
|
63
|
+
* Ensure.that(LastResponse.status(), equals(200))
|
|
64
|
+
* .otherwiseFailWith(TestCompromisedError, 'The server is down, please cheer it up!')
|
|
65
|
+
* )
|
|
66
|
+
* ```
|
|
54
67
|
*
|
|
55
|
-
*
|
|
56
|
-
* Send.a(GetRequest.to('/api/health')),
|
|
57
|
-
* Ensure.that(LastResponse.status(), equals(200))
|
|
58
|
-
* .otherwiseFailWith(TestCompromisedError, 'The server is down, please cheer it up!')
|
|
59
|
-
* );
|
|
60
|
-
*
|
|
61
|
-
* @extends {@serenity-js/core/lib/screenplay~Interaction}
|
|
68
|
+
* @group Interactions
|
|
62
69
|
*/
|
|
63
70
|
export class Ensure<Actual> extends Interaction {
|
|
71
|
+
|
|
64
72
|
/**
|
|
73
|
+
* @param {Answerable<Actual_Type>} actual
|
|
74
|
+
* An {@apilink Answerable} describing the actual state of the system.
|
|
65
75
|
*
|
|
66
|
-
* @param {
|
|
67
|
-
* @
|
|
76
|
+
* @param {Expectation<Actual_Type>} expectation
|
|
77
|
+
* An {@apilink Expectation} you expect the `actual` value to meet
|
|
68
78
|
*
|
|
69
|
-
* @returns {Ensure<
|
|
79
|
+
* @returns {Ensure<Actual_Type>}
|
|
70
80
|
*/
|
|
71
|
-
static that<
|
|
72
|
-
return new Ensure(actual, expectation);
|
|
81
|
+
static that<Actual_Type>(actual: Answerable<Actual_Type>, expectation: Expectation<Actual_Type>): Ensure<Actual_Type> {
|
|
82
|
+
return new Ensure(actual, expectation, Activity.callerLocation(5));
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
/**
|
|
76
|
-
* @param
|
|
77
|
-
* @param
|
|
86
|
+
* @param actual
|
|
87
|
+
* @param expectation
|
|
88
|
+
* @param location
|
|
78
89
|
*/
|
|
79
|
-
constructor(
|
|
90
|
+
protected constructor(
|
|
80
91
|
protected readonly actual: Answerable<Actual>,
|
|
81
92
|
protected readonly expectation: Expectation<Actual>,
|
|
93
|
+
location: FileSystemLocation,
|
|
82
94
|
) {
|
|
83
|
-
super();
|
|
95
|
+
super(d`#actor ensures that ${ actual } does ${ expectation }`, location);
|
|
84
96
|
}
|
|
85
97
|
|
|
86
98
|
/**
|
|
87
|
-
* @
|
|
88
|
-
* Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
89
|
-
* perform this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
90
|
-
*
|
|
91
|
-
* @param {UsesAbilities & CollectsArtifacts & AnswersQuestions} actor
|
|
92
|
-
* @returns {Promise<void>}
|
|
93
|
-
*
|
|
94
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
95
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
|
|
96
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~CollectsArtifacts}
|
|
97
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
|
|
99
|
+
* @inheritDoc
|
|
98
100
|
*/
|
|
99
|
-
performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void> {
|
|
100
|
-
|
|
101
|
-
actor.answer(this.actual),
|
|
102
|
-
actor.answer(this.expectation),
|
|
103
|
-
]).then(([ actual, expectation ]) =>
|
|
104
|
-
expectation(actual).then(outcome =>
|
|
105
|
-
match<ExpectationOutcome<unknown, Actual>, void>(outcome)
|
|
106
|
-
.when(ExpectationNotMet, o => {
|
|
107
|
-
actor.collect(this.artifactFrom(o.expected, o.actual), new Name(`Assertion Report`));
|
|
101
|
+
async performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void> {
|
|
102
|
+
const outcome = await actor.answer(this.expectation.isMetFor(this.actual));
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.else(o => {
|
|
113
|
-
throw new LogicError(formatted `An Expectation should return an instance of an ExpectationOutcome, not ${ o }`);
|
|
114
|
-
}),
|
|
115
|
-
),
|
|
116
|
-
);
|
|
117
|
-
}
|
|
104
|
+
return match<ExpectationOutcome<unknown, Actual>, void>(outcome)
|
|
105
|
+
.when(ExpectationNotMet, o => {
|
|
106
|
+
actor.collect(this.artifactFrom(o.expected, o.actual), new Name(`Assertion Report`));
|
|
118
107
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
toString(): string {
|
|
126
|
-
return formatted `#actor ensures that ${ this.actual } does ${ this.expectation }`;
|
|
108
|
+
throw this.errorForOutcome(o);
|
|
109
|
+
})
|
|
110
|
+
.when(ExpectationMet, _ => void 0)
|
|
111
|
+
.else(o => {
|
|
112
|
+
throw new LogicError(f`Expectation#isMetFor(actual) should return an instance of an ExpectationOutcome, not ${ o }`);
|
|
113
|
+
});
|
|
127
114
|
}
|
|
128
115
|
|
|
129
116
|
/**
|
|
130
|
-
* @
|
|
131
|
-
*
|
|
132
|
-
* the actual value does not meet the expectations set.
|
|
117
|
+
* Overrides the default {@apilink AssertionError} thrown when
|
|
118
|
+
* the actual value does not meet the expectation.
|
|
133
119
|
*
|
|
134
|
-
* @param
|
|
135
|
-
*
|
|
120
|
+
* @param typeOfRuntimeError
|
|
121
|
+
* A constructor function producing a subtype of {@apilink RuntimeError} to throw, e.g. {@apilink TestCompromisedError}
|
|
136
122
|
*
|
|
137
|
-
* @param
|
|
123
|
+
* @param message
|
|
138
124
|
* The message explaining the failure
|
|
139
|
-
*
|
|
140
|
-
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
141
125
|
*/
|
|
142
126
|
otherwiseFailWith(typeOfRuntimeError: new (message: string, cause?: Error) => RuntimeError, message?: string): Interaction {
|
|
143
127
|
return new EnsureOrFailWithCustomError(this.actual, this.expectation, typeOfRuntimeError, message);
|
|
144
128
|
}
|
|
145
129
|
|
|
146
130
|
/**
|
|
147
|
-
* @
|
|
148
|
-
* Maps an {@link @serenity-js/core/lib/screenplay/questions/expectations~ExpectationOutcome} to appropriate {@link @serenity-js/core/lib/errors~RuntimeError}.
|
|
149
|
-
*
|
|
150
|
-
* @param {@serenity-js/core/lib/screenplay/questions/expectations~ExpectationOutcome} outcome
|
|
151
|
-
* @returns {@serenity-js/core/lib/errors~RuntimeError}
|
|
152
|
-
*
|
|
153
|
-
* @protected
|
|
131
|
+
* Maps an {@apilink ExpectationOutcome} to appropriate {@apilink RuntimeError}.
|
|
154
132
|
*/
|
|
155
133
|
protected errorForOutcome(outcome: ExpectationOutcome<any, Actual>): RuntimeError {
|
|
156
134
|
return this.asAssertionError(outcome);
|
|
157
135
|
}
|
|
158
136
|
|
|
159
137
|
/**
|
|
160
|
-
* @
|
|
161
|
-
* Maps an {@link Outcome} to {@link @serenity-js/core/lib/errors~AssertionError}.
|
|
162
|
-
*
|
|
163
|
-
* @param {Outcome} outcome
|
|
164
|
-
* @returns {@serenity-js/core/lib/errors~AssertionError}
|
|
138
|
+
* Maps an {@apilink Outcome} to {@apilink AssertionError}.
|
|
165
139
|
*
|
|
166
|
-
* @
|
|
140
|
+
* @param outcome
|
|
167
141
|
*/
|
|
168
142
|
protected asAssertionError(outcome: ExpectationOutcome<any, Actual>): AssertionError {
|
|
143
|
+
const actualDescription = d`${ this.actual }`;
|
|
144
|
+
const inspectedActual = inspected(outcome.actual, { inline: true, markQuestions: false });
|
|
145
|
+
const message = actualDescription === inspectedActual
|
|
146
|
+
? `Expected ${ actualDescription } to ${ outcome.message }`
|
|
147
|
+
: `Expected ${ actualDescription } to ${ outcome.message } but got ${ inspectedActual }`;
|
|
148
|
+
|
|
169
149
|
return new AssertionError(
|
|
170
|
-
|
|
150
|
+
message,
|
|
171
151
|
outcome.expected,
|
|
172
152
|
outcome.actual,
|
|
173
153
|
);
|
|
@@ -191,7 +171,7 @@ class EnsureOrFailWithCustomError<Actual> extends Ensure<Actual> {
|
|
|
191
171
|
private readonly typeOfRuntimeError: new (message: string, cause?: Error) => RuntimeError,
|
|
192
172
|
private readonly message?: string,
|
|
193
173
|
) {
|
|
194
|
-
super(actual, expectation);
|
|
174
|
+
super(actual, expectation, Activity.callerLocation(6));
|
|
195
175
|
}
|
|
196
176
|
|
|
197
177
|
protected errorForOutcome(outcome: ExpectationOutcome<any, Actual>): RuntimeError {
|
package/src/expectations/and.ts
CHANGED
|
@@ -1,29 +1,50 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationNotMet
|
|
1
|
+
import { Answerable, AnswersQuestions, Expectation, ExpectationNotMet } from '@serenity-js/core';
|
|
2
2
|
import { match } from 'tiny-types';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Creates an {@apilink Expectation|expectation} that is met when all the `expectations` are met for the given actual value.
|
|
6
|
+
*
|
|
7
|
+
* Use `and` to combine several expectations using logical "and",
|
|
8
|
+
*
|
|
9
|
+
* ## Combining several expectations
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { actorCalled } from '@serenity-js/core'
|
|
13
|
+
* import { Ensure, and, startsWith, endsWith } from '@serenity-js/assertions'
|
|
14
|
+
*
|
|
15
|
+
* await actorCalled('Ester').attemptsTo(
|
|
16
|
+
* Ensure.that('Hello World!', and(startsWith('Hello'), endsWith('!'))),
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @param expectations
|
|
21
|
+
*
|
|
22
|
+
* @group Expectations
|
|
23
|
+
*/
|
|
24
|
+
export function and<Actual_Type>(...expectations: Array<Expectation<Actual_Type>>): Expectation<Actual_Type> {
|
|
5
25
|
return new And(expectations);
|
|
6
26
|
}
|
|
7
27
|
|
|
8
28
|
/**
|
|
9
29
|
* @package
|
|
10
30
|
*/
|
|
11
|
-
class And<Actual> extends Expectation<
|
|
12
|
-
|
|
13
|
-
super(expectations.map(assertion => assertion.toString()).join(' and '));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
answeredBy(actor: AnswersQuestions): (actual: Actual) => Promise<ExpectationOutcome<any, Actual>> {
|
|
31
|
+
class And<Actual> extends Expectation<Actual> {
|
|
32
|
+
private static readonly Separator = ' and ';
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
constructor(private readonly expectations: Array<Expectation<Actual>>) {
|
|
35
|
+
super(
|
|
36
|
+
expectations.map(expectation => expectation.toString()).join(And.Separator),
|
|
37
|
+
(actor: AnswersQuestions, actual: Answerable<Actual>) => {
|
|
38
|
+
return expectations.reduce(
|
|
39
|
+
(previous, current) =>
|
|
40
|
+
previous.then(outcome =>
|
|
41
|
+
match(outcome)
|
|
42
|
+
.when(ExpectationNotMet, o => o)
|
|
43
|
+
.else(_ => actor.answer(current.isMetFor(actual))),
|
|
44
|
+
),
|
|
45
|
+
Promise.resolve(void 0),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
);
|
|
28
49
|
}
|
|
29
50
|
}
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import { Answerable, Expectation } from '@serenity-js/core';
|
|
2
2
|
import { equal } from 'tiny-types/lib/objects';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Produces an {@apilink Expectation|expectation} that is met when the actual array of `Item[]` contains
|
|
6
|
+
* at least one `Item` that is equal to the resolved value of `expected`.
|
|
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 array contains the given item
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { actorCalled } from '@serenity-js/core'
|
|
15
|
+
* import { Ensure, and, startsWith, endsWith } from '@serenity-js/assertions'
|
|
16
|
+
*
|
|
17
|
+
* const items = [ { name: 'apples' }, { name: 'bananas' } ]
|
|
18
|
+
*
|
|
19
|
+
* await actorCalled('Ester').attemptsTo(
|
|
20
|
+
* Ensure.that(items, contain({ name: 'bananas' })),
|
|
21
|
+
* )
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param expected
|
|
25
|
+
*
|
|
26
|
+
* @group Expectations
|
|
27
|
+
*/
|
|
28
|
+
export function contain<Item>(expected: Answerable<Item>): Expectation<Item[]> {
|
|
5
29
|
return Expectation.thatActualShould<Item, Item[]>('contain', expected)
|
|
6
|
-
.soThat((actualValue, expectedValue) =>
|
|
30
|
+
.soThat((actualValue, expectedValue) => actualValue.some(item => equal(item, expectedValue)));
|
|
7
31
|
}
|
|
@@ -1,26 +1,71 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
2
|
-
import { formatted } from '@serenity-js/core/lib/io';
|
|
1
|
+
import { Answerable, AnswersQuestions, d, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Produces an {@apilink Expectation|expectation} that is met when the actual array of `Item[]` contains
|
|
5
|
+
* at least one `Item` for which the `expectation` is met.
|
|
6
|
+
*
|
|
7
|
+
* ## Ensuring that at least one item in an array meets the expectation
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { actorCalled } from '@serenity-js/core'
|
|
11
|
+
* import { Ensure, containAtLeastOneItemThat, isGreaterThan } from '@serenity-js/assertions'
|
|
12
|
+
*
|
|
13
|
+
* const items = [ 10, 15, 20 ]
|
|
14
|
+
*
|
|
15
|
+
* await actorCalled('Ester').attemptsTo(
|
|
16
|
+
* Ensure.that(items, containAtLeastOneItemThat(isGreaterThan(18))),
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @param expectation
|
|
21
|
+
*
|
|
22
|
+
* @group Expectations
|
|
23
|
+
*/
|
|
24
|
+
export function containAtLeastOneItemThat<Item>(expectation: Expectation<Item>): Expectation<Item[]> {
|
|
5
25
|
return new ContainAtLeastOneItemThatMeetsExpectation(expectation);
|
|
6
26
|
}
|
|
7
27
|
|
|
8
28
|
/**
|
|
9
29
|
* @package
|
|
10
30
|
*/
|
|
11
|
-
class ContainAtLeastOneItemThatMeetsExpectation<
|
|
12
|
-
|
|
13
|
-
|
|
31
|
+
class ContainAtLeastOneItemThatMeetsExpectation<Item> extends Expectation<Item[]> {
|
|
32
|
+
|
|
33
|
+
private static descriptionFor(expectation: Expectation<any>) {
|
|
34
|
+
return d`contain at least one item that does ${ expectation }`;
|
|
14
35
|
}
|
|
15
36
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
constructor(private readonly expectation: Expectation<Item>) {
|
|
38
|
+
super(
|
|
39
|
+
ContainAtLeastOneItemThatMeetsExpectation.descriptionFor(expectation),
|
|
40
|
+
async (actor: AnswersQuestions, actual: Answerable<Item[]>) => {
|
|
41
|
+
|
|
42
|
+
const items: Item[] = await actor.answer(actual);
|
|
43
|
+
|
|
44
|
+
if (! items || items.length === 0) {
|
|
45
|
+
return new ExpectationNotMet(
|
|
46
|
+
ContainAtLeastOneItemThatMeetsExpectation.descriptionFor(expectation),
|
|
47
|
+
undefined,
|
|
48
|
+
items,
|
|
24
49
|
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let outcome: ExpectationOutcome<unknown, Item>;
|
|
53
|
+
|
|
54
|
+
for (const item of items) {
|
|
55
|
+
|
|
56
|
+
outcome = await actor.answer(expectation.isMetFor(item))
|
|
57
|
+
|
|
58
|
+
if (outcome instanceof ExpectationMet) {
|
|
59
|
+
return new ExpectationMet(
|
|
60
|
+
ContainAtLeastOneItemThatMeetsExpectation.descriptionFor(expectation),
|
|
61
|
+
outcome.expected,
|
|
62
|
+
items
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return new ExpectationNotMet(ContainAtLeastOneItemThatMeetsExpectation.descriptionFor(expectation), outcome.expected, items);
|
|
68
|
+
}
|
|
69
|
+
);
|
|
25
70
|
}
|
|
26
71
|
}
|
|
@@ -1,26 +1,71 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
2
|
-
import { formatted } from '@serenity-js/core/lib/io';
|
|
1
|
+
import { Answerable, AnswersQuestions, d, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
3
2
|
|
|
4
|
-
|
|
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
|
+
*/
|
|
24
|
+
export function containItemsWhereEachItem<Actual>(expectation: Expectation<Actual>): Expectation<Actual[]> {
|
|
5
25
|
return new ContainItemsWhereEachItemMeetsExpectation(expectation);
|
|
6
26
|
}
|
|
7
27
|
|
|
8
28
|
/**
|
|
9
29
|
* @package
|
|
10
30
|
*/
|
|
11
|
-
class ContainItemsWhereEachItemMeetsExpectation<
|
|
12
|
-
|
|
13
|
-
|
|
31
|
+
class ContainItemsWhereEachItemMeetsExpectation<Actual> extends Expectation<Actual[]> {
|
|
32
|
+
|
|
33
|
+
private static descriptionFor(expectation: Expectation<any>) {
|
|
34
|
+
return d`contain items where each item does ${ expectation }`;
|
|
14
35
|
}
|
|
15
36
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
constructor(private readonly expectation: Expectation<Actual>) {
|
|
38
|
+
super(
|
|
39
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
40
|
+
async (actor: AnswersQuestions, actual: Answerable<Actual[]>) => {
|
|
41
|
+
|
|
42
|
+
const items: Actual[] = await actor.answer(actual);
|
|
43
|
+
|
|
44
|
+
if (! items || items.length === 0) {
|
|
45
|
+
return new ExpectationNotMet(
|
|
46
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
47
|
+
undefined,
|
|
48
|
+
items,
|
|
24
49
|
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let outcome: ExpectationOutcome<unknown, Actual>;
|
|
53
|
+
|
|
54
|
+
for (const item of items) {
|
|
55
|
+
|
|
56
|
+
outcome = await actor.answer(expectation.isMetFor(item))
|
|
57
|
+
|
|
58
|
+
if (outcome instanceof ExpectationNotMet) {
|
|
59
|
+
return new ExpectationNotMet(
|
|
60
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
61
|
+
outcome.expected,
|
|
62
|
+
items
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return new ExpectationMet(ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation), outcome.expected, items);
|
|
68
|
+
}
|
|
69
|
+
);
|
|
25
70
|
}
|
|
26
71
|
}
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { Answerable, Expectation } from '@serenity-js/core';
|
|
2
2
|
|
|
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
|
+
*/
|
|
3
22
|
export function endsWith(expected: Answerable<string>): Expectation<string> {
|
|
4
23
|
return Expectation.thatActualShould<string, string>('end with', expected)
|
|
5
24
|
.soThat((actualValue, expectedValue) => actualValue.endsWith(expectedValue));
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import { Answerable, Expectation } from '@serenity-js/core';
|
|
2
2
|
import { equal } from 'tiny-types/lib/objects';
|
|
3
3
|
|
|
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
|
+
*/
|
|
4
29
|
export function equals<Expected>(expectedValue: Answerable<Expected>): Expectation<Expected> {
|
|
5
30
|
return Expectation.thatActualShould<Expected, Expected>('equal', expectedValue)
|
|
6
31
|
.soThat((actual, expected) => equal(actual, expected));
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { Answerable, Expectation } from '@serenity-js/core';
|
|
2
2
|
|
|
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
|
+
*/
|
|
3
22
|
export function includes(expected: Answerable<string>): Expectation<string> {
|
|
4
23
|
return Expectation.thatActualShould<string, string>('include', expected)
|
|
5
24
|
.soThat((actualValue, expectedValue) => actualValue.includes(expectedValue));
|
|
@@ -7,9 +7,11 @@ 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';
|
|
14
|
+
export * from './isPresent';
|
|
13
15
|
export * from './isTrue';
|
|
14
16
|
export * from './matches';
|
|
15
17
|
export * from './not';
|