11import path from 'path' ;
22import puppeteer from 'puppeteer' ;
3+ import chalk from 'chalk' ;
34import delve from 'dlv' ;
4- import { moduleDir , tryRequire , dedupe , cleanStack , readFile , readDir } from './lib/util' ;
5+ import { tryRequire , dedupe , cleanStack , readFile , readDir } from './lib/util' ;
56import babelLoader from './lib/babel-loader' ;
67import cssLoader from './lib/css-loader' ;
78
89const WEBPACK_VERSION = String ( require ( 'webpack' ) . version || '3.0.0' ) ;
9- const WEBPACK_MAJOR = WEBPACK_VERSION . split ( '.' ) [ 0 ] | 0 ;
10+ const WEBPACK_MAJOR = parseInt ( WEBPACK_VERSION . split ( '.' ) [ 0 ] , 10 ) ;
1011
12+ /**
13+ * @param {Object } options
14+ * @param {Array } options.files - Test files to run
15+ * @param {Array } [options.browsers] - Custom list of browsers to run in
16+ * @param {Boolean } [options.headless=false] - Run in Headless Chrome?
17+ * @param {Boolean } [options.watch=false] - Start a continuous test server and retest when files change
18+ * @param {Boolean } [options.coverage=false] - Instrument and collect code coverage statistics
19+ * @param {Object } [options.webpackConfig] - Custom webpack configuration
20+ * @param {Boolean } [options.downlevel=false] - Downlevel/transpile syntax to ES5
21+ */
1122export default function configure ( options ) {
1223 let cwd = process . cwd ( ) ,
1324 res = file => path . resolve ( cwd , file ) ;
@@ -17,7 +28,9 @@ export default function configure(options) {
1728
1829 process . env . CHROME_BIN = puppeteer . executablePath ( ) ;
1930
20- let gitignore = ( readFile ( path . resolve ( cwd , '.gitignore' ) , 'utf8' ) || '' ) . replace ( / ( ^ \s * | \s * $ | # .* $ ) / g, '' ) . split ( '\n' ) . filter ( Boolean ) ;
31+ let gitignore = (
32+ readFile ( path . resolve ( cwd , '.gitignore' ) ) || ''
33+ ) . replace ( / ( ^ \s * | \s * $ | # .* $ ) / g, '' ) . split ( '\n' ) . filter ( Boolean ) ;
2134 let repoRoot = ( readDir ( cwd ) || [ ] ) . filter ( c => c [ 0 ] !== '.' && c !== 'node_modules' && gitignore . indexOf ( c ) === - 1 ) ;
2235 let rootFiles = '{' + repoRoot . join ( ',' ) + '}' ;
2336
@@ -31,6 +44,56 @@ export default function configure(options) {
3144 options . coverage ? 'karma-coverage' : [ ]
3245 ) ;
3346
47+ // Custom launchers to be injected:
48+ const launchers = { } ;
49+ let useSauceLabs = false ;
50+
51+ let browsers ;
52+ if ( options . browsers ) {
53+ browsers = options . browsers . map ( browser => {
54+ if ( / ^ c h r o m e $ / i. test ( browser ) ) {
55+ return 'Chrome' ;
56+ }
57+ if ( / ^ f i r e f o x $ / i. test ( browser ) ) {
58+ PLUGINS . push ( 'karma-firefox-launcher' ) ;
59+ return 'Firefox' ;
60+ }
61+ if ( / ^ s a u c e - / . test ( browser ) ) {
62+ if ( ! useSauceLabs ) {
63+ useSauceLabs = true ;
64+ PLUGINS . push ( 'karma-sauce-launcher' ) ;
65+ }
66+ const parts = browser . toLowerCase ( ) . split ( '-' ) ;
67+ const name = parts . join ( '_' ) ;
68+ launchers [ name ] = {
69+ base : 'SauceLabs' ,
70+ browserName : parts [ 1 ] . replace ( / ^ i e $ / gi, 'Internet Explorer' ) ,
71+ version : parts [ 2 ] || undefined ,
72+ platform : parts [ 3 ] ? parts [ 3 ] . replace ( / ^ w i n ( d o w s ) ? [ - ] + / gi, 'Windows ' ) . replace ( / ^ ( m a c o s | m a c ? o s ? x | o s ? x ) [ - ] + / gi, 'OS X ' ) : undefined
73+ } ;
74+ return name ;
75+ }
76+ return browser ;
77+ } ) ;
78+ }
79+ else {
80+ browsers = [ options . headless === false ? 'KarmaticChrome' : 'KarmaticChromeHeadless' ] ;
81+ }
82+
83+ if ( useSauceLabs ) {
84+ let missing = [ 'SAUCE_USERNAME' , 'SAUCE_ACCESS_KEY' ] . filter ( x => ! process . env [ x ] ) [ 0 ] ;
85+ if ( missing ) {
86+ throw (
87+ '\n' +
88+ chalk . bold . bgRed . white ( 'Error:' ) + ' Missing SauceLabs auth configuration.' +
89+ '\n ' + chalk . white ( `A SauceLabs browser was requested, but no ${ chalk . magentaBright ( missing ) } environment variable provided.` ) +
90+ '\n ' + chalk . white ( 'Try prepending it to your test command:' ) +
91+ ' ' + chalk . greenBright ( missing + '=... npm test' ) +
92+ '\n'
93+ ) ;
94+ }
95+ }
96+
3497 const WEBPACK_CONFIGS = [
3598 'webpack.config.babel.js' ,
3699 'webpack.config.js'
@@ -109,22 +172,27 @@ export default function configure(options) {
109172
110173 let generatedConfig = {
111174 basePath : cwd ,
112- plugins : PLUGINS . map ( require . resolve ) ,
175+ plugins : PLUGINS . map ( req => require . resolve ( req ) ) ,
113176 frameworks : [ 'jasmine' ] ,
114177 reporters : [ 'spec' ] . concat (
115- options . coverage ? 'coverage' : [ ]
178+ options . coverage ? 'coverage' : [ ] ,
179+ useSauceLabs ? 'saucelabs' : [ ]
116180 ) ,
117- browsers : [ options . headless === false ? 'KarmaticChrome' : 'KarmaticChromeHeadless' ] ,
181+ browsers,
182+ sauceLabs : {
183+ testName : pkg && pkg . name || undefined
184+ } ,
118185
119- customLaunchers : {
186+ customLaunchers : Object . assign ( {
120187 KarmaticChrome : {
121- base : 'Chrome'
188+ base : 'Chrome' ,
189+ flags : [ '--no-sandbox' ]
122190 } ,
123191 KarmaticChromeHeadless : {
124192 base : 'ChromeHeadless' ,
125193 flags : [ '--no-sandbox' ]
126194 }
127- } ,
195+ } , launchers ) ,
128196
129197 coverageReporter : {
130198 reporters : [
@@ -149,7 +217,8 @@ export default function configure(options) {
149217 } ] ,
150218
151219 files : [
152- { pattern : moduleDir ( 'babel-polyfill' ) + '/dist/polyfill.js' , watched : false , included : true , served : true }
220+ // @TODO remove me
221+ // { pattern: moduleDir('babel-polyfill')+'/dist/polyfill.js', watched: false, included: true, served: true }
153222 ] . concat ( ...files . map ( pattern => {
154223 // Expand '**/xx' patterns but exempt node_modules and gitignored directories
155224 let matches = pattern . match ( / ^ \* \* \/ ( .+ ) $ / ) ;
@@ -167,6 +236,7 @@ export default function configure(options) {
167236
168237 webpack : {
169238 devtool : 'cheap-module-eval-source-map' ,
239+ // devtool: 'module-source-map',
170240 mode : webpackConfig . mode || 'development' ,
171241 module : {
172242 // @TODO check webpack version and use loaders VS rules as the key here appropriately:
0 commit comments