Skip to content

Commit

Permalink
Merge pull request #106 from gemini-testing/hermione.ctx
Browse files Browse the repository at this point in the history
Add method 'hermione.ctx' to tests API
  • Loading branch information
eGavr authored Jan 25, 2017
2 parents d59caf0 + 62f3d6e commit 5b05581
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 39 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ Hermione is the utility for integration testing of web pages using [WebdriverIO]
- [system](#system)
- [debug](#debug)
- [mochaOpts](#mochaopts)
- [ctx](#ctx)
- [plugins](#plugins)
- [prepareBrowser](#preparebrowser)
- [prepareEnvironment](#prepareenvironment)
- [CLI](#cli)
- [Overriding settings](#overriding-settings)
- [Programmatic API](#programmatic-api)
- [run](#run)
- [readTests](#readtests)
- [Environment variables](#environment-variables)
- [HERMIONE_SKIP_BROWSERS](#hermione_skip_browsers)

Expand Down Expand Up @@ -468,6 +471,22 @@ mochaOpts: {
}
```

#### ctx
A context which will be available in tests via method `hermione.ctx`:
```javascript
ctx: {
foo: 'bar'
}
```

```javascript
it('awesome test', function() {
console.log(hermione.ctx); // {foo: 'bar'}
});
```

**Recommendation**: use `ctx` in your tests in favor of global variables.

### plugins
`Hermione` plugins are commonly used to extend built-in possibilities. For example, [hermione-allure-reporter](https://github.com/gemini-testing/hermione-allure-reporter) and [hermione-tunnel](https://github.com/gemini-testing/hermione-tunnel).

Expand Down
4 changes: 3 additions & 1 deletion lib/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const rootSection = section(_.extend(browserOptions.getTopLevel(), {
system: section({
debug: options.boolean('debug'),

mochaOpts: options.optionalObject('mochaOpts')
mochaOpts: options.optionalObject('mochaOpts'),

ctx: options.anyObject()
}),

plugins: options.anyObject(),
Expand Down
3 changes: 2 additions & 1 deletion lib/runner/mocha-runner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = class MochaRunner extends QEmitter {
super();

this._sharedMochaOpts = config.system.mochaOpts;
this._ctx = config.system.ctx;
this._browserAgent = browserAgent;
this._testSkipper = testSkipper;
}
Expand All @@ -33,7 +34,7 @@ module.exports = class MochaRunner extends QEmitter {
}

_createMocha(suiteFiles, titles, filterFn) {
const mochaAdapter = MochaAdapter.create(this._sharedMochaOpts, this._browserAgent);
const mochaAdapter = MochaAdapter.create(this._sharedMochaOpts, this._browserAgent, this._ctx);
suiteFiles = [].concat(suiteFiles);

return mochaAdapter
Expand Down
26 changes: 11 additions & 15 deletions lib/runner/mocha-runner/mocha-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ const isSkipped = (suite) => {
};

module.exports = class MochaAdapter {
static create(opts, browserAgent) {
return new MochaAdapter(opts, browserAgent);
static create(opts, browserAgent, ctx) {
return new MochaAdapter(opts, browserAgent, ctx);
}

constructor(opts, browserAgent) {
constructor(opts, browserAgent, ctx) {
this._mocha = new Mocha(opts);
this._mocha.fullTrace();
this.suite = this._mocha.suite;
Expand All @@ -35,10 +35,14 @@ module.exports = class MochaAdapter {
this._browser = null;

this._currentRunnable = null;
this._hermione = {ctx};

this._injectBrowser();
this._injectSkip();
this._injectRunnableSpy();
this._injectSkip();

this.suite.on('pre-require', () => global.hermione = this._hermione);
this.suite.on('post-require', () => delete global.hermione);
}

applySkip(testSkipper) {
Expand Down Expand Up @@ -97,18 +101,10 @@ module.exports = class MochaAdapter {

_injectSkip() {
const skip = new Skip();
const skipBuilder = new SkipBuilder(skip, this._browserAgent.browserId);
const onlyBuilder = new OnlyBuilder(skipBuilder);

this.suite.on('pre-require', () => {
const skipBuilder = new SkipBuilder(skip, this._browserAgent.browserId);
const onlyBuilder = new OnlyBuilder(skipBuilder);

global.hermione = {
skip: skipBuilder,
only: onlyBuilder
};
});

this.suite.on('post-require', () => delete global.hermione);
_.extend(this._hermione, {skip: skipBuilder, only: onlyBuilder});

this._addEventHandler(['suite', 'test'], (runnable) => skip.handleEntity(runnable));
}
Expand Down
17 changes: 17 additions & 0 deletions test/lib/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,23 @@ describe('config options', () => {
assert.deepEqual(config.system.mochaOpts.grep, /test/);
});
});

describe('ctx', () => {
it('should be empty by default', () => {
const config = createConfig();

assert.deepEqual(config.system.ctx, {});
});

it('should override ctx option', () => {
const readConfig = _.set({}, 'system.ctx', {some: 'ctx'});
Config.read.returns(readConfig);

const config = createConfig();

assert.deepEqual(config.system.ctx, {some: 'ctx'});
});
});
});

describe('prepareEnvironment', () => {
Expand Down
10 changes: 9 additions & 1 deletion test/lib/runner/mocha-runner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('mocha-runner', () => {

const mochaRunnerInit = () => {
return new MochaRunner(
{system: {mochaOpts: {}}},
{system: {mochaOpts: {}, ctx: {}}},
sinon.createStubInstance(BrowserAgent),
sinon.createStubInstance(TestSkipper)
);
Expand Down Expand Up @@ -60,6 +60,14 @@ describe('mocha-runner', () => {
));
});

it('should share a ctx from config between all mocha instances', () => {
return run_(['path/to/file', 'path/to/other/file'])
.then(() => assert.equal(
MochaAdapter.create.firstCall.args[2],
MochaAdapter.create.secondCall.args[2]
));
});

it('should run all mocha instances', () => {
return run_(['some/file', 'other/file'])
.then(() => assert.calledTwice(MochaAdapter.prototype.run));
Expand Down
56 changes: 35 additions & 21 deletions test/lib/runner/mocha-runner/mocha-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ describe('mocha-runner/mocha-adapter', () => {
});
}

const mkMochaAdapter_ = (opts) => {
testSkipper = sinon.createStubInstance(TestSkipper);

return MochaAdapter.create(opts || {}, browserAgent, testSkipper);
const mkMochaAdapter_ = (opts, ctx) => {
return MochaAdapter.create(opts || {}, browserAgent, ctx);
};

const mkBrowserStub_ = () => {
return {publicAPI: Object.create({})};
};

beforeEach(() => {
testSkipper = sinon.createStubInstance(TestSkipper);

clearRequire = sandbox.stub().named('clear-require');
browserAgent = sinon.createStubInstance(BrowserAgent);

Expand Down Expand Up @@ -147,31 +147,45 @@ describe('mocha-runner/mocha-adapter', () => {
assert.isDefined(global.hermione);
});

it('hermione.skip should return SkipBuilder instance', () => {
const mochaAdapter = mkMochaAdapter_();
describe('hermione global', () => {
afterEach(() => delete global.hermione);

mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('pre-require');
it('hermione.skip should return SkipBuilder instance', () => {
const mochaAdapter = mkMochaAdapter_();

assert.instanceOf(global.hermione.skip, SkipBuilder);
});
mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('pre-require');

it('hermione.only should return OnlyBuilder instance', () => {
const mochaAdapter = mkMochaAdapter_();
assert.instanceOf(global.hermione.skip, SkipBuilder);
});

mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('pre-require');
it('hermione.only should return OnlyBuilder instance', () => {
const mochaAdapter = mkMochaAdapter_();

assert.instanceOf(global.hermione.only, OnlyBuilder);
});
mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('pre-require');

it('should remove global "hermione" object on "post-require" event', () => {
const mochaAdapter = mkMochaAdapter_();
assert.instanceOf(global.hermione.only, OnlyBuilder);
});

mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('post-require');
it('hermione.ctx should return passed ctx', () => {
const mochaAdapter = mkMochaAdapter_({}, {some: 'ctx'});

mochaAdapter.addFiles(['path/to/file.js']);
MochaStub.prototype.suite.emit('pre-require');

assert.isUndefined(global.hermione);
assert.deepEqual(global.hermione.ctx, {some: 'ctx'});
});

it('should remove global "hermione" object on "post-require" event', () => {
const mochaAdapter = mkMochaAdapter_();

mochaAdapter.addFiles(['path/to/file']);
MochaStub.prototype.suite.emit('pre-require');
MochaStub.prototype.suite.emit('post-require');

assert.isUndefined(global.hermione);
});
});
});

Expand Down

0 comments on commit 5b05581

Please sign in to comment.