@serenity-js/core 2.33.1 → 3.0.0-rc.11
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 +476 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +6 -1
- package/lib/index.js.map +1 -1
- package/lib/io/ErrorSerialiser.js +4 -1
- package/lib/io/ErrorSerialiser.js.map +1 -1
- package/lib/io/ErrorStackParser.d.ts +2 -2
- package/lib/io/ErrorStackParser.js.map +1 -1
- package/lib/io/asyncMap.d.ts +8 -0
- package/lib/io/asyncMap.js +18 -0
- package/lib/io/asyncMap.js.map +1 -0
- package/lib/io/format.d.ts +39 -0
- package/lib/io/format.js +51 -0
- package/lib/io/format.js.map +1 -0
- package/lib/io/formatted.d.ts +5 -1
- package/lib/io/formatted.js +6 -13
- package/lib/io/formatted.js.map +1 -1
- package/lib/io/index.d.ts +2 -1
- package/lib/io/index.js +2 -1
- package/lib/io/index.js.map +1 -1
- package/lib/io/inspected.d.ts +9 -1
- package/lib/io/inspected.js +52 -15
- package/lib/io/inspected.js.map +1 -1
- package/lib/model/Timestamp.d.ts +4 -2
- package/lib/model/Timestamp.js +8 -2
- package/lib/model/Timestamp.js.map +1 -1
- package/lib/screenplay/Optional.d.ts +29 -0
- package/lib/{io/collections/reducible.js → screenplay/Optional.js} +1 -1
- package/lib/screenplay/Optional.js.map +1 -0
- package/lib/screenplay/Question.d.ts +41 -82
- package/lib/screenplay/Question.js +132 -100
- package/lib/screenplay/Question.js.map +1 -1
- package/lib/screenplay/actor/Actor.js +2 -2
- package/lib/screenplay/actor/Actor.js.map +1 -1
- package/lib/screenplay/index.d.ts +1 -1
- package/lib/screenplay/index.js +1 -1
- package/lib/screenplay/index.js.map +1 -1
- package/lib/screenplay/interactions/index.d.ts +0 -1
- package/lib/screenplay/interactions/index.js +0 -1
- package/lib/screenplay/interactions/index.js.map +1 -1
- package/lib/screenplay/questions/Check.d.ts +3 -3
- package/lib/screenplay/questions/Check.js +5 -7
- package/lib/screenplay/questions/Check.js.map +1 -1
- package/lib/screenplay/questions/Expectation.d.ts +15 -10
- package/lib/screenplay/questions/Expectation.js +28 -37
- package/lib/screenplay/questions/Expectation.js.map +1 -1
- package/lib/screenplay/questions/List.d.ts +22 -192
- package/lib/screenplay/questions/List.js +160 -208
- package/lib/screenplay/questions/List.js.map +1 -1
- package/lib/screenplay/questions/Note.d.ts +10 -0
- package/lib/screenplay/questions/Note.js +17 -1
- package/lib/screenplay/questions/Note.js.map +1 -1
- package/lib/screenplay/questions/index.d.ts +0 -3
- package/lib/screenplay/questions/index.js +0 -5
- package/lib/screenplay/questions/index.js.map +1 -1
- package/lib/stage/index.d.ts +0 -2
- package/lib/stage/index.js +0 -2
- package/lib/stage/index.js.map +1 -1
- package/package.json +7 -6
- package/src/index.ts +2 -1
- package/src/io/ErrorSerialiser.ts +5 -1
- package/src/io/ErrorStackParser.ts +2 -1
- package/src/io/asyncMap.ts +18 -0
- package/src/io/format.ts +49 -0
- package/src/io/formatted.ts +7 -15
- package/src/io/index.ts +2 -1
- package/src/io/inspected.ts +68 -15
- package/src/model/Timestamp.ts +10 -2
- package/src/screenplay/Optional.ts +30 -0
- package/src/screenplay/Question.ts +206 -124
- package/src/screenplay/actor/Actor.ts +2 -2
- package/src/screenplay/index.ts +1 -1
- package/src/screenplay/interactions/index.ts +0 -1
- package/src/screenplay/questions/Check.ts +10 -15
- package/src/screenplay/questions/Expectation.ts +47 -55
- package/src/screenplay/questions/List.ts +224 -233
- package/src/screenplay/questions/Note.ts +21 -1
- package/src/screenplay/questions/index.ts +0 -3
- package/src/stage/index.ts +0 -2
- package/lib/io/collections/index.d.ts +0 -2
- package/lib/io/collections/index.js +0 -15
- package/lib/io/collections/index.js.map +0 -1
- package/lib/io/collections/mappable.d.ts +0 -52
- package/lib/io/collections/mappable.js +0 -28
- package/lib/io/collections/mappable.js.map +0 -1
- package/lib/io/collections/reducible.d.ts +0 -16
- package/lib/io/collections/reducible.js.map +0 -1
- package/lib/screenplay/interactions/See.d.ts +0 -31
- package/lib/screenplay/interactions/See.js +0 -43
- package/lib/screenplay/interactions/See.js.map +0 -1
- package/lib/screenplay/questions/Property.d.ts +0 -91
- package/lib/screenplay/questions/Property.js +0 -99
- package/lib/screenplay/questions/Property.js.map +0 -1
- package/lib/screenplay/questions/Transform.d.ts +0 -31
- package/lib/screenplay/questions/Transform.js +0 -46
- package/lib/screenplay/questions/Transform.js.map +0 -1
- package/lib/screenplay/questions/lists/ArrayListAdapter.d.ts +0 -88
- package/lib/screenplay/questions/lists/ArrayListAdapter.js +0 -152
- package/lib/screenplay/questions/lists/ArrayListAdapter.js.map +0 -1
- package/lib/screenplay/questions/lists/ListAdapter.d.ts +0 -20
- package/lib/screenplay/questions/lists/ListAdapter.js +0 -3
- package/lib/screenplay/questions/lists/ListAdapter.js.map +0 -1
- package/lib/screenplay/questions/lists/index.d.ts +0 -2
- package/lib/screenplay/questions/lists/index.js +0 -15
- package/lib/screenplay/questions/lists/index.js.map +0 -1
- package/lib/screenplay/questions/mappings/AnswerMappingFunction.d.ts +0 -11
- package/lib/screenplay/questions/mappings/AnswerMappingFunction.js +0 -3
- package/lib/screenplay/questions/mappings/AnswerMappingFunction.js.map +0 -1
- package/lib/screenplay/questions/mappings/index.d.ts +0 -2
- package/lib/screenplay/questions/mappings/index.js +0 -15
- package/lib/screenplay/questions/mappings/index.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/append.d.ts +0 -14
- package/lib/screenplay/questions/mappings/string/append.js +0 -25
- package/lib/screenplay/questions/mappings/string/append.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/index.d.ts +0 -11
- package/lib/screenplay/questions/mappings/string/index.js +0 -24
- package/lib/screenplay/questions/mappings/string/index.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/normalize.d.ts +0 -20
- package/lib/screenplay/questions/mappings/string/normalize.js +0 -30
- package/lib/screenplay/questions/mappings/string/normalize.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/replace.d.ts +0 -17
- package/lib/screenplay/questions/mappings/string/replace.js +0 -30
- package/lib/screenplay/questions/mappings/string/replace.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/slice.d.ts +0 -28
- package/lib/screenplay/questions/mappings/string/slice.js +0 -47
- package/lib/screenplay/questions/mappings/string/slice.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/split.d.ts +0 -19
- package/lib/screenplay/questions/mappings/string/split.js +0 -36
- package/lib/screenplay/questions/mappings/string/split.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/toLocaleLowerCase.d.ts +0 -17
- package/lib/screenplay/questions/mappings/string/toLocaleLowerCase.js +0 -28
- package/lib/screenplay/questions/mappings/string/toLocaleLowerCase.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/toLocaleUpperCase.d.ts +0 -17
- package/lib/screenplay/questions/mappings/string/toLocaleUpperCase.js +0 -29
- package/lib/screenplay/questions/mappings/string/toLocaleUpperCase.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/toLowerCase.d.ts +0 -10
- package/lib/screenplay/questions/mappings/string/toLowerCase.js +0 -19
- package/lib/screenplay/questions/mappings/string/toLowerCase.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/toNumber.d.ts +0 -10
- package/lib/screenplay/questions/mappings/string/toNumber.js +0 -18
- package/lib/screenplay/questions/mappings/string/toNumber.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/toUpperCase.d.ts +0 -10
- package/lib/screenplay/questions/mappings/string/toUpperCase.js +0 -19
- package/lib/screenplay/questions/mappings/string/toUpperCase.js.map +0 -1
- package/lib/screenplay/questions/mappings/string/trim.d.ts +0 -12
- package/lib/screenplay/questions/mappings/string/trim.js +0 -21
- package/lib/screenplay/questions/mappings/string/trim.js.map +0 -1
- package/lib/screenplay/questions/proxies/PropertyPathKey.d.ts +0 -4
- package/lib/screenplay/questions/proxies/PropertyPathKey.js +0 -3
- package/lib/screenplay/questions/proxies/PropertyPathKey.js.map +0 -1
- package/lib/screenplay/questions/proxies/createMetaQuestionProxy.d.ts +0 -14
- package/lib/screenplay/questions/proxies/createMetaQuestionProxy.js +0 -35
- package/lib/screenplay/questions/proxies/createMetaQuestionProxy.js.map +0 -1
- package/lib/screenplay/questions/proxies/createQuestionProxy.d.ts +0 -13
- package/lib/screenplay/questions/proxies/createQuestionProxy.js +0 -34
- package/lib/screenplay/questions/proxies/createQuestionProxy.js.map +0 -1
- package/lib/screenplay/questions/proxies/describePath.d.ts +0 -5
- package/lib/screenplay/questions/proxies/describePath.js +0 -19
- package/lib/screenplay/questions/proxies/describePath.js.map +0 -1
- package/lib/screenplay/questions/proxies/index.d.ts +0 -2
- package/lib/screenplay/questions/proxies/index.js +0 -15
- package/lib/screenplay/questions/proxies/index.js.map +0 -1
- package/lib/screenplay/questions/proxies/key.d.ts +0 -8
- package/lib/screenplay/questions/proxies/key.js +0 -16
- package/lib/screenplay/questions/proxies/key.js.map +0 -1
- package/lib/screenplay/tasks/Loop.d.ts +0 -198
- package/lib/screenplay/tasks/Loop.js +0 -222
- package/lib/screenplay/tasks/Loop.js.map +0 -1
- package/lib/screenplay/tasks/index.d.ts +0 -1
- package/lib/screenplay/tasks/index.js +0 -14
- package/lib/screenplay/tasks/index.js.map +0 -1
- package/lib/stage/DressingRoom.d.ts +0 -37
- package/lib/stage/DressingRoom.js +0 -53
- package/lib/stage/DressingRoom.js.map +0 -1
- package/lib/stage/WithStage.d.ts +0 -51
- package/lib/stage/WithStage.js +0 -3
- package/lib/stage/WithStage.js.map +0 -1
- package/src/io/collections/index.ts +0 -2
- package/src/io/collections/mappable.ts +0 -60
- package/src/io/collections/reducible.ts +0 -16
- package/src/screenplay/interactions/See.ts +0 -45
- package/src/screenplay/questions/Property.ts +0 -98
- package/src/screenplay/questions/Transform.ts +0 -51
- package/src/screenplay/questions/lists/ArrayListAdapter.ts +0 -186
- package/src/screenplay/questions/lists/ListAdapter.ts +0 -33
- package/src/screenplay/questions/lists/index.ts +0 -2
- package/src/screenplay/questions/mappings/AnswerMappingFunction.ts +0 -13
- package/src/screenplay/questions/mappings/index.ts +0 -2
- package/src/screenplay/questions/mappings/string/append.ts +0 -28
- package/src/screenplay/questions/mappings/string/index.ts +0 -11
- package/src/screenplay/questions/mappings/string/normalize.ts +0 -33
- package/src/screenplay/questions/mappings/string/replace.ts +0 -34
- package/src/screenplay/questions/mappings/string/slice.ts +0 -53
- package/src/screenplay/questions/mappings/string/split.ts +0 -38
- package/src/screenplay/questions/mappings/string/toLocaleLowerCase.ts +0 -31
- package/src/screenplay/questions/mappings/string/toLocaleUpperCase.ts +0 -30
- package/src/screenplay/questions/mappings/string/toLowerCase.ts +0 -20
- package/src/screenplay/questions/mappings/string/toNumber.ts +0 -19
- package/src/screenplay/questions/mappings/string/toUpperCase.ts +0 -20
- package/src/screenplay/questions/mappings/string/trim.ts +0 -22
- package/src/screenplay/questions/proxies/PropertyPathKey.ts +0 -4
- package/src/screenplay/questions/proxies/createMetaQuestionProxy.ts +0 -51
- package/src/screenplay/questions/proxies/createQuestionProxy.ts +0 -49
- package/src/screenplay/questions/proxies/describePath.ts +0 -23
- package/src/screenplay/questions/proxies/index.ts +0 -2
- package/src/screenplay/questions/proxies/key.ts +0 -14
- package/src/screenplay/tasks/Loop.ts +0 -240
- package/src/screenplay/tasks/index.ts +0 -1
- package/src/stage/DressingRoom.ts +0 -53
- package/src/stage/WithStage.ts +0 -52
|
@@ -1,260 +1,251 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { LogicError } from '../../errors';
|
|
2
|
+
import { d } from '../../io';
|
|
3
|
+
import { Actor, AnswersQuestions, UsesAbilities } from '../actor';
|
|
3
4
|
import { Answerable } from '../Answerable';
|
|
4
|
-
import { Question } from '../Question';
|
|
5
|
+
import { Question, QuestionAdapter } from '../Question';
|
|
6
|
+
import { Task } from '../Task';
|
|
5
7
|
import { Expectation } from './Expectation';
|
|
6
|
-
import {
|
|
8
|
+
import { ExpectationMet } from './expectations';
|
|
7
9
|
import { MetaQuestion } from './MetaQuestion';
|
|
8
10
|
|
|
11
|
+
export class List<Item_Type> extends Question<Promise<Item_Type[]>> {
|
|
12
|
+
private subject: string;
|
|
13
|
+
|
|
14
|
+
static of<IT>(collection: Answerable<Array<IT>>): List<IT> {
|
|
15
|
+
return new List<IT>(collection);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
protected readonly collection: Answerable<Array<Item_Type>>,
|
|
20
|
+
) {
|
|
21
|
+
super();
|
|
22
|
+
this.subject = d`${ collection }`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
eachMappedTo<Mapped_Item_Type>(
|
|
26
|
+
question: MetaQuestion<Item_Type, Promise<Mapped_Item_Type> | Mapped_Item_Type>,
|
|
27
|
+
): List<Mapped_Item_Type> {
|
|
28
|
+
return new List(
|
|
29
|
+
new EachMappedTo(this.collection, question, this.subject)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
forEach(callback: (current: CurrentItem<Item_Type>, index: number, items: Array<Item_Type>) => Promise<void> | void): Task {
|
|
34
|
+
return new ForEachLoop(this.collection, this.subject, callback);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
where<Answer_Type>(
|
|
38
|
+
question: MetaQuestion<Item_Type, Promise<Answer_Type> | Answer_Type>,
|
|
39
|
+
expectation: Expectation<Answer_Type>
|
|
40
|
+
): this {
|
|
41
|
+
return new List<Item_Type>(
|
|
42
|
+
new Where(this.collection, question, expectation, this.subject)
|
|
43
|
+
) as this;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
count(): QuestionAdapter<number> {
|
|
47
|
+
return Question.about(`the number of ${ this.subject }`, async actor => {
|
|
48
|
+
const items = await this.answeredBy(actor);
|
|
49
|
+
return items.length;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
first(): QuestionAdapter<Item_Type> {
|
|
54
|
+
return Question.about(`the first of ${ this.subject }`, async actor => {
|
|
55
|
+
const items = await this.answeredBy(actor);
|
|
56
|
+
|
|
57
|
+
if (items.length === 0) {
|
|
58
|
+
throw new LogicError(d`Can't retrieve the first item from a list with 0 items: ${ items }`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return items[0];
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
last(): QuestionAdapter<Item_Type> {
|
|
66
|
+
return Question.about(`the last of ${ this.subject }`, async actor => {
|
|
67
|
+
const items = await this.answeredBy(actor);
|
|
68
|
+
|
|
69
|
+
if (items.length === 0) {
|
|
70
|
+
throw new LogicError(d`Can't retrieve the last item from a list with 0 items: ${ items }`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return items[items.length - 1];
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get(index: number): QuestionAdapter<Item_Type> {
|
|
78
|
+
return Question.about(`the ${ ordinal(index + 1) } of ${ this.subject }`, async actor => {
|
|
79
|
+
const items = await this.answeredBy(actor);
|
|
80
|
+
|
|
81
|
+
if (index < 0 || items.length <= index) {
|
|
82
|
+
throw new LogicError(`Can't retrieve the ${ ordinal(index) } item from a list with ${ items.length } items: ` + d`${ items }`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return items[index];
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<Array<Item_Type>> {
|
|
90
|
+
const collection = await actor.answer(this.collection);
|
|
91
|
+
|
|
92
|
+
if (! Array.isArray(collection)) {
|
|
93
|
+
throw new LogicError(d`A List has to wrap an Array-compatible object. ${ collection } given.`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return collection;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
describedAs(subject: string): this {
|
|
100
|
+
this.subject = subject;
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
toString(): string {
|
|
105
|
+
return this.subject;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
9
109
|
/**
|
|
10
|
-
* @
|
|
11
|
-
*
|
|
12
|
-
* Instantiate via {@link List.of}
|
|
13
|
-
*
|
|
14
|
-
* @example <caption>Example data structure</caption>
|
|
15
|
-
* interface TestAccount {
|
|
16
|
-
* username: string;
|
|
17
|
-
* role: string;
|
|
18
|
-
* environments: string[];
|
|
19
|
-
* }
|
|
20
|
-
*
|
|
21
|
-
* const testAccounts: TestAccount[] = [
|
|
22
|
-
* {
|
|
23
|
-
* "username": "tester.one@example.com",
|
|
24
|
-
* "role": "test-automation"
|
|
25
|
-
* "environments": [ "dev", "sit" ],
|
|
26
|
-
* },
|
|
27
|
-
* {
|
|
28
|
-
* "username": "tester.two@example.com",
|
|
29
|
-
* "role": "test-automation"
|
|
30
|
-
* "environments": [ "dev", "sit", "prod" ],
|
|
31
|
-
* },
|
|
32
|
-
* {
|
|
33
|
-
* "username": "release.bot@example.com",
|
|
34
|
-
* "role": "release-automation"
|
|
35
|
-
* "environments": [ "dev", "sit", "prod" ],
|
|
36
|
-
* }
|
|
37
|
-
* ]
|
|
38
|
-
*
|
|
39
|
-
* @example <caption>Using with Property</caption>
|
|
40
|
-
* import { actorCalled, List, Property } from '@serenity-js/core';
|
|
41
|
-
* import { contain, Ensure, equals } from '@serenity-js/assertions';
|
|
42
|
-
*
|
|
43
|
-
* actorCalled('Lisa').attemptsTo(
|
|
44
|
-
* Ensure.that(
|
|
45
|
-
* Property.of(
|
|
46
|
-
* List.of(testAccounts)
|
|
47
|
-
* .where(Property.at<TestAccount>().environments, contain('prod'))
|
|
48
|
-
* .where(Property.at<TestAccount>().role, equals('test-automation'))
|
|
49
|
-
* .first()
|
|
50
|
-
* ).username,
|
|
51
|
-
* equals('tester.two@example.com')
|
|
52
|
-
* )
|
|
53
|
-
* )
|
|
54
|
-
*
|
|
55
|
-
* @extends {Question}
|
|
56
|
-
* @see {@link MetaQuestion}
|
|
110
|
+
* @package
|
|
111
|
+
* @param {number} index
|
|
57
112
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
function ordinal(index: number): string {
|
|
114
|
+
const
|
|
115
|
+
lastDigit = Math.abs(index) % 10,
|
|
116
|
+
lastTwoDigits = Math.abs(index) % 100;
|
|
117
|
+
|
|
118
|
+
switch (true) {
|
|
119
|
+
case (lastDigit === 1 && lastTwoDigits !== 11):
|
|
120
|
+
return index + 'st';
|
|
121
|
+
case (lastDigit === 2 && lastTwoDigits !== 12):
|
|
122
|
+
return index + 'nd';
|
|
123
|
+
case (lastDigit === 3 && lastTwoDigits !== 13):
|
|
124
|
+
return index + 'rd';
|
|
125
|
+
default:
|
|
126
|
+
return index + 'th';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @package
|
|
132
|
+
*/
|
|
133
|
+
class Where<Item_Type, Answer_Type>
|
|
134
|
+
extends Question<Promise<Array<Item_Type>>>
|
|
66
135
|
{
|
|
136
|
+
private subject: string;
|
|
67
137
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
static of<Item_Type>(items: Answerable<Item_Type[]>): List<ArrayListAdapter<Item_Type>, Item_Type, Item_Type[], Promise<Item_Type>, Promise<Item_Type[]>> {
|
|
82
|
-
return new List<ArrayListAdapter<Item_Type>, Item_Type, Item_Type[], Promise<Item_Type>, Promise<Item_Type[]>>(
|
|
83
|
-
new ArrayListAdapter(items)
|
|
84
|
-
);
|
|
138
|
+
constructor(
|
|
139
|
+
private readonly collection: Answerable<Array<Item_Type>>,
|
|
140
|
+
private readonly question: MetaQuestion<Item_Type, Promise<Answer_Type> | Answer_Type>,
|
|
141
|
+
private readonly expectation: Expectation<Answer_Type>,
|
|
142
|
+
originalSubject: string,
|
|
143
|
+
) {
|
|
144
|
+
super();
|
|
145
|
+
|
|
146
|
+
const prefix = this.collection instanceof Where
|
|
147
|
+
? ' and'
|
|
148
|
+
: ' where';
|
|
149
|
+
|
|
150
|
+
this.subject = originalSubject + prefix + d` ${ question } does ${ expectation }`;
|
|
85
151
|
}
|
|
86
152
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
153
|
+
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<Array<Item_Type>> {
|
|
154
|
+
try {
|
|
155
|
+
const collection = await actor.answer(this.collection);
|
|
156
|
+
const results: Item_Type[] = [];
|
|
157
|
+
|
|
158
|
+
for (const item of collection) {
|
|
159
|
+
const actual = this.question.of(item) as Answerable<Answer_Type>;
|
|
160
|
+
const expectationOutcome = await actor.answer(this.expectation.isMetFor(actual));
|
|
161
|
+
|
|
162
|
+
if (expectationOutcome instanceof ExpectationMet) {
|
|
163
|
+
results.push(item);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return results;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
throw new LogicError(d`Couldn't check if ${ this.question } of an item of ${ this.collection } does ${ this.expectation }`, error);
|
|
170
|
+
}
|
|
92
171
|
}
|
|
93
172
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
98
|
-
* @example <caption>Counting items</caption>
|
|
99
|
-
* import { actorCalled, List } from '@serenity-js/core';
|
|
100
|
-
* import { Ensure, equals, property } from '@serenity-js/assertions';
|
|
101
|
-
*
|
|
102
|
-
* actorCalled('Lisa').attemptsTo(
|
|
103
|
-
* Ensure.that(
|
|
104
|
-
* List.of(testAccounts).count(),
|
|
105
|
-
* equals(3)
|
|
106
|
-
* )
|
|
107
|
-
* )
|
|
108
|
-
*
|
|
109
|
-
* @returns {Question<Promise<number>>}
|
|
110
|
-
*
|
|
111
|
-
* @see {@link List#where}
|
|
112
|
-
*/
|
|
113
|
-
count(): Question<Promise<number>> {
|
|
114
|
-
return Question.about(`the number of ${ this.collection.toString() }`, actor =>
|
|
115
|
-
this.collection.count(actor)
|
|
116
|
-
);
|
|
173
|
+
describedAs(subject: string): this {
|
|
174
|
+
this.subject = subject;
|
|
175
|
+
return this;
|
|
117
176
|
}
|
|
118
177
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
* Returns the first of items left after applying any filters,
|
|
122
|
-
*
|
|
123
|
-
* @example <caption>Retrieving the first item</caption>
|
|
124
|
-
* import { actorCalled, List } from '@serenity-js/core';
|
|
125
|
-
* import { Ensure, equals, property } from '@serenity-js/assertions';
|
|
126
|
-
*
|
|
127
|
-
* actorCalled('Lisa').attemptsTo(
|
|
128
|
-
* Ensure.that(
|
|
129
|
-
* List.of(testAccounts).first(),
|
|
130
|
-
* property('username', equals('tester.one@example.com'))
|
|
131
|
-
* )
|
|
132
|
-
* )
|
|
133
|
-
*
|
|
134
|
-
* @returns {Question<Item_Return_Type>}
|
|
135
|
-
*
|
|
136
|
-
* @see {@link List#where}
|
|
137
|
-
*/
|
|
138
|
-
first(): Question<Item_Return_Type> {
|
|
139
|
-
return Question.about(`the first of ${ this.collection.toString() }`, actor =>
|
|
140
|
-
this.collection.first(actor)
|
|
141
|
-
);
|
|
178
|
+
toString(): string {
|
|
179
|
+
return this.subject;
|
|
142
180
|
}
|
|
181
|
+
}
|
|
143
182
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
* @returns {Question<Item_Return_Type>}
|
|
160
|
-
*
|
|
161
|
-
* @see {@link List#where}
|
|
162
|
-
*/
|
|
163
|
-
last(): Question<Item_Return_Type> {
|
|
164
|
-
return Question.about(`the last of ${ this.collection.toString() }`, actor =>
|
|
165
|
-
this.collection.last(actor)
|
|
166
|
-
);
|
|
183
|
+
/**
|
|
184
|
+
* @package
|
|
185
|
+
*/
|
|
186
|
+
class EachMappedTo<Item_Type, Mapped_Item_Type> extends Question<Promise<Array<Mapped_Item_Type>>> {
|
|
187
|
+
|
|
188
|
+
private subject: string;
|
|
189
|
+
|
|
190
|
+
constructor(
|
|
191
|
+
private readonly collection: Answerable<Array<Item_Type>>,
|
|
192
|
+
private readonly mapping: MetaQuestion<Item_Type, Promise<Mapped_Item_Type> | Mapped_Item_Type>,
|
|
193
|
+
originalSubject: string,
|
|
194
|
+
) {
|
|
195
|
+
super();
|
|
196
|
+
|
|
197
|
+
this.subject = originalSubject + d` mapped to ${ this.mapping }`;
|
|
167
198
|
}
|
|
168
199
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
* List.of(testAccounts).get(1),
|
|
180
|
-
* property('username', equals('tester.two@example.com'))
|
|
181
|
-
* )
|
|
182
|
-
* )
|
|
183
|
-
*
|
|
184
|
-
* @param {number} index
|
|
185
|
-
* Zero-based index of the item to return
|
|
186
|
-
*
|
|
187
|
-
* @returns {Question<Item_Return_Type>}
|
|
188
|
-
*
|
|
189
|
-
* @see {@link List#where}
|
|
190
|
-
*/
|
|
191
|
-
get(index: number): Question<Item_Return_Type> {
|
|
192
|
-
return Question.about(`the ${ List.ordinalSuffixOf(index + 1) } of ${ this.collection }`, actor =>
|
|
193
|
-
this.collection.get(actor, index)
|
|
194
|
-
);
|
|
200
|
+
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<Array<Mapped_Item_Type>> {
|
|
201
|
+
const collection: Array<Item_Type> = await actor.answer(this.collection);
|
|
202
|
+
|
|
203
|
+
const mapped: Mapped_Item_Type[] = [];
|
|
204
|
+
|
|
205
|
+
for (const item of collection) {
|
|
206
|
+
mapped.push(await actor.answer(this.mapping.of(item)))
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return mapped;
|
|
195
210
|
}
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
*
|
|
201
|
-
* @example <caption>Filtering a list</caption>
|
|
202
|
-
* import { actorCalled, List, Property } from '@serenity-js/core';
|
|
203
|
-
* import { contain, Ensure, equals, property } from '@serenity-js/assertions';
|
|
204
|
-
*
|
|
205
|
-
* actorCalled('Lisa').attemptsTo(
|
|
206
|
-
* Ensure.that(
|
|
207
|
-
* List.of(testAccounts)
|
|
208
|
-
* .where(Property.at<TestAccount>().environments, contain('prod'))
|
|
209
|
-
* .where(Property.at<TestAccount>().role, equals('test-automation'))
|
|
210
|
-
* .first(),
|
|
211
|
-
* property('username', equals('tester.two@example.com'))
|
|
212
|
-
* )
|
|
213
|
-
* )
|
|
214
|
-
*
|
|
215
|
-
* @param {MetaQuestion<Item_Type, Promise<Answer_Type> | Answer_Type>} question
|
|
216
|
-
* @param {Expectation<any, Answer_Type>} expectation
|
|
217
|
-
*
|
|
218
|
-
* @returns {List<List_Adapter_Type, Item_Type, Collection_Type, Item_Return_Type, Collection_Return_Type>}
|
|
219
|
-
*/
|
|
220
|
-
where<Answer_Type>(
|
|
221
|
-
question: MetaQuestion<Item_Type, Promise<Answer_Type> | Answer_Type>,
|
|
222
|
-
expectation: Expectation<any, Answer_Type>,
|
|
223
|
-
): List<List_Adapter_Type, Item_Type, Collection_Type, Item_Return_Type, Collection_Return_Type> {
|
|
224
|
-
return new List<List_Adapter_Type, Item_Type, Collection_Type, Item_Return_Type, Collection_Return_Type>(
|
|
225
|
-
this.collection.withFilter(question, expectation) as List_Adapter_Type,
|
|
226
|
-
);
|
|
212
|
+
describedAs(subject: string): this {
|
|
213
|
+
this.subject = subject;
|
|
214
|
+
return this;
|
|
227
215
|
}
|
|
228
216
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
* Makes the provided {@link Actor} answer this {@link Question} and return the underlying collection.
|
|
232
|
-
*
|
|
233
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
234
|
-
* @returns {Collection_Return_Type}
|
|
235
|
-
*
|
|
236
|
-
* @see {@link Actor}
|
|
237
|
-
* @see {@link AnswersQuestions}
|
|
238
|
-
* @see {@link UsesAbilities}
|
|
239
|
-
*/
|
|
240
|
-
answeredBy(actor: AnswersQuestions & UsesAbilities): Collection_Return_Type {
|
|
241
|
-
return this.collection.items(actor);
|
|
217
|
+
toString(): string {
|
|
218
|
+
return this.subject;
|
|
242
219
|
}
|
|
220
|
+
}
|
|
243
221
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
222
|
+
/**
|
|
223
|
+
* @package
|
|
224
|
+
*/
|
|
225
|
+
class ForEachLoop<Item_Type> extends Task {
|
|
226
|
+
|
|
227
|
+
constructor(
|
|
228
|
+
private readonly collection: Answerable<Array<Item_Type>>,
|
|
229
|
+
private readonly subject: string,
|
|
230
|
+
private readonly fn: (current: CurrentItem<Item_Type>, index: number, items: Array<Item_Type>) => Promise<void> | void,
|
|
231
|
+
) {
|
|
232
|
+
super();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async performAs(actor: Actor): Promise<void> {
|
|
236
|
+
const collection: Array<Item_Type> = await actor.answer(this.collection);
|
|
237
|
+
|
|
238
|
+
for (const [index, item] of collection.entries()) {
|
|
239
|
+
await this.fn({ actor, item }, index, collection);
|
|
258
240
|
}
|
|
259
241
|
}
|
|
242
|
+
|
|
243
|
+
toString(): string {
|
|
244
|
+
return `#actor iterates over ${ this.subject }`;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export interface CurrentItem<Item_Type> {
|
|
249
|
+
item: Item_Type;
|
|
250
|
+
actor: Actor;
|
|
260
251
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatted } from '../../io';
|
|
1
2
|
import { TakeNotes } from '../abilities';
|
|
2
3
|
import { AnswersQuestions, UsesAbilities } from '../actor';
|
|
3
4
|
import { Question } from '../Question';
|
|
@@ -42,6 +43,8 @@ import { Question } from '../Question';
|
|
|
42
43
|
*/
|
|
43
44
|
export class Note<Answer> extends Question<Promise<Answer>> {
|
|
44
45
|
|
|
46
|
+
private subject: string;
|
|
47
|
+
|
|
45
48
|
/**
|
|
46
49
|
* @desc
|
|
47
50
|
* Retrieves the previously recorded answer to a given {@link Question}
|
|
@@ -58,7 +61,8 @@ export class Note<Answer> extends Question<Promise<Answer>> {
|
|
|
58
61
|
* @param {Question<Promise<Answer>> | Question<Answer> | string} topic
|
|
59
62
|
*/
|
|
60
63
|
constructor(private readonly topic: Question<Promise<Answer>> | Question<Answer> | string) {
|
|
61
|
-
super(
|
|
64
|
+
super();
|
|
65
|
+
this.subject = formatted `a note of ${ topic }`;
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
/**
|
|
@@ -76,4 +80,20 @@ export class Note<Answer> extends Question<Promise<Answer>> {
|
|
|
76
80
|
answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<Answer> {
|
|
77
81
|
return TakeNotes.as(actor).answerTo(this.topic);
|
|
78
82
|
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @desc
|
|
86
|
+
* Changes the description of this question's subject.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} subject
|
|
89
|
+
* @returns {Question<T>}
|
|
90
|
+
*/
|
|
91
|
+
describedAs(subject: string): this {
|
|
92
|
+
this.subject = subject;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
toString(): string {
|
|
97
|
+
return this.subject;
|
|
98
|
+
}
|
|
79
99
|
}
|
|
@@ -2,9 +2,6 @@ export * from './Check';
|
|
|
2
2
|
export * from './Expectation';
|
|
3
3
|
export * from './expectations';
|
|
4
4
|
export * from './List';
|
|
5
|
-
export * from './mappings';
|
|
6
5
|
export * from './MetaQuestion';
|
|
7
6
|
export * from './Note';
|
|
8
|
-
export { Property } from './Property';
|
|
9
7
|
export * from './q';
|
|
10
|
-
export * from './Transform';
|
package/src/stage/index.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
export * from './Cast';
|
|
2
2
|
export * from './Clock';
|
|
3
3
|
export * from './crew';
|
|
4
|
-
export * from './DressingRoom';
|
|
5
4
|
export * from './ListensToDomainEvents';
|
|
6
5
|
export * from './Stage';
|
|
7
6
|
export * from './StageCrewMember';
|
|
8
7
|
export * from './StageCrewMemberBuilder';
|
|
9
8
|
export * from './StageCrewMemberBuilderDependencies';
|
|
10
9
|
export * from './StageManager';
|
|
11
|
-
export * from './WithStage';
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./mappable"), exports);
|
|
14
|
-
__exportStar(require("./reducible"), exports);
|
|
15
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/io/collections/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA2B;AAC3B,8CAA4B"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @desc
|
|
3
|
-
* Describes a collection providing
|
|
4
|
-
* a [`map`-like interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
|
|
5
|
-
*
|
|
6
|
-
* @interface
|
|
7
|
-
*
|
|
8
|
-
* @see {@link Question#map}
|
|
9
|
-
* @see {@link ElementArrayFinder}
|
|
10
|
-
*/
|
|
11
|
-
export interface Mappable<Item> {
|
|
12
|
-
/**
|
|
13
|
-
* @desc
|
|
14
|
-
* Applies a {@link MappingFunction} function to each element of a {@link Mappable} collection.
|
|
15
|
-
*
|
|
16
|
-
* The callback receives an item from the collection as the first argument
|
|
17
|
-
* and its index as the second argument.
|
|
18
|
-
*
|
|
19
|
-
* @abstract
|
|
20
|
-
*
|
|
21
|
-
* @type {function<U>(callback: (item?: Item, index?: number) => U): PromiseLike<U[]> | U[]}
|
|
22
|
-
*/
|
|
23
|
-
map: <U>(callback: (item?: Item, index?: number) => U) => PromiseLike<U[]> | U[];
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* @desc
|
|
27
|
-
* A mapping function converting one type into another.
|
|
28
|
-
*
|
|
29
|
-
* @public
|
|
30
|
-
*
|
|
31
|
-
* @typedef {function(item?: V, index?: number) => Promise<O> | O} Mapping<V,O>
|
|
32
|
-
*/
|
|
33
|
-
export declare type MappingFunction<V, O> = (item?: V, index?: number) => O;
|
|
34
|
-
/**
|
|
35
|
-
* @desc
|
|
36
|
-
* Checks if the value is a {@link Mappable} collection of items.
|
|
37
|
-
*
|
|
38
|
-
* @example <caption>An Array</caption>
|
|
39
|
-
* import { Mappable } from '@serenity-js/core/lib/io';
|
|
40
|
-
*
|
|
41
|
-
* Mappable.isMappable([ 1, 2, 3 ]) === true
|
|
42
|
-
*
|
|
43
|
-
* @example <caption>Protractor's ElementArrayFinder</caption>
|
|
44
|
-
* import { Mappable } from '@serenity-js/core/lib/io';
|
|
45
|
-
* import { element } from 'protractor';
|
|
46
|
-
*
|
|
47
|
-
* Mappable.isMappable(element.all(by.tagName('li')) === true
|
|
48
|
-
*
|
|
49
|
-
* @param {Mappable<Item> | any} maybeCollection
|
|
50
|
-
* @returns {boolean}
|
|
51
|
-
*/
|
|
52
|
-
export declare function isMappable<Item>(maybeCollection: Mappable<Item> | any): maybeCollection is Mappable<Item>;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isMappable = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* @desc
|
|
6
|
-
* Checks if the value is a {@link Mappable} collection of items.
|
|
7
|
-
*
|
|
8
|
-
* @example <caption>An Array</caption>
|
|
9
|
-
* import { Mappable } from '@serenity-js/core/lib/io';
|
|
10
|
-
*
|
|
11
|
-
* Mappable.isMappable([ 1, 2, 3 ]) === true
|
|
12
|
-
*
|
|
13
|
-
* @example <caption>Protractor's ElementArrayFinder</caption>
|
|
14
|
-
* import { Mappable } from '@serenity-js/core/lib/io';
|
|
15
|
-
* import { element } from 'protractor';
|
|
16
|
-
*
|
|
17
|
-
* Mappable.isMappable(element.all(by.tagName('li')) === true
|
|
18
|
-
*
|
|
19
|
-
* @param {Mappable<Item> | any} maybeCollection
|
|
20
|
-
* @returns {boolean}
|
|
21
|
-
*/
|
|
22
|
-
function isMappable(maybeCollection) {
|
|
23
|
-
return !!maybeCollection
|
|
24
|
-
&& !!maybeCollection.map
|
|
25
|
-
&& typeof maybeCollection.map === 'function';
|
|
26
|
-
}
|
|
27
|
-
exports.isMappable = isMappable;
|
|
28
|
-
//# sourceMappingURL=mappable.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mappable.js","sourceRoot":"","sources":["../../../src/io/collections/mappable.ts"],"names":[],"mappings":";;;AAqCA;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,UAAU,CAAO,eAAqC;IAClE,OAAO,CAAC,CAAE,eAAe;WAClB,CAAC,CAAE,eAAe,CAAC,GAAG;WACtB,OAAO,eAAe,CAAC,GAAG,KAAK,UAAU,CAAC;AACrD,CAAC;AAJD,gCAIC"}
|