@serenity-js/core
Version:
The core Serenity/JS framework, providing the Screenplay Pattern interfaces, as well as the test reporting and integration infrastructure
250 lines • 7.97 kB
TypeScript
import { Ability, type SerialisedAbility } from '../abilities';
import { Notepad } from './Notepad';
/**
* An [`Ability`](https://serenity-js.org/api/core/class/Ability/) that enables an [`Actor`](https://serenity-js.org/api/core/class/Actor/) to remember information
* to be recalled during a test scenario.
*
* Under the hood, [`TakeNotes`](https://serenity-js.org/api/core/class/TakeNotes/) uses a [`Notepad`](https://serenity-js.org/api/core/class/Notepad/), which state
* can be populated both during initialisation or while the test scenario is executed.
* Populating the notepad when it's initialised can be useful to associate authentication credentials
* or personal details with a given actor, while dynamic recording of notes during a test scenario
* can be useful when the data to be recorded is not known upfront - for example when we want
* the actor to remember a JWT stored in the browser and then use it when sending API requests.
*
* **Pro tip:** [`TakeNotes`](https://serenity-js.org/api/core/class/TakeNotes/), [`Notepad`](https://serenity-js.org/api/core/class/Notepad/) and [`notes`](https://serenity-js.org/api/core/function/notes/) can be typed
* using [TypeScript generics](https://www.typescriptlang.org/docs/handbook/2/generics.html)
* to help you avoid typos when specifying note names.
*
* See [notes](https://serenity-js.org/api/core/function/notes) and [`Notepad`](https://serenity-js.org/api/core/class/Notepad/) for more usage examples.
*
* ## Remembering and retrieving a value
*
* ```ts
* import { actorCalled, Log, notes, TakeNotes } from '@serenity-js/core'
*
* await actorCalled('Leonard')
* .whoCan(TakeNotes.usingAnEmptyNotepad())
* .attemptsTo(
* notes().set('my_note', 'some value'),
* Log.the(notes().get('my_note')),
* // emits 'some value'
* )
* ```
*
* ## Using generics
*
* ```ts
* import { actorCalled, Log, notes, TakeNotes } from '@serenity-js/core'
*
* interface MyNotes {
* personalDetails: {
* firstName: string;
* lastName: string;
* }
* }
*
* await actorCalled('Leonard')
* .whoCan(TakeNotes.usingAnEmptyNotepad<MyNotes>())
* .attemptsTo(
* Log.the(notes<MyNotes>().has('personalDetails')),
* // emits false
*
* Log.the(notes<MyNotes>().get('personalDetails').isPresent()),
* // emits false
*
* notes<MyNotes>().set('personalDetails', { firstName: 'Leonard', lastName: 'McLaud' }),
*
* Log.the(notes<MyNotes>().has('personalDetails')),
* // emits true
*
* Log.the(notes<MyNotes>().get('personalDetails').isPresent()),
* // emits true
*
* Log.the(notes().get('personalDetails').firstName),
* // emits 'Leonard'
*
* Log.the(notes().get('personalDetails').firstName.toLocaleUpperCase()),
* // emits 'LEONARD'
* )
* ```
*
* ## Populating the notepad with initial state
*
* ```ts
* import { actorCalled, Log, Note, Notepad, TakeNotes } from '@serenity-js/core'
*
* interface MyNotes {
* firstName: string;
* lastName: string;
* }
*
* await actorCalled('Leonard')
* .whoCan(
* TakeNotes.using(Notepad.with<MyNotes>({
* firstName: 'Leonard',
* lastName: 'McLaud',
* }))
* )
* .attemptsTo(
* notes<MyNotes>().set('lastName', 'Shelby'),
* Log.the(notes().get('firstName')),
* // emits 'Leonard'
*
* Log.the(notes().get('lastName')),
* // emits 'Shelby'
* )
* ```
*
* ## Recording a dynamic note
*
* ```ts
* import { actorCalled, Log, Notepad, notes, TakeNotes } from '@serenity-js/core'
* import { By, Text, PageElement } from '@serenity-js/web'
* import { BrowseTheWebWithWebdriverIO } from '@serenity-js/webdriverio'
*
* interface OnlineShoppingNotes {
* promoCode: string;
* }
*
* const promoCodeBanner = () =>
* PageElement.located(By.css('[data-testid="promo-code"]'))
* .describedAs('promo code');
*
* const promoCodeInput = () =>
* PageElement.located(By.css('[data-testid="promo-code-input"]'))
* .describedAs('promo code field');
*
* await actorCalled('Leonard')
* .whoCan(
* BrowseTheWebWithWebdriverIO.using(browser),
* TakeNotes.using(Notepad.empty<OnlineShoppingNotes>())
* )
* .attemptsTo(
* notes<OnlineShoppingNotes>().set('promoCode', Text.of(promoCode()),
* // ...
* Enter.theValue(notes<OnlineShoppingNotes>().get('promoCode'))
* .into(promoCodeInput())
* )
* ```
*
* ## Clearing a notepad before each test scenario (Mocha)
*
* ```ts
* import 'mocha';
*
* beforeEach(() =>
* actorCalled('Leonard')
* .attemptsTo(
* notes().clear(),
* ))
* ```
*
* ## Clearing a notepad before each test scenario (Cucumber)
*
* ```ts
* import { Before } from '@cucumber/cucumber'
*
* Before(() =>
* actorCalled('Leonard')
* .attemptsTo(
* notes().clear(),
* ));
* ```
*
* ## Importing notes from an API response
*
* ```ts
* // given an example API:
* // GET /generate-test-user
* // which returns:
* // { "first_name": "Leonard", "last_name": "Shelby" }
*
* import { actorCalled, Log, Notepad, notes, TakeNotes } from '@serenity-js/core'
* import { CallAnApi, GetRequest, Send } from '@serenity-js/rest'
*
* interface PersonalDetails {
* first_name: string;
* last_name: string;
* }
*
* interface MyNotes {
* personalDetails?: PersonalDetails;
* }
*
* await actorCalled('Leonard')
* .whoCan(
* CallAnApi.at('https://api.example.org/'),
* TakeNotes.using(Notepad.empty<MyNotes>())
* )
* .attemptsTo(
* Send.a(GetRequest.to('/generate-test-user')),
* notes<MyNotes>().set('personalDetails', LastResponse.body<PersonalDetails>()),
*
* Log.the(notes<MyNotes>().get('personalDetails').first_name), // emits 'Leonard'
* Log.the(notes<MyNotes>().get('personalDetails').last_name), // emits 'Shelby'
* )
* ```
*
* ## Using the QuestionAdapter
*
* ```ts
* import { actorCalled, Log, Notepad, notes, TakeNotes } from '@serenity-js/core'
*
* interface AuthCredentials {
* username?: string;
* password?: string;
* }
*
* interface MyNotes {
* auth: AuthCredentials;
* }
*
* await actorCalled('Leonard')
* .whoCan(
* TakeNotes.using(
* Notepad.with<MyNotes>({ // typed initial state
* auth: {
* username: 'leonard@example.org',
* password: 'SuperSecretP@ssword!',
* }
* })
* )
* )
* .attemptsTo(
* Log.the(
* notes<MyNotes>() // typed notes
* .get('auth') // returns QuestionAdapter<AuthCredentials>
* .password // returns QuestionAdapter<string>
* .charAt(0)
* .toLocaleLowerCase(), // emits "s"
* ),
* )
* ```
*
* ## Learn more
*
* - [notes](https://serenity-js.org/api/core/function/notes)
* - [`Notepad`](https://serenity-js.org/api/core/class/Notepad/)
*
* @group Notes
*/
export declare class TakeNotes<Notes_Type extends Record<any, any>> extends Ability {
readonly notepad: Notepad<Notes_Type>;
/**
* Initialises an [`Ability`](https://serenity-js.org/api/core/class/Ability/) to [`TakeNotes`](https://serenity-js.org/api/core/class/TakeNotes/) with [`Notepad.empty`](https://serenity-js.org/api/core/class/Notepad/#empty).
*/
static usingAnEmptyNotepad<N extends Record<any, any>>(): TakeNotes<N>;
/**
* Initialises an [`Ability`](https://serenity-js.org/api/core/class/Ability/) to [`TakeNotes`](https://serenity-js.org/api/core/class/TakeNotes/) using
* a [`Notepad.with`](https://serenity-js.org/api/core/class/Notepad/#with) some initial state.
*
* @param notepad
*/
static using<N extends Record<any, any>>(notepad: Notepad<N>): TakeNotes<N>;
/**
* @param notepad
*/
constructor(notepad: Notepad<Notes_Type>);
toJSON(): SerialisedAbility;
}
//# sourceMappingURL=TakeNotes.d.ts.map