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+ */
1121export default function configure ( options ) {
1222 let cwd = process . cwd ( ) ,
1323 res = file => path . resolve ( cwd , file ) ;
@@ -17,7 +27,9 @@ export default function configure(options) {
1727
1828 process . env . CHROME_BIN = puppeteer . executablePath ( ) ;
1929
20- let gitignore = ( readFile ( path . resolve ( cwd , '.gitignore' ) , 'utf8' ) || '' ) . replace ( / ( ^ \s * | \s * $ | # .* $ ) / g, '' ) . split ( '\n' ) . filter ( Boolean ) ;
30+ let gitignore = (
31+ readFile ( path . resolve ( cwd , '.gitignore' ) ) || ''
32+ ) . replace ( / ( ^ \s * | \s * $ | # .* $ ) / g, '' ) . split ( '\n' ) . filter ( Boolean ) ;
2133 let repoRoot = ( readDir ( cwd ) || [ ] ) . filter ( c => c [ 0 ] !== '.' && c !== 'node_modules' && gitignore . indexOf ( c ) === - 1 ) ;
2234 let rootFiles = '{' + repoRoot . join ( ',' ) + '}' ;
2335
@@ -31,6 +43,56 @@ export default function configure(options) {
3143 options . coverage ? 'karma-coverage' : [ ]
3244 ) ;
3345
46+ // Custom launchers to be injected:
47+ const launchers = { } ;
48+ let useSauceLabs = false ;
49+
50+ let browsers ;
51+ if ( options . browsers ) {
52+ browsers = options . browsers . map ( browser => {
53+ if ( / ^ c h r o m e $ / i. test ( browser ) ) {
54+ return 'Chrome' ;
55+ }
56+ if ( / ^ f i r e f o x $ / i. test ( browser ) ) {
57+ PLUGINS . push ( 'karma-firefox-launcher' ) ;
58+ return 'Firefox' ;
59+ }
60+ if ( / ^ s a u c e - / . test ( browser ) ) {
61+ if ( ! useSauceLabs ) {
62+ useSauceLabs = true ;
63+ PLUGINS . push ( 'karma-sauce-launcher' ) ;
64+ }
65+ const parts = browser . toLowerCase ( ) . split ( '-' ) ;
66+ const name = parts . join ( '_' ) ;
67+ launchers [ name ] = {
68+ base : 'SauceLabs' ,
69+ browserName : parts [ 1 ] . replace ( / ^ i e $ / gi, 'Internet Explorer' ) ,
70+ version : parts [ 2 ] || undefined ,
71+ 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
72+ } ;
73+ return name ;
74+ }
75+ return browser ;
76+ } ) ;
77+ }
78+ else {
79+ browsers = [ options . headless === false ? 'KarmaticChrome' : 'KarmaticChromeHeadless' ] ;
80+ }
81+
82+ if ( useSauceLabs ) {
83+ let missing = [ 'SAUCE_USERNAME' , 'SAUCE_ACCESS_KEY' ] . filter ( x => ! process . env [ x ] ) [ 0 ] ;
84+ if ( missing ) {
85+ throw (
86+ '\n' +
87+ chalk . bold . bgRed . white ( 'Error:' ) + ' Missing SauceLabs auth configuration.' +
88+ '\n ' + chalk . white ( `A SauceLabs browser was requested, but no ${ chalk . magentaBright ( missing ) } environment variable provided.` ) +
89+ '\n ' + chalk . white ( 'Try prepending it to your test command:' ) +
90+ ' ' + chalk . greenBright ( missing + '=... npm test' ) +
91+ '\n'
92+ ) ;
93+ }
94+ }
95+
3496 const WEBPACK_CONFIGS = [
3597 'webpack.config.babel.js' ,
3698 'webpack.config.js'
@@ -109,22 +171,27 @@ export default function configure(options) {
109171
110172 let generatedConfig = {
111173 basePath : cwd ,
112- plugins : PLUGINS . map ( require . resolve ) ,
174+ plugins : PLUGINS . map ( req => require . resolve ( req ) ) ,
113175 frameworks : [ 'jasmine' ] ,
114176 reporters : [ 'spec' ] . concat (
115- options . coverage ? 'coverage' : [ ]
177+ options . coverage ? 'coverage' : [ ] ,
178+ useSauceLabs ? 'saucelabs' : [ ]
116179 ) ,
117- browsers : [ options . headless === false ? 'KarmaticChrome' : 'KarmaticChromeHeadless' ] ,
180+ browsers,
181+ sauceLabs : {
182+ testName : pkg && pkg . name || undefined
183+ } ,
118184
119- customLaunchers : {
185+ customLaunchers : Object . assign ( {
120186 KarmaticChrome : {
121- base : 'Chrome'
187+ base : 'Chrome' ,
188+ flags : [ '--no-sandbox' ]
122189 } ,
123190 KarmaticChromeHeadless : {
124191 base : 'ChromeHeadless' ,
125192 flags : [ '--no-sandbox' ]
126193 }
127- } ,
194+ } , launchers ) ,
128195
129196 coverageReporter : {
130197 reporters : [
@@ -149,7 +216,8 @@ export default function configure(options) {
149216 } ] ,
150217
151218 files : [
152- { pattern : moduleDir ( 'babel-polyfill' ) + '/dist/polyfill.js' , watched : false , included : true , served : true }
219+ // @TODO remove me
220+ // { pattern: moduleDir('babel-polyfill')+'/dist/polyfill.js', watched: false, included: true, served: true }
153221 ] . concat ( ...files . map ( pattern => {
154222 // Expand '**/xx' patterns but exempt node_modules and gitignored directories
155223 let matches = pattern . match ( / ^ \* \* \/ ( .+ ) $ / ) ;
0 commit comments