Index: trunk/phase3/resources/jquery/jquery.qunit.completenessTest.js |
— | — | @@ -46,32 +46,55 @@ |
47 | 47 | this.lazyLimit = 1000; |
48 | 48 | this.lazyCounter = 0; |
49 | 49 | |
| 50 | + var that = this; |
| 51 | + |
50 | 52 | // Bind begin and end to QUnit. |
51 | | - var that = this; |
52 | 53 | QUnit.begin = function(){ |
53 | 54 | that.checkTests( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_INJECT ); |
54 | 55 | }; |
| 56 | + |
55 | 57 | QUnit.done = function(){ |
56 | 58 | that.checkTests( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_CHECK ); |
57 | 59 | console.log( 'CompletenessTest.ACTION_CHECK', that ); |
58 | 60 | |
59 | | - // Insert HTML into header |
| 61 | + // Build HTML representing the outcome from CompletenessTest |
| 62 | + // And insert it into the header. |
60 | 63 | |
61 | 64 | var makeList = function( blob, title, style ) { |
62 | 65 | title = title || 'Values'; |
63 | | - var html = '<div style="'+style+'">' |
64 | | - + '<strong>' + mw.html.escape(title) + '</strong>'; |
| 66 | + var html = '<strong>' + mw.html.escape(title) + '</strong>'; |
65 | 67 | $.each( blob, function( key ) { |
66 | 68 | html += '<br />' + mw.html.escape(key); |
67 | 69 | }); |
68 | | - return html + '<br /><br /><em>— CompletenessTest</em></div>'; |
| 70 | + html += '<br /><br /><em>— CompletenessTest</em>'; |
| 71 | + return $( '<div>' ).css( style ).append( html ); |
69 | 72 | }; |
70 | | - if ( $.isEmptyObject( that.missingTests ) ) { |
71 | | - var testResults = makeList( { 'No missing tests!': true }, 'missingTests', 'background: #D2E0E6; color: #366097; padding:1em' ); |
| 73 | + |
| 74 | + if ( $.isEmptyObject( that.missingTests ) ) { |
| 75 | + // Good |
| 76 | + var $testResults = makeList( |
| 77 | + { 'No missing tests!': true }, |
| 78 | + 'missingTests', |
| 79 | + { |
| 80 | + background: '#D2E0E6', |
| 81 | + color: '#366097', |
| 82 | + padding: '1em' |
| 83 | + } |
| 84 | + ); |
72 | 85 | } else { |
73 | | - var testResults = makeList( that.missingTests, 'missingTests', 'background: #EE5757; color: black; padding: 1em' ); |
| 86 | + // Bad |
| 87 | + var $testResults = makeList( |
| 88 | + that.missingTests, |
| 89 | + 'missingTests', |
| 90 | + { |
| 91 | + background: '#EE5757', |
| 92 | + color: 'black', |
| 93 | + padding: '1em' |
| 94 | + } |
| 95 | + ); |
74 | 96 | } |
75 | | - $( '#qunit-testrunner-toolbar' ).prepend( testResults ); |
| 97 | + |
| 98 | + $( '#qunit-testrunner-toolbar' ).prepend( $testResults ); |
76 | 99 | }; |
77 | 100 | |
78 | 101 | return this; |
— | — | @@ -87,11 +110,18 @@ |
88 | 111 | /** |
89 | 112 | * CompletenessTest.fn.checkTests |
90 | 113 | * |
91 | | - * @param currName {String} |
92 | | - * @param currVar {mixed} |
93 | | - * @param masterVariable {Object} |
94 | | - * @param parentPathArray {Array} |
95 | | - * @param action {Number} What action is checkTests commanded to do ? |
| 114 | + * This function recursively walks through the given object, calling itself as it goes. |
| 115 | + * Depending on the action it either injects our listener into the methods, or |
| 116 | + * reads from our tracker and records which methods have not been called by the test suite. |
| 117 | + * |
| 118 | + * @param currName {String|Null} Name of the given object member (Initially this is null). |
| 119 | + * @param currVar {mixed} The variable to check (initially an object, |
| 120 | + * further down it could be anything). |
| 121 | + * @param masterVariable {Object} Throughout our interation, always keep track of the master/root. |
| 122 | + * Initially this is the same as currVar. |
| 123 | + * @param parentPathArray {Array} Array of names that indicate our breadcrumb path starting at |
| 124 | + * masterVariable. Not including currName. |
| 125 | + * @param action {Number} What is this function supposed to do (ACTION_INJECT or ACTION_CHECK) |
96 | 126 | */ |
97 | 127 | checkTests: function( currName, currVar, masterVariable, parentPathArray, action ) { |
98 | 128 | |
— | — | @@ -107,8 +137,8 @@ |
108 | 138 | |
109 | 139 | // Hard ignores |
110 | 140 | if ( this.ignoreFn( currVar, that, parentPathArray ) ) { |
| 141 | + return null; |
111 | 142 | |
112 | | - |
113 | 143 | // Functions |
114 | 144 | } else if ( type === 'function' ) { |
115 | 145 | |
— | — | @@ -127,14 +157,14 @@ |
128 | 158 | $.each( currVar.prototype, function( key, value ) { |
129 | 159 | |
130 | 160 | // Clone and brake reference to parentPathArray |
131 | | - var tmpPathArray = $.extend([], parentPathArray); |
132 | | - tmpPathArray.push('prototype'); tmpPathArray.push(key); |
| 161 | + var tmpPathArray = $.extend( [], parentPathArray ); |
| 162 | + tmpPathArray.push( 'prototype' ); tmpPathArray.push( key ); |
133 | 163 | |
134 | 164 | that.hasTest( tmpPathArray.join( '.' ) ); |
135 | 165 | } ); |
136 | 166 | } |
137 | 167 | |
138 | | - /* INJET MODE */ |
| 168 | + /* INJECT MODE */ |
139 | 169 | |
140 | 170 | } else if ( action === CompletenessTest.ACTION_INJECT ) { |
141 | 171 | |
— | — | @@ -154,14 +184,14 @@ |
155 | 185 | $.each( currVar.prototype, function( key, value ) { |
156 | 186 | |
157 | 187 | // Clone and brake reference to parentPathArray |
158 | | - var tmpPathArray = $.extend([], parentPathArray); |
159 | | - tmpPathArray.push('prototype'); tmpPathArray.push(key); |
| 188 | + var tmpPathArray = $.extend( [], parentPathArray ); |
| 189 | + tmpPathArray.push( 'prototype' ); tmpPathArray.push( key ); |
160 | 190 | |
161 | 191 | that.checkTests( key, value, masterVariable, tmpPathArray, action ); |
162 | 192 | } ); |
163 | 193 | } |
164 | 194 | |
165 | | - } //else { } |
| 195 | + } |
166 | 196 | |
167 | 197 | // Recursively. After all, this *is* the completness test |
168 | 198 | } else if ( type === 'object' ) { |
— | — | @@ -169,14 +199,14 @@ |
170 | 200 | $.each( currVar, function( key, value ) { |
171 | 201 | |
172 | 202 | // Clone and brake reference to parentPathArray |
173 | | - var tmpPathArray = $.extend([], parentPathArray); |
174 | | - tmpPathArray.push(key); |
| 203 | + var tmpPathArray = $.extend( [], parentPathArray ); |
| 204 | + tmpPathArray.push( key ); |
175 | 205 | |
176 | 206 | that.checkTests( key, value, masterVariable, tmpPathArray, action ); |
177 | 207 | |
178 | 208 | } ); |
179 | 209 | |
180 | | - } // else { } |
| 210 | + } |
181 | 211 | |
182 | 212 | return 'End of checkTests'; |
183 | 213 | }, |
— | — | @@ -184,27 +214,37 @@ |
185 | 215 | /** |
186 | 216 | * CompletenessTest.fn.hasTest |
187 | 217 | * |
| 218 | + * Checks if the given method name (ie. 'my.foo.bar') |
| 219 | + * was called during the test suite (as far as the tracker knows). |
| 220 | + * If so it adds it to missingTests. |
| 221 | + * |
188 | 222 | * @param fnName {String} |
| 223 | + * @return {Boolean} |
189 | 224 | */ |
190 | 225 | hasTest: function( fnName ) { |
191 | 226 | if ( !(fnName in this.methodCallTracker) ) { |
192 | 227 | this.missingTests[fnName] = true; |
| 228 | + return false; |
193 | 229 | } |
| 230 | + return true; |
194 | 231 | }, |
195 | 232 | |
196 | 233 | /** |
197 | 234 | * CompletenessTest.fn.injectCheck |
198 | 235 | * |
| 236 | + * Injects a function (such as a spy that updates methodCallTracker when |
| 237 | + * it's called) inside another function. |
| 238 | + * |
199 | 239 | * @param masterVariable {Object} |
200 | 240 | * @param objectPathArray {Array} |
201 | 241 | * @param injectFn {Function} |
202 | 242 | */ |
203 | | - injectCheck: function( masterVariable, objectPathArray, injectFn, functionType ) { |
| 243 | + injectCheck: function( masterVariable, objectPathArray, injectFn ) { |
204 | 244 | var prev, |
205 | 245 | curr = masterVariable, |
206 | 246 | lastMember; |
207 | 247 | |
208 | | - $.each(objectPathArray, function(i, memberName){ |
| 248 | + $.each( objectPathArray, function(i, memberName){ |
209 | 249 | prev = curr; |
210 | 250 | curr = prev[memberName]; |
211 | 251 | lastMember = memberName; |
— | — | @@ -213,7 +253,7 @@ |
214 | 254 | // Objects are by reference, members (unless objects) are not. |
215 | 255 | prev[lastMember] = function(){ |
216 | 256 | injectFn(); |
217 | | - return curr.apply(this, arguments ); |
| 257 | + return curr.apply( this, arguments ); |
218 | 258 | }; |
219 | 259 | } |
220 | 260 | }; |