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

Commit

Permalink
feat: introduce hermione.halt method
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Rybakov committed May 7, 2018
1 parent 9b067af commit da68965
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
8 changes: 8 additions & 0 deletions doc/programmatic-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ Returns promise that resolve to a stats object with following keys:

Rejects promise if critical error occurred.

## Halting

```js
gemini.halt(error, [timeout=60000ms]);
```

Method for abnormal termination of the test run in case of a terminal error. If process fails to gracefully shutdown in `timeout` milliseconds, it would be forcibly terminated (unless `timeout` is explicitly set to `0`).

## Utilites

* `gemini.getScreenshotPath(suite, stateName, browserId)` — returns path to
Expand Down
25 changes: 23 additions & 2 deletions lib/gemini.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,29 @@ module.exports = class Gemini extends PassthroughEmitter {
return this._exec(() => this._readTests(paths, options));
}

halt(err, timeout = 60000) {
this._runner.cancel();

this._criticalError = new GeminiError(err);

if (timeout === 0) {
return;
}

setTimeout(() => {
console.error(chalk.red('Forcing shutdown...'));
process.exit(1);
}, timeout).unref();
}

_exec(fn) {
return this._init().then(() => fn());
return this._init()
.then(() => fn())
.finally(() => {
if (this._criticalError) {
throw this._criticalError;
}
});
}

_init() {
Expand Down Expand Up @@ -150,7 +171,7 @@ module.exports = class Gemini extends PassthroughEmitter {

temp.init(this.config.system.tempDir);

const runner = Runner.create(this.config, stateProcessor);
const runner = this._runner = Runner.create(this.config, stateProcessor);
const envBrowsers = parseBrowsers(process.env.GEMINI_BROWSERS);
const envSkipBrowsers = parseBrowsers(process.env.GEMINI_SKIP_BROWSERS);

Expand Down
60 changes: 59 additions & 1 deletion test/unit/gemini.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ describe('gemini', () => {
};

beforeEach(() => {
sandbox.stub(Runner.prototype, 'cancel').returns(Promise.resolve());
sandbox.stub(Runner.prototype, 'cancel');
sandbox.stub(console, 'warn');
sandbox.stub(console, 'error');
sandbox.stub(pluginsLoader, 'load');
sandbox.stub(temp, 'init');
});
Expand Down Expand Up @@ -432,6 +433,63 @@ describe('gemini', () => {
});
});

describe('halt', () => {
let gemini;

beforeEach(() => {
sandbox.stub(process, 'exit');
sandbox.stub(Runner.prototype, 'run').callsFake(() => gemini.emitAndWait(Events.START_RUNNER));

gemini = initGemini();
});

it('should throw provided error', () => {
gemini.on(Events.START_RUNNER, () => {
gemini.halt(new Error('test error'));
});

return assert.isRejected(gemini.test(), /Error: test error/);
});

it('should cancel test runner', () => {
gemini.on(Events.START_RUNNER, () => {
gemini.halt(new Error('test error'));
});

return gemini.test()
.catch(() => {
assert.calledOnce(Runner.prototype.cancel);
});
});

describe('shutdown timeout', () => {
it('should force exit if timeout is reached', () => {
gemini.on(Events.START_RUNNER, () => {
gemini.halt(new Error('test error'), 250);
});

return gemini.test()
.catch(() => Promise.delay(300))
.then(() => {
assert.calledWithMatch(console.error, /Forcing shutdown.../);
assert.calledOnceWith(process.exit, 1);
});
});

it('should do nothing if timeout is set to zero', () => {
sandbox.spy(global, 'setTimeout');
gemini.on(Events.START_RUNNER, () => {
gemini.halt(new Error('test error'), 0);
});

return gemini.test()
.catch(() => {
assert.notCalled(global.setTimeout);
});
});
});
});

describe('environment variables', () => {
beforeEach(() => {
sandbox.stub(SuiteCollection.prototype, 'skipBrowsers');
Expand Down

0 comments on commit da68965

Please sign in to comment.