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 {
|
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 |
|
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 |
|
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 | }
|