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
9 changed files
with
209 additions
and
0 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
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 |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum Modes { | ||
ALL, | ||
EAGER, | ||
} |
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 |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { dummyTest } from '../../../../testUtils/testDummy'; | ||
|
||
import { create, eager, only, group } from 'vest'; | ||
|
||
describe('mode: eager', () => { | ||
let suite; | ||
|
||
describe('When tests fail', () => { | ||
beforeEach(() => { | ||
suite = create(include => { | ||
only(include); | ||
|
||
eager(); | ||
dummyTest.failing('field_1', 'first-of-field_1'); | ||
dummyTest.failing('field_1', 'second-of-field_1'); // Should not run | ||
dummyTest.failing('field_2', 'first-of-field_2'); | ||
dummyTest.failing('field_2', 'second-of-field_2'); // Should not run | ||
dummyTest.failing('field_3', 'first-of-field_3'); | ||
dummyTest.failing('field_3', 'second-of-field_3'); // Should not run | ||
}); | ||
}); | ||
|
||
it('Should fail fast for every failing field', () => { | ||
expect(suite.get().testCount).toBe(0); // sanity | ||
suite(); | ||
expect(suite.get().testCount).toBe(3); | ||
expect(suite.get().errorCount).toBe(3); | ||
expect(suite.get().getErrors('field_1')).toEqual(['first-of-field_1']); | ||
expect(suite.get().getErrors('field_2')).toEqual(['first-of-field_2']); | ||
expect(suite.get().getErrors('field_3')).toEqual(['first-of-field_3']); | ||
}); | ||
|
||
describe('When test is `only`ed', () => { | ||
it('Should fail fast for failing field', () => { | ||
suite('field_1'); | ||
expect(suite.get().testCount).toBe(1); | ||
expect(suite.get().errorCount).toBe(1); | ||
expect(suite.get().getErrors('field_1')).toEqual(['first-of-field_1']); | ||
}); | ||
}); | ||
|
||
describe('When test is in a group', () => { | ||
beforeEach(() => { | ||
suite = create(() => { | ||
eager(); | ||
group('group_1', () => { | ||
dummyTest.failing('field_1', 'first-of-field_1'); | ||
}); | ||
dummyTest.failing('field_1', 'second-of-field_1'); | ||
}); | ||
}); | ||
it('Should fail fast for failing field', () => { | ||
suite(); | ||
expect(suite.get().testCount).toBe(1); | ||
expect(suite.get().errorCount).toBe(1); | ||
expect(suite.get().getErrors('field_1')).toEqual(['first-of-field_1']); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('When tests pass', () => { | ||
beforeEach(() => { | ||
suite = create(() => { | ||
eager(); | ||
dummyTest.passing('field_1', 'first-of-field_1'); | ||
dummyTest.failing('field_1', 'second-of-field_1'); | ||
dummyTest.passing('field_2', 'first-of-field_2'); | ||
dummyTest.failing('field_2', 'second-of-field_2'); | ||
dummyTest.passing('field_3', 'first-of-field_3'); | ||
dummyTest.failing('field_3', 'second-of-field_3'); | ||
}); | ||
}); | ||
|
||
it('Should fail fast for every failing field', () => { | ||
expect(suite.get().testCount).toBe(0); // sanity | ||
suite(); | ||
expect(suite.get().testCount).toBe(6); | ||
expect(suite.get().errorCount).toBe(3); | ||
expect(suite.get().getErrors('field_1')).toEqual(['second-of-field_1']); | ||
expect(suite.get().getErrors('field_2')).toEqual(['second-of-field_2']); | ||
expect(suite.get().getErrors('field_3')).toEqual(['second-of-field_3']); | ||
}); | ||
}); | ||
|
||
describe('sanity', () => { | ||
beforeEach(() => { | ||
suite = create(() => { | ||
dummyTest.failing('field_1', 'first-of-field_1'); | ||
dummyTest.failing('field_1', 'second-of-field_1'); | ||
dummyTest.failing('field_2', 'first-of-field_2'); | ||
dummyTest.failing('field_2', 'second-of-field_2'); | ||
dummyTest.failing('field_3', 'first-of-field_3'); | ||
dummyTest.failing('field_3', 'second-of-field_3'); | ||
}); | ||
}); | ||
|
||
it('Should run all tests', () => { | ||
expect(suite.get().testCount).toBe(0); // sanity | ||
suite(); | ||
expect(suite.get().testCount).toBe(6); | ||
expect(suite.get().errorCount).toBe(6); | ||
}); | ||
}); | ||
}); |
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 |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Modes } from './Modes'; | ||
|
||
import VestTest from 'VestTest'; | ||
import ctx from 'ctx'; | ||
import { hasErrors } from 'hasFailures'; | ||
|
||
/** | ||
* Sets the suite to "eager" (fail fast) mode. | ||
* Eager mode will skip running subsequent tests of a failing fields. | ||
* | ||
* @example | ||
* // in the following example, the second test of username will not run | ||
* // if the first test of username failed. | ||
* const suite = create((data) => { | ||
* eager(); | ||
* | ||
* test('username', 'username is required', () => { | ||
* enforce(data.username).isNotBlank(); | ||
* }); | ||
* | ||
* test('username', 'username is too short', () => { | ||
* enforce(data.username).longerThan(2); | ||
* }); | ||
* }); | ||
*/ | ||
export function eager() { | ||
setMode(Modes.EAGER); | ||
} | ||
|
||
export function shouldSkipBasedOnMode(testObject: VestTest): boolean { | ||
if (isEager() && hasErrors(testObject.fieldName)) return true; | ||
|
||
return false; | ||
} | ||
|
||
function isEager(): boolean { | ||
return isMode(Modes.EAGER); | ||
} | ||
|
||
function isMode(mode: Modes): boolean { | ||
const { mode: currentMode } = ctx.useX(); | ||
|
||
return currentMode[0] === mode; | ||
} | ||
|
||
function setMode(nextMode: Modes): void { | ||
const { mode } = ctx.useX(); | ||
|
||
mode[0] = nextMode; | ||
} |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
sidebar_position: 5 | ||
--- | ||
|
||
# eager mode, failing fast | ||
|
||
Sometimes we wish to fail fast and not continue run subsequent tests of a failing field. We can do this manually per test using [skipWhen](./including_and_excluding/skipWhen.md), but if we want to do this automatically for all the tests in the suite, we can set the suite to `eager` mode. | ||
|
||
`eager` mode means that once a test of a given field fails, the suite will continue running subsequent tests of that same field. Other tests will run normally. | ||
|
||
:::tip NOTE | ||
Eager mode disregards groups and nested blocks, meaning that a failing field at any level, will skip its subsequent runs regardless of where the test was specified. | ||
::: | ||
|
||
## Usage | ||
|
||
```js | ||
import { create, eager, test, enforce } from 'vest'; | ||
|
||
const suite = create(data => { | ||
eager(); // set the suite to eager mode | ||
|
||
test('name', 'Name is required', () => { | ||
enforce(data.name).isNotBlank(); | ||
}); | ||
|
||
// this test will not run if the previous test fails | ||
// because the suite is in eager mode | ||
test('name', 'Name is too short', () => { | ||
enforce(data.name).longerThan(3); | ||
}); | ||
}); | ||
``` |
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
052f317
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
vest-next – ./website
vest-next.vercel.app
vest-website.vercel.app
vest-next-ealush.vercel.app
vest-next-git-latest-ealush.vercel.app