11'use strict' ;
22
3- var path = require ( 'path' ) ;
4- var through = require ( 'through2' ) ;
5- var querystring = require ( 'querystring' ) ;
6- var childProcess = require ( 'child_process' ) ;
3+ var path = require ( 'path' ) ;
4+
5+ var gulp = require ( 'gulp' ) ,
6+ through = require ( 'through2' ) ,
7+ querystring = require ( 'querystring' ) ,
8+ childProcess = require ( 'child_process' ) ;
79
810/**
911 * Wrap the given value in quotation marks
@@ -14,60 +16,110 @@ function quote(value) {
1416 return '"' + value + '"' ;
1517}
1618
19+ var filesAppendRegex = / \/ \* + \s * A N G U L A R I T Y _ F I L E _ L I S T \s * \* + \/ / ;
20+
1721/**
18- * Run karma once only with the given <code>options</code> and the files from the stream appended.
19- * Removes any logging from the output.
20- * No output. Ends when the Karma process ends.
21- * @param {object } options Karma options
22- * @param {number } [bannerWidth] The width of banner comment, zero or omitted for none
23- * @returns {stream.Through } A through strconcateam that performs the operation of a gulp stream
22+ * Create a through2 object stream.
23+ * Expects all the `*.js` files to be included as the files list in the karma conf
24+ * Creates a new karma config file, based on the karma config file name found in
25+ * the local project root, and augments its file list by replacing
26+ * `ANGULARITY_FILE_LIST` in ablock comment with the actual array of files.
27+ * The new karma config file is added to the stream,
28+ * All input `*.js` files are filtered out of the stream
29+ *
30+ * @param {string } configFileName The project local karma config file to augment
31+ * Defaults to "karma.conf.js"
32+ * @return {stream.Through } The output of this stream is expected to contain
33+ * just one file: the augmented karma config file.
2434 */
25- module . exports = function ( options , bannerWidth ) {
26-
27- // setup
28- options . singleRun = true ;
29- options . autoWatch = false ;
30- options . configFile = options . configFile ? path . resolve ( options . configFile ) : undefined ;
31- options . files = options . files || [ ] ;
35+ function karmaCreateConfig ( configFileName ) {
36+ configFileName = 'karma.conf.js' ;
37+ var files = [ ] ;
3238
33- // add unique all stream JS files to the options.files list
34- return through . obj ( function ( file , encoding , done ) {
35- var isValid = ! ( file . isNull ( ) ) && ( path . extname ( file . path ) === '.js' ) ;
36- if ( isValid && ( options . files . indexOf ( file . path ) < 0 ) ) {
37- options . files . push ( file . path ) ;
39+ function transformFn ( file , encoding , done ) {
40+ if ( ! file || ! file . path ) {
41+ throw 'Files must have paths' ;
3842 }
43+ files . push ( file . path ) ;
3944 done ( ) ;
45+ }
4046
41- // run once at the end of the stream
42- } , function ( done ) {
43- if ( options . files . length ) {
44- var appPath = path . join ( __dirname , 'karma-background.js' ) ;
45- var data = querystring . escape ( JSON . stringify ( options ) ) ;
46- var command = [ 'node' , quote ( appPath ) , data ] . join ( ' ' ) ;
47- childProcess . exec ( command , { cwd : process . cwd ( ) } , function ( stderr , stdout ) {
48- var report ;
49- if ( stdout ) {
50- report = stdout
51- . replace ( / ^ \s + / gm, '' ) // remove leading whitespace
52- . replace ( / ^ ( L O G .* \n $ ) / gm, options . silent ? '' : '$1' ) // remove logging
53- . replace ( / a t \s + n u l l \. .* / gm, '' ) // remove file reference
54- . replace ( / \n \n / gm, '\n' ) // consolidate consecutive line breaks
55- . replace ( / ^ \n | \n $ / g, '' ) ; // remove leading and trailing line breaks overall
56- } else if ( stderr ) {
57- var analysis = / $ E r r o r \: \s * ( .* ) $ / mg. exec ( stderr ) ;
58- report = analysis ? analysis [ 1 ] : stderr ;
59- }
60- if ( report ) {
61- var width = Number ( bannerWidth ) || 0 ;
62- var hr = new Array ( width + 1 ) ; // this is a good trick to repeat a character N times
63- var start = ( width > 0 ) ? ( hr . join ( '\u25BC' ) + '\n' ) : '' ;
64- var stop = ( width > 0 ) ? ( hr . join ( '\u25B2' ) + '\n' ) : '' ;
65- process . stdout . write ( start + '\n' + report + '\n\n' + stop ) ;
66- }
47+ function flushFn ( done ) {
48+ var stream = this ;
49+ var filesAppend = JSON . stringify ( files , null , ' ' ) ;
50+
51+ //aggregate and append to karma.conf.js in the project root folder
52+ gulp
53+ . src ( path . resolve ( configFileName ) )
54+ . on ( 'data' , function ( karmaConfigFile ) {
55+ var contents = karmaConfigFile . contents . toString ( ) ;
56+ contents = contents . replace ( filesAppendRegex , filesAppend ) ;
57+ karmaConfigFile . contents = new Buffer ( contents ) ;
58+ stream . push ( karmaConfigFile ) ;
59+ } )
60+ . on ( 'end' , function ( ) {
6761 done ( ) ;
6862 } ) ;
69- } else {
63+ }
64+
65+ return through . obj ( transformFn , flushFn ) ;
66+ }
67+
68+ /**
69+ * Run karma once only with the karma config file present in the input stream.
70+ * No output. Ends when the Karma process ends.
71+ * Runs karma in a child process, to avoid `process.exit()` called by karma.
72+ *
73+ * @param {number } [bannerWidth] The width of banner comment, zero or omitted for none
74+ * @returns {stream.Through } A through strconcateam that performs the operation of a gulp stream
75+ */
76+ function karmaRun ( bannerWidth ) {
77+ var options = {
78+ configFile : undefined
79+ } ;
80+
81+ return through . obj ( function transformFn ( file , encoding , done ) {
82+ options . configFile = file . path ;
83+ done ( ) ;
84+ } ,
85+ function streamFn ( done ) {
86+ var appPath = path . join ( __dirname , 'karma-background.js' ) ;
87+ var data = querystring . escape ( JSON . stringify ( options ) ) ;
88+ var command = [ 'node' , quote ( appPath ) , data ] . join ( ' ' ) ;
89+
90+ //TODO @bguiz replace reporter function with a standard karma reporter,
91+ //and extract it to own module
92+ //perhaps extend the spec reporter to do what is being done here, instead of post processing its output here
93+ //check if there is a webstorm/ teamcity reporter
94+ childProcess . exec ( command , { cwd : process . cwd ( ) } , function reporter ( stderr , stdout ) {
95+ var report ;
96+ if ( stdout ) {
97+ console . log ( stdout ) ;
98+ report = stdout
99+ . replace ( / ^ \s + / gm, '' ) // remove leading whitespace
100+ . replace ( / ^ ( L O G .* \n $ ) / gm, options . silent ? '' : '$1' ) // remove logging
101+ . replace ( / a t \s + n u l l \. .* / gm, '' ) // remove file reference
102+ . replace ( / \n \n / gm, '\n' ) // consolidate consecutive line breaks
103+ . replace ( / ^ \n | \n $ / g, '' ) ; // remove leading and trailing line breaks overall
104+ } else if ( stderr ) {
105+ console . log ( stderr ) ;
106+
107+ var analysis = / $ E r r o r \: \s * ( .* ) $ / mg. exec ( stderr ) ;
108+ report = analysis ? analysis [ 1 ] : stderr ;
109+ }
110+ if ( report ) {
111+ var width = Number ( bannerWidth ) || 0 ;
112+ var hr = new Array ( width + 1 ) ; // this is a good trick to repeat a character N times
113+ var start = ( width > 0 ) ? ( hr . join ( '\u25BC' ) + '\n' ) : '' ;
114+ var stop = ( width > 0 ) ? ( hr . join ( '\u25B2' ) + '\n' ) : '' ;
115+ process . stdout . write ( start + '\n' + report + '\n\n' + stop ) ;
116+ }
70117 done ( ) ;
71- }
118+ } ) ;
72119 } ) ;
73120} ;
121+
122+ module . exports = {
123+ createConfig : karmaCreateConfig ,
124+ run : karmaRun
125+ } ;
0 commit comments