diff --git a/.travis.yml b/.travis.yml index 88a7c137e..f17cdb625 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ before_script: - sh -e /etc/init.d/xvfb start - npm install -g grunt-cli - rm -rf node_modules/karma + - cd node_modules && ln -nsf ../ karma && cd ../ - export $(openssl aes-256-cbc -pass env:CREDENTIALS_PASS -d -in credentials) script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 9092a58f5..f14404356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ + +### 0.12.33 (2015-05-26) + + +#### Bug Fixes + +* catch exceptions from SourceMapConsumer ([5d42e643](https://github.com/karma-runner/karma/commit/5d42e643)) +* Safeguard IE against console.log ([0b5ff8f6](https://github.com/karma-runner/karma/commit/0b5ff8f6), closes [#1209](https://github.com/karma-runner/karma/issues/1209)) +* **config:** Default remaining client options if any are set ([632dd5e3](https://github.com/karma-runner/karma/commit/632dd5e3), closes [#961](https://github.com/karma-runner/karma/issues/961)) +* **init:** fix test-main.(js/coffee) generation ([d8521ef4](https://github.com/karma-runner/karma/commit/d8521ef4), closes [#1120](https://github.com/karma-runner/karma/issues/1120), [#896](https://github.com/karma-runner/karma/issues/896)) + + ### 0.12.31 (2015-01-02) diff --git a/client/karma.js b/client/karma.js index b1a5a4058..31c23b558 100644 --- a/client/karma.js +++ b/client/karma.js @@ -13,14 +13,17 @@ var Karma = function(socket, iframe, opener, navigator, location) { var queryParams = util.parseQueryParams(location.search); var browserId = queryParams.id || util.generateId('manual-'); var returnUrl = queryParams['return_url' + ''] || null; - var currentTransport; - var resultsBufferLimit = 1; + var resultsBufferLimit = 50; var resultsBuffer = []; this.VERSION = constant.VERSION; this.config = {}; + // Expose for testing purposes as there is no global socket.io + // registry anymore. + this.socket = socket; + var childWindow = null; var navigateContextTo = function(url) { if (self.config.useIframe === false) { @@ -104,7 +107,6 @@ var Karma = function(socket, iframe, opener, navigator, location) { this.stringify = stringify; - var clearContext = function() { reloadingContext = true; navigateContextTo('about:blank'); @@ -114,7 +116,7 @@ var Karma = function(socket, iframe, opener, navigator, location) { // we are not going to execute at all this.error = function(msg, url, line) { hasError = true; - socket.emit('error', url ? msg + '\nat ' + url + (line ? ':' + line : '') : msg); + socket.emit('karma_error', url ? msg + '\nat ' + url + (line ? ':' + line : '') : msg); this.complete(); return false; }; @@ -218,14 +220,9 @@ var Karma = function(socket, iframe, opener, navigator, location) { // report browser name, id socket.on('connect', function() { - currentTransport = socket.socket.transport.name; - - // TODO(vojta): make resultsBufferLimit configurable - if (currentTransport === 'websocket' || currentTransport === 'flashsocket') { + socket.io.engine.on('upgrade', function() { resultsBufferLimit = 1; - } else { - resultsBufferLimit = 50; - } + }); socket.emit('register', { name: navigator.userAgent, diff --git a/client/main.js b/client/main.js index 11fba2934..e891f0849 100644 --- a/client/main.js +++ b/client/main.js @@ -5,14 +5,13 @@ var util = require('./util'); var KARMA_URL_ROOT = require('./constants').KARMA_URL_ROOT; -// connect socket.io -// https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO -var socket = io.connect('http://' + location.host, { - 'reconnection delay': 500, - 'reconnection limit': 2000, - 'resource': KARMA_URL_ROOT.substr(1) + 'socket.io', - 'sync disconnect on unload': true, - 'max reconnection attempts': Infinity +// Connect to the server using socket.io http://socket.io +var socket = io('http://' + location.host, { + reconnectionDelay: 500, + reconnectionDelayMax: Infinity, + timeout: 2000, + path: '/' + KARMA_URL_ROOT.substr(1) + 'socket.io', + 'sync disconnect on unload': true }); // instantiate the updater of the view diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index 645f57b21..d75c3b614 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -351,10 +351,10 @@ on whether all tests passed or any tests failed. ## transports **Type:** Array -**Default:** `['websocket', 'flashsocket', 'xhr-polling', 'jsonp-polling']` +**Default:** `['polling', 'websocket']` **Description:** An array of allowed transport methods between the browser and testing server. This configuration setting -is handed off to [socket.io](https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO) (which manages the communication +is handed off to [socket.io](http://socket.io/) (which manages the communication between browsers and the testing server). ## client.useIframe diff --git a/docs/intro/01-installation.md b/docs/intro/01-installation.md index 03a260d60..ad166fe09 100644 --- a/docs/intro/01-installation.md +++ b/docs/intro/01-installation.md @@ -7,7 +7,6 @@ On Linux, we recommend using [NVM](https://github.com/creationix/nvm). Note: Karma works on the two latest stable versions of node. That is **0.10.x** and **0.12.x** at this point. Also works on iojs 2.x.x. - ## Installing Karma and plugins The recommended approach is to install Karma (and all the plugins your project needs) locally in diff --git a/lib/browser.js b/lib/browser.js index 43b296caa..22aa69fe5 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -89,7 +89,7 @@ var Browser = function(id, fullName, /* capturedBrowsers */ collection, emitter, return this.name; }; - this.onError = function(error) { + this.onKarmaError = function(error) { if (this.isReady()) { return; } diff --git a/lib/config.js b/lib/config.js index c353c1938..4942c86af 100644 --- a/lib/config.js +++ b/lib/config.js @@ -138,6 +138,12 @@ var normalizeConfig = function(config, configFilePath) { throw new Error('Invalid configuration: client.args must be an array of strings'); } + var defaultClient = config.defaultClient || {}; + Object.keys(defaultClient).forEach(function(key) { + var option = config.client[key]; + config.client[key] = helper.isDefined(option) ? option : defaultClient[key]; + }); + // normalize preprocessors var preprocessors = config.preprocessors || {}; var normalizedPreprocessors = config.preprocessors = Object.create(null); @@ -223,9 +229,9 @@ var Config = function() { this.urlRoot = '/'; this.reportSlowerThan = 0; this.loggers = [constant.CONSOLE_APPENDER]; - this.transports = ['websocket', 'flashsocket', 'xhr-polling', 'jsonp-polling']; + this.transports = ['polling', 'websocket']; this.plugins = ['karma-*']; - this.client = { + this.defaultClient = this.client = { args: [], useIframe: true, captureConsole: true diff --git a/lib/launchers/process.js b/lib/launchers/process.js index 067cfae87..a4cc61154 100644 --- a/lib/launchers/process.js +++ b/lib/launchers/process.js @@ -64,11 +64,11 @@ var ProcessLauncher = function(spawn, tempDir, timer) { var errorOutput = ''; - self._process.on('close', function(code) { + self._process.on('exit', function(code) { self._onProcessExit(code, errorOutput); }); - self._process.on('error', function(err) { + self._process.on('karma_error', function(err) { if (err.code === 'ENOENT') { self._retryLimit = -1; errorOutput = 'Can not find the binary ' + cmd + '\n\t' + diff --git a/lib/logger.js b/lib/logger.js index 546a99f3c..878a60e50 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -9,17 +9,6 @@ var log4js = require('log4js'); var helper = require('./helper'); var constant = require('./constants'); -// Special Wrapper for Socket.io :( -var LogWrapper = function(name, level) { - this.logger = log4js.getLogger(name); - this.logger.setLevel(level); -}; -['error', 'warn', 'info', 'debug'].forEach(function(level) { - LogWrapper.prototype[level] = function() { - this.logger[level].apply(this.logger, arguments); - }; -}); - // #### Public Functions // Setup the logger by passing in the configuration options. It needs @@ -61,15 +50,11 @@ var setup = function(level, colors, appenders) { // to be used as a logger for socket.io. // * `level`, which defaults to the global level. var create = function(name, level) { - if (name === 'socket.io') { - return new LogWrapper('socket.io', level); - } else { - var logger = log4js.getLogger(name || 'karma'); - if (helper.isDefined(level)) { - logger.setLevel(level); - } - return logger; + var logger = log4js.getLogger(name || 'karma'); + if (helper.isDefined(level)) { + logger.setLevel(level); } + return logger; }; diff --git a/lib/server.js b/lib/server.js index 28c185037..9d0172f12 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1,4 +1,4 @@ -var io = require('socket.io'); +var Server = require('socket.io'); var di = require('di'); var cfg = require('./config'); @@ -83,7 +83,7 @@ var start = function(injector, config, launcher, globalEmitter, preprocess, file } }); - var EVENTS_TO_REPLY = ['start', 'info', 'error', 'result', 'complete']; + var EVENTS_TO_REPLY = ['start', 'info', 'karma_error', 'result', 'complete']; socketServer.sockets.on('connection', function(socket) { log.debug('A browser has connected on socket ' + socket.id); @@ -196,11 +196,13 @@ var start = function(injector, config, launcher, globalEmitter, preprocess, file // to suppress "browser disconnect" warnings // TODO(vojta): change the client to not send the event (if disconnected by purpose) var sockets = socketServer.sockets.sockets; - Object.getOwnPropertyNames(sockets).forEach(function(key) { - var socket = sockets[key]; + + sockets.forEach(function(socket) { socket.removeAllListeners('disconnect'); if (!socket.disconnected) { - socket.disconnect(); + // Disconnect asynchronously. Socket.io mutates the `sockets.sockets` array + // underneath us so this would skip every other browser/socket. + process.nextTick(socket.disconnect.bind(socket)); } }); @@ -226,11 +228,6 @@ var start = function(injector, config, launcher, globalEmitter, preprocess, file clearTimeout(closeTimeout); removeAllListeners(); }); - - // shutdown socket.io flash transport, if defined - if (socketServer.flashPolicyServer) { - socketServer.flashPolicyServer.close(); - } }); }; @@ -254,16 +251,10 @@ start.$inject = ['injector', 'config', 'launcher', 'emitter', 'preprocess', 'fil var createSocketIoServer = function(webServer, executor, config) { - var server = io.listen(webServer, { + var server = new Server(webServer, { // avoid destroying http upgrades from socket.io to get proxied websockets working - 'destroy upgrade': false, - // socket.io has a timeout (15s by default) before destroying a store (a data structure where - // data associated with a socket are stored). Unfortunately this timeout is not cleared - // properly on socket.io shutdown and this timeout prevents karma from exiting cleanly. - // We change this timeout to 0 to make Karma exit just after all tests were executed. - 'client store expiration': 0, - logger: logger.create('socket.io', constant.LOG_ERROR), - resource: config.urlRoot + 'socket.io', + destroyUpgrade: false, + path: config.urlRoot + 'socket.io/', transports: config.transports }); diff --git a/package.json b/package.json index d803a2123..dab001622 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ ], "dependencies": { "di": "~0.0.1", - "socket.io": "0.9.16", + "socket.io": "~1.3.5", "chokidar": ">=0.8.2", "glob": "~3.2.7", "minimatch": "~0.2", @@ -201,6 +201,8 @@ "grunt-jscs": "^1.8.0", "grunt-mocha-test": "^0.12.7", "grunt-npm": "0.0.2", + "grunt-simple-mocha": "*", + "karma-browserify": "^4.1.2", "karma-browserstack-launcher": "*", "karma-chrome-launcher": "*", "karma-coffee-preprocessor": "*", @@ -209,7 +211,7 @@ "karma-firefox-launcher": "*", "karma-growl-reporter": "*", "karma-html2js-preprocessor": "*", - "karma-jasmine": "^0.1.5", + "karma-jasmine": "~0.3.5", "karma-junit-reporter": "*", "karma-live-preprocessor": "*", "karma-mocha": "*", diff --git a/scripts/presubmit.sh b/scripts/presubmit.sh index 9575345b0..6aa9f2389 100755 --- a/scripts/presubmit.sh +++ b/scripts/presubmit.sh @@ -154,11 +154,6 @@ else git push $REMOTE :$TRAVIS_BRANCH fi - -# Authenticate NPM. -npm config set email "karmarunnerbot@gmail.com" -npm config set _auth $NPM_TOKEN - if [ "$PUSH_TO_NPM" ]; then if [ "$REMOTE_BRANCH" = "$STABLE_BRANCH" ]; then npm publish --tag latest @@ -172,5 +167,4 @@ else fi # Clean up the credentials. -npm config set _auth "" rm .git/credentials diff --git a/test/client/karma.conf.js b/test/client/karma.conf.js index c08e52a2e..06e11c40a 100644 --- a/test/client/karma.conf.js +++ b/test/client/karma.conf.js @@ -3,22 +3,19 @@ module.exports = function(config) { // base path, that will be used to resolve files and exclude basePath: '../..', - frameworks: ['jasmine', 'commonjs'], + frameworks: ['browserify', 'mocha'], // list of files / patterns to load in the browser files: [ - 'client/*.js', 'test/client/*.js' ], // list of files to exclude exclude: [ - 'client/main.js' ], preprocessors: { - 'client/*.js': ['commonjs'], - 'test/client/*.js': ['commonjs'] + 'test/client/*.js': ['browserify'] }, // use dots reporter, as travis terminal does not support escaping sequences @@ -72,11 +69,11 @@ module.exports = function(config) { reportSlowerThan: 500, plugins: [ - 'karma-jasmine', + 'karma-mocha', 'karma-chrome-launcher', 'karma-firefox-launcher', 'karma-junit-reporter', - 'karma-commonjs' + 'karma-browserify' ] }); }; diff --git a/test/client/karma.spec.js b/test/client/karma.spec.js index e866e33c3..00afa447e 100644 --- a/test/client/karma.spec.js +++ b/test/client/karma.spec.js @@ -1,25 +1,29 @@ +var sinon = require('sinon'); +var chai = require('chai'); +chai.use(require('sinon-chai')); +var expect = chai.expect + var Karma = require('../../client/karma'); var MockSocket = require('./mocks').Socket; describe('Karma', function() { - var socket, k, spyStart, windowNavigator, windowLocation, spyWindowOpener; + var socket, k, windowNavigator, windowLocation, windowStub, startSpy; var setTransportTo = function(transportName) { socket._setTransportNameTo(transportName); socket.emit('connect'); }; - beforeEach(function() { socket = new MockSocket(); windowNavigator = {}; windowLocation = {search: ''}; - spyWindowOpener = jasmine.createSpy('window.open').andReturn({}); - k = new Karma(socket, {}, spyWindowOpener, windowNavigator, windowLocation); - spyStart = spyOn(k, 'start'); - }); + windowStub = sinon.stub().returns({}); + k = new Karma(socket, {}, windowStub, windowNavigator, windowLocation); + startSpy = sinon.spy(k, 'start'); + }); it('should start execution when all files loaded and pass config', function() { var config = { @@ -27,10 +31,10 @@ describe('Karma', function() { }; socket.emit('execute', config); - expect(spyStart).not.toHaveBeenCalled(); + expect(startSpy).to.not.have.been.called; k.loaded(); - expect(spyStart).toHaveBeenCalledWith(config); + expect(startSpy).to.have.been.calledWith(config); }); @@ -40,19 +44,19 @@ describe('Karma', function() { }; socket.emit('execute', config); - expect(spyStart).not.toHaveBeenCalled(); + expect(k.start).to.not.have.been.called; k.loaded(); - expect(spyStart).toHaveBeenCalledWith(config); - expect(spyWindowOpener).toHaveBeenCalledWith('about:blank'); + expect(startSpy).to.have.been.calledWith(config); + expect(windowStub).to.have.been.calledWith('about:blank'); }); it('should not start execution if any error during loading files', function() { k.error('syntax error', '/some/file.js', 11); k.loaded(); - - expect(spyStart).not.toHaveBeenCalled(); + sinon.spy(k, 'start'); + expect(startSpy).to.not.have.been.called; }); @@ -62,11 +66,11 @@ describe('Karma', function() { k.start = ADAPTER_START_FN; k.error('syntax error', '/some/file.js', 11); k.loaded(); - expect(k.start).not.toBe(ADAPTER_START_FN); + expect(k.start).to.not.be.eql(ADAPTER_START_FN); k.start = ADAPTER_START_FN; k.loaded(); - expect(k.start).not.toBe(ADAPTER_START_FN); + expect(k.start).to.not.be.eql(ADAPTER_START_FN); }); @@ -76,15 +80,15 @@ describe('Karma', function() { k.error('page reload'); k.setupContext(mockWindow); - expect(mockWindow.__karma__).toBeUndefined(); - expect(mockWindow.onbeforeunload).toBeUndefined(); - expect(mockWindow.onerror).toBeUndefined(); + expect(mockWindow.__karma__).to.not.exist; + expect(mockWindow.onbeforeunload).to.not.exist; + expect(mockWindow.onerror).to.not.exist; }); it('should report navigator name', function() { - var spyInfo = jasmine.createSpy('onInfo').andCallFake(function(info) { - expect(info.name).toBe('Fake browser name'); + var spyInfo = sinon.spy(function(info) { + expect(info.name).to.be.eql('Fake browser name'); }); windowNavigator.userAgent = 'Fake browser name'; @@ -92,53 +96,51 @@ describe('Karma', function() { socket.on('register', spyInfo); socket.emit('connect'); - expect(spyInfo).toHaveBeenCalled(); + expect(spyInfo).to.have.been.called; }); it('should report browser id', function() { windowLocation.search = '?id=567'; socket = new MockSocket(); - k = new Karma(socket, {}, window.open, windowNavigator, windowLocation); + k = new Karma(socket, {}, windowStub, windowNavigator, windowLocation); - var spyInfo = jasmine.createSpy('onInfo').andCallFake(function(info) { - expect(info.id).toBe('567'); + var spyInfo = sinon.spy(function(info) { + expect(info.id).to.be.eql('567'); }); socket.on('register', spyInfo); socket.emit('connect'); - expect(spyInfo).toHaveBeenCalled(); + expect(spyInfo).to.have.been.called; }); describe('result', function() { - var spyResult; - - beforeEach(function() { - spyResult = jasmine.createSpy('onResult'); + it('should buffer results when polling', function() { + var spyResult = sinon.stub(); socket.on('result', spyResult); - }); - - it('should buffer results when polling', function() { - setTransportTo('xhr-polling'); + setTransportTo('polling'); // emit 49 results for (var i = 1; i < 50; i++) { k.result({id: i}); } - expect(spyResult).not.toHaveBeenCalled(); + expect(spyResult).to.not.have.been.called; k.result('result', {id: 50}); - expect(spyResult).toHaveBeenCalled(); - expect(spyResult.argsForCall[0][0].length).toBe(50); + expect(spyResult).to.have.been.called; + expect(spyResult.args[0][0].length).to.be.eql(50); }); it('should buffer results when polling', function() { - setTransportTo('xhr-polling'); + var spyResult = sinon.stub(); + socket.on('result', spyResult); + + setTransportTo('polling'); // emit 40 results for (var i = 1; i <= 40; i++) { @@ -146,14 +148,15 @@ describe('Karma', function() { } k.complete(); - expect(spyResult).toHaveBeenCalled(); - expect(spyResult.argsForCall[0][0].length).toBe(40); + expect(spyResult).to.have.been.called; + expect(spyResult.args[0][0].length).to.be.eql(40); }); it('should emit "start" with total specs count first', function() { var log = []; - spyResult.andCallFake(function() { + + socket.on('result', function() { log.push('result'); }); @@ -161,34 +164,41 @@ describe('Karma', function() { log.push('start'); }); + setTransportTo('websocket'); + // adapter didn't call info({total: x}) k.result(); - expect(log).toEqual(['start', 'result']); + expect(log).to.be.eql(['start', 'result']); }); it('should not emit "start" if already done by the adapter', function() { var log = []; - var spyStart = jasmine.createSpy('onStart').andCallFake(function() { + + var spyStart = sinon.spy(function() { log.push('start'); }); - spyResult.andCallFake(function() { + + spyResult = sinon.spy(function() { log.push('result'); }); + socket.on('result', spyResult); socket.on('start', spyStart); + setTransportTo('websocket'); + k.info({total: 321}); k.result(); - expect(log).toEqual(['start', 'result']); - expect(spyStart).toHaveBeenCalledWith({total: 321}); + expect(log).to.be.eql(['start', 'result']); + expect(spyStart).to.have.been.calledWith({total: 321}); }); }); describe('setupContext', function() { it('should capture alert', function() { - spyOn(k, 'log'); + sinon.spy(k, 'log'); var mockWindow = { alert: function() { @@ -198,7 +208,7 @@ describe('Karma', function() { k.setupContext(mockWindow); mockWindow.alert('What?'); - expect(k.log).toHaveBeenCalledWith('alert', ['What?']); + expect(k.log).to.have.been.calledWith('alert', ['What?']); }) }); @@ -209,8 +219,8 @@ describe('Karma', function() { k.store('a', 10); k.store('b', [1, 2, 3]); - expect(k.store('a')).toBe(10); - expect(k.store('b')).toEqual([1, 2, 3]); + expect(k.store('a')).to.be.eql(10); + expect(k.store('b')).to.be.eql([1, 2, 3]); }); @@ -218,45 +228,47 @@ describe('Karma', function() { var array = [1, 2, 3, 4, 5]; k.store('one.array', array); - expect(k.store('one.array')).toEqual(array); - expect(k.store('one.array')).not.toBe(array); + expect(k.store('one.array')).to.be.eql(array); + expect(k.store('one.array')).to.be.eql(array); }); }); describe('complete', function() { + var clock; - beforeEach(function() { - spyOn(window, 'setTimeout').andCallFake(function(fn) { - fn(); - }); + before(function() { + clock = sinon.useFakeTimers(); }); + after(function() { + clock.restore(); + }); it('should clean the result buffer before completing', function() { - var spyResult = jasmine.createSpy('onResult'); + var spyResult = sinon.stub(); socket.on('result', spyResult); - setTransportTo('xhr-polling'); + setTransportTo('polling'); // emit 40 results for (var i = 0; i < 40; i++) { k.result({id: i}); } - expect(spyResult).not.toHaveBeenCalled(); + expect(spyResult).to.not.have.been.called; k.complete(); - expect(spyResult).toHaveBeenCalled(); + expect(spyResult).to.have.been.called; }); - it('should navigate the client to return_url if specified', function() { + it('should navigate the client to return_url if specified', function(done) { windowLocation.search = '?id=567&return_url=http://return.com'; socket = new MockSocket(); - k = new Karma(socket, {}, window.open, windowNavigator, windowLocation); + k = new Karma(socket, {}, windowStub, windowNavigator, windowLocation); - spyOn(socket, 'disconnect'); + sinon.spy(socket, 'disconnect'); socket.on('complete', function(data, ack) { ack(); @@ -264,13 +276,16 @@ describe('Karma', function() { k.complete(); - waitsFor(function(){ - return windowLocation.href === 'http://return.com'; - }, '', 9000); + clock.tick(500); + setTimeout(function() { + expect(windowLocation.href).to.be.eql('http://return.com'); + done() + }, 5); + clock.tick(10) }); it('should patch the console if captureConsole is true', function() { - spyOn(k, 'log'); + sinon.spy(k, 'log'); k.config.captureConsole = true; var mockWindow = { @@ -281,11 +296,12 @@ describe('Karma', function() { k.setupContext(mockWindow); mockWindow.console.log('What?'); - expect(k.log).toHaveBeenCalledWith('log', ['What?']); + expect(k.log).to.have.been.calledWith('log'); + expect(k.log.args[0][1][0]).to.be.eql('What?'); }); it('should not patch the console if captureConsole is false', function() { - spyOn(k, 'log'); + sinon.spy(k, 'log'); k.config.captureConsole = false; var mockWindow = { @@ -296,7 +312,7 @@ describe('Karma', function() { k.setupContext(mockWindow); mockWindow.console.log('hello'); - expect(k.log).not.toHaveBeenCalled(); + expect(k.log).to.not.have.been.called; }); }); }); diff --git a/test/client/mocks.js b/test/client/mocks.js index 67a746d1d..f3909cec9 100644 --- a/test/client/mocks.js +++ b/test/client/mocks.js @@ -26,15 +26,26 @@ var Emitter = function() { var MockSocket = function() { Emitter.call(this); - this.socket = {transport: {name: 'websocket'}}; + var transportName = 'websocket'; + + this.io = { + engine: { + on: function(event, cb) { + if (event === 'upgrade' && transportName === 'websocket') { + //setTimeout(cb, 0); + cb(); + } + } + } + }; this.disconnect = function() { this.emit('disconnect'); }; // MOCK API - this._setTransportNameTo = function(transportName) { - this.socket.transport.name = transportName; + this._setTransportNameTo = function(name) { + transportName = name; }; }; diff --git a/test/client/stringify.spec.js b/test/client/stringify.spec.js index 140d878ac..6e6154dfb 100644 --- a/test/client/stringify.spec.js +++ b/test/client/stringify.spec.js @@ -1,21 +1,23 @@ -var stringify = require('../../client/stringify'); +var chai = require('chai'); +var expect = chai.expect +var stringify = require('../../client/stringify'); describe('stringify', function() { it('should serialize string', function() { - expect(stringify('aaa')).toBe("'aaa'"); + expect(stringify('aaa')).to.be.eql("'aaa'"); }); it('should serialize booleans', function() { - expect(stringify(true)).toBe('true'); - expect(stringify(false)).toBe('false'); + expect(stringify(true)).to.be.eql('true'); + expect(stringify(false)).to.be.eql('false'); }); it('should serialize null and undefined', function() { - expect(stringify(null)).toBe('null'); - expect(stringify()).toBe('undefined'); + expect(stringify(null)).to.be.eql('null'); + expect(stringify()).to.be.eql('undefined'); }); @@ -23,13 +25,13 @@ describe('stringify', function() { function abc(a, b, c) { return 'whatever'; } var def = function(d, e, f) { return 'whatever'; }; - expect(stringify(abc)).toBe('function abc(a, b, c) { ... }'); - expect(stringify(def)).toBe('function (d, e, f) { ... }'); + expect(stringify(abc)).to.be.eql('function abc(a, b, c) { ... }'); + expect(stringify(def)).to.be.eql('function (d, e, f) { ... }'); }); it('should serialize arrays', function() { - expect(stringify(['a', 'b', null, true, false])).toBe("['a', 'b', null, true, false]"); + expect(stringify(['a', 'b', null, true, false])).to.be.eql("['a', 'b', null, true, false]"); }); it('should serialize objects', function () { @@ -37,38 +39,38 @@ describe('stringify', function() { obj = {a: 'a', b: 'b', c: null, d: true, e: false}; - expect(stringify(obj)).toBe('Object{a: \'a\', b: \'b\', c: null, d: true, e: false}'); + expect(stringify(obj)).to.be.eql('Object{a: \'a\', b: \'b\', c: null, d: true, e: false}'); function MyObj() { this.a = 'a'; } obj = new MyObj(); - expect(stringify(obj)).toBe('MyObj{a: \'a\'}'); + expect(stringify(obj)).to.be.eql('MyObj{a: \'a\'}'); obj = {constructor: null}; - expect(stringify(obj)).toBe('Object{constructor: null}'); + expect(stringify(obj)).to.be.eql('Object{constructor: null}'); obj = Object.create(null); obj.a = 'a'; - expect(stringify(obj)).toBe('Object{a: \'a\'}'); + expect(stringify(obj)).to.be.eql('Object{a: \'a\'}'); }); it('should serialize html', function() { var div = document.createElement('div'); - expect(stringify(div)).toBe('
'); + expect(stringify(div)).to.be.eql('
'); div.innerHTML = 'some text'; - expect(stringify(div)).toBe('
some text
'); + expect(stringify(div)).to.be.eql('
some text
'); }); it('should serialize across iframes', function() { var div = document.createElement('div'); - expect(__karma__.stringify(div)).toBe('
'); + expect(__karma__.stringify(div)).to.be.eql('
'); - expect(__karma__.stringify([1, 2])).toBe('[1, 2]'); + expect(__karma__.stringify([1, 2])).to.be.eql('[1, 2]'); }); }); diff --git a/test/client/util.spec.js b/test/client/util.spec.js index 8c7c01d58..e747a82c3 100644 --- a/test/client/util.spec.js +++ b/test/client/util.spec.js @@ -1,11 +1,14 @@ +var chai = require('chai'); +var expect = chai.expect + var util = require('../../client/util'); describe('util', function() { - describe('parseQueryParams', function() { + it('parseQueryParams', function() { var params = util.parseQueryParams('?id=123&return_url=http://whatever.com'); - expect(params).toEqual({id: '123', return_url: 'http://whatever.com'}); + expect(params).to.be.eql({id: '123', return_url: 'http://whatever.com'}); }); }); diff --git a/test/e2e/support/reconnecting/test.js b/test/e2e/support/reconnecting/test.js index b58430e91..03af1cafe 100644 --- a/test/e2e/support/reconnecting/test.js +++ b/test/e2e/support/reconnecting/test.js @@ -1,43 +1,34 @@ describe('plus', function() { - var breath = function() { - var finished = false; - setTimeout(function() { - finished = true; - }, 0) - - waitsFor(function() { - return finished; - }); - }; - // super hacky way to get the actual socket to manipulate it... var socket = function() { var location = window.parent.location; - return window.parent.io.sockets[location.protocol + '//' + location.host]; + return window.parent.karma.socket; }; it('should pass', function() { expect(1).toBe(1); }); - it('should disconnect', function() { + it('should disconnect', function(done) { + console.log(2); expect(2).toBe(2); socket().disconnect(); - breath(); + done(); }); it('should work', function() { expect(plus(1, 2)).toBe(3); }); - it('should re-connect', function() { + it('should re-connect', function(done) { + console.log(4); expect(4).toBe(4); - socket().reconnect(); + socket().connect(); // window.parent.socket.socket.connect(); - breath(); + done(); }); it('should work', function() { diff --git a/test/unit/browser.spec.coffee b/test/unit/browser.spec.coffee index 53771c606..5a70c8a4e 100644 --- a/test/unit/browser.spec.coffee +++ b/test/unit/browser.spec.coffee @@ -66,9 +66,9 @@ describe 'Browser', -> #========================================================================== - # Browser.onError + # Browser.onKarmaError #========================================================================== - describe 'onError', -> + describe 'onKarmaError', -> beforeEach -> browser = new Browser 'fake-id', 'full name', collection, emitter, socket @@ -79,7 +79,7 @@ describe 'Browser', -> emitter.on 'browser_error', spy browser.state = Browser.STATE_EXECUTING - browser.onError() + browser.onKarmaError() expect(browser.lastResult.error).to.equal true expect(spy).to.have.been.called @@ -89,7 +89,7 @@ describe 'Browser', -> emitter.on 'browser_error', spy browser.state = Browser.STATE_READY - browser.onError() + browser.onKarmaError() expect(browser.lastResult.error).to.equal false expect(spy).not.to.have.been.called @@ -275,7 +275,7 @@ describe 'Browser', -> socket.emit 'result', {success: true} expect(browser.lastResult.success).to.equal 1 - socket.emit 'error', {} + socket.emit 'karma_error', {} expect(browser.lastResult.error).to.equal true # should be ignored, keep executing diff --git a/test/unit/config.spec.coffee b/test/unit/config.spec.coffee index ca67a2e04..182561293 100644 --- a/test/unit/config.spec.coffee +++ b/test/unit/config.spec.coffee @@ -207,6 +207,22 @@ describe 'config', -> expect(config.basePath).to.equal resolveWinPath('./some') expect(config.urlRoot).to.equal '/' # default value + it 'should default unset options in client config', -> + config = e.parseConfig null, {client: {args: ['--test']}} + + expect(config.client.useIframe).to.not.be.undefined + expect(config.client.captureConsole).to.not.be.undefined + + config = e.parseConfig null, {client: {useIframe: true}} + + expect(config.client.args).to.not.be.undefined + expect(config.client.captureConsole).to.not.be.undefined + + config = e.parseConfig null, {client: {captureConsole: true}} + + expect(config.client.useIframe).to.not.be.undefined + expect(config.client.args).to.not.be.undefined + describe 'normalizeConfig', -> diff --git a/test/unit/helper.spec.coffee b/test/unit/helper.spec.coffee index 83fd0e2ec..a71e30c69 100644 --- a/test/unit/helper.spec.coffee +++ b/test/unit/helper.spec.coffee @@ -213,11 +213,6 @@ describe 'helper', -> done = null - # async helper - waitForDoneAnd = (resume) -> - waitsFor (-> done.callCount), 'done callback', 50 - runs resume if resume - fs = fsMock.create home: 'some.js': fsMock.file() diff --git a/test/unit/launchers/process.spec.coffee b/test/unit/launchers/process.spec.coffee index bd0254f1d..65edf9a5e 100644 --- a/test/unit/launchers/process.spec.coffee +++ b/test/unit/launchers/process.spec.coffee @@ -70,8 +70,8 @@ describe 'launchers/process.js', -> emitter.on 'browser_process_failure', failureSpy launcher.start 'http://host:9876/' - mockSpawn._processes[0].emit 'error', {code: 'ENOENT'} - mockSpawn._processes[0].emit 'close', 1 + mockSpawn._processes[0].emit 'karma_error', {code: 'ENOENT'} + mockSpawn._processes[0].emit 'exit', 1 mockTempDir.remove.callArg 1 scheduleNextTick -> @@ -111,7 +111,7 @@ describe 'launchers/process.js', -> expect(mockSpawn._processes[0].kill).to.have.been.called # process exits - mockSpawn._processes[0].emit 'close', 0 + mockSpawn._processes[0].emit 'exit', 0 mockTempDir.remove.callArg 1 killingLauncher.done -> @@ -133,7 +133,7 @@ describe 'launchers/process.js', -> # expect killing browser expect(browserProcess.kill).to.have.been.called - browserProcess.emit 'close', 0 + browserProcess.emit 'exit', 0 mockTempDir.remove.callArg 1 mockSpawn.reset() @@ -158,7 +158,7 @@ describe 'launchers/process.js', -> # expect killing browser expect(browserProcess.kill).to.have.been.called - browserProcess.emit 'close', 0 + browserProcess.emit 'exit', 0 mockTempDir.remove.callArg 1 mockTempDir.remove.reset() @@ -174,7 +174,7 @@ describe 'launchers/process.js', -> # expect killing browser expect(browserProcess.kill).to.have.been.called - browserProcess.emit 'close', 0 + browserProcess.emit 'exit', 0 mockTempDir.remove.callArg 1 mockTempDir.remove.reset() @@ -190,7 +190,7 @@ describe 'launchers/process.js', -> # expect killing browser expect(browserProcess.kill).to.have.been.called - browserProcess.emit 'close', 0 + browserProcess.emit 'exit', 0 mockTempDir.remove.callArg 1 mockTempDir.remove.reset() @@ -211,7 +211,7 @@ describe 'launchers/process.js', -> mockSpawn.reset() # crash - browserProcess.emit 'close', 1 + browserProcess.emit 'exit', 1 mockTempDir.remove.callArg 1 mockTempDir.remove.reset()