diff --git a/lib/cli.js b/lib/cli.js index a76ab37d3..cfb927bcd 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -51,6 +51,17 @@ var processArgs = function(argv, options) { options.reporters = options.reporters.split(','); } + if (helper.isString(options.removedFiles)) { + options.removedFiles = options.removedFiles.split(','); + } + + if (helper.isString(options.addedFiles)) { + options.addedFiles = options.addedFiles.split(','); + } + + if (helper.isString(options.changedFiles)) { + options.changedFiles = options.changedFiles.split(','); + } options.configFile = path.resolve(argv._.shift() || 'karma.conf.js'); return options; diff --git a/lib/helper.js b/lib/helper.js index 707b3329b..30fc409ea 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -17,6 +17,7 @@ exports.isDefined = function(value) { exports.isFunction = _.isFunction; exports.isString = _.isString; exports.isObject = _.isObject; +exports.isArray = _.isArray; var ABS_URL = /^https?:\/\//; exports.isUrlAbsolute = function(url) { diff --git a/lib/middleware/runner.js b/lib/middleware/runner.js index 1a195c3ff..d4b2f187d 100644 --- a/lib/middleware/runner.js +++ b/lib/middleware/runner.js @@ -4,6 +4,8 @@ * It basically triggers a test run and streams stdout back. */ +var path = require('path'); +var helper = require('../helper'); var log = require('../logger').create(); var constant = require('../constants'); var json = require('connect').json(); @@ -43,12 +45,37 @@ var createRunnerMiddleware = function(emitter, fileList, capturedBrowsers, repor }); }); - var clientArgs = request.body.args; - log.debug('Setting client.args to ', clientArgs); - config.client.args = clientArgs; + var data = request.body; + log.debug('Setting client.args to ', data.args); + config.client.args = data.args; - log.debug('Refreshing all the files / patterns'); - fileList.refresh(); + var fullRefresh = true; + + if (helper.isArray(data.changedFiles)) { + data.changedFiles.forEach(function(filepath) { + fileList.changeFile(path.resolve(config.basePath, filepath)); + fullRefresh = false; + }); + } + + if (helper.isArray(data.addedFiles)) { + data.addedFiles.forEach(function(filepath) { + fileList.addFile(path.resolve(config.basePath, filepath)); + fullRefresh = false; + }); + } + + if (helper.isArray(data.removedFiles)) { + data.removedFiles.forEach(function(filepath) { + fileList.removeFile(path.resolve(config.basePath, filepath)); + fullRefresh = false; + }); + } + + if (fullRefresh) { + log.debug('Refreshing all the files / patterns'); + fileList.refresh(); + } }); }; }; diff --git a/lib/runner.js b/lib/runner.js index c1814c7ed..bce673005 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -58,5 +58,10 @@ exports.run = function(config, done) { } }); - request.end(JSON.stringify({args: config.clientArgs})); + request.end(JSON.stringify({ + args: config.clientArgs, + removedFiles: config.removedFiles, + changedFiles: config.changedFiles, + addedFiles: config.addedFiles + })); }; diff --git a/test/unit/cli.spec.coffee b/test/unit/cli.spec.coffee index 18842f090..5dae993b0 100644 --- a/test/unit/cli.spec.coffee +++ b/test/unit/cli.spec.coffee @@ -81,6 +81,18 @@ describe 'cli', -> expect(options.reporters).to.deep.equal ['dots'] + it 'should parse removed/added/changed files to array', -> + options = processArgs [ + '--removed-files', 'r1.js,r2.js', + '--changed-files', 'ch1.js,ch2.js', + '--added-files', 'a1.js,a2.js' + ] + + expect(options.removedFiles).to.deep.equal ['r1.js', 'r2.js'] + expect(options.addedFiles).to.deep.equal ['a1.js', 'a2.js'] + expect(options.changedFiles).to.deep.equal ['ch1.js', 'ch2.js'] + + describe 'parseClientArgs', -> it 'should return arguments after --', -> args = cli.parseClientArgs ['node', 'karma.js', 'runArg', '--flag', '--', '--foo', '--bar', diff --git a/test/unit/middleware/runner.spec.coffee b/test/unit/middleware/runner.spec.coffee index 140ca6772..03d29693c 100644 --- a/test/unit/middleware/runner.spec.coffee +++ b/test/unit/middleware/runner.spec.coffee @@ -11,6 +11,7 @@ describe 'middleware.runner', -> createRunnerMiddleware = require('../../../lib/middleware/runner').create handler = nextSpy = response = mockReporter = capturedBrowsers = emitter = config = null + fileListMock = null beforeEach -> mockReporter = @@ -21,6 +22,10 @@ describe 'middleware.runner', -> capturedBrowsers = new BrowserCollection emitter fileListMock = refresh: -> emitter.emit 'run_start' + addFile: -> null + removeFile: -> null + changeFile: -> null + nextSpy = sinon.spy() response = new HttpResponseMock config = {client: {}} @@ -73,6 +78,38 @@ describe 'middleware.runner', -> request.emit 'end' + it 'should refresh explicit files if specified', (done) -> + capturedBrowsers.add new Browser + sinon.stub capturedBrowsers, 'areAllReady', -> true + sinon.stub fileListMock, 'refresh' + sinon.stub fileListMock, 'addFile' + sinon.stub fileListMock, 'changeFile' + sinon.stub fileListMock, 'removeFile' + + request = new HttpRequestMock '/__run__', { + 'content-type': 'application/json' + 'content-length': 1 + } + request.setEncoding = -> null + + handler request, response, nextSpy + message = + addedFiles: ['/new.js'] + removedFiles: ['/foo.js', '/bar.js'] + changedFiles: ['/changed.js'] + + request.emit 'data', JSON.stringify(message) + request.emit 'end' + + process.nextTick -> + expect(fileListMock.refresh).not.to.have.been.called + expect(fileListMock.addFile).to.have.been.calledWith '/new.js' + expect(fileListMock.removeFile).to.have.been.calledWith '/foo.js' + expect(fileListMock.removeFile).to.have.been.calledWith '/bar.js' + expect(fileListMock.changeFile).to.have.been.calledWith '/changed.js' + done() + + it 'should ignore other urls', (done) -> handler new HttpRequestMock('/something'), response, -> expect(response).to.beNotServed()