Skip to content
Permalink
Browse files
feat(assertions): containAtLeastOneThat(expectation)
  • Loading branch information
jan-molak committed Mar 7, 2019
1 parent 82dd65d commit dec56182187bb60cc53e8ce09e2e776e9b947b4e
@@ -0,0 +1,39 @@
import 'mocha';

import { expect } from '@integration/testing-tools';
import { Actor, AssertionError, Question } from '@serenity-js/core';
import { containAtLeastOneThat, Ensure, equals, isGreaterThan } from '../../src';

describe('containAtLeastOneThat', () => {

const Astrid = Actor.named('Astrid');

/** @test {containAtLeastOneThat} */
it(`allows for the actor flow to continue when the "actual" includes at least one item that meets the expectation`, () => {
return Astrid.attemptsTo(
Ensure.that([ 0, 1, 2 ], containAtLeastOneThat(isGreaterThan(1))),
);
});

/** @test {containAtLeastOneThat} */
it(`breaks the actor flow when "actual" does not include at least one item that meets the expectation`, () => {
return expect(Astrid.attemptsTo(
Ensure.that([ 0, 1, 2 ], containAtLeastOneThat(equals(7))),
)).to.be.rejectedWith(AssertionError, `Expected [ 0, 1, 2 ] to contain at least one that does equal 7`);
});

/** @test {containAtLeastOneThat} */
it(`breaks the actor flow when "actual" is an empty list`, () => {
return expect(Astrid.attemptsTo(
Ensure.that([], containAtLeastOneThat(equals(42))),
)).to.be.rejectedWith(AssertionError, `Expected [ ] to contain at least one that does equal 42`);
});

/** @test {atLeastOne} */
it(`contributes to a human-readable description`, () => {
const numbers = () => Question.about('list of numbers', actor => [ 0, 1, 2 ]);

expect(Ensure.that(numbers(), containAtLeastOneThat(isGreaterThan(1))).toString())
.to.equal(`#actor ensures that list of numbers does contain at least one that does have value greater than 1`);
});
});
@@ -0,0 +1,28 @@
import { AnswersQuestions } from '@serenity-js/core';
import { formatted } from '@serenity-js/core/lib/io';
import { Expectation } from '../Expectation';
import { ExpectationMet, ExpectationNotMet, Outcome } from '../outcomes';

export function containAtLeastOneThat<Actual>(expectation: Expectation<any, Actual>): Expectation<any, Actual[]> {
return new ContainAtLeastOneThatMeetsExpectation(expectation);
}

class ContainAtLeastOneThatMeetsExpectation<Expected, Actual> extends Expectation<Expected, Actual[]> {
constructor(private readonly expectation: Expectation<Expected, Actual>) {
super();
}
answeredBy(actor: AnswersQuestions): (actual: Actual[]) => Promise<Outcome<Expected, Actual[]>> {
return (actual: Actual[]) =>
actual.length === 0
? Promise.resolve(new ExpectationNotMet(this.toString(), null, actual))
: Promise.all(actual.map(item => this.expectation.answeredBy(actor)(item)))
.then(results => results.some(result => result instanceof ExpectationMet)
? new ExpectationMet(this.toString(), results[0].expected, actual)
: new ExpectationNotMet(this.toString(), results[0].expected, actual),
);
}

toString(): string {
return formatted `contain at least one that does ${ this.expectation }`;
}
}
@@ -1,5 +1,6 @@
export * from './and';
export * from './contains';
export * from './containAtLeastOneThat';
export * from './endsWith';
export * from './equals';
export * from './includes';
@@ -22,6 +22,7 @@ describe ('`formatted` tag function', () => {
{ description: 'a number parameter', actual: formatted `Answer: ${ 42 }`, expected: 'Answer: 42' },
{ description: 'a string parameter', actual: formatted `Hello ${ 'World' }!`, expected: "Hello 'World'!" },
{ description: 'an object parameter', actual: formatted `${ { twitter: '@JanMolak'} }`, expected: "{ twitter: '@JanMolak' }" },
{ description: 'an empty array', actual: formatted `${ [] }`, expected: '[ ]' },
{ description: 'an array parameter', actual: formatted `${ [1, 2, '3'] }`, expected: "[ 1, 2, '3' ]" },
{ description: 'an array of params', actual: formatted `${ [ Promise.resolve(1), q('2') ] }`, expected: '[ a promised value, the meaning of life ]' },
{ description: 'an object array parameter', actual: formatted `${ [{ name: 'Jan'}] }`, expected: "[ { name: 'Jan' } ]" },
@@ -33,7 +33,7 @@ function descriptionOf(value: KnowableUnknown<any>): string {
}

if (Array.isArray(value)) {
return `[ ${ value.map(item => descriptionOf(item)).join(', ') } ]`;
return `[ ${ value.map(item => descriptionOf(item)).join(', ') } ]`.replace(/\s+/, ' ');
}

if (isAPromise(value)) {

0 comments on commit dec5618

Please sign in to comment.