UNPKG

grunt-blanket-mocha-server

Version:

Easily serve mocha tests with (or without) blanket coverage. "Goes Great" with grunt-blanket-mocha.

246 lines (204 loc) 8.32 kB
## # grunt-blanket-mocha-server # # Copyright (c) 2013 Stu Salsbury # Licensed under the MIT license. # ###* @module ### module.exports = (grunt) -> path = require('path') fs = require('fs') _ = grunt.util._ ###* * Fail with message if array is not of minimum length or any file * does not exist. obj[prop] may be a single file path or an array of them. * @param {string} grunt The grunt process object * @param {string} prop Name of the property being tested * @param {number} min Minimum acceptable extant files * @return {undefined} ### minViolationTest = (obj, prop, min) -> if _.isUndefined(min) then min = 0 if obj[prop] files = if _.isArray(obj[prop]) then obj[prop] else [obj[prop]] if files.length < min grunt.fatal "Configuration property \"#{prop}\" did not match the " + "minimum of #{min} files (it matched #{actual})." _.each files, (file) -> if !fs.existsSync(file) grunt.fatal "File not found: \"#{file}\"" else if min > 0 grunt.fatal "Configuration property \"#{prop}\" needs to specify at " + "least one file." undefined ###* * Return a normalized path with the process directory stripped. * Result is suitable for a src reference that is absolute to the root * of the webserver. * @param {object} obj The config object * @param {[type]} prop The property to modify * @return {undefined} ### resolveFile = (obj, prop) -> obj[prop] = path.resolve obj[prop] minViolationTest obj, prop preNodeModulesMatch = obj[prop].match /^(.*)\/node_modules\/.*$/ if preNodeModulesMatch obj[prop] = obj[prop].replace preNodeModulesMatch[1], '' else inAppPath = process.cwd() + path.sep + 'node_modules' + path.sep + 'grunt-blanket-mocha-server' if !(fs.existsSync(inAppPath)) obj[prop] = obj[prop].replace( path.resolve(__dirname + '/..'), '' ) else # console.log obj[prop].red # console.log path.resolve(__dirname + '/../..').green # console.log path.resolve(__dirname + '\\..\\..').green obj[prop] = obj[prop].replace( path.resolve(__dirname + '/../..'), # path.resolve(__dirname + '/..'), '/node_modules' # '/node_modules/grunt-blanket-mocha-server' ) # console.log obj[prop].yellow obj[prop] = obj[prop].replace /[\\]/g, '/' undefined ###* * Applies grunt.file.expand to the property of the object and optionally can * ensures that a minimum number of files matches. * @param {Object} grunt The Grunt object * @param {Object} obj The object with the property on which to operate * @param {string} prop The name of the property to expand * @param {number} [min] If specified, the minimum number of matching files * that is considered valid for configuration. * @return {undefined} ### expandFiles = (obj, prop, min) -> cwd = process.cwd() # seek files relative to the grunt process if obj[prop] obj[prop] = grunt.file.expand { cwd: cwd }, if _.isArray(obj[prop]) then obj[prop] else [obj[prop]] minViolationTest obj, prop, min if obj[prop] # passed the tests -- no clean up the dir base _.each obj[prop], (val, index) -> obj[prop][index] = path.resolve(val) .replace(path.resolve(process.cwd()), '') .replace(/[\\]/g, '/') undefined # ###* # * Wraps each specified path in an html script tag specifying type # * text/javascript and charset utf-8. # * @param {Array.<string>} patterns of paths to wrap # * @param {number} minimum number of scripts that should match pattern # * @return {undefined} html script tags for each script file in patterns # ### # wrapScriptTags = (obj, prop, min) -> # paths = expandFiles obj, prop, process.cwd(), min # if paths && paths.length # joinedPaths = paths.join( # '" type="text/javascript" charset="utf-8"></script>\n' + # '<script src="/' # ) # obj[prop] = "<script src=\"#{joinedPaths}\" type=\"text/javascript\" " + # "charset=\"utf-8\"></script>\n" # else # obj[prop] = '' # undefined ###* * Produce html attributes for key value pairs * @param {Object} attributes Key value pairs * @return {string} space-separated html attributes ### produceAttributes = (attributes) -> _.reduce( attributes, (result, attributeVal, attributeKey) -> result += " #{attributeKey}=\"#{attributeVal}\" " , '' ) ###* * Produce html attributes for key value pairs * @param {Object} blanketOptions Key value pairs representing runtime options * to set on blanket * @return {string} script statements to assign options, e.g. * 'blanket.options('myKey', 'myVal');' ### producePhantomOptions = (blanketOptions) -> _.reduce( blanketOptions, (result, optionVal, optionKey) -> result += "blanket.options('#{optionKey}', '#{optionVal}');\n" , '\n' ) grunt.registerMultiTask 'blanket_mocha_server', 'Serve runtime-configured browser-based mocha tests with ' + 'blanket.js coverage.', () -> myDirName = __dirname.replace /[\\]/g, '/' gbmsLib = myDirName + '/../lib/' gbmsSupport = myDirName + '/support/' gbmPath = '/node_modules/grunt-blanket-mocha/support' if fs.existsSync(myDirName + '/..' + gbmPath) gbmSupport = myDirName + '/..' + gbmPath + '/' else gbmSupport = process.cwd() + gbmPath + '/' defaultOptions = server: true htmlFile: null sutFiles: null testFiles: null blanketOptions: null blanketPhantomOptions: null noCoverage: false mochaPath: gbmsLib + 'mocha.js' mochaCssPath: gbmsLib + 'mocha.css' mochaSetupScript: 'mocha.setup(\'bdd\');' blanketPath: gbmsLib + 'blanket.js' gruntReporterPath: gbmSupport + 'grunt-reporter.js' mochaBlanketPath: gbmSupport + 'mocha-blanket.js' assertionLibs: gbmsLib + 'chai.js' assertionsSetupScript: 'window.expect = chai.expect; var should = chai.should();' runnerTemplate: gbmsSupport + 'test-runner-template.html' options = _.merge defaultOptions, @options() config = options resolveFile config, 'mochaPath', 1 resolveFile config, 'mochaCssPath', 0 resolveFile config, 'blanketPath', 0 resolveFile config, 'gruntReporterPath', 0 resolveFile config, 'mochaBlanketPath', 0 expandFiles config, 'assertionLibs', 1 expandFiles config, 'sutFiles' expandFiles config, 'testFiles' config.runnerTemplate = path.resolve config.runnerTemplate if !fs.existsSync(config.runnerTemplate) grunt.fatal "Specified runnerTemplate (#{config.runnerTempalate} " + ") not found." config.assertionsSetupScript config.blanketOptions = produceAttributes config.blanketOptions config.blanketPhantomOptions = producePhantomOptions config.blanketPhantomOptions runnerTarget = path.resolve config.htmlFile runnerTargetDir = path.dirname(runnerTarget) # runnerTarget.replace /\/[^\/]*$/, '/' if !fs.existsSync(runnerTargetDir) grunt.log.writeln 'making runner directory: ' + runnerTargetDir fs.mkdirSync runnerTargetDir grunt.log.writeln 'writing runner: ' + runnerTarget fs.writeFileSync( runnerTarget, grunt.template.process( fs.readFileSync(config.runnerTemplate, 'utf8'), { data: config } ) ) if options.server cwd = process.cwd() process.chdir __dirname + '/..' grunt.loadNpmTasks 'grunt-contrib-connect' process.chdir cwd grunt.config 'connect', {blanket_mocha_server_connect: {options: options}} grunt.task.run 'connect:blanket_mocha_server_connect'