-
Notifications
You must be signed in to change notification settings - Fork 116
/
grunt-karma.js
144 lines (126 loc) · 4.02 KB
/
grunt-karma.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* grunt-karma
* https://github.com/karma-runner/grunt-karma
*
* Copyright (c) 2013 Dave Geddes
* Licensed under the MIT license.
*/
var runner = require('karma').runner
var Server = require('karma').Server
var path = require('path')
var _ = require('lodash')
function finished (code) {
return this(code === 0)
}
// Parse out all cli arguments in the form of `--arg=something` or
// `-c=otherthing` and return the array.
function parseArgs (args) {
return _.filter(args, function (arg) {
return arg.match(/^--?/)
})
}
module.exports = function (grunt) {
grunt.registerMultiTask('karma', 'run karma.', function () {
var done = this.async()
var options = this.options({
background: false,
client: {}
})
// Allow for passing cli arguments to `client.args` using `--grep=x`
var args = parseArgs(process.argv.slice(2))
if (options.client && _.isArray(options.client.args)) {
args = options.client.args.concat(args)
}
// If arguments are provided we pass them to karma
if (args.length > 0) {
if (!options.client) {
options.client = {}
}
options.client.args = args
}
// Only create client info if data is provided
if (options.client) {
// Merge karma default options
_.defaults(options.client, {
args: []
})
}
var opts = _.cloneDeep(options)
// Merge options onto data, with data taking precedence.
var data = _.merge(opts, this.data)
// But override the browsers array.
if (data.browsers && this.data.browsers) {
data.browsers = this.data.browsers
}
// Merge client.args
if (this.data.client && _.isArray(this.data.client.args)) {
data.client.args = this.data.client.args.concat(options.client.args)
}
if (data.configFile) {
data.configFile = path.resolve(data.configFile)
}
// Combines both sets of files. The order should be:
// - first, values from options.files,
// - then, values from this.files.
if (options.files || this.files.length) {
// For our 'files' option, we support arbitrarily nested arrays,
// as a convenient way to specify files without the user needing to
// concat or flatten anything within their Gruntfile.
data.files = _.flattenDeep(options.files || [])
// The 'files' task data expanded by Grunt internally produces
// a structure that is exactly 2 levels deep.
this.files.forEach((file) => {
file.src.forEach((src) => {
let obj = {
pattern: src
};
['watched', 'served', 'included'].forEach((opt) => {
if (opt in file) {
obj[opt] = file[opt]
}
})
data.files.push(obj)
})
})
}
// Allow the use of templates in preprocessors
if (_.isPlainObject(data.preprocessors)) {
var preprocessors = {}
Object.keys(data.preprocessors).forEach(function (key) {
var value = data.preprocessors[key]
if (options.basePath) {
key = path.join(options.basePath, key)
}
key = path.resolve(key)
key = grunt.template.process(key)
preprocessors[key] = value
})
data.preprocessors = preprocessors
}
// support `karma run`, useful for grunt watch
if (this.flags.run) {
runner.run(data, finished.bind(done))
return
}
// allow karma to be run in the background so it doesn't block grunt
if (data.background) {
var backgroundProcess = require('child_process').fork(
path.join(__dirname, '..', 'lib', 'background.js')
)
backgroundProcess.on('close', function (code) {
var error = code
if (error) {
grunt.log.error('background karma process exited with error (code: ' + code + ')')
}
})
process.on('exit', function () {
backgroundProcess.kill()
})
backgroundProcess.send({ config: data })
done()
} else {
var server = new Server(data, finished.bind(done))
server.start()
}
})
}