UNPKG

4.66 kBJavaScriptView Raw
1const { Server } = require('karma')
2const isCI = require('is-ci')
3
4function ensureArray(v) {
5 if (!Array.isArray(v)) {
6 return [v]
7 }
8 return v
9}
10
11module.exports = (options = {}) => {
12 return {
13 name: 'karma',
14 command: 'test',
15 apply(poi) {
16 if (typeof options.chainWebpack === 'function') {
17 poi.chainWebpack(options.chainWebpack)
18 }
19
20 const inferValue = (key, fallback) => {
21 if (typeof poi.options[key] !== 'undefined') {
22 return poi.options[key]
23 }
24 if (typeof options[key] !== 'undefined') {
25 return options[key]
26 }
27 return fallback
28 }
29
30 let isTypeScript = false
31
32 poi.chainWebpack(config => {
33 const coverage = inferValue('coverage')
34
35 isTypeScript = config.module.rules.has('typescript')
36
37 if (coverage) {
38 /* for general usage */
39 const istanbulinstrumenterRule = config.module
40 .rule('istanbul-instrumenter')
41 .test(/\.(jsx?)$/)
42 .exclude.add(/(node_modules|\.test\.jsx?)/)
43 .end()
44 .enforce('pre')
45 istanbulinstrumenterRule
46 .use('istanbul-instrumenter-loader')
47 .loader('istanbul-instrumenter-loader')
48 .options({
49 esModules: true
50 })
51
52 /* for vue (assumes vue-loader) */
53 const vueRule = config.module.rule('vue')
54 vueRule.use('vue-loader').tap(options => {
55 const instrumenterLoader =
56 'istanbul-instrumenter-loader?esModules=true'
57 options.preLoaders = options.preLoaders || {}
58 options.preLoaders.js =
59 typeof options.preLoaders.js === 'string'
60 ? `${options.preLoaders.js}!${instrumenterLoader}`
61 : instrumenterLoader
62 return options
63 })
64 }
65 })
66
67 poi.cli.handleCommand('test', 'Unit testing with Karma', () => {
68 const webpackConfig = poi.createWebpackConfig()
69
70 let files = inferValue('files', ['test/unit/**/*.test.js'])
71 files = ensureArray(files)
72 files.push({
73 pattern: 'static/**/*',
74 watched: false,
75 included: false,
76 served: true,
77 nocache: false
78 })
79
80 const port = inferValue('port', 5001)
81
82 let frameworks = inferValue('frameworks', ['mocha'])
83 frameworks = ensureArray(frameworks)
84 frameworks = frameworks.concat(isTypeScript ? ['karma-typescript'] : [])
85
86 const watch = !isCI && inferValue('watch', false)
87 const coverage = inferValue('coverage')
88
89 let reporters = inferValue('reporters', ['mocha'])
90 reporters = ensureArray(reporters)
91 reporters = reporters.concat(isTypeScript ? ['karma-typescript'] : [])
92 reporters = reporters.concat(coverage ? ['coverage'] : [])
93
94 const defaultBrowser = inferValue('headless')
95 ? 'ChromeHeadless'
96 : 'Chrome'
97 let browsers = inferValue('browsers') || defaultBrowser
98 browsers = ensureArray(browsers)
99
100 const defaultConfig = {
101 port,
102 frameworks,
103 basePath: process.cwd(),
104 files,
105 proxies: { '/': '/base/static/' },
106 reporters,
107 coverageReporter: {
108 dir: 'coverage',
109 reporters: [
110 { type: 'text' },
111 { type: 'html', subdir: 'report-html' },
112 { type: 'lcov', subdir: 'report-lcov' }
113 ]
114 },
115 preprocessors: files.reduce((current, next) => {
116 if (typeof next === 'object' && next.included === false) {
117 return current
118 }
119 const key = next.pattern || next
120 current[key] = [
121 'webpack',
122 ...(isTypeScript ? ['typescript'] : []),
123 'sourcemap'
124 ]
125 return current
126 }, {}),
127 webpackMiddleware: {
128 stats: 'errors-only',
129 noInfo: true
130 },
131 browsers,
132 singleRun: !watch
133 }
134
135 if (isTypeScript) {
136 defaultConfig.karmaTypescriptConfig = {
137 tsconfig: './tsconfig.json',
138 compilerOptions: {
139 module: 'commonjs'
140 }
141 }
142 }
143
144 delete webpackConfig.entry
145
146 const karmaConfig =
147 typeof options.karma === 'function'
148 ? options.karma(defaultConfig)
149 : Object.assign({}, defaultConfig, options.karma)
150 karmaConfig.webpack = webpackConfig
151
152 const server = new Server(karmaConfig)
153 server.start()
154 })
155 }
156 }
157}