UNPKG

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