1
1
var q = require ( 'q' ) ;
2
- var promise = require ( 'selenium-webdriver' ) . promise ;
3
2
4
3
/**
5
4
* Execute the Runner's test cases through Mocha.
@@ -21,14 +20,56 @@ exports.run = function(runner, specs) {
21
20
// wait until then to load mocha-webdriver adapters as well.
22
21
mocha . suite . on ( 'pre-require' , function ( ) {
23
22
try {
24
- global . after = wrapped ( global . after ) ;
25
- global . afterEach = wrapped ( global . afterEach ) ;
26
- global . before = wrapped ( global . before ) ;
27
- global . beforeEach = wrapped ( global . beforeEach ) ;
28
-
29
- global . it = wrapped ( global . it ) ;
30
- global . it . only = wrapped ( global . iit ) ;
31
- global . it . skip = wrapped ( global . xit ) ;
23
+ // We need to re-wrap all of the global functions, which `selenium-webdriver/testing` only
24
+ // does when it is required. So first we must remove it from the cache.
25
+ delete require . cache [ require . resolve ( 'selenium-webdriver/testing' ) ] ;
26
+ var seleniumAdapter = require ( 'selenium-webdriver/testing' ) ;
27
+
28
+ // Save unwrapped version
29
+ var unwrappedFns = { } ;
30
+ [ 'after' , 'afterEach' , 'before' , 'beforeEach' , 'it' , 'xit' , 'iit' ] . forEach ( function ( fnName ) {
31
+ unwrappedFns [ fnName ] = global [ fnName ] || Mocha [ fnName ] ;
32
+ } ) ;
33
+
34
+ var wrapFn = function ( seleniumWrappedFn , opt_fnName ) {
35
+ // This does not work on functions that can be nested (e.g. `describe`)
36
+ return function ( ) {
37
+ // Set globals to unwrapped version to avoid circular reference
38
+ var wrappedFns = { } ;
39
+ for ( var fnName in unwrappedFns ) {
40
+ wrappedFns [ fnName ] = global [ fnName ] ;
41
+ global [ fnName ] = unwrappedFns [ fnName ] ;
42
+ }
43
+
44
+ var args = arguments ;
45
+ // Allow before/after hooks to use names
46
+ if ( opt_fnName && ( arguments . length > 1 ) && ( seleniumWrappedFn . length < 2 ) ) {
47
+ global [ opt_fnName ] = global [ opt_fnName ] . bind ( this , args [ 0 ] ) ;
48
+ args = Array . prototype . slice . call ( arguments , 1 ) ;
49
+ }
50
+
51
+ try {
52
+ seleniumWrappedFn . apply ( this , args ) ;
53
+ } finally {
54
+ // Restore wrapped version
55
+ for ( fnName in wrappedFns ) {
56
+ global [ fnName ] = wrappedFns [ fnName ] ;
57
+ }
58
+ }
59
+ } ;
60
+ } ;
61
+
62
+ // Wrap functions
63
+ global . after = wrapFn ( seleniumAdapter . after , 'after' ) ;
64
+ global . afterEach = wrapFn ( seleniumAdapter . afterEach , 'afterEach' ) ;
65
+ global . before = wrapFn ( seleniumAdapter . before , 'before' ) ;
66
+ global . beforeEach = wrapFn ( seleniumAdapter . beforeEach , 'beforeEach' ) ;
67
+
68
+ global . it = wrapFn ( seleniumAdapter . it ) ;
69
+ global . iit = wrapFn ( seleniumAdapter . it . only ) ;
70
+ global . xit = wrapFn ( seleniumAdapter . xit ) ;
71
+ global . it . only = wrapFn ( seleniumAdapter . it . only ) ;
72
+ global . it . skip = wrapFn ( seleniumAdapter . it . skip ) ;
32
73
} catch ( err ) {
33
74
deferred . reject ( err ) ;
34
75
}
@@ -97,112 +138,3 @@ exports.run = function(runner, specs) {
97
138
98
139
return deferred . promise ;
99
140
} ;
100
-
101
-
102
-
103
- var flow = ( function ( ) {
104
- var initial = process . env [ 'SELENIUM_PROMISE_MANAGER' ] ;
105
- try {
106
- process . env [ 'SELENIUM_PROMISE_MANAGER' ] = '1' ;
107
- return promise . controlFlow ( ) ;
108
- } finally {
109
- if ( initial === undefined ) {
110
- delete process . env [ 'SELENIUM_PROMISE_MANAGER' ] ;
111
- } else {
112
- process . env [ 'SELENIUM_PROMISE_MANAGER' ] = initial ;
113
- }
114
- }
115
- } ) ( ) ;
116
-
117
- /**
118
- * Wraps a function on Mocha's BDD interface so it runs inside a
119
- * webdriver.promise.ControlFlow and waits for the flow to complete before
120
- * continuing.
121
- * @param {!Function } globalFn The function to wrap.
122
- * @return {!Function } The new function.
123
- */
124
- function wrapped ( globalFn ) {
125
- return function ( ) {
126
- if ( arguments . length === 1 ) {
127
- return globalFn ( makeAsyncTestFn ( arguments [ 0 ] ) ) ;
128
-
129
- } else if ( arguments . length === 2 ) {
130
- return globalFn ( arguments [ 0 ] , makeAsyncTestFn ( arguments [ 1 ] ) ) ;
131
-
132
- } else {
133
- throw Error ( 'Invalid # arguments: ' + arguments . length ) ;
134
- }
135
- } ;
136
- }
137
-
138
- /**
139
- * Wraps a function so that all passed arguments are ignored.
140
- * @param {!Function } fn The function to wrap.
141
- * @return {!Function } The wrapped function.
142
- */
143
- function seal ( fn ) {
144
- return function ( ) {
145
- fn ( ) ;
146
- } ;
147
- }
148
-
149
- /**
150
- * Make a wrapper to invoke caller's test function, fn. Run the test function
151
- * within a ControlFlow.
152
- *
153
- * Should preserve the semantics of Mocha's Runnable.prototype.run (See
154
- * https://github.com/mochajs/mocha/blob/master/lib/runnable.js#L192)
155
- *
156
- * @param {!Function } fn
157
- * @return {!Function }
158
- */
159
- function makeAsyncTestFn ( fn ) {
160
- var isAsync = fn . length > 0 ;
161
- var isGenerator = promise . isGenerator ( fn ) ;
162
- if ( isAsync && isGenerator ) {
163
- throw new TypeError (
164
- 'generator-based tests must not take a callback; for async testing,'
165
- + ' return a promise (or yield on a promise)' ) ;
166
- }
167
-
168
- var ret = /** @type {function(this: mocha.Context) }*/ function ( done ) {
169
- var self = this ;
170
- var runTest = function ( resolve , reject ) {
171
- try {
172
- if ( self . isAsync ) {
173
- fn . call ( self , function ( err ) { err ? reject ( err ) : resolve ( ) ; } ) ;
174
- } else if ( self . isGenerator ) {
175
- resolve ( promise . consume ( fn , self ) ) ;
176
- } else {
177
- resolve ( fn . call ( self ) ) ;
178
- }
179
- } catch ( ex ) {
180
- reject ( ex ) ;
181
- }
182
- } ;
183
-
184
- if ( ! promise . USE_PROMISE_MANAGER ) {
185
- new promise . Promise ( runTest ) . then ( seal ( done ) , done ) ;
186
- return ;
187
- }
188
-
189
- var runnable = this . runnable ( ) ;
190
- var mochaCallback = runnable . callback ;
191
- runnable . callback = function ( ) {
192
- flow . reset ( ) ;
193
- return mochaCallback . apply ( this , arguments ) ;
194
- } ;
195
-
196
- flow . execute ( function controlFlowExecute ( ) {
197
- return new promise . Promise ( function ( fulfill , reject ) {
198
- return runTest ( fulfill , reject ) ;
199
- } , flow ) ;
200
- } , runnable . fullTitle ( ) ) . then ( seal ( done ) , done ) ;
201
- } ;
202
-
203
- ret . toString = function ( ) {
204
- return fn . toString ( ) ;
205
- } ;
206
-
207
- return ret ;
208
- }
0 commit comments