@serenity-js/assertions 3.0.0-rc.2 → 3.0.0-rc.20
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 +461 -1
- package/README.md +1 -1
- package/lib/Ensure.d.ts +1 -1
- package/lib/Ensure.js +7 -10
- package/lib/Ensure.js.map +1 -1
- package/lib/expectations/and.d.ts +1 -1
- package/lib/expectations/and.js +6 -6
- package/lib/expectations/and.js.map +1 -1
- package/lib/expectations/contain.d.ts +1 -1
- package/lib/expectations/containAtLeastOneItemThat.d.ts +1 -1
- package/lib/expectations/containAtLeastOneItemThat.js +16 -9
- package/lib/expectations/containAtLeastOneItemThat.js.map +1 -1
- package/lib/expectations/containItemsWhereEachItem.d.ts +1 -1
- package/lib/expectations/containItemsWhereEachItem.js +16 -9
- package/lib/expectations/containItemsWhereEachItem.js.map +1 -1
- package/lib/expectations/index.d.ts +1 -1
- package/lib/expectations/index.js +6 -2
- package/lib/expectations/index.js.map +1 -1
- package/lib/expectations/isFalse.js.map +1 -1
- package/lib/expectations/isPresent.d.ts +14 -0
- package/lib/expectations/isPresent.js +50 -0
- package/lib/expectations/isPresent.js.map +1 -0
- package/lib/expectations/isTrue.js.map +1 -1
- package/lib/expectations/matches.d.ts +1 -1
- package/lib/expectations/not.d.ts +1 -1
- package/lib/expectations/not.js +7 -8
- package/lib/expectations/not.js.map +1 -1
- package/lib/expectations/or.d.ts +1 -1
- package/lib/expectations/or.js +17 -12
- package/lib/expectations/or.js.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/package.json +12 -33
- package/src/Ensure.ts +17 -21
- package/src/expectations/and.ts +19 -18
- package/src/expectations/contain.ts +1 -1
- package/src/expectations/containAtLeastOneItemThat.ts +38 -14
- package/src/expectations/containItemsWhereEachItem.ts +38 -14
- package/src/expectations/index.ts +1 -1
- package/src/expectations/isFalse.ts +1 -1
- package/src/expectations/isPresent.ts +58 -0
- package/src/expectations/isTrue.ts +1 -1
- package/src/expectations/matches.ts +1 -1
- package/src/expectations/not.ts +15 -15
- package/src/expectations/or.ts +28 -25
- package/lib/expectations/property.d.ts +0 -2
- package/lib/expectations/property.js +0 -28
- package/lib/expectations/property.js.map +0 -1
- package/src/expectations/property.ts +0 -33
|
@@ -1,26 +1,50 @@
|
|
|
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
|
-
export function containItemsWhereEachItem<Actual>(expectation: Expectation<
|
|
3
|
+
export function containItemsWhereEachItem<Actual>(expectation: Expectation<Actual>): Expectation<Actual[]> {
|
|
5
4
|
return new ContainItemsWhereEachItemMeetsExpectation(expectation);
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @package
|
|
10
9
|
*/
|
|
11
|
-
class ContainItemsWhereEachItemMeetsExpectation<
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
class ContainItemsWhereEachItemMeetsExpectation<Actual> extends Expectation<Actual[]> {
|
|
11
|
+
|
|
12
|
+
private static descriptionFor(expectation: Expectation<any>) {
|
|
13
|
+
return d`contain items where each item does ${ expectation }`;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
constructor(private readonly expectation: Expectation<Actual>) {
|
|
17
|
+
super(
|
|
18
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
19
|
+
async (actor: AnswersQuestions, actual: Answerable<Actual[]>) => {
|
|
20
|
+
|
|
21
|
+
const items: Actual[] = await actor.answer(actual);
|
|
22
|
+
|
|
23
|
+
if (! items || items.length === 0) {
|
|
24
|
+
return new ExpectationNotMet(
|
|
25
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
26
|
+
undefined,
|
|
27
|
+
items,
|
|
24
28
|
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let outcome: ExpectationOutcome<unknown, Actual>;
|
|
32
|
+
|
|
33
|
+
for (const item of items) {
|
|
34
|
+
|
|
35
|
+
outcome = await actor.answer(expectation.isMetFor(item))
|
|
36
|
+
|
|
37
|
+
if (outcome instanceof ExpectationNotMet) {
|
|
38
|
+
return new ExpectationNotMet(
|
|
39
|
+
ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation),
|
|
40
|
+
outcome.expected,
|
|
41
|
+
items
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return new ExpectationMet(ContainItemsWhereEachItemMeetsExpectation.descriptionFor(expectation), outcome.expected, items);
|
|
47
|
+
}
|
|
48
|
+
);
|
|
25
49
|
}
|
|
26
50
|
}
|
|
@@ -10,9 +10,9 @@ export * from './isBefore';
|
|
|
10
10
|
export * from './isFalse';
|
|
11
11
|
export * from './isGreaterThan';
|
|
12
12
|
export * from './isLessThan';
|
|
13
|
+
export * from './isPresent';
|
|
13
14
|
export * from './isTrue';
|
|
14
15
|
export * from './matches';
|
|
15
16
|
export * from './not';
|
|
16
17
|
export * from './or';
|
|
17
|
-
export * from './property';
|
|
18
18
|
export * from './startsWith';
|
|
@@ -3,5 +3,5 @@ import { Expectation } from '@serenity-js/core';
|
|
|
3
3
|
import { equals } from './equals';
|
|
4
4
|
|
|
5
5
|
export function isFalse(): Expectation<boolean> {
|
|
6
|
-
return Expectation.to<boolean>(`equal false`).soThatActual(equals(false));
|
|
6
|
+
return Expectation.to<never, boolean>(`equal false`).soThatActual(equals(false));
|
|
7
7
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Answerable, AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, Optional } from '@serenity-js/core';
|
|
2
|
+
|
|
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`
|
|
8
|
+
*
|
|
9
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<Answerable<boolean>, Optional>}
|
|
10
|
+
*
|
|
11
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
12
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
13
|
+
* @see {@link @serenity-js/core/lib/screenplay/interactions~Wait}
|
|
14
|
+
*/
|
|
15
|
+
export function isPresent<Actual>(): Expectation<Actual> {
|
|
16
|
+
return new IsPresent<Actual>();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class IsPresent<Actual> extends Expectation<Actual> {
|
|
20
|
+
private static isOptional(value: any): value is Optional {
|
|
21
|
+
return value !== undefined
|
|
22
|
+
&& value !== null
|
|
23
|
+
&& typeof value.isPresent === 'function';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private static valueToCheck<A>(actual: Answerable<A>, actor: AnswersQuestions): Answerable<A> {
|
|
27
|
+
if (IsPresent.isOptional(actual)) {
|
|
28
|
+
return actual;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return actor.answer(actual);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private static async isPresent<A>(value: Answerable<A>, actor: AnswersQuestions): Promise<boolean> {
|
|
35
|
+
if (IsPresent.isOptional(value)) {
|
|
36
|
+
return actor.answer(value.isPresent());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return value !== undefined
|
|
40
|
+
&& value !== null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
super(
|
|
45
|
+
'become present',
|
|
46
|
+
async (actor: AnswersQuestions, actual: Answerable<Actual>) => {
|
|
47
|
+
|
|
48
|
+
const value = await IsPresent.valueToCheck(actual, actor);
|
|
49
|
+
|
|
50
|
+
const result = await IsPresent.isPresent(value, actor);
|
|
51
|
+
|
|
52
|
+
return result
|
|
53
|
+
? new ExpectationMet('become present', undefined, undefined)
|
|
54
|
+
: new ExpectationNotMet('become present', undefined, undefined);
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -3,5 +3,5 @@ import { Expectation } from '@serenity-js/core';
|
|
|
3
3
|
import { equals } from './equals';
|
|
4
4
|
|
|
5
5
|
export function isTrue(): Expectation<boolean> {
|
|
6
|
-
return Expectation.to<boolean>(`equal true`).soThatActual(equals(true));
|
|
6
|
+
return Expectation.to<never, boolean>(`equal true`).soThatActual(equals(true));
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Answerable, Expectation } from '@serenity-js/core';
|
|
2
2
|
|
|
3
|
-
export function matches(expected: Answerable<RegExp>): Expectation<
|
|
3
|
+
export function matches(expected: Answerable<RegExp>): Expectation<string> {
|
|
4
4
|
return Expectation.thatActualShould<RegExp, string>('match', expected)
|
|
5
5
|
.soThat((actualValue, expectedValue) => expectedValue.test(actualValue));
|
|
6
6
|
}
|
package/src/expectations/not.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet
|
|
2
|
-
import { match } from 'tiny-types';
|
|
1
|
+
import { Answerable, AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet } from '@serenity-js/core';
|
|
3
2
|
|
|
4
|
-
export function not<
|
|
5
|
-
return new Not<
|
|
3
|
+
export function not<Actual>(assertion: Expectation<Actual>): Expectation<Actual> {
|
|
4
|
+
return new Not<Actual>(assertion);
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @package
|
|
10
9
|
*/
|
|
11
|
-
class Not<
|
|
10
|
+
class Not<Actual> extends Expectation<Actual> {
|
|
12
11
|
private static flipped(message: string): string {
|
|
13
12
|
return message.startsWith('not ')
|
|
14
13
|
? message.slice(4)
|
|
15
14
|
: `not ${ message }`;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
constructor(private readonly expectation: Expectation<
|
|
19
|
-
super(
|
|
20
|
-
|
|
17
|
+
constructor(private readonly expectation: Expectation<Actual>) {
|
|
18
|
+
super(
|
|
19
|
+
Not.flipped(expectation.toString()),
|
|
20
|
+
async (actor: AnswersQuestions, actual: Answerable<Actual>) => {
|
|
21
|
+
const subject = Not.flipped(expectation.toString());
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
const outcome = await actor.answer(expectation.isMetFor(actual));
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.else(o => new ExpectationMet(this.subject, o.expected, o.actual)));
|
|
25
|
+
return outcome instanceof ExpectationNotMet
|
|
26
|
+
? new ExpectationMet(subject, outcome.expected, outcome.actual)
|
|
27
|
+
: new ExpectationNotMet(subject, outcome.expected, outcome.actual);
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
30
|
}
|
|
31
31
|
}
|
package/src/expectations/or.ts
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
1
|
+
import { Answerable, AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome, LogicError } from '@serenity-js/core';
|
|
2
2
|
|
|
3
|
-
export function or<Actual>(...assertions: Array<Expectation<
|
|
3
|
+
export function or<Actual>(...assertions: Array<Expectation<Actual>>): Expectation<Actual> {
|
|
4
4
|
return new Or(assertions);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @package
|
|
9
9
|
*/
|
|
10
|
-
class Or<Actual> extends Expectation<
|
|
10
|
+
class Or<Actual> extends Expectation<Actual> {
|
|
11
11
|
private static readonly Separator = ' or ';
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
.map(
|
|
16
|
-
.join(Or.Separator)
|
|
13
|
+
private static descriptionFor<A>(expectations: Array<Expectation<A>>): string {
|
|
14
|
+
return expectations
|
|
15
|
+
.map(expectation => expectation.toString())
|
|
16
|
+
.join(Or.Separator);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
constructor(private readonly expectations: Array<Expectation<Actual>>) {
|
|
20
|
+
super(
|
|
21
|
+
Or.descriptionFor(expectations),
|
|
22
|
+
async (actor: AnswersQuestions, actual: Answerable<Actual>) => {
|
|
23
|
+
if (! expectations || expectations.length === 0) {
|
|
24
|
+
throw new LogicError(`No expectations provided to or()`);
|
|
25
|
+
}
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
previous.then((outcomesSoFar: Array<ExpectationOutcome<any, Actual>>) =>
|
|
25
|
-
current.answeredBy(actor)(actual)
|
|
26
|
-
.then(outcome => outcomesSoFar.concat(outcome)), // todo: should stop on the first met expectation
|
|
27
|
-
),
|
|
28
|
-
Promise.resolve([]),
|
|
29
|
-
).
|
|
30
|
-
then((outcomes: Array<ExpectationOutcome<any, Actual>>) => {
|
|
27
|
+
let outcome: ExpectationOutcome<unknown, Actual>;
|
|
28
|
+
for (const expectation of expectations) {
|
|
29
|
+
outcome = await actor.answer(expectation.isMetFor(actual));
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
if (outcome instanceof ExpectationMet) {
|
|
32
|
+
return outcome;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
return new ExpectationNotMet(
|
|
37
|
+
Or.descriptionFor(expectations),
|
|
38
|
+
outcome.expected,
|
|
39
|
+
outcome.actual,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
);
|
|
40
43
|
}
|
|
41
44
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.property = void 0;
|
|
4
|
-
const core_1 = require("@serenity-js/core");
|
|
5
|
-
const io_1 = require("@serenity-js/core/lib/io");
|
|
6
|
-
function property(propertyName, expectation) {
|
|
7
|
-
return new HasProperty(propertyName, expectation);
|
|
8
|
-
}
|
|
9
|
-
exports.property = property;
|
|
10
|
-
/**
|
|
11
|
-
* @package
|
|
12
|
-
*/
|
|
13
|
-
class HasProperty extends core_1.Expectation {
|
|
14
|
-
constructor(propertyName, expectation) {
|
|
15
|
-
super((0, io_1.formatted) `have property ${propertyName} that does ${expectation}`);
|
|
16
|
-
this.propertyName = propertyName;
|
|
17
|
-
this.expectation = expectation;
|
|
18
|
-
}
|
|
19
|
-
answeredBy(actor) {
|
|
20
|
-
return (actual) => this.expectation.answeredBy(actor)(actual[this.propertyName])
|
|
21
|
-
.then((outcome) => {
|
|
22
|
-
return outcome instanceof core_1.ExpectationMet
|
|
23
|
-
? new core_1.ExpectationMet(this.toString(), outcome.expected, actual[this.propertyName])
|
|
24
|
-
: new core_1.ExpectationNotMet(this.toString(), outcome.expected, actual[this.propertyName]);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=property.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"property.js","sourceRoot":"","sources":["../../src/expectations/property.ts"],"names":[],"mappings":";;;AAAA,4CAAyH;AACzH,iDAAqD;AAErD,SAAgB,QAAQ,CACpB,YAAsB,EACtB,WAA+C;IAE/C,OAAO,IAAI,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;AACtD,CAAC;AALD,4BAKC;AAED;;GAEG;AACH,MAAM,WAAmD,SAAQ,kBAAqC;IAClG,YACqB,YAAsB,EACtB,WAA+C;QAEhE,KAAK,CAAC,IAAA,cAAS,EAAC,iBAAkB,YAAa,cAAe,WAAY,EAAE,CAAC,CAAC;QAH7D,iBAAY,GAAZ,YAAY,CAAU;QACtB,gBAAW,GAAX,WAAW,CAAoC;IAGpE,CAAC;IAED,UAAU,CAAC,KAAuB;QAE9B,OAAO,CAAC,MAAc,EAAE,EAAE,CACtB,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;aACxD,IAAI,CAAC,CAAC,OAAkD,EAAE,EAAE;YAEzD,OAAO,OAAO,YAAY,qBAAc;gBACpC,CAAC,CAAC,IAAI,qBAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAClF,CAAC,CAAC,IAAI,wBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAC9F,CAAC,CAAC,CAAC;IACf,CAAC;CACJ"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
2
|
-
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
-
|
|
4
|
-
export function property<Actual, Property extends keyof Actual>(
|
|
5
|
-
propertyName: Property,
|
|
6
|
-
expectation: Expectation<any, Actual[Property]>,
|
|
7
|
-
): Expectation<Actual[Property], Actual> {
|
|
8
|
-
return new HasProperty(propertyName, expectation);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @package
|
|
13
|
-
*/
|
|
14
|
-
class HasProperty<Property extends keyof Actual, Actual> extends Expectation<Actual[Property], Actual> {
|
|
15
|
-
constructor(
|
|
16
|
-
private readonly propertyName: Property,
|
|
17
|
-
private readonly expectation: Expectation<any, Actual[Property]>,
|
|
18
|
-
) {
|
|
19
|
-
super(formatted `have property ${ propertyName } that does ${ expectation }`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
answeredBy(actor: AnswersQuestions): (actual: Actual) => Promise<ExpectationOutcome<Actual[Property], any>> {
|
|
23
|
-
|
|
24
|
-
return (actual: Actual) =>
|
|
25
|
-
this.expectation.answeredBy(actor)(actual[this.propertyName])
|
|
26
|
-
.then((outcome: ExpectationOutcome<any, Actual[Property]>) => {
|
|
27
|
-
|
|
28
|
-
return outcome instanceof ExpectationMet
|
|
29
|
-
? new ExpectationMet(this.toString(), outcome.expected, actual[this.propertyName])
|
|
30
|
-
: new ExpectationNotMet(this.toString(), outcome.expected, actual[this.propertyName]);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|