OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** @fileoverview Runs the Polymer Password Settings tests. */ | 5 /** @fileoverview Runs the Polymer Password Settings tests. */ |
6 | 6 |
7 /** @const {string} Path to root from chrome/test/data/webui/settings/. */ | 7 /** @const {string} Path to root from chrome/test/data/webui/settings/. */ |
8 var ROOT_PATH = '../../../../../'; | 8 var ROOT_PATH = '../../../../../'; |
9 | 9 |
10 // Polymer BrowserTest fixture. | 10 // Polymer BrowserTest fixture. |
11 GEN_INCLUDE( | 11 GEN_INCLUDE( |
12 [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); | 12 [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); |
13 | 13 |
| 14 // Fake data generator. |
| 15 GEN_INCLUDE([ROOT_PATH + |
| 16 'chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js']); |
| 17 |
14 /** | 18 /** |
15 * @constructor | 19 * @constructor |
16 * @extends {PolymerTest} | 20 * @extends {PolymerTest} |
17 */ | 21 */ |
18 function SettingsPasswordSectionBrowserTest() {} | 22 function SettingsPasswordSectionBrowserTest() {} |
19 | 23 |
20 SettingsPasswordSectionBrowserTest.prototype = { | 24 SettingsPasswordSectionBrowserTest.prototype = { |
21 __proto__: PolymerTest.prototype, | 25 __proto__: PolymerTest.prototype, |
22 | 26 |
23 /** @override */ | 27 /** @override */ |
24 browsePreload: | 28 browsePreload: |
25 'chrome://md-settings/passwords_and_forms_page/passwords_section.html', | 29 'chrome://md-settings/passwords_and_forms_page/passwords_section.html', |
26 | 30 |
27 /** @override */ | 31 /** @override */ |
28 extraLibraries: PolymerTest.getLibraries(ROOT_PATH), | 32 extraLibraries: PolymerTest.getLibraries(ROOT_PATH), |
29 | 33 |
30 /** @override */ | 34 /** @override */ |
31 setUp: function() { | 35 setUp: function() { |
32 PolymerTest.prototype.setUp.call(this); | 36 PolymerTest.prototype.setUp.call(this); |
33 | 37 |
34 // Test is run on an individual element that won't have a page language. | 38 // Test is run on an individual element that won't have a page language. |
35 this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); | 39 this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); |
36 }, | 40 }, |
37 | 41 |
38 /** | 42 /** |
39 * Creates a single item for the list of passwords. | |
40 * @param {string} url | |
41 * @param {string} username | |
42 * @param {number} passwordLength | |
43 * @return {chrome.passwordsPrivate.PasswordUiEntry} | |
44 * @private | |
45 */ | |
46 createPasswordItem_: function(url, username, passwordLength) { | |
47 return { | |
48 loginPair: {originUrl: url, username: username}, | |
49 linkUrl: 'http://' + url + '/login', | |
50 numCharactersInPassword: passwordLength | |
51 }; | |
52 }, | |
53 | |
54 /** | |
55 * Creates a single item for the list of password exceptions. | |
56 * @param {string} url | |
57 * @return {chrome.passwordsPrivate.ExceptionPair} | |
58 * @private | |
59 */ | |
60 createExceptionItem_: function(url) { | |
61 return { | |
62 exceptionUrl: url, | |
63 linkUrl: 'http://' + url + '/login', | |
64 }; | |
65 }, | |
66 | |
67 /** | |
68 * Helper method that validates a that elements in the password list match | 43 * Helper method that validates a that elements in the password list match |
69 * the expected data. | 44 * the expected data. |
70 * @param {!Array<!Element>} nodes The nodes that will be checked. | 45 * @param {!Array<!Element>} nodes The nodes that will be checked. |
71 * @param {!Array<!chrome.passwordsPrivate.PasswordUiEntry>} passwordList The | 46 * @param {!Array<!chrome.passwordsPrivate.PasswordUiEntry>} passwordList The |
72 * expected data. | 47 * expected data. |
73 * @private | 48 * @private |
74 */ | 49 */ |
75 validatePasswordList: function(nodes, passwordList) { | 50 validatePasswordList: function(nodes, passwordList) { |
76 assertEquals(passwordList.length, nodes.length); | 51 assertEquals(passwordList.length, nodes.length); |
77 for (var index = 0; index < passwordList.length; ++index) { | 52 for (var index = 0; index < passwordList.length; ++index) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 * This test will validate that the section is loaded with data. | 168 * This test will validate that the section is loaded with data. |
194 */ | 169 */ |
195 TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { | 170 TEST_F('SettingsPasswordSectionBrowserTest', 'uiTests', function() { |
196 var self = this; | 171 var self = this; |
197 | 172 |
198 suite('PasswordsSection', function() { | 173 suite('PasswordsSection', function() { |
199 test('verifySavedPasswordLength', function() { | 174 test('verifySavedPasswordLength', function() { |
200 assertEquals(self.browsePreload, document.location.href); | 175 assertEquals(self.browsePreload, document.location.href); |
201 | 176 |
202 var passwordList = [ | 177 var passwordList = [ |
203 self.createPasswordItem_('site1.com', 'luigi', 1), | 178 FakeDataMaker.passwordEntry('site1.com', 'luigi', 1), |
204 self.createPasswordItem_('longwebsite.com', 'peach', 7), | 179 FakeDataMaker.passwordEntry('longwebsite.com', 'peach', 7), |
205 self.createPasswordItem_('site2.com', 'mario', 70), | 180 FakeDataMaker.passwordEntry('site2.com', 'mario', 70), |
206 self.createPasswordItem_('site1.com', 'peach', 11), | 181 FakeDataMaker.passwordEntry('site1.com', 'peach', 11), |
207 self.createPasswordItem_('google.com', 'mario', 7), | 182 FakeDataMaker.passwordEntry('google.com', 'mario', 7), |
208 self.createPasswordItem_('site2.com', 'luigi', 8), | 183 FakeDataMaker.passwordEntry('site2.com', 'luigi', 8), |
209 ]; | 184 ]; |
210 | 185 |
211 var passwordsSection = self.createPasswordsSection_(passwordList, []); | 186 var passwordsSection = self.createPasswordsSection_(passwordList, []); |
212 | 187 |
213 // Assert that the data is passed into the iron list. If this fails, | 188 // Assert that the data is passed into the iron list. If this fails, |
214 // then other expectations will also fail. | 189 // then other expectations will also fail. |
215 assertEquals(passwordList, passwordsSection.$.passwordList.items); | 190 assertEquals(passwordList, passwordsSection.$.passwordList.items); |
216 | 191 |
217 self.validatePasswordList( | 192 self.validatePasswordList( |
218 self.getIronListChildren_(passwordsSection.$.passwordList), | 193 self.getIronListChildren_(passwordsSection.$.passwordList), |
219 passwordList); | 194 passwordList); |
220 }); | 195 }); |
221 | 196 |
222 // Test verifies that removing a password will update the elements. | 197 // Test verifies that removing a password will update the elements. |
223 test('verifyPasswordListRemove', function() { | 198 test('verifyPasswordListRemove', function() { |
224 var passwordList = [ | 199 var passwordList = [ |
225 self.createPasswordItem_('anotherwebsite.com', 'luigi', 1), | 200 FakeDataMaker.passwordEntry('anotherwebsite.com', 'luigi', 1), |
226 self.createPasswordItem_('longwebsite.com', 'peach', 7), | 201 FakeDataMaker.passwordEntry('longwebsite.com', 'peach', 7), |
227 self.createPasswordItem_('website.com', 'mario', 70) | 202 FakeDataMaker.passwordEntry('website.com', 'mario', 70) |
228 ]; | 203 ]; |
229 | 204 |
230 var passwordsSection = self.createPasswordsSection_(passwordList, []); | 205 var passwordsSection = self.createPasswordsSection_(passwordList, []); |
231 | 206 |
232 self.validatePasswordList( | 207 self.validatePasswordList( |
233 self.getIronListChildren_(passwordsSection.$.passwordList), | 208 self.getIronListChildren_(passwordsSection.$.passwordList), |
234 passwordList); | 209 passwordList); |
235 // Simulate 'longwebsite.com' being removed from the list. | 210 // Simulate 'longwebsite.com' being removed from the list. |
236 passwordsSection.splice('savedPasswords', 1, 1); | 211 passwordsSection.splice('savedPasswords', 1, 1); |
237 self.flushPasswordSection_(passwordsSection); | 212 self.flushPasswordSection_(passwordsSection); |
238 | 213 |
239 assertFalse(self.listContainsUrl(passwordsSection.savedPasswords, | 214 assertFalse(self.listContainsUrl(passwordsSection.savedPasswords, |
240 'longwebsite.com')); | 215 'longwebsite.com')); |
241 assertFalse(self.listContainsUrl(passwordList, 'longwebsite.com')); | 216 assertFalse(self.listContainsUrl(passwordList, 'longwebsite.com')); |
242 | 217 |
243 self.validatePasswordList( | 218 self.validatePasswordList( |
244 self.getIronListChildren_(passwordsSection.$.passwordList), | 219 self.getIronListChildren_(passwordsSection.$.passwordList), |
245 passwordList); | 220 passwordList); |
246 }); | 221 }); |
247 | 222 |
248 // Test verifies that pressing the 'remove' button will trigger a remove | 223 // Test verifies that pressing the 'remove' button will trigger a remove |
249 // event. Does not actually remove any passwords. | 224 // event. Does not actually remove any passwords. |
250 test('verifyPasswordItemRemoveButton', function(done) { | 225 test('verifyPasswordItemRemoveButton', function(done) { |
251 var passwordList = [ | 226 var passwordList = [ |
252 self.createPasswordItem_('one', 'six', 5), | 227 FakeDataMaker.passwordEntry('one', 'six', 5), |
253 self.createPasswordItem_('two', 'five', 3), | 228 FakeDataMaker.passwordEntry('two', 'five', 3), |
254 self.createPasswordItem_('three', 'four', 1), | 229 FakeDataMaker.passwordEntry('three', 'four', 1), |
255 self.createPasswordItem_('four', 'three', 2), | 230 FakeDataMaker.passwordEntry('four', 'three', 2), |
256 self.createPasswordItem_('five', 'two', 4), | 231 FakeDataMaker.passwordEntry('five', 'two', 4), |
257 self.createPasswordItem_('six', 'one', 6), | 232 FakeDataMaker.passwordEntry('six', 'one', 6), |
258 ]; | 233 ]; |
259 | 234 |
260 var passwordsSection = self.createPasswordsSection_(passwordList, []); | 235 var passwordsSection = self.createPasswordsSection_(passwordList, []); |
261 | 236 |
262 var passwords = | 237 var passwords = |
263 self.getIronListChildren_(passwordsSection.$.passwordList); | 238 self.getIronListChildren_(passwordsSection.$.passwordList); |
264 | 239 |
265 // The index of the button currently being checked. | 240 // The index of the button currently being checked. |
266 var index = 0; | 241 var index = 0; |
267 | 242 |
(...skipping 20 matching lines...) Expand all Loading... |
288 done(); | 263 done(); |
289 } | 264 } |
290 }); | 265 }); |
291 | 266 |
292 // Start removing. | 267 // Start removing. |
293 clickRemoveButton(); | 268 clickRemoveButton(); |
294 }); | 269 }); |
295 | 270 |
296 test('verifyPasswordExceptions', function() { | 271 test('verifyPasswordExceptions', function() { |
297 var exceptionList = [ | 272 var exceptionList = [ |
298 self.createExceptionItem_('docs.google.com'), | 273 FakeDataMaker.exceptionEntry('docs.google.com'), |
299 self.createExceptionItem_('mail.com'), | 274 FakeDataMaker.exceptionEntry('mail.com'), |
300 self.createExceptionItem_('google.com'), | 275 FakeDataMaker.exceptionEntry('google.com'), |
301 self.createExceptionItem_('inbox.google.com'), | 276 FakeDataMaker.exceptionEntry('inbox.google.com'), |
302 self.createExceptionItem_('maps.google.com'), | 277 FakeDataMaker.exceptionEntry('maps.google.com'), |
303 self.createExceptionItem_('plus.google.com'), | 278 FakeDataMaker.exceptionEntry('plus.google.com'), |
304 ]; | 279 ]; |
305 | 280 |
306 var passwordsSection = self.createPasswordsSection_([], exceptionList); | 281 var passwordsSection = self.createPasswordsSection_([], exceptionList); |
307 | 282 |
308 // Assert that the data is passed into the iron list. If this fails, | 283 // Assert that the data is passed into the iron list. If this fails, |
309 // then other expectations will also fail. | 284 // then other expectations will also fail. |
310 assertEquals(exceptionList, | 285 assertEquals(exceptionList, |
311 passwordsSection.$.passwordExceptionsList.items); | 286 passwordsSection.$.passwordExceptionsList.items); |
312 | 287 |
313 self.validateExceptionList_( | 288 self.validateExceptionList_( |
314 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), | 289 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), |
315 exceptionList); | 290 exceptionList); |
316 }); | 291 }); |
317 | 292 |
318 // Test verifies that removing an exception will update the elements. | 293 // Test verifies that removing an exception will update the elements. |
319 test('verifyPasswordExceptionRemove', function() { | 294 test('verifyPasswordExceptionRemove', function() { |
320 var exceptionList = [ | 295 var exceptionList = [ |
321 self.createExceptionItem_('docs.google.com'), | 296 FakeDataMaker.exceptionEntry('docs.google.com'), |
322 self.createExceptionItem_('mail.com'), | 297 FakeDataMaker.exceptionEntry('mail.com'), |
323 self.createExceptionItem_('google.com'), | 298 FakeDataMaker.exceptionEntry('google.com'), |
324 self.createExceptionItem_('inbox.google.com'), | 299 FakeDataMaker.exceptionEntry('inbox.google.com'), |
325 self.createExceptionItem_('maps.google.com'), | 300 FakeDataMaker.exceptionEntry('maps.google.com'), |
326 self.createExceptionItem_('plus.google.com'), | 301 FakeDataMaker.exceptionEntry('plus.google.com'), |
327 ]; | 302 ]; |
328 | 303 |
329 var passwordsSection = self.createPasswordsSection_([], exceptionList); | 304 var passwordsSection = self.createPasswordsSection_([], exceptionList); |
330 | 305 |
331 self.validateExceptionList_( | 306 self.validateExceptionList_( |
332 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), | 307 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), |
333 exceptionList); | 308 exceptionList); |
334 | 309 |
335 // Simulate 'mail.com' being removed from the list. | 310 // Simulate 'mail.com' being removed from the list. |
336 passwordsSection.splice('passwordExceptions', 1, 1); | 311 passwordsSection.splice('passwordExceptions', 1, 1); |
337 assertFalse(self.exceptionsListContainsUrl( | 312 assertFalse(self.exceptionsListContainsUrl( |
338 passwordsSection.passwordExceptions, 'mail.com')); | 313 passwordsSection.passwordExceptions, 'mail.com')); |
339 assertFalse(self.exceptionsListContainsUrl(exceptionList, 'mail.com')); | 314 assertFalse(self.exceptionsListContainsUrl(exceptionList, 'mail.com')); |
340 self.flushPasswordSection_(passwordsSection); | 315 self.flushPasswordSection_(passwordsSection); |
341 | 316 |
342 self.validateExceptionList_( | 317 self.validateExceptionList_( |
343 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), | 318 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList), |
344 exceptionList); | 319 exceptionList); |
345 }); | 320 }); |
346 | 321 |
347 // Test verifies that pressing the 'remove' button will trigger a remove | 322 // Test verifies that pressing the 'remove' button will trigger a remove |
348 // event. Does not actually remove any exceptions. | 323 // event. Does not actually remove any exceptions. |
349 test('verifyPasswordExceptionRemoveButton', function(done) { | 324 test('verifyPasswordExceptionRemoveButton', function(done) { |
350 var exceptionList = [ | 325 var exceptionList = [ |
351 self.createExceptionItem_('docs.google.com'), | 326 FakeDataMaker.exceptionEntry('docs.google.com'), |
352 self.createExceptionItem_('mail.com'), | 327 FakeDataMaker.exceptionEntry('mail.com'), |
353 self.createExceptionItem_('google.com'), | 328 FakeDataMaker.exceptionEntry('google.com'), |
354 self.createExceptionItem_('inbox.google.com'), | 329 FakeDataMaker.exceptionEntry('inbox.google.com'), |
355 self.createExceptionItem_('maps.google.com'), | 330 FakeDataMaker.exceptionEntry('maps.google.com'), |
356 self.createExceptionItem_('plus.google.com'), | 331 FakeDataMaker.exceptionEntry('plus.google.com'), |
357 ]; | 332 ]; |
358 | 333 |
359 var passwordsSection = self.createPasswordsSection_([], exceptionList); | 334 var passwordsSection = self.createPasswordsSection_([], exceptionList); |
360 | 335 |
361 var exceptions = | 336 var exceptions = |
362 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList); | 337 self.getIronListChildren_(passwordsSection.$.passwordExceptionsList); |
363 | 338 |
364 // The index of the button currently being checked. | 339 // The index of the button currently being checked. |
365 var index = 0; | 340 var index = 0; |
366 | 341 |
(...skipping 15 matching lines...) Expand all Loading... |
382 else | 357 else |
383 done(); | 358 done(); |
384 }); | 359 }); |
385 | 360 |
386 // Start removing. | 361 // Start removing. |
387 clickRemoveButton(); | 362 clickRemoveButton(); |
388 }); | 363 }); |
389 | 364 |
390 test('usePasswordDialogTwice', function() { | 365 test('usePasswordDialogTwice', function() { |
391 var BLANK_PASSWORD = ' '; | 366 var BLANK_PASSWORD = ' '; |
392 var item = self.createPasswordItem_('google.com', 'homer', | 367 var item = FakeDataMaker.passwordEntry('google.com', 'homer', |
393 BLANK_PASSWORD.length); | 368 BLANK_PASSWORD.length); |
394 var passwordDialog = self.createPasswordDialog_(item); | 369 var passwordDialog = self.createPasswordDialog_(item); |
395 | 370 |
396 passwordDialog.open(); | 371 passwordDialog.open(); |
397 Polymer.dom.flush(); | 372 Polymer.dom.flush(); |
398 | 373 |
399 assertEquals(item.loginPair.originUrl, | 374 assertEquals(item.loginPair.originUrl, |
400 passwordDialog.$.websiteInput.value); | 375 passwordDialog.$.websiteInput.value); |
401 assertEquals(item.loginPair.username, | 376 assertEquals(item.loginPair.username, |
402 passwordDialog.$.usernameInput.value); | 377 passwordDialog.$.usernameInput.value); |
403 assertEquals(BLANK_PASSWORD, | 378 assertEquals(BLANK_PASSWORD, |
404 passwordDialog.$.passwordInput.value); | 379 passwordDialog.$.passwordInput.value); |
405 // Password should NOT be visible. | 380 // Password should NOT be visible. |
406 assertEquals('password', | 381 assertEquals('password', |
407 passwordDialog.$.passwordInput.type); | 382 passwordDialog.$.passwordInput.type); |
408 | 383 |
409 passwordDialog.close(); | 384 passwordDialog.close(); |
410 Polymer.dom.flush(); | 385 Polymer.dom.flush(); |
411 | 386 |
412 var blankPassword2 = ' '.repeat(17); | 387 var blankPassword2 = ' '.repeat(17); |
413 var item2 = self.createPasswordItem_('drive.google.com', 'marge', | 388 var item2 = FakeDataMaker.passwordEntry('drive.google.com', 'marge', |
414 blankPassword2.length); | 389 blankPassword2.length); |
415 | 390 |
416 passwordDialog.item = item2; | 391 passwordDialog.item = item2; |
417 passwordDialog.open(); | 392 passwordDialog.open(); |
418 Polymer.dom.flush(); | 393 Polymer.dom.flush(); |
419 | 394 |
420 assertEquals(item2.loginPair.originUrl, | 395 assertEquals(item2.loginPair.originUrl, |
421 passwordDialog.$.websiteInput.value); | 396 passwordDialog.$.websiteInput.value); |
422 assertEquals(item2.loginPair.username, | 397 assertEquals(item2.loginPair.username, |
423 passwordDialog.$.usernameInput.value); | 398 passwordDialog.$.usernameInput.value); |
424 assertEquals(blankPassword2, | 399 assertEquals(blankPassword2, |
425 passwordDialog.$.passwordInput.value); | 400 passwordDialog.$.passwordInput.value); |
426 // Password should NOT be visible. | 401 // Password should NOT be visible. |
427 assertEquals('password', | 402 assertEquals('password', |
428 passwordDialog.$.passwordInput.type); | 403 passwordDialog.$.passwordInput.type); |
429 }); | 404 }); |
430 | 405 |
431 test('showSavedPassword', function() { | 406 test('showSavedPassword', function() { |
432 var PASSWORD = 'bAn@n@5'; | 407 var PASSWORD = 'bAn@n@5'; |
433 var item = self.createPasswordItem_('goo.gl', 'bart', PASSWORD.length); | 408 var item = FakeDataMaker.passwordEntry('goo.gl', 'bart', PASSWORD.length); |
434 var passwordDialog = self.createPasswordDialog_(item); | 409 var passwordDialog = self.createPasswordDialog_(item); |
435 | 410 |
436 passwordDialog.open(); | 411 passwordDialog.open(); |
437 Polymer.dom.flush(); | 412 Polymer.dom.flush(); |
438 | 413 |
439 passwordDialog.password = PASSWORD; | 414 passwordDialog.password = PASSWORD; |
440 passwordDialog.showPassword = true; | 415 passwordDialog.showPassword = true; |
441 | 416 |
442 Polymer.dom.flush(); | 417 Polymer.dom.flush(); |
443 | 418 |
444 assertEquals(PASSWORD, | 419 assertEquals(PASSWORD, |
445 passwordDialog.$.passwordInput.value); | 420 passwordDialog.$.passwordInput.value); |
446 // Password should be visible. | 421 // Password should be visible. |
447 assertEquals('text', | 422 assertEquals('text', |
448 passwordDialog.$.passwordInput.type); | 423 passwordDialog.$.passwordInput.type); |
449 }); | 424 }); |
450 | 425 |
451 // Test will timeout if event is not received. | 426 // Test will timeout if event is not received. |
452 test('onShowSavedPassword', function(done) { | 427 test('onShowSavedPassword', function(done) { |
453 var item = self.createPasswordItem_('goo.gl', 'bart', 1); | 428 var item = FakeDataMaker.passwordEntry('goo.gl', 'bart', 1); |
454 var passwordDialog = self.createPasswordDialog_(item); | 429 var passwordDialog = self.createPasswordDialog_(item); |
455 | 430 |
456 passwordDialog.open(); | 431 passwordDialog.open(); |
457 Polymer.dom.flush(); | 432 Polymer.dom.flush(); |
458 | 433 |
459 passwordDialog.addEventListener('show-password', function(event) { | 434 passwordDialog.addEventListener('show-password', function(event) { |
460 assertEquals(item.loginPair.originUrl, event.detail.originUrl); | 435 assertEquals(item.loginPair.originUrl, event.detail.originUrl); |
461 assertEquals(item.loginPair.username, event.detail.username); | 436 assertEquals(item.loginPair.username, event.detail.username); |
462 done(); | 437 done(); |
463 }); | 438 }); |
464 | 439 |
465 MockInteractions.tap(passwordDialog.$.showPasswordButton); | 440 MockInteractions.tap(passwordDialog.$.showPasswordButton); |
466 }); | 441 }); |
467 }); | 442 }); |
468 | 443 |
469 mocha.run(); | 444 mocha.run(); |
470 }); | 445 }); |
OLD | NEW |