-
Notifications
You must be signed in to change notification settings - Fork 334
/
createKarmaConfig.js
215 lines (192 loc) · 6.44 KB
/
createKarmaConfig.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
import path from 'path'
import merge from 'webpack-merge'
import createWebpackConfig from './createWebpackConfig'
import debug from './debug'
import {deepToString, typeOf} from './utils'
// The following defaults are combined into a single extglob-style pattern to
// avoid generating "pattern ... does not match any file" warnings.
// Exclude top-level test dirs and __tests__ dirs under src/ from code coverage
// by default.
const DEFAULT_EXCLUDE_FROM_COVERAGE = ['test/', 'tests/', 'src/**/__tests__/']
// Not every file in a test directory is a test and tests may also be co-located
// with the code they test, so determine test files by suffix.
const DEFAULT_TEST_FILES = ['+(src|test?(s))/**/*+(-test|.spec|.test).js']
/**
* Browser, framework and reporter config can be passed as strings or as plugin
* objects. This handles figuring out which names and plugins have been provided
* and automatically extracting the first browser/framework/reporter name from a
* plugin object.
*/
export function processPluginConfig(configs) {
let names = []
let plugins = []
configs.forEach(config => {
if (typeOf(config) === 'string') {
names.push(config)
}
else {
names.push(Object.keys(config)[0].split(':').pop())
plugins.push(config)
}
})
return [names, plugins]
}
/**
* Finds a karma plugin with the given type:name id. If a plugin object contains
* multiple plugins (e.g. karma-chai-plugins), only the first will be checked.
*/
export function findPlugin(plugins, findId) {
for (let i = 0, l = plugins.length; i < l; i++) {
if (typeOf(plugins[i]) !== 'object') {
continue
}
if (Object.keys(plugins[i])[0] === findId) {
return plugins[i]
}
}
return null
}
/**
* Handles creation of Karma config based on Karma plugins.
*/
export function getKarmaPluginConfig({codeCoverage = false, userConfig = {}} = {}) {
let browsers = ['PhantomJS']
let frameworks = ['mocha']
let plugins = [
require('karma-sourcemap-loader'),
require('karma-webpack'),
]
// Default reporter if the user configure their own frameworks
let reporters = ['dots']
// Browsers, frameworks and reporters can be configured as a list containing
// names of bundled plugins, or plugin objects.
if (userConfig.browsers) {
let [browserNames, browserPlugins] = processPluginConfig(userConfig.browsers)
browsers = browserNames
plugins = plugins.concat(browserPlugins)
}
if (userConfig.frameworks) {
let [frameworkNames, frameworkPlugins] = processPluginConfig(userConfig.frameworks)
frameworks = frameworkNames
plugins = plugins.concat(frameworkPlugins)
}
else {
// Use the Mocha reporter by default if the user didn't configure frameworks
reporters = ['mocha']
}
if (userConfig.reporters) {
let [reporterNames, reporterPlugins] = processPluginConfig(userConfig.reporters)
reporters = reporterNames
plugins = plugins.concat(reporterPlugins)
}
// Plugins can be provided as a list of imported plugin objects
if (userConfig.plugins) {
plugins = plugins.concat(userConfig.plugins)
}
// Ensure nwb's version of plugins get loaded if they're going to be used and =
// haven't been provided by the user.
if (frameworks.indexOf('mocha') !== -1 && !findPlugin(plugins, 'framework:mocha')) {
plugins.push(require('karma-mocha'))
}
if (reporters.indexOf('mocha') !== -1 && !findPlugin(plugins, 'reporter:mocha')) {
plugins.push(require('karma-mocha-reporter'))
}
if (browsers.indexOf('PhantomJS') !== -1 && !findPlugin(plugins, 'launcher:PhantomJS')) {
plugins.push(require('karma-phantomjs-launcher'))
}
if (browsers.some(function matchChrom(b) { return /Chrom/.test(b) }) &&
!findPlugin(plugins, 'launcher:Chrome')) {
plugins.push(require('karma-chrome-launcher'))
}
if (codeCoverage) {
plugins.push(require('karma-coverage'))
reporters.push('coverage')
}
return {browsers, frameworks, plugins, reporters}
}
export default function createKarmaConfig(args, buildConfig, pluginConfig, userConfig) {
let isCi = process.env.CI || process.env.CONTINUOUS_INTEGRATION
let codeCoverage = isCi || !!args.coverage
let userKarma = userConfig.karma || {}
let {browsers, frameworks, plugins, reporters} = getKarmaPluginConfig({
codeCoverage,
userConfig: userKarma,
})
let {excludeFromCoverage = DEFAULT_EXCLUDE_FROM_COVERAGE} = userKarma
if (typeOf(excludeFromCoverage) === 'string') excludeFromCoverage = [excludeFromCoverage]
let testFiles = userKarma.testFiles || DEFAULT_TEST_FILES
if (typeOf(testFiles) === 'string') testFiles = [testFiles]
// Polyfill by default for browsers which lack features (hello PhantomJS)
let files = [require.resolve('babel-polyfill/dist/polyfill.js')]
let preprocessors = {}
if (userKarma.testContext) {
files.push(userKarma.testContext)
preprocessors[userKarma.testContext] = ['webpack', 'sourcemap']
}
else {
testFiles.forEach(testGlob => {
files.push(testGlob)
preprocessors[testGlob] = ['webpack', 'sourcemap']
})
}
// Tweak Babel config for code coverage when necessary
buildConfig = {...buildConfig}
if (!buildConfig.babel) {
buildConfig.babel = {}
}
if (codeCoverage) {
let exclude = ['node_modules/', ...excludeFromCoverage, ...testFiles]
if (userKarma.testContext) {
exclude.push(userKarma.testContext)
}
buildConfig.babel.plugins = [
[require.resolve('babel-plugin-istanbul'), {exclude}]
]
}
let karmaConfig = merge({
browsers,
coverageReporter: {
dir: path.resolve('coverage'),
reporters: [
{type: 'html', subdir: 'html'},
{type: 'lcovonly', subdir: '.'},
{type: 'text-summary'},
],
},
files,
frameworks,
mochaReporter: {
showDiff: true,
},
plugins,
preprocessors,
reporters,
singleRun: isCi || !args.server,
webpack: createWebpackConfig(merge(buildConfig, {
devtool: 'cheap-module-inline-source-map',
node: {
fs: 'empty',
},
plugins: {
status: {
quiet: true,
}
},
resolve: {
alias: {
expect: path.dirname(require.resolve('expect/package')),
src: path.resolve('src'),
},
},
server: {
hot: false,
},
}), pluginConfig, userConfig),
webpackMiddleware: {
noInfo: true,
quiet: true,
},
}, userKarma.extra)
debug('karma config: %s', deepToString(karmaConfig))
return karmaConfig
}