@@ -7,6 +7,8 @@ var gulp = require('gulp'),
77 querystring = require ( 'querystring' ) ,
88 childProcess = require ( 'child_process' ) ;
99
10+ var yargs = require ( '../util/yargs' ) ;
11+
1012/**
1113 * Wrap the given value in quotation marks
1214 * @param {* } value The value to wrap
@@ -16,7 +18,73 @@ function quote(value) {
1618 return '"' + value + '"' ;
1719}
1820
21+ var defaultReporterName = 'angularity-karma-reporter' ;
22+
1923var filesAppendRegex = / \/ \* + \s * A N G U L A R I T Y _ F I L E _ L I S T \s * \* + \/ / ;
24+ var reportersAppendRegex = / \/ \* + \s * A N G U L A R I T Y _ R E P O R T E R _ L I S T \s * \* + \/ / ;
25+ var pluginsAppendRegex = / \/ \* + \s * A N G U L A R I T Y _ P L U G I N _ L I S T \s * \* + \/ / ;
26+ var karmaReporterMatchNameRegex = / ^ k a r m a - ( .+ ) - r e p o r t e r $ / ;
27+
28+ /**
29+ * Determine the `require` path for a plugin.
30+ *
31+ * @param {string } reporterName Either a package name,
32+ * *OR* an absolute path, for a karma reporter.
33+ * @return {string } In karma config file, `plugins` will be inline `require`d
34+ * using this return value.
35+ */
36+ function getKarmaReporterPluginPath ( reporterName ) {
37+ if ( typeof reporterName !== 'string' ) {
38+ throw 'Get Karma Reporter Plugin Path: Reporter name is unspecified' ;
39+ }
40+
41+ if ( reporterName === defaultReporterName ) {
42+ return defaultReporterName ;
43+ }
44+ else {
45+ var reporterPath = ( path . dirname ( reporterName ) === '.' ) ?
46+ path . resolve ( 'node_modules' , 'karma-' + reporterName + '-reporter' ) :
47+ reporterName ;
48+ try {
49+ require ( reporterPath ) ;
50+ }
51+ catch ( ex ) {
52+ throw 'Get Karma Reporter Plugin Path: Attempt to require reporter from path ' +
53+ reporterPath + ' with no success.' ;
54+ }
55+ reporterPath = path . normalize ( reporterPath ) ;
56+ //quirk: nodejs identifies all windows (both win32 and win64) as win32
57+ if ( process . platform === 'win32' ) {
58+ //replace any single backslash characters in file paths with
59+ //double backslash on windows; neither path.normalize nor path.resolve do this
60+ reporterPath = reporterPath . replace ( / \\ / g , '\\\\' ) ;
61+ }
62+ return reporterPath ;
63+ }
64+ }
65+
66+ /**
67+ * Determine the registered reporter name.
68+ *
69+ * @param {string } reporterName Either the registered reporter name,
70+ * *OR* an absolute path, for a karma reporter.
71+ * @return {string } The registered reporter name for use in
72+ * the `reporters` section of the karma config file.
73+ */
74+ function getKarmaReporterName ( reporterName ) {
75+ if ( typeof reporterName !== 'string' ) {
76+ throw 'Get Karma Reporter Name: Reporter name is unspecified' ;
77+ }
78+
79+ var name = ( path . dirname ( reporterName ) === '.' ) ?
80+ reporterName :
81+ path . basename ( reporterName ) ;
82+ var match = karmaReporterMatchNameRegex . exec ( name ) ;
83+ if ( ! ! match && match . length === 2 ) {
84+ name = match [ 1 ] ;
85+ }
86+ return name
87+ }
2088
2189/**
2290 * Create a through2 object stream.
@@ -27,13 +95,15 @@ var filesAppendRegex = /\/\*+\s*ANGULARITY_FILE_LIST\s*\*+\// ;
2795 * The new karma config file is added to the stream,
2896 * All input `*.js` files are filtered out of the stream
2997 *
30- * @param {string } configFileName The project local karma config file to augment
98+ * @param {Array.<string> } [reporters] The name of the karma reporter to use
99+ * @param {string } [configFileName] The project local karma config file to augment
31100 * Defaults to "karma.conf.js"
32101 * @return {stream.Through } The output of this stream is expected to contain
33102 * just one file: the augmented karma config file.
34103 */
35- function karmaCreateConfig ( configFileName ) {
36- configFileName = 'karma.conf.js' ;
104+ function karmaCreateConfig ( reporters , configFileName ) {
105+ reporters = reporters || [ ] ;
106+ configFileName = configFileName || 'karma.conf.js' ;
37107 var files = [ ] ;
38108
39109 function transformFn ( file , encoding , done ) {
@@ -47,13 +117,20 @@ function karmaCreateConfig(configFileName) {
47117 function flushFn ( done ) {
48118 var stream = this ;
49119 var filesAppend = JSON . stringify ( files , null , ' ' ) ;
120+ var reportersAppend = JSON . stringify ( reporters . map ( getKarmaReporterName ) , null , ' ' ) ;
121+ var pluginsAppend = '[\n' + reporters . map ( function ( reporter ) {
122+ return 'require("' + getKarmaReporterPluginPath ( reporter ) + '")' ;
123+ } ) . join ( ',\n ' ) + '\n]' ;
50124
51125 //aggregate and append to karma.conf.js in the project root folder
52126 gulp
53127 . src ( path . resolve ( configFileName ) )
54128 . on ( 'data' , function ( karmaConfigFile ) {
55- var contents = karmaConfigFile . contents . toString ( ) ;
56- contents = contents . replace ( filesAppendRegex , filesAppend ) ;
129+ var contents = karmaConfigFile . contents . toString ( )
130+ . replace ( filesAppendRegex , filesAppend )
131+ . replace ( reportersAppendRegex , reportersAppend )
132+ . replace ( reportersAppendRegex , reportersAppend )
133+ . replace ( pluginsAppendRegex , pluginsAppend ) ;
57134 karmaConfigFile . contents = new Buffer ( contents ) ;
58135 stream . push ( karmaConfigFile ) ;
59136 } )
@@ -70,13 +147,15 @@ function karmaCreateConfig(configFileName) {
70147 * No output. Ends when the Karma process ends.
71148 * Runs karma in a child process, to avoid `process.exit()` called by karma.
72149 *
150+ * @param {Array.<string> } [reporters] The name of the karma reporter to use
73151 * @param {number } [bannerWidth] The width of banner comment, zero or omitted for none
74152 * @returns {stream.Through } A through strconcateam that performs the operation of a gulp stream
75153 */
76- function karmaRun ( bannerWidth ) {
154+ function karmaRun ( reporters , bannerWidth ) {
77155 var options = {
78156 configFile : undefined
79157 } ;
158+ reporters = reporters || [ ] ;
80159
81160 return through . obj ( function transformFn ( file , encoding , done ) {
82161 options . configFile = file . path ;
@@ -87,23 +166,32 @@ function karmaRun(bannerWidth) {
87166 var data = querystring . escape ( JSON . stringify ( options ) ) ;
88167 var command = [ 'node' , quote ( appPath ) , data ] . join ( ' ' ) ;
89168
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
94169 childProcess . exec ( command , { cwd : process . cwd ( ) } , function reporter ( stderr , stdout ) {
170+ if ( reporters . length > 0 ) {
171+ if ( stdout ) {
172+ process . stdout . write ( stdout ) ;
173+ }
174+ if ( stderr ) {
175+ process . stderr . write ( stderr ) ;
176+ }
177+ done ( ) ;
178+ return ;
179+ }
180+
181+ //TODO @bguiz replace reporter function with a standard karma reporter,
182+ //and extract it to own module
183+
184+ //default reporter by parsing the stdout and stderr of karma
95185 var report ;
96186 if ( stdout ) {
97- console . log ( stdout ) ;
98187 report = stdout
99188 . replace ( / ^ \s + / gm, '' ) // remove leading whitespace
100189 . replace ( / ^ ( L O G .* \n $ ) / gm, options . silent ? '' : '$1' ) // remove logging
101190 . replace ( / a t \s + n u l l \. .* / gm, '' ) // remove file reference
102191 . replace ( / \n \n / gm, '\n' ) // consolidate consecutive line breaks
103192 . replace ( / ^ \n | \n $ / g, '' ) ; // remove leading and trailing line breaks overall
104- } else if ( stderr ) {
105- console . log ( stderr ) ;
106-
193+ }
194+ else if ( stderr ) {
107195 var analysis = / $ E r r o r \: \s * ( .* ) $ / mg. exec ( stderr ) ;
108196 report = analysis ? analysis [ 1 ] : stderr ;
109197 }
@@ -119,7 +207,37 @@ function karmaRun(bannerWidth) {
119207 } ) ;
120208} ;
121209
210+ var yargsOptionDefiniton = {
211+ key : 'karmareporter' ,
212+ value : {
213+ describe : 'Specify a custom Karma reporter to use. ' +
214+ 'Either a locally npm installed module, or an asolute path to one.' ,
215+ alias : [ 'k' ] ,
216+ default : defaultReporterName ,
217+ string :true ,
218+ }
219+ } ;
220+ var checkKarmaReporter = yargs . createCheck ( )
221+ . withGate ( function ( argv ) {
222+ return ! argv . help ;
223+ } )
224+ . withTest ( {
225+ karmareporter : function ( value ) {
226+ if ( typeof value !== 'undefined' ) {
227+ try {
228+ getKarmaReporterPluginPath ( value ) ;
229+ }
230+ catch ( ex ) {
231+ return 'Illegal value for "reporter"\n' + ex ;
232+ }
233+ }
234+ } ,
235+ } )
236+ . commit ( ) ;
237+
122238module . exports = {
123239 createConfig : karmaCreateConfig ,
124- run : karmaRun
240+ run : karmaRun ,
241+ yargsCheck : checkKarmaReporter ,
242+ yargsOption : yargsOptionDefiniton ,
125243} ;
0 commit comments