1
+ var path = require ( 'path' ) ,
2
+ glob = require ( 'glob' ) ,
3
+ config_ = {
4
+ configDir : './' ,
5
+ jasmineNodeOpts : { }
6
+ } ,
7
+ //this allows for ease of maintaining public apis of the config while still
8
+ // allowing for easy variable renames or future config api changes while
9
+ // supported backwards compatibility
10
+ configMap_ = {
11
+
12
+ //structure is internal name -> supported config apis
13
+ 'specs' : [ 'specs' ] ,
14
+ 'exclude' : [ 'exclude' ] ,
15
+ 'capabilities' : [ 'capabilities' ] ,
16
+ 'seleniumHost' : [ 'seleniumAddress' ] ,
17
+ 'rootElement' : [ 'rootElement' ] ,
18
+ 'baseUrl' : [ 'baseUrl' ] ,
19
+ 'timeout' : [ 'allScriptsTimeout' ] ,
20
+ 'browserParams' : [ 'params' ] ,
21
+ 'framework' : [ 'framework' ] ,
22
+ 'jasmineOpts' : [ 'jasmineNodeOpts' ] ,
23
+ 'mochaOpts' : [ 'mochaOpts' ] ,
24
+ 'seleniumLocal.jar' : [ 'seleniumServerJar' ] ,
25
+ 'seleniumLocal.args' : [ 'seleniumArgs' ] ,
26
+ 'seleniumLocal.port' : [ 'seleniumPort' ] ,
27
+ 'sauceAccount.user' : [ 'sauceUser' ] ,
28
+ 'sauceAccount.key' : [ 'sauceKey' ] ,
29
+ 'chromeDriver' : [ 'chromeDriver' ] ,
30
+ 'chromeOnly' : [ 'chromeOnly' ] ,
31
+ 'configDir' : [ 'configDir' ] ,
32
+ 'cucumberOpts.require' : [ 'cucumberOpts.require' ] ,
33
+ 'cucumberOpts.format' : [ 'cucumberOpts.format' ] ,
34
+ 'cucumberOpts.tags' : [ 'cucumberOpts.tags' ]
35
+ } ;
36
+
37
+ /**
38
+ * Merge config objects together.
39
+ *
40
+ * @private
41
+ * @param {Object } into
42
+ * @param {Object } from
43
+ *
44
+ * @return {Object } The 'into' config.
45
+ */
46
+ var merge_ = function ( into , from ) {
47
+ for ( var key in from ) {
48
+ if ( into [ key ] instanceof Object && ! ( into [ key ] instanceof Array ) ) {
49
+ merge_ ( into [ key ] , from [ key ] ) ;
50
+ } else {
51
+ into [ key ] = from [ key ] ;
52
+ }
53
+ }
54
+ return into ;
55
+ } ;
56
+
57
+ /**
58
+ * Resolve a list of file patterns into a list of individual file paths.
59
+ *
60
+ * @param {Array/String } patterns
61
+ * @param {Boolean } opt_omitWarnings whether to omit did not match warnings
62
+ *
63
+ * @return {Array } The resolved file paths.
64
+ */
65
+ var resolveFilePatterns = function ( patterns , opt_omitWarnings ) {
66
+ var resolvedFiles = [ ] ;
67
+
68
+ patterns = ( typeof patterns === 'string' ) ?
69
+ [ patterns ] : patterns ;
70
+
71
+ if ( patterns ) {
72
+ for ( var i = 0 ; i < patterns . length ; ++ i ) {
73
+ var matches = glob . sync ( patterns [ i ] , { cwd : config_ . configDir } ) ;
74
+ if ( ! matches . length && ! opt_omitWarnings ) {
75
+ util . puts ( 'Warning: pattern ' + patterns [ i ] + ' did not match any files.' ) ;
76
+ }
77
+ for ( var j = 0 ; j < matches . length ; ++ j ) {
78
+ resolvedFiles . push ( path . resolve ( config_ . configDir , matches [ j ] ) ) ;
79
+ }
80
+ }
81
+ }
82
+ return resolvedFiles ;
83
+ } ;
84
+
85
+ /**
86
+ * Helper to resolve file pattern strings relative to the cwd
87
+ *
88
+ * @private
89
+ * @param {Array } list
90
+ */
91
+ var processFilePatterns_ = function ( list ) {
92
+ var patterns = list . split ( ',' ) ;
93
+ patterns . forEach ( function ( spec , index , arr ) {
94
+ arr [ index ] = path . resolve ( process . cwd ( ) , spec ) ;
95
+ } ) ;
96
+ return patterns ;
97
+ } ;
98
+
99
+ /**
100
+ * Add the options in the parameter config to this runner instance.
101
+ *
102
+ * @private
103
+ * @param {Object } additionalConfig
104
+ */
105
+ var addConfig_ = function ( additionalConfig ) {
106
+ // All filepaths should be kept relative to the current config location.
107
+ // This will not affect absolute paths.
108
+ [ 'seleniumServerJar' , 'chromeDriver' , 'onPrepare' ] . forEach ( function ( name ) {
109
+ if ( additionalConfig [ name ] && additionalConfig . configDir &&
110
+ typeof additionalConfig [ name ] === 'string' ) {
111
+ additionalConfig [ name ] =
112
+ path . resolve ( additionalConfig . configDir , additionalConfig [ name ] ) ;
113
+ }
114
+ } ) ;
115
+
116
+ // Make sure they're not trying to add in deprecated config vals
117
+ if ( additionalConfig . jasmineNodeOpts &&
118
+ additionalConfig . jasmineNodeOpts . specFolders ) {
119
+ throw new Error ( 'Using config.jasmineNodeOpts.specFolders is deprecated ' +
120
+ 'since Protractor 0.6.0. Please switch to config.specs.' ) ;
121
+ }
122
+ merge_ ( config_ , additionalConfig ) ;
123
+ } ;
124
+
125
+
126
+ /**
127
+ * Merges in passed in configuration data with existing class defaults
128
+ * @public
129
+ * @param {Object } config - A set of properties collected that will be merged
130
+ * with AbstractTestRunner defaults
131
+ */
132
+ var loadConfig = function ( configObj , configToLoad ) {
133
+
134
+ if ( ! configToLoad || ! configObj ) {
135
+ return ;
136
+ }
137
+
138
+ /* helper to set the correct value for string dot notation */
139
+ function setConfig_ ( obj , str , val ) {
140
+ str = str . split ( '.' ) ;
141
+ while ( str . length > 1 ) {
142
+ obj = obj [ str . shift ( ) ] ;
143
+ }
144
+ obj [ str . shift ( ) ] = val ;
145
+ }
146
+
147
+ /* helper to retrieve the correct value for string dot notation */
148
+ function getConfig_ ( obj , str ) {
149
+ var arr = str . split ( "." ) ;
150
+ while ( arr . length && ( obj = obj [ arr . shift ( ) ] ) ) ;
151
+ return obj ;
152
+ }
153
+
154
+ /* helper to determine whether a config value is empty based on type */
155
+ function isEmpty_ ( val ) {
156
+ return ( val !== null &&
157
+ val !== '' &&
158
+ val !== undefined &&
159
+ ! ( val instanceof Array &&
160
+ ! val . length ) &&
161
+ ! ( val instanceof Object &&
162
+ ! Object . keys ( val ) . length )
163
+ ) ;
164
+ }
165
+
166
+ //object definition driven merging
167
+ var key , configDef , configAlias , i ;
168
+ for ( key in configMap_ ) {
169
+
170
+ configDef = configMap_ [ key ] ;
171
+ for ( i = 0 ; i < configDef . length ; i ++ ) {
172
+ configAlias = configDef [ i ] ;
173
+ var configVal = getConfig_ ( configToLoad , configAlias ) ;
174
+ if ( isEmpty_ ( configVal ) ) {
175
+ //override config default w/ passed in config
176
+ setConfig_ ( configObj , key , configVal ) ;
177
+ }
178
+ }
179
+ }
180
+ } ;
181
+
182
+
183
+
184
+
185
+ /**
186
+ * Public function specialized towards merging in a file's config
187
+ *
188
+ * @public
189
+ * @param {String } filename
190
+ */
191
+ var addFileConfig = function ( filename ) {
192
+ if ( ! filename ) {
193
+ return ;
194
+ }
195
+ var filePath = path . resolve ( process . cwd ( ) , filename ) ;
196
+ var fileConfig = require ( filePath ) . config ;
197
+ fileConfig . configDir = path . dirname ( filePath ) ;
198
+ addConfig_ ( fileConfig ) ;
199
+ } ;
200
+
201
+
202
+ /**
203
+ * Public function specialized towards merging in config from argv
204
+ *
205
+ * @public
206
+ * @param {Object } argv
207
+ */
208
+ var addArgvConfig = function ( argv ) {
209
+ if ( ! argv ) {
210
+ return ;
211
+ }
212
+ // Interpret/parse spec include/exclude patterns
213
+ if ( argv . specs ) {
214
+ argv . specs = processFilePatterns_ ( argv . specs ) ;
215
+ }
216
+ if ( argv . exclude ) {
217
+ argv . exclude = processFilePatterns ( argv . exclude ) ;
218
+ }
219
+
220
+ addConfig_ ( argv ) ;
221
+ } ;
222
+
223
+
224
+ /**
225
+ * Public getter for the final, computed config object
226
+ *
227
+ * @public
228
+ * @return {Object } config
229
+ */
230
+ var getConfig = function ( ) {
231
+ return config_ ;
232
+ } ;
233
+
234
+
235
+ exports . addArgvConfig = addArgvConfig ;
236
+ exports . addFileConfig = addFileConfig ;
237
+ exports . getConfig = getConfig ;
238
+ exports . loadConfig = loadConfig ;
239
+ exports . resolveFilePatterns = resolveFilePatterns ;
0 commit comments