1 | const { Server } = require('karma')
|
2 | const isCI = require('is-ci')
|
3 |
|
4 | function ensureArray(v) {
|
5 | if (!Array.isArray(v)) {
|
6 | return [v]
|
7 | }
|
8 | return v
|
9 | }
|
10 |
|
11 | module.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 |
|
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 |
|
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 | }
|