Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.

Commit b21aa58

Browse files
committed
feat: emit async INIT event instead of async plugins load
1 parent a9c5eed commit b21aa58

File tree

4 files changed

+108
-46
lines changed

4 files changed

+108
-46
lines changed

doc/events.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Gemini events
22

3-
* `AFTER_TESTS_READ` - emitted after all tests were read (during `run`, `update` or `readTests` call). The event is emitted with 1 argument `data`:
3+
* `INIT` - emitted before any job start (`test`, `update` or `readTests`). If handler returns a promise then job will start only after the promise will be resolved. Emitted only once no matter how many times job will be performed.
4+
5+
* `AFTER_TESTS_READ` - emitted after all tests were read (during `test`, `update` or `readTests` call). The event is emitted with 1 argument `data`:
46
* `data.suiteCollection` - suite collection with all suites parsed from test files
57

68
* `UPDATE_RESULT` — emitted always during update. The event is emitted with 1 argument `result`:

lib/constants/events.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict';
22

33
module.exports = {
4+
INIT: 'init',
5+
46
AFTER_TESTS_READ: 'afterTestsRead',
57

68
START_RUNNER: 'startRunner',

lib/gemini.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module.exports = class Gemini extends PassthroughEmitter {
4646
this.SuiteCollection = SuiteCollection;
4747

4848
setupLog(this.config.system.debug);
49+
this._loadPlugins();
4950
}
5051

5152
getScreenshotPath(suite, stateName, browserId) {
@@ -89,12 +90,16 @@ module.exports = class Gemini extends PassthroughEmitter {
8990
}
9091

9192
_exec(fn) {
92-
return this._loadPlugins().then(() => fn());
93+
return this._init().then(() => fn());
94+
}
95+
96+
_init() {
97+
this._init = () => Promise.resolve(); // init only once
98+
return this.emitAndWait(Events.INIT);
9399
}
94100

95101
_loadPlugins() {
96-
this._loadPlugins = () => Promise.resolve(); // load plugins only once
97-
return Promise.all(pluginsLoader.load(this, this.config.system.plugins, PREFIX));
102+
pluginsLoader.load(this, this.config.system.plugins, PREFIX);
98103
}
99104

100105
_readTests(paths, options) {

test/unit/gemini.js

Lines changed: 95 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('gemini', () => {
6767
beforeEach(() => {
6868
sandbox.stub(Runner.prototype, 'cancel').returns(Promise.resolve());
6969
sandbox.stub(console, 'warn');
70-
sandbox.stub(pluginsLoader, 'load').returns([]);
70+
sandbox.stub(pluginsLoader, 'load');
7171
sandbox.stub(temp, 'init');
7272
});
7373

@@ -126,63 +126,36 @@ describe('gemini', () => {
126126
});
127127

128128
describe('load plugins', () => {
129-
it('should load plugins', () => {
130-
return runGeminiTest()
131-
.then(() => assert.calledOnce(pluginsLoader.load));
132-
});
129+
it('should load plugins on construction', () => {
130+
initGemini();
133131

134-
it('should load plugins before reading tests', () => {
135-
return runGeminiTest()
136-
.then(() => assert.callOrder(pluginsLoader.load, testReaderStub));
132+
assert.calledOnce(pluginsLoader.load);
137133
});
138134

139135
it('should load plugins for gemini instance', () => {
140136
const gemini = initGemini();
141137

142-
return gemini.test()
143-
.then(() => assert.calledWith(pluginsLoader.load, gemini));
144-
});
145-
146-
it('should load plugins from config', () => {
147-
return runGeminiTest({plugins: {'some-plugin': true}})
148-
.then(() => assert.calledWith(pluginsLoader.load, sinon.match.any, {'some-plugin': true}));
138+
assert.calledWith(pluginsLoader.load, gemini);
149139
});
150140

151-
it('should load plugins with appropriate prefix', () => {
152-
const prefix = require('../../package').name + '-';
141+
it('should fail on plugin load error', () => {
142+
pluginsLoader.load.throws(new Error('o.O'));
153143

154-
return runGeminiTest()
155-
.then(() => assert.calledWith(pluginsLoader.load, sinon.match.any, sinon.match.any, prefix));
144+
assert.throws(() => initGemini(), /o.O/);
156145
});
157146

158-
it('should wait until plugins loaded', () => {
159-
const afterPluginLoad = sinon.spy();
160-
pluginsLoader.load.callsFake(() => {
161-
return [Promise.delay(20).then(afterPluginLoad)];
162-
});
163-
sandbox.stub(Runner.prototype, 'run').returns(Promise.resolve());
147+
it('should load plugins from config', () => {
148+
initGemini({plugins: {'some-plugin': true}});
164149

165-
return runGeminiTest()
166-
.then(() => assert.callOrder(afterPluginLoad, Runner.prototype.run));
150+
assert.calledWith(pluginsLoader.load, sinon.match.any, {'some-plugin': true});
167151
});
168152

169-
it('should not run tests if plugin failed on load', () => {
170-
const err = new Error('o.O');
171-
pluginsLoader.load.callsFake(() => [Promise.reject(err)]);
172-
sandbox.stub(Runner.prototype, 'run').returns(Promise.resolve());
153+
it('should load plugins with appropriate prefix', () => {
154+
const prefix = require('../../package').name + '-';
173155

174-
const result = runGeminiTest();
156+
initGemini();
175157

176-
return assert.isRejected(result, err)
177-
.then(() => assert.notCalled(Runner.prototype.run));
178-
});
179-
180-
it('should load plugins only once', () => {
181-
const gemini = initGemini();
182-
183-
return gemini.readTests()
184-
.then((collection) => gemini.test(collection))
185-
.then(() => assert.calledOnce(pluginsLoader.load));
158+
assert.calledWith(pluginsLoader.load, sinon.match.any, sinon.match.any, prefix);
186159
});
187160
});
188161

@@ -199,6 +172,46 @@ describe('gemini', () => {
199172
Config.prototype.getBrowserIds.returns([]);
200173
});
201174

175+
describe('INIT', () => {
176+
it('should emit INIT event on reading', () => {
177+
const onInit = sinon.spy();
178+
179+
gemini = initGemini()
180+
.on(Events.INIT, onInit);
181+
182+
return gemini.readTests()
183+
.then(() => assert.calledOnce(onInit));
184+
});
185+
186+
it('should wait INIT handler before reading any test', () => {
187+
const afterInit = sinon.spy();
188+
189+
gemini = initGemini()
190+
.on(Events.INIT, () => Promise.delay(10).then(afterInit));
191+
192+
return gemini.readTests()
193+
.then(() => assert.callOrder(afterInit, testReaderStub));
194+
});
195+
196+
it('should fail on INIT handler reject', () => {
197+
gemini = initGemini()
198+
.on(Events.INIT, () => Promise.reject('o.O'));
199+
200+
return assert.isRejected(gemini.readTests(), /o.O/);
201+
});
202+
203+
it('should emit INIT only once', () => {
204+
const onInit = sinon.spy();
205+
206+
gemini = initGemini()
207+
.on(Events.INIT, onInit);
208+
209+
return gemini.readTests()
210+
.then(() => gemini.readTests())
211+
.then(() => assert.calledOnce(onInit));
212+
});
213+
});
214+
202215
it('should pass sets from cli to test-reader', () => {
203216
const opts = {
204217
cliOpts: {sets: ['set1']}
@@ -363,6 +376,46 @@ describe('gemini', () => {
363376
return gemini.test()
364377
.then(() => assert.calledOnceWith(onAfterTestRead, {suiteCollection: sinon.match.instanceOf(SuiteCollection)}));
365378
});
379+
380+
describe('INIT', () => {
381+
it('should emit INIT event on run', () => {
382+
const onInit = sinon.spy();
383+
384+
gemini = initGemini()
385+
.on(Events.INIT, onInit);
386+
387+
return gemini.test()
388+
.then(() => assert.calledOnce(onInit));
389+
});
390+
391+
it('should wait INIT handler before run', () => {
392+
const afterInit = sinon.spy();
393+
394+
gemini = initGemini()
395+
.on(Events.INIT, () => Promise.delay(10).then(afterInit));
396+
397+
return gemini.test()
398+
.then(() => assert.callOrder(afterInit, Runner.prototype.run));
399+
});
400+
401+
it('should fail on INIT handler reject', () => {
402+
gemini = initGemini()
403+
.on(Events.INIT, () => Promise.reject('o.O'));
404+
405+
return assert.isRejected(gemini.test(), /o.O/);
406+
});
407+
408+
it('should emit INIT only once', () => {
409+
const onInit = sinon.spy();
410+
411+
gemini = initGemini()
412+
.on(Events.INIT, onInit);
413+
414+
return gemini.test()
415+
.then(() => gemini.test())
416+
.then(() => assert.calledOnce(onInit));
417+
});
418+
});
366419
});
367420

368421
describe('environment variables', () => {

0 commit comments

Comments
 (0)