@serenity-js/web
Advanced tools
Comparing version 3.0.0-rc.3 to 3.0.0-rc.4
@@ -6,2 +6,14 @@ # Change Log | ||
# [3.0.0-rc.4](https://github.com/serenity-js/serenity-js/compare/v3.0.0-rc.3...v3.0.0-rc.4) (2021-12-30) | ||
### Features | ||
* **web:** ElementExpectation makes it easier to define custom PageElement-related Expectations ([92ebf7d](https://github.com/serenity-js/serenity-js/commit/92ebf7db720d0fe88ddbe17b9958fa993b1fd02e)) | ||
* **web:** Text.ofAll accepts mapped PageElements ([5314246](https://github.com/serenity-js/serenity-js/commit/5314246305fa3f62446d5ec718f36354152be68d)) | ||
# [3.0.0-rc.3](https://github.com/serenity-js/serenity-js/compare/v3.0.0-rc.2...v3.0.0-rc.3) (2021-12-29) | ||
@@ -8,0 +20,0 @@ |
import { AnswersQuestions, Expectation, ExpectationOutcome } from '@serenity-js/core'; | ||
import { PageElement } from '../screenplay'; | ||
/** | ||
* @access private | ||
* @desc | ||
* A convenience method to create a custom {@link PageElement}-related {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @example <caption>Using an expectation in an assertion</caption> | ||
* import { Ensure } from '@serenity-js/assertions'; | ||
* import { actorCalled } from '@serenity-js/core'; | ||
* import { By, PageElement } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Ensure.that(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @example <caption>Using an expectation in a synchronisation statement</caption> | ||
* import { actorCalled, Duration } from '@serenity-js/core'; | ||
* import { By, PageElement, Wait } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Wait.upTo(Duration.ofSeconds(2)).until(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @public | ||
* @extends {@serenity-js/core/lib/screenplay/questions~Expectation} | ||
*/ | ||
export declare class ElementExpectation extends Expectation<any, PageElement> { | ||
private readonly fn; | ||
static forElementTo(message: string, fn: (actual: PageElement) => Promise<boolean>): Expectation<any, PageElement>; | ||
constructor(subject: string, fn: (actual: PageElement) => Promise<boolean>); | ||
/** | ||
* @desc | ||
* Creates an {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @param {string} description | ||
* A description of the expectation. | ||
* Please note that Serenity/JS will use it to describe your expectation in sentences like these: | ||
* - `actor ensures that <something> does <description>` | ||
* - `actor ensures that <something> does not <description>` | ||
* - `actor waits until <something> does <description>` | ||
* - `actor waits until <something> does not <description>` | ||
* | ||
* To work with the above templates, the description should be similar to | ||
* - `become present`, | ||
* - `become active`, | ||
* - `equal X`, | ||
* - `has value greater than Y`. | ||
* | ||
* Descriptions like "is present", "is active", "equals X", "is greater than Y" WILL NOT work well. | ||
* | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
* An asynchronous callback function that receives a {@link PageElement} and returns a {@link Promise} | ||
* that should resolve to `true` when the expectation is met, and `false` otherwise. | ||
* | ||
* @returns {ElementExpectation<any, PageElement>} | ||
*/ | ||
static forElementTo(description: string, fn: (actual: PageElement) => Promise<boolean>): Expectation<any, PageElement>; | ||
/** | ||
* @param {string} description | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
*/ | ||
constructor(description: string, fn: (actual: PageElement) => Promise<boolean>); | ||
/** | ||
* @param {@serenity-js/core/lib/screenplay/actor~AnswersQuestions} actor | ||
* @returns {function(actual: PageElement): Promise<ExpectationOutcome<boolean, PageElement>>} | ||
*/ | ||
answeredBy(actor: AnswersQuestions): (actual: PageElement) => Promise<ExpectationOutcome<boolean, PageElement>>; | ||
} |
@@ -6,12 +6,89 @@ "use strict"; | ||
/** | ||
* @access private | ||
* @desc | ||
* A convenience method to create a custom {@link PageElement}-related {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @example <caption>Using an expectation in an assertion</caption> | ||
* import { Ensure } from '@serenity-js/assertions'; | ||
* import { actorCalled } from '@serenity-js/core'; | ||
* import { By, PageElement } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Ensure.that(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @example <caption>Using an expectation in a synchronisation statement</caption> | ||
* import { actorCalled, Duration } from '@serenity-js/core'; | ||
* import { By, PageElement, Wait } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Wait.upTo(Duration.ofSeconds(2)).until(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @public | ||
* @extends {@serenity-js/core/lib/screenplay/questions~Expectation} | ||
*/ | ||
class ElementExpectation extends core_1.Expectation { | ||
constructor(subject, fn) { | ||
super(subject); | ||
/** | ||
* @param {string} description | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
*/ | ||
constructor(description, fn) { | ||
super(description); | ||
this.fn = fn; | ||
} | ||
static forElementTo(message, fn) { | ||
return new ElementExpectation(message, fn); | ||
/** | ||
* @desc | ||
* Creates an {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @param {string} description | ||
* A description of the expectation. | ||
* Please note that Serenity/JS will use it to describe your expectation in sentences like these: | ||
* - `actor ensures that <something> does <description>` | ||
* - `actor ensures that <something> does not <description>` | ||
* - `actor waits until <something> does <description>` | ||
* - `actor waits until <something> does not <description>` | ||
* | ||
* To work with the above templates, the description should be similar to | ||
* - `become present`, | ||
* - `become active`, | ||
* - `equal X`, | ||
* - `has value greater than Y`. | ||
* | ||
* Descriptions like "is present", "is active", "equals X", "is greater than Y" WILL NOT work well. | ||
* | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
* An asynchronous callback function that receives a {@link PageElement} and returns a {@link Promise} | ||
* that should resolve to `true` when the expectation is met, and `false` otherwise. | ||
* | ||
* @returns {ElementExpectation<any, PageElement>} | ||
*/ | ||
static forElementTo(description, fn) { | ||
return new ElementExpectation(description, fn); | ||
} | ||
/** | ||
* @param {@serenity-js/core/lib/screenplay/actor~AnswersQuestions} actor | ||
* @returns {function(actual: PageElement): Promise<ExpectationOutcome<boolean, PageElement>>} | ||
*/ | ||
answeredBy(actor) { | ||
@@ -18,0 +95,0 @@ return (actual) => this.fn(actual) |
@@ -0,1 +1,2 @@ | ||
export * from './ElementExpectation'; | ||
export * from './isActive'; | ||
@@ -2,0 +3,0 @@ export * from './isClickable'; |
@@ -13,2 +13,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./ElementExpectation"), exports); | ||
__exportStar(require("./isActive"), exports); | ||
@@ -15,0 +16,0 @@ __exportStar(require("./isClickable"), exports); |
import { Adapter, Answerable, MetaQuestion, Question } from '@serenity-js/core'; | ||
import { PageElement, PageElements } from '../models'; | ||
import { PageElement } from '../models'; | ||
/** | ||
@@ -91,3 +91,3 @@ * @desc | ||
* | ||
* @param {Answerable<PageElements>} elements | ||
* @param {Answerable<PageElement[]>} elements | ||
* @returns {Question<Promise<string[]>> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>} | ||
@@ -97,5 +97,3 @@ * | ||
*/ | ||
static ofAll(elements: PageElements): Question<Promise<string[]>> & // eslint-disable-line @typescript-eslint/indent | ||
MetaQuestion<Answerable<PageElement>, Promise<string[]>> & // eslint-disable-line @typescript-eslint/indent | ||
Adapter<string[]>; | ||
static ofAll(elements: Answerable<PageElement[]>): Question<Promise<string[]>> & Adapter<string[]>; | ||
} |
@@ -8,2 +8,3 @@ "use strict"; | ||
const ElementQuestion_1 = require("./ElementQuestion"); | ||
const f = (0, core_1.format)({ markQuestions: false }); | ||
/** | ||
@@ -97,3 +98,3 @@ * @desc | ||
* | ||
* @param {Answerable<PageElements>} elements | ||
* @param {Answerable<PageElement[]>} elements | ||
* @returns {Question<Promise<string[]>> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>} | ||
@@ -104,3 +105,6 @@ * | ||
static ofAll(elements) { | ||
return (0, core_1.createAdapter)(new TextOfMultipleElements(elements)); | ||
return core_1.Question.about(f `the text of ${elements}`, async (actor) => { | ||
const pageElements = await actor.answer(elements); | ||
return (0, io_1.asyncMap)(pageElements, element => element.text()); | ||
}); | ||
} | ||
@@ -118,20 +122,6 @@ } | ||
async answeredBy(actor) { | ||
const element = await this.resolve(actor, this.element); | ||
const element = await actor.answer(this.element); | ||
return element.text(); | ||
} | ||
} | ||
class TextOfMultipleElements extends ElementQuestion_1.ElementQuestion { | ||
constructor(elements) { | ||
super(`the text of ${elements}`); | ||
this.elements = elements; | ||
} | ||
of(parent) { | ||
// todo: return Question.about directly? | ||
return new TextOfMultipleElements(this.elements.of(parent)); | ||
} | ||
async answeredBy(actor) { | ||
const elements = await this.resolve(actor, this.elements); | ||
return (0, io_1.asyncMap)(elements, element => element.text()); | ||
} | ||
} | ||
//# sourceMappingURL=Text.js.map |
{ | ||
"name": "@serenity-js/web", | ||
"version": "3.0.0-rc.3", | ||
"version": "3.0.0-rc.4", | ||
"description": "Serenity/JS Screenplay Pattern APIs for the Web", | ||
@@ -49,4 +49,4 @@ "author": { | ||
"dependencies": { | ||
"@serenity-js/assertions": "3.0.0-rc.3", | ||
"@serenity-js/core": "3.0.0-rc.3", | ||
"@serenity-js/assertions": "3.0.0-rc.4", | ||
"@serenity-js/core": "3.0.0-rc.4", | ||
"tiny-types": "^1.17.0" | ||
@@ -85,3 +85,3 @@ }, | ||
}, | ||
"gitHead": "69da7444e581c457e29e87edcd910ec06a069338" | ||
"gitHead": "126a1cad42bcb1416ca68e62f54bf0d3eb3ea157" | ||
} |
@@ -6,16 +6,94 @@ import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core'; | ||
/** | ||
* @access private | ||
* @desc | ||
* A convenience method to create a custom {@link PageElement}-related {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @example <caption>Using an expectation in an assertion</caption> | ||
* import { Ensure } from '@serenity-js/assertions'; | ||
* import { actorCalled } from '@serenity-js/core'; | ||
* import { By, PageElement } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Ensure.that(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @example <caption>Using an expectation in a synchronisation statement</caption> | ||
* import { actorCalled, Duration } from '@serenity-js/core'; | ||
* import { By, PageElement, Wait } from '@serenity-js/web'; | ||
* | ||
* const submitButton = () => | ||
* PageElement.located(By.css('.submit')).describedAs('submit button'); | ||
* | ||
* actorCalled('Izzy').attemptsTo( | ||
* Wait.upTo(Duration.ofSeconds(2)).until(submitButton(), isPresent()) | ||
* ); | ||
* | ||
* @public | ||
* @extends {@serenity-js/core/lib/screenplay/questions~Expectation} | ||
*/ | ||
export class ElementExpectation extends Expectation<any, PageElement> { | ||
static forElementTo(message: string, fn: (actual: PageElement) => Promise<boolean>): Expectation<any, PageElement> { | ||
return new ElementExpectation(message, fn); | ||
/** | ||
* @desc | ||
* Creates an {@link @serenity-js/core/lib/screenplay/questions~Expectation} | ||
* | ||
* @example <caption>Defining an expectation</caption> | ||
* import { Expectation } from '@serenity-js/core'; | ||
* import { ElementExpectation, PageElement } from '@serenity-js/web'; | ||
* | ||
* export function isPresent(): Expectation<boolean, PageElement> { | ||
* return ElementExpectation.forElementTo('become present', actual => actual.isPresent()); | ||
* } | ||
* | ||
* @param {string} description | ||
* A description of the expectation. | ||
* Please note that Serenity/JS will use it to describe your expectation in sentences like these: | ||
* - `actor ensures that <something> does <description>` | ||
* - `actor ensures that <something> does not <description>` | ||
* - `actor waits until <something> does <description>` | ||
* - `actor waits until <something> does not <description>` | ||
* | ||
* To work with the above templates, the description should be similar to | ||
* - `become present`, | ||
* - `become active`, | ||
* - `equal X`, | ||
* - `has value greater than Y`. | ||
* | ||
* Descriptions like "is present", "is active", "equals X", "is greater than Y" WILL NOT work well. | ||
* | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
* An asynchronous callback function that receives a {@link PageElement} and returns a {@link Promise} | ||
* that should resolve to `true` when the expectation is met, and `false` otherwise. | ||
* | ||
* @returns {ElementExpectation<any, PageElement>} | ||
*/ | ||
static forElementTo(description: string, fn: (actual: PageElement) => Promise<boolean>): Expectation<any, PageElement> { | ||
return new ElementExpectation(description, fn); | ||
} | ||
/** | ||
* @param {string} description | ||
* @param {function(actual: PageElement): Promise<boolean>} fn | ||
*/ | ||
constructor( | ||
subject: string, | ||
description: string, | ||
private readonly fn: (actual: PageElement) => Promise<boolean>, | ||
) { | ||
super(subject); | ||
super(description); | ||
} | ||
/** | ||
* @param {@serenity-js/core/lib/screenplay/actor~AnswersQuestions} actor | ||
* @returns {function(actual: PageElement): Promise<ExpectationOutcome<boolean, PageElement>>} | ||
*/ | ||
answeredBy(actor: AnswersQuestions): (actual: PageElement) => Promise<ExpectationOutcome<boolean, PageElement>> { | ||
@@ -22,0 +100,0 @@ return (actual: PageElement) => |
@@ -0,1 +1,2 @@ | ||
export * from './ElementExpectation'; | ||
export * from './isActive'; | ||
@@ -2,0 +3,0 @@ export * from './isClickable'; |
@@ -1,7 +0,9 @@ | ||
import { Adapter, Answerable, AnswersQuestions, createAdapter, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core'; | ||
import { Adapter, Answerable, AnswersQuestions, createAdapter, format, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core'; | ||
import { asyncMap } from '@serenity-js/core/lib/io'; | ||
import { PageElement, PageElements } from '../models'; | ||
import { PageElement } from '../models'; | ||
import { ElementQuestion } from './ElementQuestion'; | ||
const f = format({ markQuestions: false }); | ||
/** | ||
@@ -103,3 +105,3 @@ * @desc | ||
* | ||
* @param {Answerable<PageElements>} elements | ||
* @param {Answerable<PageElement[]>} elements | ||
* @returns {Question<Promise<string[]>> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>} | ||
@@ -109,10 +111,9 @@ * | ||
*/ | ||
static ofAll(elements: PageElements): | ||
Question<Promise<string[]>> & // eslint-disable-line @typescript-eslint/indent | ||
MetaQuestion<Answerable<PageElement>, Promise<string[]>> & // eslint-disable-line @typescript-eslint/indent | ||
Adapter<string[]> // eslint-disable-line @typescript-eslint/indent | ||
{ | ||
return createAdapter<Promise<string[]>, ElementQuestion<Promise<string[]>> & MetaQuestion<Answerable<PageElement>, Promise<string[]>>>( | ||
new TextOfMultipleElements(elements) | ||
); | ||
static ofAll(elements: Answerable<PageElement[]>): Question<Promise<string[]>> & Adapter<string[]> { | ||
return Question.about(f `the text of ${ elements }`, async actor => { | ||
const pageElements: PageElement[] = await actor.answer(elements); | ||
return asyncMap(pageElements, element => element.text()); | ||
}) | ||
} | ||
@@ -134,3 +135,3 @@ } | ||
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> { | ||
const element = await this.resolve(actor, this.element); | ||
const element = await actor.answer(this.element); | ||
@@ -140,21 +141,1 @@ return element.text(); | ||
} | ||
class TextOfMultipleElements | ||
extends ElementQuestion<Promise<string[]>> | ||
implements MetaQuestion<Answerable<PageElement>, Promise<string[]>> | ||
{ | ||
constructor(private readonly elements: PageElements) { | ||
super(`the text of ${ elements }`); | ||
} | ||
of(parent: Answerable<PageElement>): Question<Promise<string[]>> { | ||
// todo: return Question.about directly? | ||
return new TextOfMultipleElements(this.elements.of(parent)); | ||
} | ||
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string[]> { | ||
const elements: PageElement[] = await this.resolve(actor, this.elements); | ||
return asyncMap(elements, element => element.text()); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
538102
11809
+ Added@serenity-js/assertions@3.0.0-rc.4(transitive)
+ Added@serenity-js/core@3.0.0-rc.4(transitive)
- Removed@serenity-js/assertions@3.0.0-rc.3(transitive)
- Removed@serenity-js/core@3.0.0-rc.3(transitive)
Updated@serenity-js/core@3.0.0-rc.4