From cbfbe4ecad09effafa62bc795c3f1ecebc493853 Mon Sep 17 00:00:00 2001 From: sylvain-hamel Date: Thu, 3 Apr 2014 22:22:36 -0400 Subject: [PATCH] chore: add unit tests --- .jscs.json | 3 +- Gruntfile.coffee | 35 ++++++++- index.js | 36 +++++---- package.json | 11 ++- test/launcher.spec.coffee | 159 ++++++++++++++++++++++++++++++++++++++ test/mocha-globals.coffee | 16 ++++ 6 files changed, 238 insertions(+), 22 deletions(-) create mode 100644 test/launcher.spec.coffee create mode 100644 test/mocha-globals.coffee diff --git a/.jscs.json b/.jscs.json index fb2277e..f223181 100644 --- a/.jscs.json +++ b/.jscs.json @@ -110,7 +110,8 @@ "requireLineFeedAtFileEnd": true, "maximumLineLength": 100, "requireCapitalizedConstructors": true, - "requireDotNotation": true + "requireDotNotation": true, + "disallowSpacesInsideParentheses" : true } diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 2f614e8..58721bc 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -4,6 +4,10 @@ JSHINT_NODE = module.exports = (grunt) -> + allSrc = ['index.js'] + allTests = ['test/mocha-globals.coffee', 'test/*.spec.coffee'] + all = [].concat(allSrc).concat(allTests).concat(['Gruntfile.coffee']) + # Project configuration. grunt.initConfig pkgFile: 'package.json' @@ -26,7 +30,7 @@ module.exports = (grunt) -> jshint: default: files: - src: ['index.js'] + src: allSrc options: JSHINT_NODE options: @@ -54,15 +58,37 @@ module.exports = (grunt) -> globals: {} jscs: - default: files: src: ['index.js'] + default: files: src: allSrc options: config: '.jscs.json' + simplemocha: + options: + ui: 'bdd' + reporter: 'dot' + unit: + src: allTests + + watch: + files: all + tasks:['default'] + + # CoffeeLint options + # http://www.coffeelint.org/#options + coffeelint: + unittests: files: src: ['Gruntfile.coffee', 'test/**/*.coffee'] + options: + max_line_length: + value: 100 + + grunt.loadNpmTasks 'grunt-contrib-watch' grunt.loadNpmTasks 'grunt-npm' grunt.loadNpmTasks 'grunt-bump' grunt.loadNpmTasks 'grunt-auto-release' grunt.loadNpmTasks 'grunt-contrib-jshint' grunt.loadNpmTasks 'grunt-jscs-checker' + grunt.loadNpmTasks 'grunt-simple-mocha' + grunt.loadNpmTasks 'grunt-coffeelint' grunt.registerTask 'release', 'Bump the version and publish to NPM.', (type) -> grunt.task.run [ @@ -70,5 +96,6 @@ module.exports = (grunt) -> "bump:#{type||'patch'}", 'npm-publish' ] - grunt.registerTask 'default', ['lint'] - grunt.registerTask 'lint', ['jshint', 'jscs'] + grunt.registerTask 'test', ['simplemocha'] + grunt.registerTask 'default', ['lint', 'test'] + grunt.registerTask 'lint', ['jshint', 'jscs', 'coffeelint'] diff --git a/index.js b/index.js index 29eca28..795cf64 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,21 @@ var exec = require('child_process').exec; var processName = 'iexplore.exe'; +function getInternetExplorerExe() { + var suffix = '\\Internet Explorer\\' + processName, + prefixes = [process.env['' + 'PROGRAMW6432'], // '' + ' trick to keep jscs happy + process.env['' + 'PROGRAMFILES(X86)'], + process.env['' + 'PROGRAMFILES']], + prefix, i; + + for (i = 0; i < prefixes.length; i++) { + prefix = prefixes[i]; + if (prefix && fs.existsSync(prefix + suffix)) { + return prefix + suffix; + } + } +} + var IEBrowser = function(baseBrowserDecorator, logger, args) { baseBrowserDecorator(this); @@ -76,27 +91,16 @@ var IEBrowser = function(baseBrowserDecorator, logger, args) { this._onProcessExit = function(code, errorOutput) { var pid = this._process.pid; killExtraIEProcess(pid, function() { - baseOnProcessExit(code, errorOutput); + if (baseOnProcessExit) { + baseOnProcessExit(code, errorOutput); + } }); }; + // this is to expose the function for unit testing + this._getInternetExplorerExe = getInternetExplorerExe; }; -function getInternetExplorerExe() { - var suffix = '\\Internet Explorer\\' + processName, - prefixes = [process.env['' + 'PROGRAMW6432'], // '' + ' trick to keep jscs happy - process.env['' + 'PROGRAMFILES(X86)'], - process.env['' + 'PROGRAMFILES']], - prefix, i; - - for (i = 0; i < prefixes.length; i++) { - prefix = prefixes[i]; - if (prefix && fs.existsSync(prefix + suffix)) { - return prefix + suffix; - } - } -} - IEBrowser.prototype = { name: 'IE', DEFAULT_CMD: { diff --git a/package.json b/package.json index 5737219..d6eb0b5 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,20 @@ "license": "MIT", "devDependencies": { "grunt": "~0.4.1", + "grunt-simple-mocha": "~0.4.0", "grunt-bump": "~0.0.7", "grunt-npm": "~0.0.2", "grunt-auto-release": "~0.0.2", "grunt-contrib-jshint": "~0.7.2", - "grunt-jscs-checker": "~0.4.0" + "grunt-jscs-checker": "~0.4.0", + "mocks": "0.0.11", + "sinon": "~1.7.3", + "chai": "~1.7.2", + "sinon-chai": "~2.4.0", + "grunt-coffeelint": "~0.0.6", + "karma": "~0.12.0", + "di": "~0.0.1", + "grunt-contrib-watch" : "~0.6.1" }, "contributors": [ "sylvain-hamel ", diff --git a/test/launcher.spec.coffee b/test/launcher.spec.coffee new file mode 100644 index 0000000..4269f8a --- /dev/null +++ b/test/launcher.spec.coffee @@ -0,0 +1,159 @@ +util = require 'util' +di = require 'di' +mocks = require 'mocks' +fs = require 'fs' + +describe 'launcher', -> + injector = null + launcher = null + module = null + IELauncher = null + EventEmitter = null + + beforeEach -> + EventEmitter = require('../node_modules/karma/lib/events').EventEmitter + IELauncher = mocks.loadFile(__dirname + '/../index').module.exports + module = { + 'baseBrowserDecorator': ['value', (->)], + 'emitter': ['value', new EventEmitter] + 'logger': ['value', { + create : -> + return { + error : (->), + debug : (->) + } + }] + 'args': ['value', []] + } + + afterEach -> + injector = null + launcher = null + + describe 'exports', -> + it 'should export launcher:IE', (done) -> + expect(IELauncher['launcher:IE']).to.defined + done() + + describe 'initialization', -> + + beforeEach -> + injector = new di.Injector([module, IELauncher]) + launcher = injector.get('launcher:IE') + + it 'should initialize name', (done) -> + expect(launcher.name).to.equal "IE" + done() + + it 'should initialize ENV_CMD', (done) -> + expect(launcher.ENV_CMD).to.equal "IE_BIN" + done() + + it 'should initialize DEFAULT_CMD.win32', (done) -> + expect(launcher.DEFAULT_CMD.win32).to.beDefined + done() + + describe '_getOptions', -> + + getOptions = null + + beforeEach -> + getOptions = (url, module) -> + injector = new di.Injector([module, IELauncher]) + launcher = injector.get('launcher:IE') + launcher._getOptions('url') + + it 'should add -extoff', (done) -> + options = getOptions('url', module) + expect(options[0]).to.equal '-extoff' + done() + + it 'should include args.flags', (done) -> + module.args[1] = {flags: ['-flag1', '-flag2']} + options = getOptions('url', module) + expect(options[1]).to.equal '-flag1' + expect(options[2]).to.equal '-flag2' + done() + + it 'should return url as the last flag', (done) -> + options = getOptions('url', module) + expect(options[options.length-1]).to.equal 'url' + done() + + it 'should convert x-ua-compatible arg to encoded url', (done) -> + module.args[1] = {'x-ua-compatible':'browser=mode'} + options = getOptions('url', module) + expect(options[options.length-1]).to.equal 'url?x-ua-compatible=browser%3Dmode' + done() + + describe 'locating iexplore.exe', -> + + win32Location = null + fsMock = null + + beforeEach -> + process.env['' + 'PROGRAMW6432'] = '\\fake\\PROGRAMW6432' + process.env['' + 'PROGRAMFILES(X86)'] = '\\fake\\PROGRAMFILES(X86)' + process.env['' + 'PROGRAMFILES'] = '\\fake\\PROGRAMFILES' + + fsMock = mocks.fs.create + 'folder1': + 'Internet Explorer': + 'iexplore.exe' : 1 + + IELauncher = mocks.loadFile(__dirname + '/../index', { + fs:fsMock + }).module.exports + + win32Location = () -> + injector = new di.Injector([module, IELauncher]) + launcher = injector.get('launcher:IE') + launcher._getInternetExplorerExe() + + it 'should locate in PROGRAMW6432', (done) -> + process.env['' + 'PROGRAMW6432'] = '\\folder1' + expect(win32Location()).to.equal '\\folder1\\Internet Explorer\\iexplore.exe' + done() + + it 'should locate in PROGRAMFILES(X86)', (done) -> + process.env['' + 'PROGRAMFILES(X86)'] = '\\folder1' + expect(win32Location()).to.equal '\\folder1\\Internet Explorer\\iexplore.exe' + done() + + it 'should locate in PROGRAMFILES', (done) -> + process.env['' + 'PROGRAMFILES'] = '\\folder1' + expect(win32Location()).to.equal '\\folder1\\Internet Explorer\\iexplore.exe' + done() + + it 'should return undefined when not found', (done) -> + expect(win32Location()).to.equal undefined + done() + + describe '_onProcessExit', -> + + onProcessExit = null + child_processCmd = null + + beforeEach -> + onProcessExit = () -> + + child_processMock = { + exec : (cmd, cb)-> + child_processCmd = cmd + cb() + } + + IELauncher = mocks.loadFile(__dirname + '/../index', { + child_process:child_processMock + }).module.exports + + injector = new di.Injector([module, IELauncher]) + launcher = injector.get('launcher:IE') + launcher._process = { pid : 10 } + launcher._onProcessExit(1, 2) + + it 'should call wmic with process ID', (done) -> + onProcessExit() + expect(child_processCmd).to.equal 'wmic.exe Path win32_Process where ' + + '\"Name=\'iexplore.exe\' and CommandLine Like \'%SCODEF:10%\'\" call Terminate' + done() diff --git a/test/mocha-globals.coffee b/test/mocha-globals.coffee new file mode 100644 index 0000000..21987db --- /dev/null +++ b/test/mocha-globals.coffee @@ -0,0 +1,16 @@ +sinon = require 'sinon' +chai = require 'chai' + +# publish globals that all specs can use +global.expect = chai.expect +global.should = chai.should() +global.sinon = sinon + +# chai plugins +chai.use(require 'sinon-chai') + +beforeEach -> + global.sinon = sinon.sandbox.create() + +afterEach -> + global.sinon.restore()