Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ Sets up a test where:
- the function can return a Promise which either resolves (success) or rejects (fails).
- all other return value is ignored.
- `flags` - a set of test utilities described in [Flags](#flags).

```javascript
lab.experiment('my plan', () => {

Expand All @@ -418,7 +418,7 @@ The `test` function is passed a `flags` object that can be used to create notes

#### `context`

An object that is passed to `before` and `after` functions in addition to tests themselves. `context` is used to set properties inside the before function that can be used by a test function later. It is meant to reduce module level variables that are set by the `before` / `beforeEach` functions. Tests aren't able to manipulate the context object for other tests.
An object that is passed to `before` and `after` functions in addition to tests themselves. `context` is used to set properties inside the before function that can be used by a test function later. It is meant to reduce module level variables that are set by the `before` / `beforeEach` functions. The context object may only be modified in `before`, `beforeEach`, `after`, and `afterEach` functions. The object is passed to tests as a shallow clone, so any data added to the context in a test function will be lost.

```javascript
lab.before(({ context }) => {
Expand Down Expand Up @@ -748,7 +748,7 @@ Semantics:
- `$lab:coverage:push$` copies the current skip state to the top of the stack, and leaves it as the current state as well
- `$lab:coverage:pop$` replaces the current skip state with the top of the stack, and removes the top of the stack
- if the stack is empty, `lab` will tell you by throwing the error `"unable to pop coverage bypass stack"`

### Excluding paths from coverage reporting

The `--coverage-exclude` argument can be repeated multiple times in order to add multiple paths to exclude. By default the `node_modules` and `test` directories are excluded. If you want to exclude those as well as a directory named `public` you can run lab as follows:
Expand Down
2 changes: 1 addition & 1 deletion lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ internals.executeTests = async function (experiment, state, skip) {

const start = Date.now();
try {
test.context = Hoek.clone(state.currentContext);
test.context = Hoek.clone(state.currentContext, { shallow: true });
await internals.protect(test, state);
}
catch (ex) {
Expand Down
72 changes: 72 additions & 0 deletions test/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,78 @@ describe('Runner', () => {
expect(notebook.failures).to.equal(1);
});

it('passes shallow clones of context to tests', async () => {

const script = Lab.script({ schedule: false });

const testContext = {
testData: { hello: 'there' }
};

const innerContext = {
testData: { goodbye: 'you' },
additionalData: { another: 'object' }
};

script.experiment('test', () => {

script.before(({ context }) => {

context.testData = testContext.testData;
});

script.test('has test context', ({ context }) => {

expect(context,'has proper context').to.equal(testContext);
expect(context,'is a shallow clone').to.not.shallow.equal(testContext);
expect(context.testData,'is a reference').to.shallow.equal(testContext.testData);
context.anotherProperty = { something: 'random' };
});

script.test('does not see changes to context from previous test', ({ context }) => {

expect(context,'has proper context').to.equal(testContext);
expect(context,'is a shallow clone').to.not.shallow.equal(testContext);
expect(context.testData,'is a reference').to.shallow.equal(testContext.testData);
expect(context.anotherProperty,'uses the original clone').to.not.exist();
});

script.experiment('inner test', () => {

script.before(({ context }) => {

context.testData = innerContext.testData;
context.additionalData = innerContext.additionalData;
});

script.test('still has test context', ({ context }) => {

expect(context,'has proper context').to.equal(innerContext);
expect(context,'is a shallow clone').to.not.shallow.equal(innerContext);
expect(context.testData,'is a reference').to.shallow.equal(innerContext.testData);
expect(context.additionalData,'is a reference').to.shallow.equal(innerContext.additionalData);
});

script.after(({ context }) => {

context.addedAfter = { another: 'object' };
});
});

script.test(({ context }) => {

expect(context,'is a shallow clone').to.not.shallow.equal(innerContext);
expect(context.testData,'is a reference').to.shallow.equal(innerContext.testData);
expect(context.additionalData,'is a reference').to.shallow.equal(innerContext.additionalData);
expect(context.addedAfter,'keeps references from after').to.equal({ another: 'object' });
});
});

const notebook = await Lab.execute(script, {}, null);
expect(notebook.tests.length,'has 4 tests').to.equal(4);
expect(notebook.failures,'has 0 failures').to.equal(0);
});

it('nullifies test context on finish', async () => {

const script = Lab.script({ schedule: false });
Expand Down