-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
207 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,8 +82,8 @@ export class TestBuilder<C extends Context> implements TestImplementation { | |
* ### With description and action | ||
* | ||
* ``` typescript | ||
* .step("do the thing", async() { | ||
* await thing.do(); | ||
* .step("click the new post link", async () { | ||
* await Link('New post').click(); | ||
* }); | ||
* ``` | ||
* | ||
|
@@ -92,15 +92,15 @@ export class TestBuilder<C extends Context> implements TestImplementation { | |
* ``` typescript | ||
* .step( | ||
* { | ||
* description: "do the thing", | ||
* action: async() { | ||
* await things.do(); | ||
* description: "click the new post link", | ||
* action: async () { | ||
* await Link('New post').click(); | ||
* } | ||
* }, | ||
* { | ||
* description: "another thing", | ||
* action: async() { | ||
* await anotherThing.do(); | ||
* description: "fill in the text", | ||
* action: async () { | ||
* await TextField('Title').fillIn('An introduction to BigTest'); | ||
* } | ||
* } | ||
* ); | ||
|
@@ -112,31 +112,39 @@ export class TestBuilder<C extends Context> implements TestImplementation { | |
* they can be used like this: | ||
* | ||
* ``` typescript | ||
* .step(Link('New post').click()) | ||
* .step(TextField('Title').fillIn('An introduction to BigTest')) | ||
* ``` | ||
* | ||
* Or like this if you prefer: | ||
* | ||
* ``` typescript | ||
* .step( | ||
* Link('New post').click(), | ||
* TextField('Text').fillIn('BigTest is cool!'), | ||
* Button('Submit').click(), | ||
* Headline('BigTest is cool!').exists() | ||
* TextField('Title').fillIn('An introduction to BigTest'), | ||
* ) | ||
* ``` | ||
* | ||
* ### Returning from context | ||
* | ||
* Returning an object from a step merges it into the context, and it can | ||
* then be used in subsequent steps. | ||
* | ||
* ``` typescript | ||
* .step("given a user", async() { | ||
* .step("given a user", async () { | ||
* return { user: await User.create() } | ||
* }) | ||
* .step("and the user has a post", async({ user }) { | ||
* .step("and the user has a post", async ({ user }) { | ||
* return { post: await Post.create({ user }) } | ||
* }) | ||
* .step("when I visit the post", async({ user, post }) { | ||
* .step("when I visit the post", async ({ user, post }) { | ||
* await Page.visit(`/users/${user.id}/posts/${post.id}`); | ||
* }) | ||
* ``` | ||
* | ||
* @param description The description of this step | ||
* @param action An async function which receives the current context and may return an object which extends the context | ||
* @typeParam R The return type of the action function can either be | ||
* @param action An async function which receives the current context and may return an object which extends the context. See {@link Action}. | ||
* @typeParam R The return type of the action function can optionally be an object which will be merged into the context. | ||
*/ | ||
step<R extends Context | void>(description: string, action: Action<C,R>): TestBuilder<R extends void ? C : C & R>; | ||
/** | ||
|
@@ -166,8 +174,69 @@ export class TestBuilder<C extends Context> implements TestImplementation { | |
}); | ||
} | ||
|
||
assertion(...assertions: AssertionList<C>): TestBuilder<C>; | ||
/** | ||
* Add one or more assertions to this test. The arguments to this function | ||
* should be either a description and a check, or one or more objects which | ||
* have `description` and `check` properties. Interactor assertions can be | ||
* used as an assertion directly, but interactor actions cannot. | ||
* | ||
* The check is an async function, if it completes without error, the | ||
* assertion passes. Its return value is ignored. | ||
* | ||
* ### With description and check | ||
* | ||
* ``` typescript | ||
* .assertion("the new post link is no longer shown", async () { | ||
* await Link('New post').absent(); | ||
* }); | ||
* ``` | ||
* | ||
* ### With assertion objects | ||
* | ||
* ``` typescript | ||
* .step( | ||
* { | ||
* description: "the new post link is no longer shown", | ||
* check: async () { | ||
* await Link('New post').absent(); | ||
* } | ||
* }, | ||
* { | ||
* description: "the heading has changed", | ||
* check: async () { | ||
* await Heading('Create a new post').exists(); | ||
* } | ||
* } | ||
* ); | ||
* ``` | ||
* | ||
* ### With interactor | ||
* | ||
* Interactor assertions implement the assertion object interface, so they | ||
* can be used like this: | ||
* | ||
* ``` typescript | ||
* .assertion(Link('New post').absent()) | ||
* .assertion(Headline('Create a new post').exists()) | ||
* ``` | ||
* | ||
* Or like this if you prefer: | ||
* | ||
* ``` typescript | ||
* .assertion( | ||
* Link('New post').absent(), | ||
* Headline('Create a new post').exists() | ||
* ) | ||
* ``` | ||
* | ||
* @param description The description of this assertion | ||
* @param check An async function which receives the context. See {@link Check}. | ||
*/ | ||
assertion(description: string, check: Check<C>): TestBuilder<C>; | ||
/** | ||
* @param steps A list of assertion objects, each of which must have a `description` and `check` property. | ||
*/ | ||
assertion(...assertions: AssertionList<C>): TestBuilder<C>; | ||
assertion(...args: [string, Check<C>] | AssertionList<C>): TestBuilder<C> { | ||
if(this.state === 'child') { | ||
throw new TestStructureError(`Cannot add step after adding ${this.state}`); | ||
|
@@ -191,6 +260,45 @@ export class TestBuilder<C extends Context> implements TestImplementation { | |
}, 'assertion'); | ||
} | ||
|
||
/** | ||
* Add a child test to this test. Child tests are executed after all of a | ||
* tests steps have run. Each child test may in turn add steps and | ||
* assertions. | ||
* | ||
* A callback function must be provided as the second argument. This function | ||
* receives a {@link TestBuilder} which you can use to construct the child | ||
* test. The finished child test is then returned from the callback | ||
* function. | ||
* | ||
* ### Example | ||
* | ||
* ``` typescript | ||
* .child("signing in", (test) => { | ||
* return ( | ||
* test | ||
* .step(TextField('Email').fillIn('jonas@example.com')) | ||
* .step(TextField('Password').fillIn('password123')) | ||
* .step(Button('Submit').click() | ||
* ) | ||
* }); | ||
* ``` | ||
* | ||
* Or more consisely: | ||
* | ||
* ``` typescript | ||
* .child("signing in", (test) => test | ||
* .step(TextField('Email').fillIn('[email protected]')) | ||
* .step(TextField('Password').fillIn('password123')) | ||
* .step(Button('Submit').click() | ||
* ); | ||
* ``` | ||
* | ||
* *Note: the odd signature using a callback function was chosen because it | ||
* improves type checking and inference when using TypeScript.* | ||
* | ||
* @param description The description of this child test | ||
* @param childFn a callback function | ||
*/ | ||
child(description: string, childFn: (inner: TestBuilder<C>) => TestBuilder<Context>): TestBuilder<C> { | ||
let child = childFn(test(description)); | ||
return new TestBuilder({ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
export * from './interfaces'; | ||
export { test, TestBuilder } from './dsl'; | ||
export { validateTest, MAXIMUM_DEPTH } from './validate-test'; | ||
export { validateTest, TestValidationError, MAXIMUM_DEPTH } from './validate-test'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.