Skip to content

Commit 3d4fa00

Browse files
committed
feat: Add stopper to the public API
Add the `stopper` as a command to the public API allowing for enabling users to programically terminate a running server.
1 parent 66ae80b commit 3d4fa00

5 files changed

Lines changed: 70 additions & 12 deletions

File tree

docs/dev/04-public-api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ runner.run({port: 9876}, function(exitCode) {
118118
})
119119
```
120120

121+
## karma.stopper
122+
123+
### **stopper.stop(options, [callback=process.exit])**
124+
125+
This function will signal a running server to stop. Equivalent of `karma stop`.
126+
127+
```javascript
128+
var stopper = require('karma').stopper
129+
runner.stop({port: 9876}, function(exitCode) {
130+
if (exitCode === 0) {
131+
console.log('Server stop as initiated')
132+
}
133+
process.exit(exitCode)
134+
})
135+
```
136+
121137
## Callback function notes
122138

123139
- If there is an error, the error code will be provided as the second parameter to the error callback.

lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var constants = require('./constants')
44
var Server = require('./server')
55
var runner = require('./runner')
6+
var stopper = require('./stopper')
67
var launcher = require('./launcher')
78

89
// TODO: remove in 1.0
@@ -21,6 +22,7 @@ module.exports = {
2122
VERSION: constants.VERSION,
2223
Server: Server,
2324
runner: runner,
25+
stopper: stopper,
2426
launcher: launcher,
2527
server: oldServer
2628
}

lib/stopper.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ var http = require('http')
22

33
var cfg = require('./config')
44
var logger = require('./logger')
5+
var helper = require('./helper')
56

6-
exports.stop = function (config) {
7+
exports.stop = function (config, done) {
78
logger.setupFromConfig(config)
9+
done = helper.isFunction(done) ? done : process.exit
810
var log = logger.create('stopper')
911
config = cfg.parseConfig(config.configFile, config)
12+
1013
var options = {
1114
hostname: config.hostname,
1215
path: config.urlRoot + 'stop',
@@ -17,14 +20,20 @@ exports.stop = function (config) {
1720
var request = http.request(options)
1821

1922
request.on('response', function (response) {
23+
if (response.statusCode !== 200) {
24+
log.error('Server returned status code: ' + response.statusCode)
25+
done(1)
26+
return
27+
}
28+
2029
log.info('Server stopped.')
21-
process.exit(response.statusCode === 200 ? 0 : 1)
30+
done(0)
2231
})
2332

2433
request.on('error', function (e) {
2534
if (e.code === 'ECONNREFUSED') {
2635
log.error('There is no server listening on port %d', options.port)
27-
process.exit(1, e.code)
36+
done(1, e.code)
2837
} else {
2938
throw e
3039
}

test/e2e/steps/core_steps.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = function coreSteps () {
55
var exec = ref.exec
66
var spawn = ref.spawn
77
var rimraf = require('rimraf')
8+
var stopper = require('../../../lib/stopper')
89

910
this.World = require('../support/world').World
1011
require('../support/after_hooks').call(this)
@@ -39,13 +40,22 @@ module.exports = function coreSteps () {
3940
return callback()
4041
})
4142

43+
this.When(/^I stop a server programmatically/, function (callback) {
44+
var _this = this
45+
setTimeout(function () {
46+
stopper.stop(_this.configFile, function (exitCode) {
47+
_this.stopperExitCode = exitCode
48+
})
49+
callback()
50+
}, 1000)
51+
})
52+
4253
this.When(/^I start a server in background/, function (callback) {
4354
this.writeConfigFile(tmpDir, tmpConfigFile, (function (_this) {
4455
return function (err, hash) {
4556
if (err) {
4657
return callback.fail(new Error(err))
4758
}
48-
4959
var configFile = path.join(tmpDir, hash + '.' + tmpConfigFile)
5060
var runtimePath = path.join(baseDir, 'bin', 'karma')
5161
_this.child = spawn('' + runtimePath, ['start', '--log-level', 'debug', configFile])
@@ -173,7 +183,6 @@ module.exports = function coreSteps () {
173183
var actualOutput = this.lastRun.stdout.toString()
174184
var actualError = this.lastRun.error
175185
var actualStderr = this.lastRun.stderr.toString()
176-
177186
if (actualOutput.match(new RegExp(expectedOutput))) {
178187
return callback()
179188
}
@@ -183,11 +192,15 @@ module.exports = function coreSteps () {
183192
}
184193
})
185194

186-
this.Then(/^The server is dead( with exit code ([0-9]+))?$/, function (withExitCode, code, callback) {
187-
setTimeout((function (_this) {
188-
if (_this.childExitCode === undefined) return callback(new Error('Server has not exited.'))
189-
if (code === undefined || parseInt(code, 10) === _this.childExitCode) return callback()
190-
callback(new Error('Exit-code mismatch'))
191-
})(this), 1000)
192-
})
195+
this.Then(/^The (server|stopper) is dead( with exit code ([0-9]+))?$/,
196+
function (stopperOrServer, withExitCode, code, callback) {
197+
var server = stopperOrServer === 'server'
198+
var _this = this
199+
setTimeout(function () {
200+
var actualExitCode = server ? _this.childExitCode : _this.stopperExitCode
201+
if (actualExitCode === undefined) return callback(new Error('Server has not exited.'))
202+
if (code === undefined || parseInt(code, 10) === actualExitCode) return callback()
203+
callback(new Error('Exit-code mismatch'))
204+
}, 1000)
205+
})
193206
}

test/e2e/stop.feature

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,21 @@ Feature: Stop karma
4242
"""
4343
Server stopped.
4444
"""
45+
46+
47+
Scenario: A server can be stopped programically
48+
Given a configuration with:
49+
"""
50+
files = ['basic/plus.js', 'basic/test.js'];
51+
browsers = ['PhantomJS'];
52+
plugins = [
53+
'karma-jasmine',
54+
'karma-phantomjs-launcher'
55+
];
56+
singleRun = false;
57+
logLevel = 'error';
58+
"""
59+
When I start a server in background
60+
And I stop a server programmatically
61+
Then The server is dead with exit code 0
62+
And The stopper is dead with exit code 0

0 commit comments

Comments
 (0)