]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blame - tests.js
Merge pull request #103 from Zwilla/patch-3
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / tests.js
CommitLineData
88e2cdaa
IC
1// Usage:
2// $ phantomjs tests.js
3
4
5var page = require('webpage').create();
6var url = 'src/index.html';
ddeb8613 7var testMaxTime = 20000;
88e2cdaa 8
e00964cc
IC
9page.viewportSize = {
10 width: 1024,
11 height: 720
12};
13
88e2cdaa
IC
14page.onResourceError = function(e) {
15 console.log("Error loading " + e.url);
16 phantom.exit();
17}
18
19function fail() {
20 console.log("Failed");
21 phantom.exit();
22}
23
3eef9d0d
IC
24function waitForGenerate(fn, maxTime) {
25 if (!maxTime) {
26 maxTime = testMaxTime;
27 }
28 var start = new Date().getTime();
29 var prevAddressCount = -1;
30 var wait = function keepWaiting() {
31 var now = new Date().getTime();
32 var hasTimedOut = now - start > maxTime;
33 var addressCount = page.evaluate(function() {
34 return $(".address").length;
35 });
36 var hasFinished = addressCount > 0 && addressCount == prevAddressCount;
37 prevAddressCount = addressCount;
38 if (hasFinished) {
39 fn();
40 }
41 else if (hasTimedOut) {
42 console.log("Test timed out");
43 fn();
44 }
45 else {
46 setTimeout(keepWaiting, 100);
47 }
48 }
49 wait();
50}
51
c3719b00
IC
52function waitForFeedback(fn, maxTime) {
53 if (!maxTime) {
54 maxTime = testMaxTime;
55 }
56 var start = new Date().getTime();
57 var wait = function keepWaiting() {
58 var now = new Date().getTime();
59 var hasTimedOut = now - start > maxTime;
60 if (hasTimedOut) {
61 console.log("Test timed out");
62 fn();
63 return;
64 }
65 var feedback = page.evaluate(function() {
66 var feedback = $(".feedback");
67 if (feedback.css("display") == "none") {
68 return "";
69 }
70 return feedback.text();
71 });
72 var hasFinished = feedback.length > 0 && feedback != "Calculating...";
73 if (hasFinished) {
74 fn();
75 }
76 else {
77 setTimeout(keepWaiting, 100);
78 }
79 }
80 wait();
81}
82
057722b0
IC
83function waitForEntropyFeedback(fn, maxTime) {
84 if (!maxTime) {
85 maxTime = testMaxTime;
86 }
87 var origFeedback = page.evaluate(function() {
dd944906 88 return $(".entropy-container").text();
057722b0
IC
89 });
90 var start = new Date().getTime();
91 var wait = function keepWaiting() {
92 var now = new Date().getTime();
93 var hasTimedOut = now - start > maxTime;
94 if (hasTimedOut) {
95 console.log("Test timed out");
96 fn();
97 return;
98 }
99 var feedback = page.evaluate(function() {
dd944906 100 return $(".entropy-container").text();
057722b0
IC
101 });
102 var hasFinished = feedback != origFeedback;
103 if (hasFinished) {
104 fn();
105 }
106 else {
107 setTimeout(keepWaiting, 100);
108 }
109 }
110 wait();
111}
112
88e2cdaa
IC
113function next() {
114 if (tests.length > 0) {
115 var testsStr = tests.length == 1 ? "test" : "tests";
116 console.log(tests.length + " " + testsStr + " remaining");
117 tests.shift()();
118 }
119 else {
120 console.log("Finished with 0 failures");
121 phantom.exit();
122 }
123}
124
fb372687
IC
125/**
126 * Randomize array element order in-place.
127 * Using Durstenfeld shuffle algorithm.
128 * See http://stackoverflow.com/a/12646864
129 */
130function shuffle(array) {
131 for (var i = array.length - 1; i > 0; i--) {
132 var j = Math.floor(Math.random() * (i + 1));
133 var temp = array[i];
134 array[i] = array[j];
135 array[j] = temp;
136 }
137 return array;
138}
139
88e2cdaa
IC
140tests = [
141
142// Page loads with status of 'success'
143function() {
144page.open(url, function(status) {
145 if (status != "success") {
146 console.log("Page did not load with status 'success'");
147 fail();
148 }
149 next();
150});
151},
152
153// Page has text
154function() {
155page.open(url, function(status) {
156 var content = page.evaluate(function() {
157 return document.body.textContent.trim();
158 });
159 if (!content) {
160 console.log("Page does not have text");
161 fail();
162 }
163 next();
164});
165},
166
167// Entering mnemonic generates addresses
168function() {
169page.open(url, function(status) {
88e2cdaa
IC
170 // set the phrase
171 page.evaluate(function() {
172 $(".phrase").val("abandon abandon ability").trigger("input");
173 });
174 // get the address
3eef9d0d 175 waitForGenerate(function() {
06c4c6e3
IC
176 var addressCount = page.evaluate(function() {
177 return $(".address").length;
88e2cdaa 178 });
06c4c6e3
IC
179 if (addressCount != 20) {
180 console.log("Mnemonic did not generate addresses");
88e2cdaa
IC
181 console.log("Expected: " + expected);
182 console.log("Got: " + actual);
183 fail();
184 }
185 next();
3eef9d0d 186 });
88e2cdaa
IC
187});
188},
189
190// Random button generates random mnemonic
191function() {
192page.open(url, function(status) {
193 // check initial phrase is empty
194 var phrase = page.evaluate(function() {
195 return $(".phrase").text();
196 });
197 if (phrase != "") {
198 console.log("Initial phrase is not blank");
199 fail();
200 }
201 // press the 'generate' button
202 page.evaluate(function() {
203 $(".generate").click();
204 });
205 // get the new phrase
3eef9d0d 206 waitForGenerate(function() {
88e2cdaa
IC
207 var phrase = page.evaluate(function() {
208 return $(".phrase").val();
209 });
210 if (phrase.length <= 0) {
211 console.log("Phrase not generated by pressing button");
212 fail();
213 }
214 next();
3eef9d0d 215 });
88e2cdaa
IC
216});
217},
218
219// Mnemonic length can be customized
220function() {
221page.open(url, function(status) {
222 // set the length to 6
54563907 223 var expectedLength = "6";
88e2cdaa 224 page.evaluate(function() {
54563907
IC
225 $(".strength option[selected]").removeAttr("selected");
226 $(".strength option[value=6]").prop("selected", true);
88e2cdaa
IC
227 });
228 // press the 'generate' button
229 page.evaluate(function() {
230 $(".generate").click();
231 });
232 // check the new phrase is six words long
3eef9d0d 233 waitForGenerate(function() {
88e2cdaa
IC
234 var actualLength = page.evaluate(function() {
235 var words = $(".phrase").val().split(" ");
236 return words.length;
237 });
238 if (actualLength != expectedLength) {
239 console.log("Phrase not generated with correct length");
240 console.log("Expected: " + expectedLength);
241 console.log("Actual: " + actualLength);
242 fail();
243 }
54563907 244 next();
3eef9d0d 245 });
88e2cdaa
IC
246});
247},
248
88e2cdaa 249// Passphrase can be set
54563907
IC
250function() {
251page.open(url, function(status) {
252 // set the phrase and passphrase
253 var expected = "15pJzUWPGzR7avffV9nY5by4PSgSKG9rba";
254 page.evaluate(function() {
255 $(".phrase").val("abandon abandon ability");
256 $(".passphrase").val("secure_passphrase").trigger("input");
257 });
258 // check the address is generated correctly
3eef9d0d 259 waitForGenerate(function() {
54563907
IC
260 var actual = page.evaluate(function() {
261 return $(".address:first").text();
262 });
263 if (actual != expected) {
264 console.log("Passphrase results in wrong address");
265 console.log("Expected: " + expected);
266 console.log("Actual: " + actual);
267 fail();
268 }
269 next();
3eef9d0d 270 });
54563907
IC
271});
272},
273
88e2cdaa 274// Network can be set to bitcoin testnet
54563907
IC
275function() {
276page.open(url, function(status) {
59193779 277 // set the phrase and coin
54563907
IC
278 var expected = "mucaU5iiDaJDb69BHLeDv8JFfGiyg2nJKi";
279 page.evaluate(function() {
280 $(".phrase").val("abandon abandon ability");
281 $(".phrase").trigger("input");
282 $(".network option[selected]").removeAttr("selected");
52d589ea 283 $(".network option").filter(function() {
534481b6 284 return $(this).html() == "BTC - Bitcoin Testnet";
52d589ea 285 }).prop("selected", true);
54563907
IC
286 $(".network").trigger("change");
287 });
288 // check the address is generated correctly
3eef9d0d 289 waitForGenerate(function() {
54563907
IC
290 var actual = page.evaluate(function() {
291 return $(".address:first").text();
292 });
293 if (actual != expected) {
294 console.log("Bitcoin testnet address is incorrect");
295 console.log("Expected: " + expected);
296 console.log("Actual: " + actual);
297 fail();
298 }
299 next();
3eef9d0d 300 });
54563907
IC
301});
302},
303
88e2cdaa 304// Network can be set to litecoin
59193779
IC
305function() {
306page.open(url, function(status) {
307 // set the phrase and coin
308 var expected = "LQ4XU8RX2ULPmPq9FcUHdVmPVchP9nwXdn";
309 page.evaluate(function() {
310 $(".phrase").val("abandon abandon ability");
311 $(".phrase").trigger("input");
312 $(".network option[selected]").removeAttr("selected");
52d589ea 313 $(".network option").filter(function() {
534481b6 314 return $(this).html() == "LTC - Litecoin";
52d589ea 315 }).prop("selected", true);
59193779
IC
316 $(".network").trigger("change");
317 });
318 // check the address is generated correctly
3eef9d0d 319 waitForGenerate(function() {
59193779
IC
320 var actual = page.evaluate(function() {
321 return $(".address:first").text();
322 });
323 if (actual != expected) {
324 console.log("Litecoin address is incorrect");
325 console.log("Expected: " + expected);
326 console.log("Actual: " + actual);
327 fail();
328 }
329 next();
3eef9d0d 330 });
59193779
IC
331});
332},
333
a96cfdf3 334// Network can be set to ripple
335function() {
336page.open(url, function(status) {
337 // set the phrase and coin
338 var expected = "rLTFnqbmCVPGx6VfaygdtuKWJgcN4v1zRS";
339 page.evaluate(function() {
340 $(".phrase").val("ill clump only blind unit burden thing track silver cloth review awake useful craft whale all satisfy else trophy sunset walk vanish hope valve");
341 $(".phrase").trigger("input");
342 $(".network option[selected]").removeAttr("selected");
343 $(".network option").filter(function() {
534481b6 344 return $(this).html() == "XRP - Ripple";
a96cfdf3 345 }).prop("selected", true);
346 $(".network").trigger("change");
59193779
IC
347 });
348 // check the address is generated correctly
3eef9d0d 349 waitForGenerate(function() {
59193779
IC
350 var actual = page.evaluate(function() {
351 return $(".address:first").text();
352 });
353 if (actual != expected) {
56b1275f 354 console.log("Ripple address is incorrect");
59193779
IC
355 console.log("Expected: " + expected);
356 console.log("Actual: " + actual);
357 fail();
358 }
359 next();
3eef9d0d 360 });
59193779
IC
361});
362},
363
88e2cdaa 364// Network can be set to dogecoin
59193779
IC
365function() {
366page.open(url, function(status) {
367 // set the phrase and coin
368 var expected = "DPQH2AtuzkVSG6ovjKk4jbUmZ6iXLpgbJA";
369 page.evaluate(function() {
370 $(".phrase").val("abandon abandon ability");
371 $(".phrase").trigger("input");
372 $(".network option[selected]").removeAttr("selected");
52d589ea 373 $(".network option").filter(function() {
534481b6 374 return $(this).html() == "DOGE - Dogecoin";
52d589ea 375 }).prop("selected", true);
59193779
IC
376 $(".network").trigger("change");
377 });
378 // check the address is generated correctly
3eef9d0d 379 waitForGenerate(function() {
59193779
IC
380 var actual = page.evaluate(function() {
381 return $(".address:first").text();
382 });
383 if (actual != expected) {
384 console.log("Dogecoin address is incorrect");
385 console.log("Expected: " + expected);
386 console.log("Actual: " + actual);
387 fail();
388 }
389 next();
3eef9d0d 390 });
59193779
IC
391});
392},
393
88e2cdaa 394// Network can be set to shadowcash
59193779
IC
395function() {
396page.open(url, function(status) {
397 // set the phrase and coin
398 var expected = "SiSZtfYAXEFvMm3XM8hmtkGDyViRwErtCG";
399 page.evaluate(function() {
400 $(".phrase").val("abandon abandon ability");
401 $(".phrase").trigger("input");
402 $(".network option[selected]").removeAttr("selected");
52d589ea 403 $(".network option").filter(function() {
534481b6 404 return $(this).html() == "SDC - ShadowCash";
52d589ea 405 }).prop("selected", true);
59193779
IC
406 $(".network").trigger("change");
407 });
408 // check the address is generated correctly
3eef9d0d 409 waitForGenerate(function() {
59193779
IC
410 var actual = page.evaluate(function() {
411 return $(".address:first").text();
412 });
413 if (actual != expected) {
414 console.log("Shadowcash address is incorrect");
415 console.log("Expected: " + expected);
416 console.log("Actual: " + actual);
417 fail();
418 }
419 next();
3eef9d0d 420 });
59193779
IC
421});
422},
423
88e2cdaa 424// Network can be set to shadowcash testnet
59193779
IC
425function() {
426page.open(url, function(status) {
427 // set the phrase and coin
428 var expected = "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe";
429 page.evaluate(function() {
430 $(".phrase").val("abandon abandon ability");
431 $(".phrase").trigger("input");
432 $(".network option[selected]").removeAttr("selected");
52d589ea 433 $(".network option").filter(function() {
534481b6 434 return $(this).html() == "SDC - ShadowCash Testnet";
52d589ea 435 }).prop("selected", true);
59193779
IC
436 $(".network").trigger("change");
437 });
438 // check the address is generated correctly
3eef9d0d 439 waitForGenerate(function() {
59193779
IC
440 var actual = page.evaluate(function() {
441 return $(".address:first").text();
442 });
443 if (actual != expected) {
444 console.log("Shadowcash testnet address is incorrect");
445 console.log("Expected: " + expected);
446 console.log("Actual: " + actual);
447 fail();
448 }
449 next();
3eef9d0d 450 });
59193779
IC
451});
452},
453
88e2cdaa 454// Network can be set to viacoin
59193779
IC
455function() {
456page.open(url, function(status) {
457 // set the phrase and coin
458 var expected = "Vq9Eq4N5SQnjqZvxtxzo7hZPW5XnyJsmXT";
459 page.evaluate(function() {
460 $(".phrase").val("abandon abandon ability");
461 $(".phrase").trigger("input");
462 $(".network option[selected]").removeAttr("selected");
52d589ea 463 $(".network option").filter(function() {
534481b6 464 return $(this).html() == "VIA - Viacoin";
52d589ea 465 }).prop("selected", true);
59193779
IC
466 $(".network").trigger("change");
467 });
468 // check the address is generated correctly
3eef9d0d 469 waitForGenerate(function() {
59193779
IC
470 var actual = page.evaluate(function() {
471 return $(".address:first").text();
472 });
473 if (actual != expected) {
474 console.log("Viacoin address is incorrect");
475 console.log("Expected: " + expected);
476 console.log("Actual: " + actual);
477 fail();
478 }
479 next();
3eef9d0d 480 });
59193779
IC
481});
482},
483
88e2cdaa 484// Network can be set to viacoin testnet
59193779
IC
485function() {
486page.open(url, function(status) {
487 // set the phrase and coin
488 var expected = "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe";
489 page.evaluate(function() {
490 $(".phrase").val("abandon abandon ability");
491 $(".phrase").trigger("input");
492 $(".network option[selected]").removeAttr("selected");
52d589ea 493 $(".network option").filter(function() {
534481b6 494 return $(this).html() == "VIA - Viacoin Testnet";
52d589ea 495 }).prop("selected", true);
59193779
IC
496 $(".network").trigger("change");
497 });
498 // check the address is generated correctly
3eef9d0d 499 waitForGenerate(function() {
59193779
IC
500 var actual = page.evaluate(function() {
501 return $(".address:first").text();
502 });
503 if (actual != expected) {
504 console.log("Viacoin testnet address is incorrect");
505 console.log("Expected: " + expected);
506 console.log("Actual: " + actual);
507 fail();
508 }
509 next();
3eef9d0d 510 });
59193779
IC
511});
512},
513
88e2cdaa 514// Network can be set to jumbucks
59193779
IC
515function() {
516page.open(url, function(status) {
517 // set the phrase and coin
518 var expected = "JLEXccwDXADK4RxBPkRez7mqsHVoJBEUew";
519 page.evaluate(function() {
520 $(".phrase").val("abandon abandon ability");
521 $(".phrase").trigger("input");
522 $(".network option[selected]").removeAttr("selected");
52d589ea 523 $(".network option").filter(function() {
534481b6 524 return $(this).html() == "JBS - Jumbucks";
52d589ea 525 }).prop("selected", true);
59193779
IC
526 $(".network").trigger("change");
527 });
528 // check the address is generated correctly
3eef9d0d 529 waitForGenerate(function() {
59193779
IC
530 var actual = page.evaluate(function() {
531 return $(".address:first").text();
532 });
533 if (actual != expected) {
534 console.log("Jumbucks address is incorrect");
535 console.log("Expected: " + expected);
536 console.log("Actual: " + actual);
537 fail();
538 }
539 next();
3eef9d0d 540 });
59193779
IC
541});
542},
543
88e2cdaa 544// Network can be set to clam
59193779
IC
545function() {
546page.open(url, function(status) {
547 // set the phrase and coin
548 var expected = "xCp4sakjVx4pUAZ6cBCtuin8Ddb6U1sk9y";
549 page.evaluate(function() {
550 $(".phrase").val("abandon abandon ability");
551 $(".phrase").trigger("input");
552 $(".network option[selected]").removeAttr("selected");
52d589ea 553 $(".network option").filter(function() {
534481b6 554 return $(this).html() == "CLAM - Clams";
52d589ea 555 }).prop("selected", true);
59193779
IC
556 $(".network").trigger("change");
557 });
558 // check the address is generated correctly
3eef9d0d 559 waitForGenerate(function() {
59193779
IC
560 var actual = page.evaluate(function() {
561 return $(".address:first").text();
562 });
563 if (actual != expected) {
564 console.log("CLAM address is incorrect");
565 console.log("Expected: " + expected);
566 console.log("Actual: " + actual);
567 fail();
f3fad1b5
IC
568 }
569 next();
570 });
571});
572},
573
0921f370 574// Network can be set to crown
575function() {
576page.open(url, function(status) {
577 // set the phrase and coin
578 var expected = "18pWSwSUAQdiwMHUfFZB1fM2xue9X1FqE5";
579 page.evaluate(function() {
580 $(".phrase").val("abandon abandon ability");
581 $(".phrase").trigger("input");
582 $(".network option[selected]").removeAttr("selected");
583 $(".network option").filter(function() {
584 return $(this).html() == "CRW - Crown";
585 }).prop("selected", true);
586 $(".network").trigger("change");
587 });
588 // check the address is generated correctly
589 waitForGenerate(function() {
590 var actual = page.evaluate(function() {
591 return $(".address:first").text();
592 });
593 if (actual != expected) {
594 console.log("CRW address is incorrect");
595 console.log("Expected: " + expected);
596 console.log("Actual: " + actual);
597 fail();
598 }
599 next();
600 });
601});
602},
603
f3fad1b5
IC
604// Network can be set to dash
605function() {
606page.open(url, function(status) {
607 // set the phrase and coin
608 var expected = "XdbhtMuGsPSkE6bPdNTHoFSszQKmK4S5LT";
609 page.evaluate(function() {
610 $(".phrase").val("abandon abandon ability");
611 $(".phrase").trigger("input");
612 $(".network option[selected]").removeAttr("selected");
52d589ea 613 $(".network option").filter(function() {
534481b6 614 return $(this).html() == "DASH - Dash";
52d589ea 615 }).prop("selected", true);
f3fad1b5
IC
616 $(".network").trigger("change");
617 });
618 // check the address is generated correctly
619 waitForGenerate(function() {
620 var actual = page.evaluate(function() {
621 return $(".address:first").text();
622 });
623 if (actual != expected) {
624 console.log("DASH address is incorrect");
625 console.log("Expected: " + expected);
626 console.log("Actual: " + actual);
627 fail();
00fd1a03 628 }
629 next();
630 });
631});
632},
633
c0386f3b
KR
634function() {
635page.open(url, function(status) {
636 // set the phrase and coin
637 var expected = "yaR52EN4oojdJfBgzWJTymC4uuCLPT29Gw";
638 page.evaluate(function() {
639 $(".phrase").val("abandon abandon ability");
640 $(".phrase").trigger("input");
641 $(".network option[selected]").removeAttr("selected");
642 $(".network option").filter(function() {
534481b6 643 return $(this).html() == "DASH - Dash Testnet";
c0386f3b
KR
644 }).prop("selected", true);
645 $(".network").trigger("change");
646 });
647 // check the address is generated correctly
648 waitForGenerate(function() {
649 var actual = page.evaluate(function() {
650 return $(".address:first").text();
651 });
652 if (actual != expected) {
653 console.log("DASH Testnet address is incorrect");
654 console.log("Expected: " + expected);
655 console.log("Actual: " + actual);
656 fail();
657 }
658 next();
659 });
660});
661},
662
00fd1a03 663// Network can be set to game
664function() {
665page.open(url, function(status) {
666 // set the phrase and coin
667 var expected = "GSMY9bAp36cMR4zyT4uGVS7GFjpdXbao5Q";
668 page.evaluate(function() {
669 $(".phrase").val("abandon abandon ability");
670 $(".phrase").trigger("input");
671 $(".network option[selected]").removeAttr("selected");
672 $(".network option").filter(function() {
534481b6 673 return $(this).html() == "GAME - GameCredits";
00fd1a03 674 }).prop("selected", true);
675 $(".network").trigger("change");
676 });
677 // check the address is generated correctly
678 waitForGenerate(function() {
679 var actual = page.evaluate(function() {
680 return $(".address:first").text();
681 });
682 if (actual != expected) {
683 console.log("GAME address is incorrect");
684 console.log("Expected: " + expected);
685 console.log("Actual: " + actual);
686 fail();
59193779 687 }
bfb3dab6
IC
688 next();
689 });
690});
691},
692
693// Network can be set to namecoin
694function() {
695page.open(url, function(status) {
696 // set the phrase and coin
697 var expected = "Mw2vK2Bvex1yYtYF6sfbEg2YGoUc98YUD2";
698 page.evaluate(function() {
699 $(".phrase").val("abandon abandon ability");
700 $(".phrase").trigger("input");
701 $(".network option[selected]").removeAttr("selected");
52d589ea 702 $(".network option").filter(function() {
534481b6 703 return $(this).html() == "NMC - Namecoin";
52d589ea 704 }).prop("selected", true);
bfb3dab6
IC
705 $(".network").trigger("change");
706 });
707 // check the address is generated correctly
708 waitForGenerate(function() {
709 var actual = page.evaluate(function() {
710 return $(".address:first").text();
711 });
712 if (actual != expected) {
713 console.log("Namecoin address is incorrect");
714 console.log("Expected: " + expected);
715 console.log("Actual: " + actual);
716 fail();
717 }
718 next();
719 });
720});
721},
722
723// Network can be set to peercoin
724function() {
725page.open(url, function(status) {
726 // set the phrase and coin
727 var expected = "PVAiioTaK2eDHSEo3tppT9AVdBYqxRTBAm";
728 page.evaluate(function() {
729 $(".phrase").val("abandon abandon ability");
730 $(".phrase").trigger("input");
731 $(".network option[selected]").removeAttr("selected");
52d589ea 732 $(".network option").filter(function() {
534481b6 733 return $(this).html() == "PPC - Peercoin";
52d589ea 734 }).prop("selected", true);
bfb3dab6
IC
735 $(".network").trigger("change");
736 });
737 // check the address is generated correctly
738 waitForGenerate(function() {
739 var actual = page.evaluate(function() {
740 return $(".address:first").text();
741 });
742 if (actual != expected) {
743 console.log("Peercoin address is incorrect");
744 console.log("Expected: " + expected);
745 console.log("Actual: " + actual);
746 fail();
747 }
59193779 748 next();
3eef9d0d 749 });
59193779
IC
750});
751},
752
24137d96
IC
753// Network can be set to ethereum
754function() {
755
756page.open(url, function(status) {
757
758 // set the phrase and coin
759 page.evaluate(function() {
760 $(".phrase").val("abandon abandon ability");
761 $(".phrase").trigger("input");
762 $(".network option[selected]").removeAttr("selected");
52d589ea 763 $(".network option").filter(function() {
534481b6 764 return $(this).html() == "ETH - Ethereum";
52d589ea 765 }).prop("selected", true);
24137d96
IC
766 $(".network").trigger("change");
767 });
768 waitForGenerate(function() {
769 // check the address is generated correctly
770 // this value comes from
771 // https://www.myetherwallet.com/#view-wallet-info
49b21f12 772 // Unusual capitalization is due to checksum
24137d96
IC
773 var expected = "0xe5815d5902Ad612d49283DEdEc02100Bd44C2772";
774 var actual = page.evaluate(function() {
775 return $(".address:first").text();
776 });
49b21f12 777 if (actual != expected) {
24137d96
IC
778 console.log("Ethereum address is incorrect");
779 console.log("Expected: " + expected);
780 console.log("Actual: " + actual);
781 fail();
782 }
783 // check the private key is correct
784 // this private key can be imported into
785 // https://www.myetherwallet.com/#view-wallet-info
786 // and it should correlate to the address above
0163fe6a 787 var expected = "0x8f253078b73d7498302bb78c171b23ce7a8fb511987d2b2702b731638a4a15e7";
24137d96
IC
788 var actual = page.evaluate(function() {
789 return $(".privkey:first").text();
790 });
791 if (actual != expected) {
792 console.log("Ethereum privkey is incorrect");
793 console.log("Expected: " + expected);
794 console.log("Actual: " + actual);
795 fail();
796 }
797 // check the public key is correct
798 // TODO
799 // don't have any third-party source to generate the expected value
800 //var expected = "?";
801 //var actual = page.evaluate(function() {
802 // return $(".pubkey:first").text();
803 //});
804 //if (actual != expected) {
805 // console.log("Ethereum privkey is incorrect");
806 // console.log("Expected: " + expected);
807 // console.log("Actual: " + actual);
808 // fail();
809 //}
810 next();
811 });
812});
813},
814
7a5a87a0
GH
815// Network can be set to Slimcoin
816function() {
817page.open(url, function(status) {
818 // set the phrase and coin
819 var expected = "SNzPi1CafHFm3WWjRo43aMgiaEEj3ogjww";
820 page.evaluate(function() {
821 $(".phrase").val("abandon abandon ability");
822 $(".phrase").trigger("input");
823 $(".network option[selected]").removeAttr("selected");
824 $(".network option").filter(function() {
534481b6 825 return $(this).html() == "SLM - Slimcoin";
7a5a87a0
GH
826 }).prop("selected", true);
827 $(".network").trigger("change");
828 });
829 // check the address is generated correctly
830 waitForGenerate(function() {
831 var actual = page.evaluate(function() {
832 return $(".address:first").text();
833 });
834 if (actual != expected) {
835 console.log("Slimcoin address is incorrect");
836 console.log("Expected: " + expected);
837 console.log("Actual: " + actual);
838 fail();
839 }
840 next();
841 });
842});
843},
844
845// Network can be set to Slimcointn
846function() {
847page.open(url, function(status) {
848 // set the phrase and coin
849 var expected = "n3nMgWufTek5QQAr6uwMhg5xbzj8xqc4Dq";
850 page.evaluate(function() {
851 $(".phrase").val("abandon abandon ability");
852 $(".phrase").trigger("input");
853 $(".network option[selected]").removeAttr("selected");
854 $(".network option").filter(function() {
534481b6 855 return $(this).html() == "SLM - Slimcoin Testnet";
7a5a87a0
GH
856 }).prop("selected", true);
857 $(".network").trigger("change");
858 });
859 // check the address is generated correctly
860 waitForGenerate(function() {
861 var actual = page.evaluate(function() {
862 return $(".address:first").text();
863 });
864 if (actual != expected) {
865 console.log("Slimcoin testnet address is incorrect");
866 console.log("Expected: " + expected);
867 console.log("Actual: " + actual);
868 fail();
869 }
870 next();
871 });
872});
873},
874
daab55dc
IC
875// Network can be set to bitcoin cash
876function() {
877page.open(url, function(status) {
878 // set the phrase and coin
879 var expected = "1JKvb6wKtsjNoCRxpZ4DGrbniML7z5U16A";
880 page.evaluate(function() {
881 $(".phrase").val("abandon abandon ability");
882 $(".phrase").trigger("input");
883 $(".network option[selected]").removeAttr("selected");
884 $(".network option").filter(function() {
885 return $(this).html() == "BCH - Bitcoin Cash";
886 }).prop("selected", true);
887 $(".network").trigger("change");
888 });
889 // check the address is generated correctly
890 waitForGenerate(function() {
891 var actual = page.evaluate(function() {
892 return $(".address:first").text();
893 });
894 if (actual != expected) {
895 console.log("Bitcoin Cash address is incorrect");
896 console.log("Expected: " + expected);
897 console.log("Actual: " + actual);
898 fail();
899 }
900 next();
901 });
902});
903},
904
c18511dd
IC
905// Network can be set to myriadcoin
906function() {
907page.open(url, function(status) {
908 // set the phrase and coin
909 var expected = "MJEswvRR46wh9BoiVj9DzKYMBkCramhoBV";
910 page.evaluate(function() {
911 $(".phrase").val("abandon abandon ability");
912 $(".phrase").trigger("input");
913 $(".network option[selected]").removeAttr("selected");
914 $(".network option").filter(function() {
915 return $(this).html() == "XMY - Myriadcoin";
916 }).prop("selected", true);
917 $(".network").trigger("change");
918 });
919 // check the address is generated correctly
920 waitForGenerate(function() {
921 var actual = page.evaluate(function() {
922 return $(".address:first").text();
923 });
924 if (actual != expected) {
925 console.log("Myriadcoin address is incorrect");
926 console.log("Expected: " + expected);
927 console.log("Actual: " + actual);
928 fail();
929 }
930 next();
931 });
932});
933},
934
47b64d3e
IC
935// Network can be set to pivx
936function() {
937page.open(url, function(status) {
938 // set the phrase and coin
939 var expected = "DBxgT7faCuno7jmtKuu6KWCiwqsVPqh1tS";
940 page.evaluate(function() {
941 $(".phrase").val("abandon abandon ability");
942 $(".phrase").trigger("input");
943 $(".network option[selected]").removeAttr("selected");
944 $(".network option").filter(function() {
945 return $(this).html() == "PIVX - PIVX";
946 }).prop("selected", true);
947 $(".network").trigger("change");
948 });
949 // check the address is generated correctly
950 waitForGenerate(function() {
951 var actual = page.evaluate(function() {
952 return $(".address:first").text();
953 });
954 if (actual != expected) {
955 console.log("PIVX address is incorrect");
956 console.log("Expected: " + expected);
957 console.log("Actual: " + actual);
958 fail();
959 }
960 next();
961 });
962});
963},
964
965// Network can be set to pivx testnet
966function() {
967page.open(url, function(status) {
968 // set the phrase and coin
969 var expected = "yB5U384n6dGkVE3by5y9VdvHHPwPg68fQj";
970 page.evaluate(function() {
971 $(".phrase").val("abandon abandon ability");
972 $(".phrase").trigger("input");
973 $(".network option[selected]").removeAttr("selected");
974 $(".network option").filter(function() {
975 return $(this).html() == "PIVX - PIVX Testnet";
976 }).prop("selected", true);
977 $(".network").trigger("change");
978 });
979 // check the address is generated correctly
980 waitForGenerate(function() {
981 var actual = page.evaluate(function() {
982 return $(".address:first").text();
983 });
984 if (actual != expected) {
985 console.log("PIVX Testnet address is incorrect");
986 console.log("Expected: " + expected);
987 console.log("Actual: " + actual);
988 fail();
989 }
990 next();
991 });
992});
993},
994
8a9f3913
IC
995// Network can be set to maza
996function() {
997page.open(url, function(status) {
998 // set the phrase and coin
999 var expected = "MGW4Bmi2NEm4PxSjgeFwhP9vg18JHoRnfw";
1000 page.evaluate(function() {
1001 $(".phrase").val("abandon abandon ability");
1002 $(".phrase").trigger("input");
1003 $(".network option[selected]").removeAttr("selected");
1004 $(".network option").filter(function() {
1005 return $(this).html() == "MAZA - Maza";
1006 }).prop("selected", true);
1007 $(".network").trigger("change");
1008 });
1009 // check the address is generated correctly
1010 waitForGenerate(function() {
1011 var actual = page.evaluate(function() {
1012 return $(".address:first").text();
1013 });
1014 if (actual != expected) {
1015 console.log("Maza address is incorrect");
1016 console.log("Expected: " + expected);
1017 console.log("Actual: " + actual);
1018 fail();
1019 }
1020 next();
1021 });
1022});
1023},
1024
88e2cdaa 1025// BIP39 seed is set from phrase
c196ad55
IC
1026function() {
1027page.open(url, function(status) {
1028 // set the phrase
1029 var expected = "20da140d3dd1df8713cefcc4d54ce0e445b4151027a1ab567b832f6da5fcc5afc1c3a3f199ab78b8e0ab4652efd7f414ac2c9a3b81bceb879a70f377aa0a58f3";
1030 page.evaluate(function() {
1031 $(".phrase").val("abandon abandon ability");
1032 $(".phrase").trigger("input");
1033 });
1034 // check the address is generated correctly
3eef9d0d 1035 waitForGenerate(function() {
c196ad55
IC
1036 var actual = page.evaluate(function() {
1037 return $(".seed").val();
1038 });
1039 if (actual != expected) {
1040 console.log("BIP39 seed is incorrectly generated from mnemonic");
1041 console.log("Expected: " + expected);
1042 console.log("Actual: " + actual);
1043 fail();
1044 }
1045 next();
3eef9d0d 1046 });
c196ad55
IC
1047});
1048},
1049
88e2cdaa 1050// BIP32 root key is set from phrase
ec60b662
IC
1051function() {
1052page.open(url, function(status) {
1053 // set the phrase
1054 var expected = "xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi";
1055 page.evaluate(function() {
1056 $(".phrase").val("abandon abandon ability");
1057 $(".phrase").trigger("input");
1058 });
1059 // check the address is generated correctly
3eef9d0d 1060 waitForGenerate(function() {
ec60b662
IC
1061 var actual = page.evaluate(function() {
1062 return $(".root-key").val();
1063 });
1064 if (actual != expected) {
1065 console.log("Root key is incorrectly generated from mnemonic");
1066 console.log("Expected: " + expected);
1067 console.log("Actual: " + actual);
1068 fail();
1069 }
1070 next();
3eef9d0d 1071 });
ec60b662
IC
1072});
1073},
1074
88e2cdaa 1075// Tabs show correct addresses when changed
cf7258fd
IC
1076function() {
1077page.open(url, function(status) {
1078 // set the phrase
1079 var expected = "17uQ7s2izWPwBmEVFikTmZUjbBKWYdJchz";
1080 page.evaluate(function() {
1081 $(".phrase").val("abandon abandon ability");
1082 $(".phrase").trigger("input");
1083 });
1084 // change tabs
1085 waitForGenerate(function() {
1086 page.evaluate(function() {
1087 $("#bip32-tab a").click();
1088 });
1089 // check the address is generated correctly
1090 waitForGenerate(function() {
1091 var actual = page.evaluate(function() {
1092 return $(".address:first").text();
1093 });
1094 if (actual != expected) {
1095 console.log("Clicking tab generates incorrect address");
1096 console.log("Expected: " + expected);
1097 console.log("Actual: " + actual);
1098 fail();
1099 }
1100 next();
1101 });
1102 });
1103});
1104},
88e2cdaa
IC
1105
1106// BIP44 derivation path is shown
d077e1e7
IC
1107function() {
1108page.open(url, function(status) {
1109 // set the phrase
1110 var expected = "m/44'/0'/0'/0";
1111 page.evaluate(function() {
1112 $(".phrase").val("abandon abandon ability");
1113 $(".phrase").trigger("input");
1114 });
1115 // check the derivation path of the first address
1116 waitForGenerate(function() {
1117 var actual = page.evaluate(function() {
1118 return $("#bip44 .path").val();
1119 });
1120 if (actual != expected) {
1121 console.log("BIP44 derivation path is incorrect");
1122 console.log("Expected: " + expected);
1123 console.log("Actual: " + actual);
1124 fail();
1125 }
1126 next();
1127 });
1128});
1129},
1130
88e2cdaa 1131// BIP44 extended private key is shown
4fd2925d
IC
1132function() {
1133page.open(url, function(status) {
1134 // set the phrase
1135 var expected = "xprvA2DxxvPZcyRvYgZMGS53nadR32mVDeCyqQYyFhrCVbJNjPoxMeVf7QT5g7mQASbTf9Kp4cryvcXnu2qurjWKcrdsr91jXymdCDNxKgLFKJG";
1136 page.evaluate(function() {
1137 $(".phrase").val("abandon abandon ability");
1138 $(".phrase").trigger("input");
1139 });
06286adb 1140 // check the BIP44 extended private key
4fd2925d
IC
1141 waitForGenerate(function() {
1142 var actual = page.evaluate(function() {
1143 return $(".extended-priv-key").val();
1144 });
1145 if (actual != expected) {
1146 console.log("BIP44 extended private key is incorrect");
1147 console.log("Expected: " + expected);
1148 console.log("Actual: " + actual);
1149 fail();
1150 }
1151 next();
1152 });
1153});
1154},
1155
88e2cdaa 1156// BIP44 extended public key is shown
39fd45bb
IC
1157function() {
1158page.open(url, function(status) {
1159 // set the phrase
1160 var expected = "xpub6FDKNRvTTLzDmAdpNTc49ia9b4byd6vqCdUa46Fp3vqMcC96uBoufCmZXQLiN5AK3iSCJMhf9gT2sxkpyaPepRuA7W3MujV5tGmF5VfbueM";
1161 page.evaluate(function() {
1162 $(".phrase").val("abandon abandon ability");
1163 $(".phrase").trigger("input");
1164 });
06286adb 1165 // check the BIP44 extended public key
39fd45bb
IC
1166 waitForGenerate(function() {
1167 var actual = page.evaluate(function() {
1168 return $(".extended-pub-key").val();
1169 });
1170 if (actual != expected) {
1171 console.log("BIP44 extended public key is incorrect");
1172 console.log("Expected: " + expected);
1173 console.log("Actual: " + actual);
1174 fail();
1175 }
1176 next();
1177 });
1178});
1179},
1180
88e2cdaa 1181// BIP44 account field changes address list
048bc3e0
IC
1182function() {
1183page.open(url, function(status) {
1184 // set the phrase
1185 var expected = "1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H";
1186 page.evaluate(function() {
1187 $(".phrase").val("abandon abandon ability");
1188 $(".phrase").trigger("input");
1189 });
1190 waitForGenerate(function() {
1191 // change the bip44 purpose field to 45
1192 page.evaluate(function() {
1193 $("#bip44 .account").val("1");
1194 $("#bip44 .account").trigger("input");
1195 });
1196 waitForGenerate(function() {
1197 // check the address for the new derivation path
1198 var actual = page.evaluate(function() {
1199 return $(".address:first").text();
1200 });
1201 if (actual != expected) {
1202 console.log("BIP44 account field generates incorrect address");
1203 console.log("Expected: " + expected);
1204 console.log("Actual: " + actual);
1205 fail();
1206 }
1207 next();
1208 });
1209 });
1210});
1211},
1212
fa4da086
IC
1213// BIP44 change field changes address list
1214function() {
1215page.open(url, function(status) {
1216 // set the phrase
1217 var expected = "1KAGfWgqfVbSSXY56fNQ7YnhyKuoskHtYo";
1218 page.evaluate(function() {
1219 $(".phrase").val("abandon abandon ability");
1220 $(".phrase").trigger("input");
1221 });
1222 waitForGenerate(function() {
1223 // change the bip44 purpose field to 45
1224 page.evaluate(function() {
1225 $("#bip44 .change").val("1");
1226 $("#bip44 .change").trigger("input");
1227 });
1228 waitForGenerate(function() {
1229 // check the address for the new derivation path
1230 var actual = page.evaluate(function() {
1231 return $(".address:first").text();
1232 });
1233 if (actual != expected) {
1234 console.log("BIP44 change field generates incorrect address");
1235 console.log("Expected: " + expected);
1236 console.log("Actual: " + actual);
1237 fail();
1238 }
1239 next();
1240 });
1241 });
1242});
1243},
048bc3e0 1244
88e2cdaa 1245// BIP32 derivation path can be set
651382a3
IC
1246function() {
1247page.open(url, function(status) {
1248 // set the phrase
1249 var expected = "16pYQQdLD1hH4hwTGLXBaZ9Teboi1AGL8L";
1250 page.evaluate(function() {
1251 $(".phrase").val("abandon abandon ability");
1252 $(".phrase").trigger("input");
1253 });
1254 // change tabs
1255 waitForGenerate(function() {
1256 page.evaluate(function() {
1257 $("#bip32-tab a").click();
1258 });
1259 // set the derivation path to m/1
1260 waitForGenerate(function() {
1261 page.evaluate(function() {
1262 $("#bip32 .path").val("m/1");
1263 $("#bip32 .path").trigger("input");
1264 });
1265 // check the address is generated correctly
1266 waitForGenerate(function() {
1267 var actual = page.evaluate(function() {
1268 return $(".address:first").text();
1269 });
1270 if (actual != expected) {
1271 console.log("Custom BIP32 path generates incorrect address");
1272 console.log("Expected: " + expected);
1273 console.log("Actual: " + actual);
1274 fail();
1275 }
1276 next();
1277 });
1278 });
1279 });
1280});
1281},
1282
88e2cdaa 1283// BIP32 can use hardened derivation paths
651382a3
IC
1284function() {
1285page.open(url, function(status) {
1286 // set the phrase
1287 var expected = "14aXZeprXAE3UUKQc4ihvwBvww2LuEoHo4";
1288 page.evaluate(function() {
1289 $(".phrase").val("abandon abandon ability");
1290 $(".phrase").trigger("input");
1291 });
1292 // change tabs
1293 waitForGenerate(function() {
1294 page.evaluate(function() {
1295 $("#bip32-tab a").click();
1296 });
1297 // set the derivation path to m/0'
1298 waitForGenerate(function() {
1299 page.evaluate(function() {
1300 $("#bip32 .path").val("m/0'");
1301 $("#bip32 .path").trigger("input");
1302 });
1303 // check the address is generated correctly
1304 waitForGenerate(function() {
1305 var actual = page.evaluate(function() {
1306 return $(".address:first").text();
1307 });
1308 if (actual != expected) {
1309 console.log("Hardened BIP32 path generates incorrect address");
1310 console.log("Expected: " + expected);
1311 console.log("Actual: " + actual);
1312 fail();
1313 }
1314 next();
1315 });
1316 });
1317 });
1318});
1319},
1320
88e2cdaa 1321// BIP32 extended private key is shown
9e9dcfda
IC
1322function() {
1323page.open(url, function(status) {
1324 // set the phrase
1325 var expected = "xprv9va99uTVE5aLiutUVLTyfxfe8v8aaXjSQ1XxZbK6SezYVuikA9MnjQVTA8rQHpNA5LKvyQBpLiHbBQiiccKiBDs7eRmBogsvq3THFeLHYbe";
1326 page.evaluate(function() {
1327 $(".phrase").val("abandon abandon ability");
1328 $(".phrase").trigger("input");
1329 });
1330 // change tabs
1331 waitForGenerate(function() {
1332 page.evaluate(function() {
1333 $("#bip32-tab a").click();
1334 });
1335 // check the extended private key is generated correctly
1336 waitForGenerate(function() {
1337 var actual = page.evaluate(function() {
1338 return $(".extended-priv-key").val();
1339 });
1340 if (actual != expected) {
1341 console.log("BIP32 extended private key is incorrect");
1342 console.log("Expected: " + expected);
1343 console.log("Actual: " + actual);
1344 fail();
1345 }
1346 next();
1347 });
1348 });
1349});
1350},
1351
88e2cdaa 1352// BIP32 extended public key is shown
9e9dcfda
IC
1353function() {
1354page.open(url, function(status) {
1355 // set the phrase
1356 var expected = "xpub69ZVZQzP4T8dwPxwbMzz36cNgwy4yzTHmETZMyihzzXXNi3thgg3HCow1RtY252wdw5rS8369xKnraN5Q93y3FkFfJp2XEHWUrkyXsjS93P";
1357 page.evaluate(function() {
1358 $(".phrase").val("abandon abandon ability");
1359 $(".phrase").trigger("input");
1360 });
1361 // change tabs
1362 waitForGenerate(function() {
1363 page.evaluate(function() {
1364 $("#bip32-tab a").click();
1365 });
1366 // check the extended public key is generated correctly
1367 waitForGenerate(function() {
1368 var actual = page.evaluate(function() {
1369 return $(".extended-pub-key").val();
1370 });
1371 if (actual != expected) {
1372 console.log("BIP32 extended public key is incorrect");
1373 console.log("Expected: " + expected);
1374 console.log("Actual: " + actual);
1375 fail();
1376 }
1377 next();
1378 });
1379 });
1380});
1381},
88e2cdaa
IC
1382
1383// Derivation path is shown in table
5f844c62
IC
1384function() {
1385page.open(url, function(status) {
1386 // set the phrase
1387 var expected = "m/44'/0'/0'/0/0";
1388 page.evaluate(function() {
1389 $(".phrase").val("abandon abandon ability");
1390 $(".phrase").trigger("input");
1391 });
1392 // check for derivation path in table
1393 waitForGenerate(function() {
1394 var actual = page.evaluate(function() {
1395 return $(".index:first").text();
1396 });
1397 if (actual != expected) {
1398 console.log("Derivation path shown incorrectly in table");
1399 console.log("Expected: " + expected);
1400 console.log("Actual: " + actual);
1401 fail();
1402 }
1403 next();
1404 });
1405});
1406},
1407
88e2cdaa 1408// Derivation path for address can be hardened
4974fd7f
IC
1409function() {
1410page.open(url, function(status) {
1411 // set the phrase
1412 var expected = "18exLzUv7kfpiXRzmCjFDoC9qwNLFyvwyd";
1413 page.evaluate(function() {
1414 $(".phrase").val("abandon abandon ability");
1415 $(".phrase").trigger("input");
1416 });
1417 // change tabs
1418 waitForGenerate(function() {
1419 page.evaluate(function() {
1420 $("#bip32-tab a").click();
1421 });
1422 waitForGenerate(function() {
1423 // select the hardened addresses option
1424 page.evaluate(function() {
1425 $(".hardened-addresses").prop("checked", true);
1426 $(".hardened-addresses").trigger("change");
1427 });
1428 waitForGenerate(function() {
1429 // check the generated address is hardened
1430 var actual = page.evaluate(function() {
1431 return $(".address:first").text();
1432 });
1433 if (actual != expected) {
1434 console.log("Hardened address is incorrect");
1435 console.log("Expected: " + expected);
1436 console.log("Actual: " + actual);
1437 fail();
1438 }
1439 next();
1440 });
1441 });
1442 });
1443});
1444},
1445
88e2cdaa 1446// Derivation path visibility can be toggled
a775b5c6
IC
1447function() {
1448page.open(url, function(status) {
1449 // set the phrase
1450 page.evaluate(function() {
1451 $(".phrase").val("abandon abandon ability");
1452 $(".phrase").trigger("input");
1453 });
a775b5c6
IC
1454 waitForGenerate(function() {
1455 // toggle path visibility
1456 page.evaluate(function() {
1457 $(".index-toggle").click();
1458 });
1459 // check the path is not visible
1460 var isInvisible = page.evaluate(function() {
1461 return $(".index:first span").hasClass("invisible");
1462 });
1463 if (!isInvisible) {
1464 console.log("Toggled derivation path is visible");
1465 fail();
1466 }
1467 next();
1468 });
1469});
1470},
1471
88e2cdaa 1472// Address is shown
06c4c6e3
IC
1473function() {
1474page.open(url, function(status) {
1475 var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug";
1476 // set the phrase
1477 page.evaluate(function() {
1478 $(".phrase").val("abandon abandon ability").trigger("input");
1479 });
1480 // get the address
1481 waitForGenerate(function() {
1482 var actual = page.evaluate(function() {
1483 return $(".address:first").text();
1484 });
1485 if (actual != expected) {
1486 console.log("Address is not shown");
1487 console.log("Expected: " + expected);
1488 console.log("Got: " + actual);
1489 fail();
1490 }
1491 next();
1492 });
1493});
1494},
1495
88e2cdaa 1496// Addresses are shown in order of derivation path
3f1faa4d
IC
1497function() {
1498page.open(url, function(status) {
1499 // set the phrase
1500 page.evaluate(function() {
1501 $(".phrase").val("abandon abandon ability").trigger("input");
1502 });
1503 // get the derivation paths
1504 waitForGenerate(function() {
1505 var paths = page.evaluate(function() {
1506 return $(".index").map(function(i, e) {
1507 return $(e).text();
1508 });
1509 });
1510 if (paths.length != 20) {
1511 console.log("Total paths is less than expected: " + paths.length);
1512 fail();
1513 }
1514 for (var i=0; i<paths.length; i++) {
1515 var expected = "m/44'/0'/0'/0/" + i;
1516 var actual = paths[i];
1517 if (actual != expected) {
1518 console.log("Path " + i + " is incorrect");
1519 console.log("Expected: " + expected);
1520 console.log("Actual: " + actual);
1521 fail();
1522 }
1523 }
1524 next();
1525 });
1526});
1527},
21372fab 1528
88e2cdaa 1529// Address visibility can be toggled
21372fab
IC
1530function() {
1531page.open(url, function(status) {
1532 // set the phrase
1533 page.evaluate(function() {
1534 $(".phrase").val("abandon abandon ability");
1535 $(".phrase").trigger("input");
1536 });
1537 waitForGenerate(function() {
1538 // toggle address visibility
1539 page.evaluate(function() {
1540 $(".address-toggle").click();
1541 });
1542 // check the address is not visible
1543 var isInvisible = page.evaluate(function() {
1544 return $(".address:first span").hasClass("invisible");
1545 });
1546 if (!isInvisible) {
1547 console.log("Toggled address is visible");
1548 fail();
1549 }
1550 next();
1551 });
1552});
1553},
1554
1b12b2f5
IC
1555// Public key is shown
1556function() {
1557page.open(url, function(status) {
1558 var expected = "033f5aed5f6cfbafaf223188095b5980814897295f723815fea5d3f4b648d0d0b3";
1559 // set the phrase
1560 page.evaluate(function() {
1561 $(".phrase").val("abandon abandon ability").trigger("input");
1562 });
1563 // get the address
1564 waitForGenerate(function() {
1565 var actual = page.evaluate(function() {
1566 return $(".pubkey:first").text();
1567 });
1568 if (actual != expected) {
1569 console.log("Public key is not shown");
1570 console.log("Expected: " + expected);
1571 console.log("Got: " + actual);
1572 fail();
1573 }
1574 next();
1575 });
1576});
1577},
1578
1579// Public key visibility can be toggled
1580function() {
1581page.open(url, function(status) {
1582 // set the phrase
1583 page.evaluate(function() {
1584 $(".phrase").val("abandon abandon ability");
1585 $(".phrase").trigger("input");
1586 });
1587 waitForGenerate(function() {
1588 // toggle public key visibility
1589 page.evaluate(function() {
1590 $(".public-key-toggle").click();
1591 });
1592 // check the public key is not visible
1593 var isInvisible = page.evaluate(function() {
1594 return $(".pubkey:first span").hasClass("invisible");
1595 });
1596 if (!isInvisible) {
1597 console.log("Toggled public key is visible");
1598 fail();
1599 }
1600 next();
1601 });
1602});
1603},
1604
88e2cdaa 1605// Private key is shown
8cd5e231
IC
1606function() {
1607page.open(url, function(status) {
1608 var expected = "L26cVSpWFkJ6aQkPkKmTzLqTdLJ923e6CzrVh9cmx21QHsoUmrEE";
1609 // set the phrase
1610 page.evaluate(function() {
1611 $(".phrase").val("abandon abandon ability").trigger("input");
1612 });
1613 // get the address
1614 waitForGenerate(function() {
1615 var actual = page.evaluate(function() {
1616 return $(".privkey:first").text();
1617 });
1618 if (actual != expected) {
1619 console.log("Private key is not shown");
1620 console.log("Expected: " + expected);
1621 console.log("Got: " + actual);
1622 fail();
1623 }
1624 next();
1625 });
1626});
1627},
1628
88e2cdaa 1629// Private key visibility can be toggled
6848d03b
IC
1630function() {
1631page.open(url, function(status) {
1632 // set the phrase
1633 page.evaluate(function() {
1634 $(".phrase").val("abandon abandon ability");
1635 $(".phrase").trigger("input");
1636 });
1637 waitForGenerate(function() {
1638 // toggle private key visibility
1639 page.evaluate(function() {
1640 $(".private-key-toggle").click();
1641 });
1642 // check the private key is not visible
1643 var isInvisible = page.evaluate(function() {
1644 return $(".privkey:first span").hasClass("invisible");
1645 });
1646 if (!isInvisible) {
1647 console.log("Toggled private key is visible");
1648 fail();
1649 }
1650 next();
1651 });
1652});
1653},
88e2cdaa
IC
1654
1655// More addresses can be generated
35631659
IC
1656function() {
1657page.open(url, function(status) {
1658 // set the phrase
1659 page.evaluate(function() {
1660 $(".phrase").val("abandon abandon ability");
1661 $(".phrase").trigger("input");
1662 });
1663 waitForGenerate(function() {
1664 // generate more addresses
1665 page.evaluate(function() {
1666 $(".more").click();
1667 });
1668 waitForGenerate(function() {
1669 // check there are more addresses
1670 var addressCount = page.evaluate(function() {
1671 return $(".address").length;
1672 });
1673 if (addressCount != 40) {
1674 console.log("More addresses cannot be generated");
1675 fail();
1676 }
1677 next();
1678 });
1679 });
1680});
1681},
1682
88e2cdaa 1683// A custom number of additional addresses can be generated
8a89b9da
IC
1684function() {
1685page.open(url, function(status) {
1686 // set the phrase
1687 page.evaluate(function() {
1688 $(".phrase").val("abandon abandon ability");
1689 $(".phrase").trigger("input");
1690 });
1691 waitForGenerate(function() {
1692 // get the current number of addresses
1693 var oldAddressCount = page.evaluate(function() {
1694 return $(".address").length;
1695 });
1696 // set a custom number of additional addresses
1697 page.evaluate(function() {
1698 $(".rows-to-add").val(1);
1699 });
1700 // generate more addresses
1701 page.evaluate(function() {
1702 $(".more").click();
1703 });
1704 waitForGenerate(function() {
1705 // check there are the correct number of addresses
1706 var newAddressCount = page.evaluate(function() {
1707 return $(".address").length;
1708 });
1709 if (newAddressCount - oldAddressCount != 1) {
1710 console.log("Number of additional addresses cannot be customized");
1711 console.log(newAddressCount)
1712 console.log(oldAddressCount)
1713 fail();
1714 }
1715 next();
1716 });
1717 });
1718});
1719},
1720
88e2cdaa 1721// Additional addresses are shown in order of derivation path
4d387bf5
IC
1722function() {
1723page.open(url, function(status) {
1724 // set the phrase
1725 page.evaluate(function() {
1726 $(".phrase").val("abandon abandon ability").trigger("input");
1727 });
1728 waitForGenerate(function() {
1729 // generate more addresses
1730 page.evaluate(function() {
1731 $(".more").click();
1732 });
1733 // get the derivation paths
1734 waitForGenerate(function() {
1735 var paths = page.evaluate(function() {
1736 return $(".index").map(function(i, e) {
1737 return $(e).text();
1738 });
1739 });
1740 if (paths.length != 40) {
1741 console.log("Total additional paths is less than expected: " + paths.length);
1742 fail();
1743 }
1744 for (var i=0; i<paths.length; i++) {
1745 var expected = "m/44'/0'/0'/0/" + i;
1746 var actual = paths[i];
1747 if (actual != expected) {
1748 console.log("Path " + i + " is not in correct order");
1749 console.log("Expected: " + expected);
1750 console.log("Actual: " + actual);
1751 fail();
1752 }
1753 }
1754 next();
1755 });
1756 });
1757});
1758},
88e2cdaa
IC
1759
1760// BIP32 root key can be set by the user
61ed16a9
IC
1761function() {
1762page.open(url, function(status) {
1763 var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug";
1764 // set the root key
1765 page.evaluate(function() {
1766 $(".root-key").val("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi").trigger("input");
1767 });
1768 waitForGenerate(function() {
1769 var actual = page.evaluate(function() {
1770 return $(".address:first").text();
1771 });
1772 if (actual != expected) {
bc324fd2 1773 console.log("Setting BIP32 root key results in wrong address");
61ed16a9
IC
1774 console.log("Expected: " + expected);
1775 console.log("Actual: " + actual);
1776 fail();
1777 }
1778 next();
1779 });
1780});
1781},
1782
54563907 1783// Setting BIP32 root key clears the existing phrase, passphrase and seed
bc324fd2
IC
1784function() {
1785page.open(url, function(status) {
1786 var expected = "";
1787 // set a mnemonic
1788 page.evaluate(function() {
1789 $(".phrase").val("A non-blank but invalid value");
1790 });
1791 // Accept any confirm dialogs
1792 page.onConfirm = function() {
1793 return true;
1794 };
1795 // set the root key
1796 page.evaluate(function() {
1797 $(".root-key").val("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi").trigger("input");
1798 });
1799 waitForGenerate(function() {
1800 var actual = page.evaluate(function() {
1801 return $(".phrase").val();
1802 });
1803 if (actual != expected) {
1804 console.log("Phrase not cleared when setting BIP32 root key");
1805 console.log("Expected: " + expected);
1806 console.log("Actual: " + actual);
1807 fail();
1808 }
1809 next();
1810 });
1811});
1812},
1813
54563907 1814// Clearing of phrase, passphrase and seed can be cancelled by user
abfbe450
IC
1815function() {
1816page.open(url, function(status) {
1817 var expected = "abandon abandon ability";
1818 // set a mnemonic
1819 page.evaluate(function() {
1820 $(".phrase").val("abandon abandon ability");
1821 });
1822 // Cancel any confirm dialogs
1823 page.onConfirm = function() {
1824 return false;
1825 };
1826 // set the root key
1827 page.evaluate(function() {
1828 $(".root-key").val("xprv9s21ZrQH143K3d3vzEDD3KpSKmxsZ3y7CqhAL1tinwtP6wqK4TKEKjpBuo6P2hUhB6ZENo7TTSRytiP857hBZVpBdk8PooFuRspE1eywwNZ").trigger("input");
1829 });
1830 var actual = page.evaluate(function() {
1831 return $(".phrase").val();
1832 });
1833 if (actual != expected) {
1834 console.log("Phrase not retained when cancelling changes to BIP32 root key");
1835 console.log("Expected: " + expected);
1836 console.log("Actual: " + actual);
1837 fail();
1838 }
1839 next();
1840});
1841},
7ff86d4c 1842
88e2cdaa 1843// Custom BIP32 root key is used when changing the derivation path
7ff86d4c
IC
1844function() {
1845page.open(url, function(status) {
1846 var expected = "1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H";
1847 // set the root key
1848 page.evaluate(function() {
1849 $(".root-key").val("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi").trigger("input");
1850 });
1851 waitForGenerate(function() {
1852 // change the derivation path
1853 page.evaluate(function() {
1854 $("#account").val("1").trigger("input");
1855 });
1856 // check the bip32 root key is used for derivation, not the blank phrase
1857 waitForGenerate(function() {
1858 var actual = page.evaluate(function() {
1859 return $(".address:first").text();
1860 });
1861 if (actual != expected) {
1862 console.log("Changing the derivation path does not use BIP32 root key");
1863 console.log("Expected: " + expected);
1864 console.log("Actual: " + actual);
1865 fail();
1866 }
1867 next();
1868 });
1869 });
1870});
1871},
88e2cdaa
IC
1872
1873// Incorrect mnemonic shows error
c3719b00
IC
1874function() {
1875page.open(url, function(status) {
1876 // set the root key
1877 page.evaluate(function() {
1878 $(".phrase").val("abandon abandon abandon").trigger("input");
1879 });
1880 waitForFeedback(function() {
1881 // check there is an error shown
1882 var feedback = page.evaluate(function() {
1883 return $(".feedback").text();
1884 });
1885 if (feedback.length <= 0) {
1886 console.log("Invalid mnemonic does not show error");
1887 fail();
1888 }
1889 next();
1890 });
1891});
1892},
1893
88e2cdaa 1894// Incorrect word shows suggested replacement
20f80cfa
IC
1895function() {
1896page.open(url, function(status) {
1897 // set the root key
1898 page.evaluate(function() {
1899 $(".phrase").val("abandon abandon abiliti").trigger("input");
1900 });
1901 // check there is a suggestion shown
1902 waitForFeedback(function() {
1903 var feedback = page.evaluate(function() {
1904 return $(".feedback").text();
1905 });
1906 if (feedback.indexOf("did you mean ability?") < 0) {
1907 console.log("Incorrect word does not show suggested replacement");
1908 console.log("Error: " + error);
1909 fail();
6ea15134
IC
1910 }
1911 next();
1912 });
1913});
1914},
1915
1916// Github pull request 48
1917// First four letters of word shows that word, not closest
1918// since first four letters gives unique word in BIP39 wordlist
1919// eg ille should show illegal, not idle
1920function() {
1921page.open(url, function(status) {
1922 // set the incomplete word
1923 page.evaluate(function() {
1924 $(".phrase").val("ille").trigger("input");
1925 });
1926 // check there is a suggestion shown
1927 waitForFeedback(function() {
1928 var feedback = page.evaluate(function() {
1929 return $(".feedback").text();
1930 });
1931 if (feedback.indexOf("did you mean illegal?") < 0) {
1932 console.log("Start of word does not show correct suggestion");
1933 console.log("Error: " + error);
1934 fail();
20f80cfa
IC
1935 }
1936 next();
1937 });
1938});
1939},
1940
88e2cdaa 1941// Incorrect BIP32 root key shows error
02f4a90e
IC
1942function() {
1943page.open(url, function(status) {
1944 // set the root key
1945 page.evaluate(function() {
1946 $(".root-key").val("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpj").trigger("input");
1947 });
1948 // check there is an error shown
1949 waitForFeedback(function() {
1950 var feedback = page.evaluate(function() {
1951 return $(".feedback").text();
1952 });
1953 if (feedback != "Invalid root key") {
1954 console.log("Invalid root key does not show error");
1955 console.log("Error: " + error);
1956 fail();
1957 }
1958 next();
1959 });
1960});
1961},
1962
88e2cdaa 1963// Derivation path not starting with m shows error
f976b541
IC
1964function() {
1965page.open(url, function(status) {
1966 // set the mnemonic phrase
1967 page.evaluate(function() {
1968 $(".phrase").val("abandon abandon ability").trigger("input");
1969 });
1970 waitForGenerate(function() {
1971 // select the bip32 tab so custom derivation path can be set
1972 page.evaluate(function() {
1973 $("#bip32-tab a").click();
1974 });
1975 waitForGenerate(function() {
1976 // set the incorrect derivation path
1977 page.evaluate(function() {
1978 $("#bip32 .path").val("n/0").trigger("input");
1979 });
1980 waitForFeedback(function() {
1981 var feedback = page.evaluate(function() {
1982 return $(".feedback").text();
1983 });
1984 if (feedback != "First character must be 'm'") {
1985 console.log("Derivation path not starting with m should show error");
1986 console.log("Error: " + error);
1987 fail();
1988 }
1989 next();
1990 });
1991 });
1992 });
1993});
1994},
1995
88e2cdaa 1996// Derivation path containing invalid characters shows useful error
55c0ffcb
IC
1997function() {
1998page.open(url, function(status) {
1999 // set the mnemonic phrase
2000 page.evaluate(function() {
2001 $(".phrase").val("abandon abandon ability").trigger("input");
2002 });
2003 waitForGenerate(function() {
2004 // select the bip32 tab so custom derivation path can be set
2005 page.evaluate(function() {
2006 $("#bip32-tab a").click();
2007 });
2008 waitForGenerate(function() {
2009 // set the incorrect derivation path
2010 page.evaluate(function() {
2011 $("#bip32 .path").val("m/1/0wrong1/1").trigger("input");
2012 });
2013 waitForFeedback(function() {
2014 var feedback = page.evaluate(function() {
2015 return $(".feedback").text();
2016 });
2017 if (feedback != "Invalid characters 0wrong1 found at depth 2") {
2018 console.log("Derivation path with invalid characters should show error");
2019 console.log("Error: " + error);
2020 fail();
2021 }
2022 next();
2023 });
2024 });
2025 });
2026});
2027},
88e2cdaa
IC
2028
2029// Github Issue 11: Default word length is 15
b630f83d 2030// https://github.com/iancoleman/bip39/issues/11
ca976aa9
IC
2031function() {
2032page.open(url, function(status) {
2033 // get the word length
2034 var defaultLength = page.evaluate(function() {
2035 return $(".strength").val();
2036 });
2037 if (defaultLength != 15) {
2038 console.log("Default word length is not 15");
2039 fail();
2040 }
2041 next();
2042});
2043},
2044
88e2cdaa
IC
2045
2046// Github Issue 12: Generate more rows with private keys hidden
b630f83d 2047// https://github.com/iancoleman/bip39/issues/12
c97627fa
IC
2048function() {
2049page.open(url, function(status) {
2050 // set the phrase
2051 page.evaluate(function() {
2052 $(".phrase").val("abandon abandon ability");
2053 $(".phrase").trigger("input");
2054 });
2055 waitForGenerate(function() {
2056 // toggle private keys hidden, then generate more addresses
2057 page.evaluate(function() {
2058 $(".private-key-toggle").click();
2059 $(".more").click();
2060 });
2061 waitForGenerate(function() {
2062 // check more have been generated
2063 var expected = 40;
2064 var numPrivKeys = page.evaluate(function() {
2065 return $(".privkey").length;
2066 });
2067 if (numPrivKeys != expected) {
2068 console.log("Wrong number of addresses when clicking 'more' with hidden privkeys");
2069 console.log("Expected: " + expected);
2070 console.log("Actual: " + numPrivKeys);
2071 fail();
2072 }
2073 // check no private keys are shown
2074 var numHiddenPrivKeys = page.evaluate(function() {
2075 return $(".privkey span[class=invisible]").length;
2076 });
2077 if (numHiddenPrivKeys != expected) {
2078 console.log("Generating more does not retain hidden state of privkeys");
2079 console.log("Expected: " + expected);
2080 console.log("Actual: " + numHiddenPrivKeys);
2081 fail();
2082 }
2083 next();
2084 });
2085 });
2086});
2087},
88e2cdaa
IC
2088
2089// Github Issue 19: Mnemonic is not sensitive to whitespace
b630f83d 2090// https://github.com/iancoleman/bip39/issues/19
a7becc43
IC
2091function() {
2092page.open(url, function(status) {
2093 // set the phrase
2094 var expected = "xprv9s21ZrQH143K3isaZsWbKVoTtbvd34Y1ZGRugGdMeBGbM3AgBVzTH159mj1cbbtYSJtQr65w6L5xy5L9SFC7c9VJZWHxgAzpj4mun5LhrbC";
2095 page.evaluate(function() {
2096 var doubleSpace = " ";
2097 $(".phrase").val("urge cat" + doubleSpace + "bid");
2098 $(".phrase").trigger("input");
2099 });
2100 waitForGenerate(function() {
2101 // Check the bip32 root key is correct
2102 var actual = page.evaluate(function() {
2103 return $(".root-key").val();
2104 });
2105 if (actual != expected) {
2106 console.log("Mnemonic is sensitive to whitespace");
2107 console.log("Expected: " + expected);
2108 console.log("Actual: " + actual);
2109 fail();
2110 }
2111 next();
2112 });
2113});
2114},
88e2cdaa 2115
e3001539 2116// Github Issue 23: Part 1: Use correct derivation path when changing tabs
b630f83d 2117// https://github.com/iancoleman/bip39/issues/23
e3001539
IC
2118function() {
2119page.open(url, function(status) {
2120 // 1) and 2) set the phrase
2121 page.evaluate(function() {
2122 $(".phrase").val("abandon abandon ability").trigger("input");
2123 });
2124 waitForGenerate(function() {
2125 // 3) select bip32 tab
2126 page.evaluate(function() {
2127 $("#bip32-tab a").click();
2128 });
2129 waitForGenerate(function() {
2130 // 4) switch from bitcoin to litecoin
2131 page.evaluate(function() {
52d589ea 2132 $(".network option").filter(function() {
534481b6 2133 return $(this).html() == "LTC - Litecoin";
52d589ea
IC
2134 }).prop("selected", true);
2135 $(".network").trigger("change");
e3001539
IC
2136 });
2137 waitForGenerate(function() {
2138 // 5) Check derivation path is displayed correctly
2139 var expected = "m/0/0";
2140 var actual = page.evaluate(function() {
2141 return $(".index:first").text();
2142 });
2143 if (actual != expected) {
2144 console.log("Github Issue 23 Part 1: derivation path display error");
2145 console.log("Expected: " + expected);
2146 console.log("Actual: " + actual);
2147 fail();
2148 }
2149 // 5) Check address is displayed correctly
2150 var expected = "LS8MP5LZ5AdzSZveRrjm3aYVoPgnfFh5T5";
2151 var actual = page.evaluate(function() {
2152 return $(".address:first").text();
2153 });
2154 if (actual != expected) {
2155 console.log("Github Issue 23 Part 1: address display error");
2156 console.log("Expected: " + expected);
2157 console.log("Actual: " + actual);
2158 fail();
2159 }
2160 next();
2161 });
2162 });
2163 });
2164});
2165},
2166
2167// Github Issue 23 Part 2: Coin selection in derivation path
b630f83d 2168// https://github.com/iancoleman/bip39/issues/23#issuecomment-238011920
af4fd3a2
IC
2169function() {
2170page.open(url, function(status) {
2171 // set the phrase
2172 page.evaluate(function() {
2173 $(".phrase").val("abandon abandon ability").trigger("input");
2174 });
2175 waitForGenerate(function() {
2176 // switch from bitcoin to clam
2177 page.evaluate(function() {
52d589ea 2178 $(".network option").filter(function() {
534481b6 2179 return $(this).html() == "CLAM - Clams";
52d589ea
IC
2180 }).prop("selected", true);
2181 $(".network").trigger("change");
af4fd3a2
IC
2182 });
2183 waitForGenerate(function() {
2184 // check derivation path is displayed correctly
2185 var expected = "m/44'/23'/0'/0/0";
2186 var actual = page.evaluate(function() {
2187 return $(".index:first").text();
2188 });
2189 if (actual != expected) {
2190 console.log("Github Issue 23 Part 2: Coin in BIP44 derivation path is incorrect");
2191 console.log("Expected: " + expected);
2192 console.log("Actual: " + actual);
2193 fail();
2194 }
2195 next();
2196 });
2197 });
2198});
2199},
88e2cdaa 2200
f3d0aca1 2201// Github Issue 26: When using a Root key derrived altcoins are incorrect
b630f83d 2202// https://github.com/iancoleman/bip39/issues/26
558ef9ac
IC
2203function() {
2204page.open(url, function(status) {
2205 // 1) 2) and 3) set the root key
2206 page.evaluate(function() {
2207 $(".root-key").val("xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi").trigger("input");
2208 });
2209 waitForGenerate(function() {
2210 // 4) switch from bitcoin to viacoin
2211 page.evaluate(function() {
52d589ea 2212 $(".network option").filter(function() {
534481b6 2213 return $(this).html() == "VIA - Viacoin";
52d589ea
IC
2214 }).prop("selected", true);
2215 $(".network").trigger("change");
558ef9ac
IC
2216 });
2217 waitForGenerate(function() {
2218 // 5) ensure the derived address is correct
2219 var expected = "Vq9Eq4N5SQnjqZvxtxzo7hZPW5XnyJsmXT";
2220 var actual = page.evaluate(function() {
2221 return $(".address:first").text();
2222 });
2223 if (actual != expected) {
2224 console.log("Github Issue 26: address is incorrect when changing networks and using root-key to derive");
2225 console.log("Expected: " + expected);
2226 console.log("Actual: " + actual);
2227 fail();
2228 }
2229 next();
2230 });
2231 });
2232});
2233},
f3d0aca1 2234
e1bae843
IC
2235// Selecting a language with no existing phrase should generate a phrase in
2236// that language.
2237function() {
2238page.open(url, function(status) {
2239 // Select a language
2240 // Need to manually simulate hash being set due to quirk between
2241 // 'click' event triggered by javascript vs triggered by mouse.
2242 // Perhaps look into page.sendEvent
2243 // http://phantomjs.org/api/webpage/method/send-event.html
2244 page.evaluate(function() {
2245 window.location.hash = "#japanese";
2246 $("a[href='#japanese']").trigger("click");
2247 });
2248 waitForGenerate(function() {
2249 // Check the mnemonic is in Japanese
2250 var phrase = page.evaluate(function() {
2251 return $(".phrase").val();
2252 });
2253 if (phrase.length <= 0) {
2254 console.log("No Japanese phrase generated");
2255 fail();
2256 }
2257 if (phrase.charCodeAt(0) < 128) {
2258 console.log("First character of Japanese phrase is ascii");
2259 console.log("Phrase: " + phrase);
2260 fail();
2261 }
2262 next();
2263 });
2264});
2265},
2266
2267// Selecting a language with existing phrase should update the phrase to use
2268// that language.
2269function() {
2270page.open(url, function(status) {
2271 // Set the phrase to an English phrase.
2272 page.evaluate(function() {
2273 $(".phrase").val("abandon abandon ability").trigger("input");
2274 });
2275 waitForGenerate(function() {
2276 // Change to Italian
2277 // Need to manually simulate hash being set due to quirk between
2278 // 'click' event triggered by javascript vs triggered by mouse.
2279 // Perhaps look into page.sendEvent
2280 // http://phantomjs.org/api/webpage/method/send-event.html
2281 page.evaluate(function() {
2282 window.location.hash = "#italian";
2283 $("a[href='#italian']").trigger("click");
2284 });
2285 waitForGenerate(function() {
2286 // Check only the language changes, not the phrase
2287 var expected = "abaco abaco abbaglio";
2288 var actual = page.evaluate(function() {
2289 return $(".phrase").val();
2290 });
2291 if (actual != expected) {
2292 console.log("Changing language with existing phrase");
2293 console.log("Expected: " + expected);
2294 console.log("Actual: " + actual);
2295 fail();
2296 }
2297 // Check the address is correct
2298 var expected = "1Dz5TgDhdki9spa6xbPFbBqv5sjMrx3xgV";
2299 var actual = page.evaluate(function() {
2300 return $(".address:first").text();
2301 });
2302 if (actual != expected) {
2303 console.log("Changing language generates incorrect address");
2304 console.log("Expected: " + expected);
2305 console.log("Actual: " + actual);
2306 fail();
2307 }
2308 next();
2309 });
2310 });
2311});
2312},
2313
2314// Suggested replacement for erroneous word in non-English language
2315function() {
2316page.open(url, function(status) {
2317 // Set an incorrect phrase in Italian
2318 page.evaluate(function() {
2319 $(".phrase").val("abaco abaco zbbaglio").trigger("input");
2320 });
2321 waitForFeedback(function() {
2322 // Check the suggestion is correct
2323 var feedback = page.evaluate(function() {
2324 return $(".feedback").text();
2325 });
2326 if (feedback.indexOf("did you mean abbaglio?") < 0) {
2327 console.log("Incorrect Italian word does not show suggested replacement");
2328 console.log("Error: " + error);
2329 fail();
2330 }
2331 next();
2332 });
2333});
2334},
2335
2336
2337// Japanese word does not break across lines.
2338// Point 2 from
2339// https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md#japanese
2340function() {
2341page.open(url, function(status) {
2342 hasWordBreakCss = page.content.indexOf("word-break: keep-all;") > -1;
2343 if (!hasWordBreakCss) {
2344 console.log("Japanese words can break across lines mid-word");
2345 console.log("Check CSS for '.phrase { word-break: keep-all; }'");
2346 fail();
2347 }
2348 // Run the next test
2349 next();
2350});
2351},
2352
2353// Language can be specified at page load using hash value in url
2354function() {
2355page.open(url, function(status) {
2356 // Set the page hash as if it were on a fresh page load
2357 page.evaluate(function() {
2358 window.location.hash = "#japanese";
2359 });
2360 // Generate a random phrase
2361 page.evaluate(function() {
2362 $(".generate").trigger("click");
2363 });
2364 waitForGenerate(function() {
2365 // Check the phrase is in Japanese
2366 var phrase = page.evaluate(function() {
2367 return $(".phrase").val();
2368 });
2369 if (phrase.length <= 0) {
2370 console.log("No phrase generated using url hash");
2371 fail();
2372 }
2373 if (phrase.charCodeAt(0) < 128) {
2374 console.log("Language not detected from url hash on page load.");
2375 console.log("Phrase: " + phrase);
2376 fail();
2377 }
2378 next();
2379 });
2380});
2381},
2382
c6624d51
IC
2383// Entropy unit tests
2384function() {
2385page.open(url, function(status) {
adc8ce12 2386 var response = page.evaluate(function() {
c6624d51
IC
2387 var e;
2388 // binary entropy is detected
adc8ce12
IC
2389 try {
2390 e = Entropy.fromString("01010101");
2391 if (e.base.str != "binary") {
2392 return "Binary entropy not detected correctly";
2393 }
2394 }
2395 catch (e) {
2396 return e.message;
c6624d51
IC
2397 }
2398 // base6 entropy is detected
adc8ce12
IC
2399 try {
2400 e = Entropy.fromString("012345012345");
2401 if (e.base.str != "base 6") {
2402 return "base6 entropy not detected correctly";
2403 }
2404 }
2405 catch (e) {
2406 return e.message;
c6624d51
IC
2407 }
2408 // dice entropy is detected
adc8ce12
IC
2409 try {
2410 e = Entropy.fromString("123456123456");
2411 if (e.base.str != "base 6 (dice)") {
2412 return "dice entropy not detected correctly";
2413 }
2414 }
2415 catch (e) {
2416 return e.message;
c6624d51
IC
2417 }
2418 // base10 entropy is detected
adc8ce12
IC
2419 try {
2420 e = Entropy.fromString("0123456789");
2421 if (e.base.str != "base 10") {
2422 return "base10 entropy not detected correctly";
2423 }
2424 }
2425 catch (e) {
2426 return e.message;
c6624d51
IC
2427 }
2428 // hex entropy is detected
adc8ce12
IC
2429 try {
2430 e = Entropy.fromString("0123456789ABCDEF");
2431 if (e.base.str != "hexadecimal") {
2432 return "hexadecimal entropy not detected correctly";
2433 }
2434 }
2435 catch (e) {
2436 return e.message;
2437 }
2438 // card entropy is detected
2439 try {
2440 e = Entropy.fromString("AC4DTHKS");
2441 if (e.base.str != "card") {
2442 return "card entropy not detected correctly";
2443 }
2444 }
2445 catch (e) {
2446 return e.message;
c6624d51
IC
2447 }
2448 // entropy is case insensitive
adc8ce12
IC
2449 try {
2450 e = Entropy.fromString("aBcDeF");
2451 if (e.cleanStr != "aBcDeF") {
2452 return "Entropy should not be case sensitive";
2453 }
2454 }
2455 catch (e) {
2456 return e.message;
c6624d51
IC
2457 }
2458 // dice entropy is converted to base6
adc8ce12
IC
2459 try {
2460 e = Entropy.fromString("123456");
425b75a9 2461 if (e.cleanStr != "123450") {
adc8ce12
IC
2462 return "Dice entropy is not automatically converted to base6";
2463 }
2464 }
2465 catch (e) {
2466 return e.message;
c6624d51
IC
2467 }
2468 // dice entropy is preferred to base6 if ambiguous
adc8ce12
IC
2469 try {
2470 e = Entropy.fromString("12345");
2471 if (e.base.str != "base 6 (dice)") {
2472 return "dice not used as default over base 6";
2473 }
2474 }
2475 catch (e) {
2476 return e.message;
c6624d51
IC
2477 }
2478 // unused characters are ignored
adc8ce12
IC
2479 try {
2480 e = Entropy.fromString("fghijkl");
2481 if (e.cleanStr != "f") {
2482 return "additional characters are not ignored";
2483 }
2484 }
2485 catch (e) {
2486 return e.message;
c6624d51
IC
2487 }
2488 // the lowest base is used by default
2489 // 7 could be decimal or hexadecimal, but should be detected as decimal
adc8ce12
IC
2490 try {
2491 e = Entropy.fromString("7");
2492 if (e.base.str != "base 10") {
2493 return "lowest base is not used";
2494 }
c6624d51 2495 }
adc8ce12
IC
2496 catch (e) {
2497 return e.message;
c6624d51
IC
2498 }
2499 // Leading zeros are retained
adc8ce12
IC
2500 try {
2501 e = Entropy.fromString("000A");
2502 if (e.cleanStr != "000A") {
2503 return "Leading zeros are not retained";
2504 }
2505 }
2506 catch (e) {
2507 return e.message;
c6624d51
IC
2508 }
2509 // Leading zeros are correctly preserved for hex in binary string
adc8ce12
IC
2510 try {
2511 e = Entropy.fromString("2A");
2512 if (e.binaryStr != "00101010") {
2513 return "Hex leading zeros are not correct in binary";
2514 }
2515 }
2516 catch (e) {
2517 return e.message;
2518 }
1cf1bbaf
IC
2519 // Leading zeros for base 6 as binary string
2520 // 20 = 2 events at 2.58 bits per event = 5 bits
2521 // 20 in base 6 = 12 in base 10 = 1100 in base 2
2522 // so it needs 1 bit of padding to be the right bit length
adc8ce12 2523 try {
1cf1bbaf
IC
2524 e = Entropy.fromString("20");
2525 if (e.binaryStr != "01100") {
0d0f07f9
IC
2526 return "Base 6 as binary has leading zeros";
2527 }
2528 }
2529 catch (e) {
2530 return e.message;
2531 }
1cf1bbaf 2532 // Leading zeros for base 10 as binary string
0d0f07f9 2533 try {
1cf1bbaf
IC
2534 e = Entropy.fromString("17");
2535 if (e.binaryStr != "010001") {
0d0f07f9
IC
2536 return "Base 10 as binary has leading zeros";
2537 }
2538 }
2539 catch (e) {
2540 return e.message;
2541 }
87ad2c6e 2542 // Leading zeros for card entropy as binary string.
9d33c892 2543 // Card entropy is hashed so 2c does not necessarily produce leading zeros.
0d0f07f9 2544 try {
9d33c892
IC
2545 e = Entropy.fromString("2c");
2546 if (e.binaryStr != "0010") {
0d0f07f9 2547 return "Card entropy as binary has leading zeros";
adc8ce12
IC
2548 }
2549 }
2550 catch (e) {
2551 return e.message;
c6624d51
IC
2552 }
2553 // Keyboard mashing results in weak entropy
2554 // Despite being a long string, it's less than 30 bits of entropy
adc8ce12
IC
2555 try {
2556 e = Entropy.fromString("aj;se ifj; ask,dfv js;ifj");
2557 if (e.binaryStr.length >= 30) {
2558 return "Keyboard mashing should produce weak entropy";
2559 }
c6624d51 2560 }
adc8ce12
IC
2561 catch (e) {
2562 return e.message;
2563 }
2564 // Card entropy is used if every pair could be a card
2565 try {
2566 e = Entropy.fromString("4c3c2c");
2567 if (e.base.str != "card") {
2568 return "Card entropy not used if all pairs are cards";
2569 }
2570 }
2571 catch (e) {
2572 return e.message;
2573 }
2574 // Card entropy uses base 52
2575 // [ cards, binary ]
2576 try {
2577 var cards = [
9d33c892
IC
2578 [ "ac", "0101" ],
2579 [ "acqs", "11011100" ],
2580 [ "acks", "01011100" ],
2581 [ "2cac", "11111000" ],
2582 [ "2c", "0010" ],
2583 [ "3d", "0001" ],
2584 [ "4h", "1001" ],
87ad2c6e 2585 [ "5s", "1001" ],
9d33c892
IC
2586 [ "6c", "0000" ],
2587 [ "7d", "0001" ],
87ad2c6e 2588 [ "8h", "1011" ],
9d33c892
IC
2589 [ "9s", "0010" ],
2590 [ "tc", "1001" ],
2591 [ "jd", "1111" ],
2592 [ "qh", "0010" ],
2593 [ "ks", "0101" ],
2594 [ "ks2c", "01010100" ],
2595 [ "KS2C", "01010100" ],
adc8ce12
IC
2596 ];
2597 for (var i=0; i<cards.length; i++) {
2598 var card = cards[i][0];
2599 var result = cards[i][1];
2600 e = Entropy.fromString(card);
2601 console.log(e.binary + " " + result);
2602 if (e.binaryStr !== result) {
886f06ee 2603 return "card entropy " + card + " not parsed correctly: " + result + " != " + e.binaryStr;
adc8ce12
IC
2604 }
2605 }
2606 }
2607 catch (e) {
2608 return e.message;
2609 }
2610 return "PASS";
c6624d51 2611 });
adc8ce12 2612 if (response != "PASS") {
c6624d51 2613 console.log("Entropy unit tests");
adc8ce12 2614 console.log(response);
c6624d51
IC
2615 fail();
2616 };
2617 next();
2618});
2619},
2620
2621// Entropy can be entered by the user
2622function() {
2623page.open(url, function(status) {
2624 expected = {
2625 mnemonic: "abandon abandon ability",
2626 address: "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug",
2627 }
2628 // use entropy
2629 page.evaluate(function() {
2630 $(".use-entropy").prop("checked", true).trigger("change");
2631 $(".entropy").val("00000000 00000000 00000000 00000000").trigger("input");
2632 });
2633 // check the mnemonic is set and address is correct
2634 waitForGenerate(function() {
2635 var actual = page.evaluate(function() {
2636 return {
2637 address: $(".address:first").text(),
2638 mnemonic: $(".phrase").val(),
2639 }
2640 });
2641 if (actual.mnemonic != expected.mnemonic) {
2642 console.log("Entropy does not generate correct mnemonic");
2643 console.log("Expected: " + expected.mnemonic);
2644 console.log("Got: " + actual.mnemonic);
2645 fail();
2646 }
2647 if (actual.address != expected.address) {
2648 console.log("Entropy does not generate correct address");
2649 console.log("Expected: " + expected.address);
2650 console.log("Got: " + actual.address);
2651 fail();
2652 }
2653 next();
2654 });
2655});
2656},
2657
2658// A warning about entropy is shown to the user, with additional information
2659function() {
2660page.open(url, function(status) {
2661 // get text content from entropy sections of page
2662 var hasWarning = page.evaluate(function() {
2663 var entropyText = $(".entropy-container").text();
2664 var warning = "mnemonic may be insecure";
2665 if (entropyText.indexOf(warning) == -1) {
2666 return false;
2667 }
2668 var readMoreText = $("#entropy-notes").parent().text();
2669 var goodSources = "flipping a fair coin, rolling a fair dice, noise measurements etc";
2670 if (readMoreText.indexOf(goodSources) == -1) {
2671 return false;
2672 }
2673 return true;
2674 });
2675 // check the warnings and information are shown
2676 if (!hasWarning) {
2677 console.log("Page does not contain warning about using own entropy");
2678 fail();
2679 }
2680 next();
2681});
2682},
2683
2684// The types of entropy available are described to the user
2685function() {
2686page.open(url, function(status) {
2687 // get placeholder text for entropy field
2688 var placeholder = page.evaluate(function() {
2689 return $(".entropy").attr("placeholder");
2690 });
2691 var options = [
2692 "binary",
2693 "base 6",
2694 "dice",
2695 "base 10",
2696 "hexadecimal",
439f0e25 2697 "cards",
c6624d51
IC
2698 ];
2699 for (var i=0; i<options.length; i++) {
2700 var option = options[i];
2701 if (placeholder.indexOf(option) == -1) {
2702 console.log("Available entropy type is not shown to user: " + option);
2703 fail();
2704 }
2705 }
2706 next();
2707});
2708},
2709
2710// The actual entropy used is shown to the user
2711function() {
2712page.open(url, function(status) {
2713 // use entropy
2714 var badEntropySource = page.evaluate(function() {
2715 var entropy = "Not A Very Good Entropy Source At All";
2716 $(".use-entropy").prop("checked", true).trigger("change");
2717 $(".entropy").val(entropy).trigger("input");
2718 });
2719 // check the actual entropy being used is shown
057722b0 2720 waitForEntropyFeedback(function() {
c6624d51
IC
2721 var expectedText = "AedEceAA";
2722 var entropyText = page.evaluate(function() {
2723 return $(".entropy-container").text();
2724 });
2725 if (entropyText.indexOf(expectedText) == -1) {
2726 console.log("Actual entropy used is not shown");
2727 fail();
2728 }
2729 next();
2730 });
2731});
2732},
2733
2734// Binary entropy can be entered
2735function() {
2736page.open(url, function(status) {
2737 // use entropy
2738 page.evaluate(function() {
2739 $(".use-entropy").prop("checked", true).trigger("change");
2740 $(".entropy").val("01").trigger("input");
2741 });
2742 // check the entropy is shown to be the correct type
057722b0 2743 waitForEntropyFeedback(function() {
c6624d51
IC
2744 var entropyText = page.evaluate(function() {
2745 return $(".entropy-container").text();
2746 });
2747 if (entropyText.indexOf("binary") == -1) {
2748 console.log("Binary entropy is not detected and presented to user");
2749 fail();
2750 }
2751 next();
2752 });
2753});
2754},
2755
2756// Base 6 entropy can be entered
2757function() {
2758page.open(url, function(status) {
2759 // use entropy
2760 page.evaluate(function() {
2761 $(".use-entropy").prop("checked", true).trigger("change");
2762 $(".entropy").val("012345").trigger("input");
2763 });
2764 // check the entropy is shown to be the correct type
057722b0 2765 waitForEntropyFeedback(function() {
c6624d51
IC
2766 var entropyText = page.evaluate(function() {
2767 return $(".entropy-container").text();
2768 });
2769 if (entropyText.indexOf("base 6") == -1) {
2770 console.log("Base 6 entropy is not detected and presented to user");
2771 fail();
2772 }
2773 next();
2774 });
2775});
2776},
2777
2778// Base 6 dice entropy can be entered
2779function() {
2780page.open(url, function(status) {
2781 // use entropy
2782 page.evaluate(function() {
2783 $(".use-entropy").prop("checked", true).trigger("change");
2784 $(".entropy").val("123456").trigger("input");
2785 });
2786 // check the entropy is shown to be the correct type
057722b0 2787 waitForEntropyFeedback(function() {
c6624d51
IC
2788 var entropyText = page.evaluate(function() {
2789 return $(".entropy-container").text();
2790 });
2791 if (entropyText.indexOf("dice") == -1) {
2792 console.log("Dice entropy is not detected and presented to user");
2793 fail();
2794 }
2795 next();
2796 });
2797});
2798},
2799
2800// Base 10 entropy can be entered
2801function() {
2802page.open(url, function(status) {
2803 // use entropy
2804 page.evaluate(function() {
2805 $(".use-entropy").prop("checked", true).trigger("change");
2806 $(".entropy").val("789").trigger("input");
2807 });
2808 // check the entropy is shown to be the correct type
057722b0 2809 waitForEntropyFeedback(function() {
c6624d51
IC
2810 var entropyText = page.evaluate(function() {
2811 return $(".entropy-container").text();
2812 });
2813 if (entropyText.indexOf("base 10") == -1) {
2814 console.log("Base 10 entropy is not detected and presented to user");
2815 fail();
2816 }
2817 next();
2818 });
2819});
2820},
2821
2822// Hexadecimal entropy can be entered
2823function() {
2824page.open(url, function(status) {
2825 // use entropy
2826 page.evaluate(function() {
2827 $(".use-entropy").prop("checked", true).trigger("change");
2828 $(".entropy").val("abcdef").trigger("input");
2829 });
2830 // check the entropy is shown to be the correct type
057722b0 2831 waitForEntropyFeedback(function() {
c6624d51
IC
2832 var entropyText = page.evaluate(function() {
2833 return $(".entropy-container").text();
2834 });
2835 if (entropyText.indexOf("hexadecimal") == -1) {
2836 console.log("Hexadecimal entropy is not detected and presented to user");
2837 fail();
2838 }
2839 next();
2840 });
2841});
2842},
2843
2844// Dice entropy value is shown as the converted base 6 value
2845function() {
2846page.open(url, function(status) {
2847 // use entropy
2848 page.evaluate(function() {
2849 $(".use-entropy").prop("checked", true).trigger("change");
2850 $(".entropy").val("123456").trigger("input");
2851 });
2852 // check the entropy is shown as base 6, not as the original dice value
057722b0 2853 waitForEntropyFeedback(function() {
c6624d51
IC
2854 var entropyText = page.evaluate(function() {
2855 return $(".entropy-container").text();
2856 });
425b75a9 2857 if (entropyText.indexOf("123450") == -1) {
c6624d51
IC
2858 console.log("Dice entropy is not shown to user as base 6 value");
2859 fail();
2860 }
2861 if (entropyText.indexOf("123456") > -1) {
2862 console.log("Dice entropy value is shown instead of true base 6 value");
2863 fail();
2864 }
2865 next();
2866 });
2867});
2868},
2869
2870// The number of bits of entropy accumulated is shown
2871function() {
2872page.open(url, function(status) {
057722b0
IC
2873 //[ entropy, bits ]
2874 var tests = [
2875 [ "0000 0000 0000 0000 0000", "20" ],
2876 [ "0", "1" ],
2877 [ "0000", "4" ],
0d0f07f9
IC
2878 [ "6", "2" ], // 6 in card is 0 in base 6, 0 in base 6 is 2.6 bits (rounded down to 2 bits)
2879 [ "7", "3" ], // 7 in base 10 is 111 in base 2, no leading zeros
057722b0
IC
2880 [ "8", "4" ],
2881 [ "F", "4" ],
1cf1bbaf 2882 [ "29", "6" ],
057722b0
IC
2883 [ "0A", "8" ],
2884 [ "1A", "8" ], // hex is always multiple of 4 bits of entropy
2885 [ "2A", "8" ],
2886 [ "4A", "8" ],
2887 [ "8A", "8" ],
2888 [ "FA", "8" ],
2889 [ "000A", "16" ],
0d0f07f9
IC
2890 [ "5555", "11" ],
2891 [ "6666", "10" ], // uses dice, so entropy is actually 0000 in base 6, which is 4 lots of 2.58 bits, which is 10.32 bits (rounded down to 10 bits)
1cf1bbaf 2892 [ "2227", "13" ], // Uses base 10, which is 4 lots of 3.32 bits, which is 13.3 bits (rounded down to 13)
057722b0
IC
2893 [ "222F", "16" ],
2894 [ "FFFF", "16" ],
1cf1bbaf 2895 [ "0000101017", "33" ], // 10 events at 3.32 bits per event
6422c1cd 2896 [ "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks", "225" ], // cards are not replaced, so a full deck is not 52^52 entropy which is 296 bits, it's 52!, which is 225 bits
057722b0 2897 ]
c6624d51
IC
2898 // use entropy
2899 page.evaluate(function(e) {
2900 $(".use-entropy").prop("checked", true).trigger("change");
2901 });
2902 // Run each test
2903 var nextTest = function runNextTest(i) {
057722b0
IC
2904 var entropy = tests[i][0];
2905 var expected = tests[i][1];
c6624d51
IC
2906 // set entropy
2907 page.evaluate(function(e) {
c6624d51
IC
2908 $(".entropy").val(e).trigger("input");
2909 }, entropy);
2910 // check the number of bits of entropy is shown
057722b0 2911 waitForEntropyFeedback(function() {
c6624d51 2912 var entropyText = page.evaluate(function() {
dd944906 2913 return $(".entropy-container").text();
c6624d51 2914 });
1cf1bbaf 2915 if (entropyText.replace(/\s/g,"").indexOf("Bits" + expected) == -1) {
c6624d51
IC
2916 console.log("Accumulated entropy is not shown correctly for " + entropy);
2917 fail();
2918 }
057722b0 2919 var isLastTest = i == tests.length - 1;
c6624d51
IC
2920 if (isLastTest) {
2921 next();
2922 }
2923 else {
2924 runNextTest(i+1);
2925 }
2926 });
2927 }
2928 nextTest(0);
2929});
2930},
2931
fb353f9d 2932// There is feedback provided about the supplied entropy
c6624d51
IC
2933function() {
2934page.open(url, function(status) {
2935 var tests = [
2936 {
2937 entropy: "A",
fb353f9d
IC
2938 filtered: "A",
2939 type: "hexadecimal",
2940 events: 1,
2941 bits: 4,
c6624d51 2942 words: 0,
20f459ce 2943 strength: "less than a second",
c6624d51
IC
2944 },
2945 {
2946 entropy: "AAAAAAAA",
fb353f9d
IC
2947 filtered: "AAAAAAAA",
2948 type: "hexadecimal",
2949 events: 8,
2950 bits: 32,
c6624d51 2951 words: 3,
20f459ce 2952 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
c6624d51
IC
2953 },
2954 {
2955 entropy: "AAAAAAAA B",
fb353f9d
IC
2956 filtered: "AAAAAAAAB",
2957 type: "hexadecimal",
2958 events: 9,
2959 bits: 36,
c6624d51 2960 words: 3,
20f459ce 2961 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
c6624d51
IC
2962 },
2963 {
2964 entropy: "AAAAAAAA BBBBBBBB",
fb353f9d
IC
2965 filtered: "AAAAAAAABBBBBBBB",
2966 type: "hexadecimal",
2967 events: 16,
2968 bits: 64,
c6624d51 2969 words: 6,
20f459ce 2970 strength: "less than a second - Repeats like \"aaa\" are easy to guess",
c6624d51
IC
2971 },
2972 {
2973 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC",
fb353f9d
IC
2974 filtered: "AAAAAAAABBBBBBBBCCCCCCCC",
2975 type: "hexadecimal",
2976 events: 24,
2977 bits: 96,
c6624d51 2978 words: 9,
20f459ce 2979 strength: "less than a second",
c6624d51
IC
2980 },
2981 {
2982 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD",
fb353f9d
IC
2983 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD",
2984 type: "hexadecimal",
2985 events: 32,
2986 bits: 128,
c6624d51 2987 words: 12,
20f459ce 2988 strength: "2 minutes",
e6a799cc
IC
2989 },
2990 {
2991 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA",
2992 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDA",
2993 type: "hexadecimal",
2994 events: 32,
2995 bits: 128,
2996 words: 12,
20f459ce 2997 strength: "2 days",
c6624d51
IC
2998 },
2999 {
e6a799cc
IC
3000 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA EEEEEEEE",
3001 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDAEEEEEEEE",
fb353f9d
IC
3002 type: "hexadecimal",
3003 events: 40,
3004 bits: 160,
c6624d51 3005 words: 15,
20f459ce 3006 strength: "3 years",
1cf1bbaf
IC
3007 },
3008 {
e6a799cc
IC
3009 entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDA EEEEEEEE FFFFFFFF",
3010 filtered: "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDAEEEEEEEEFFFFFFFF",
fb353f9d
IC
3011 type: "hexadecimal",
3012 events: 48,
3013 bits: 192,
1cf1bbaf 3014 words: 18,
20f459ce 3015 strength: "centuries",
fb353f9d 3016 },
391c7f26
IC
3017 {
3018 entropy: "7d",
3019 type: "card",
3020 events: 1,
3021 bits: 5,
3022 words: 0,
20f459ce 3023 strength: "less than a second",
391c7f26
IC
3024 },
3025 {
3026 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
3027 type: "card (full deck)",
3028 events: 52,
6422c1cd
IC
3029 bits: 225,
3030 words: 21,
20f459ce 3031 strength: "centuries",
391c7f26
IC
3032 },
3033 {
3034 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks3d",
3035 type: "card (full deck, 1 duplicate: 3d)",
3036 events: 53,
87ad2c6e 3037 bits: 254,
6422c1cd 3038 words: 21,
20f459ce 3039 strength: "centuries",
391c7f26
IC
3040 },
3041 {
3042 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d",
bbc29c80 3043 type: "card (2 duplicates: 3d 4d, 1 missing: KS)",
391c7f26 3044 events: 53,
87ad2c6e 3045 bits: 254,
6422c1cd 3046 words: 21,
20f459ce 3047 strength: "centuries",
391c7f26
IC
3048 },
3049 {
3050 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d5d6d",
bbc29c80 3051 type: "card (4 duplicates: 3d 4d 5d..., 1 missing: KS)",
391c7f26 3052 events: 53,
87ad2c6e
IC
3053 bits: 264,
3054 words: 24,
20f459ce 3055 strength: "centuries",
391c7f26 3056 },
9bc39377 3057 // Next test was throwing uncaught error in zxcvbn
6422c1cd 3058 // Also tests 451 bits, ie Math.log2(52!)*2 = 225.58 * 2
9bc39377
IC
3059 {
3060 entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsksac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
3061 type: "card (full deck, 52 duplicates: ac 2c 3c...)",
3062 events: 104,
87ad2c6e
IC
3063 bits: 499,
3064 words: 45,
20f459ce 3065 strength: "centuries",
9bc39377 3066 },
5c653a12
IC
3067 // Case insensitivity to duplicate cards
3068 {
3069 entropy: "asAS",
3070 type: "card (1 duplicate: AS)",
3071 events: 2,
87ad2c6e 3072 bits: 9,
5c653a12 3073 words: 0,
20f459ce 3074 strength: "less than a second",
5c653a12
IC
3075 },
3076 {
3077 entropy: "ASas",
3078 type: "card (1 duplicate: as)",
3079 events: 2,
87ad2c6e 3080 bits: 9,
5c653a12 3081 words: 0,
20f459ce 3082 strength: "less than a second",
5c653a12 3083 },
bbc29c80
IC
3084 // Missing cards are detected
3085 {
3086 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
3087 type: "card (1 missing: 9C)",
3088 events: 51,
87ad2c6e
IC
3089 bits: 221,
3090 words: 18,
20f459ce 3091 strength: "centuries",
bbc29c80
IC
3092 },
3093 {
3094 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
3095 type: "card (2 missing: 9C 5D)",
3096 events: 50,
87ad2c6e
IC
3097 bits: 216,
3098 words: 18,
20f459ce 3099 strength: "centuries",
bbc29c80
IC
3100 },
3101 {
3102 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d7d8d9dtdjd kdah2h3h 5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks",
3103 type: "card (4 missing: 9C 5D QD...)",
3104 events: 48,
87ad2c6e 3105 bits: 208,
6422c1cd 3106 words: 18,
20f459ce 3107 strength: "centuries",
bbc29c80
IC
3108 },
3109 // More than six missing cards does not show message
3110 {
3111 entropy: "ac2c3c4c5c6c7c8c tcjcqckcad2d3d4d 6d 8d9d jd kdah2h3h 5h6h7h8h9hthjhqhkh 2s3s4s5s6s7s8s9stsjsqsks",
3112 type: "card",
3113 events: 45,
87ad2c6e 3114 bits: 195,
6422c1cd 3115 words: 18,
20f459ce 3116 strength: "centuries",
bbc29c80 3117 },
fc7c248f
IC
3118 // Multiple decks of cards increases bits per event
3119 {
3120 entropy: "3d",
3121 events: 1,
3122 bits: 4,
3123 bitsPerEvent: 4.34,
3124 },
3125 {
3126 entropy: "3d3d",
3127 events: 2,
3128 bits: 9,
3129 bitsPerEvent: 4.80,
3130 },
3131 {
3132 entropy: "3d3d3d",
3133 events: 3,
3134 bits: 15,
3135 bitsPerEvent: 5.01,
3136 },
3137 {
3138 entropy: "3d3d3d3d",
3139 events: 4,
3140 bits: 20,
3141 bitsPerEvent: 5.14,
3142 },
3143 {
3144 entropy: "3d3d3d3d3d",
3145 events: 5,
3146 bits: 26,
3147 bitsPerEvent: 5.22,
3148 },
3149 {
3150 entropy: "3d3d3d3d3d3d",
3151 events: 6,
3152 bits: 31,
3153 bitsPerEvent: 5.28,
3154 },
3155 {
3156 entropy: "3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d",
3157 events: 33,
3158 bits: 184,
3159 bitsPerEvent: 5.59,
20f459ce 3160 strength: 'less than a second - Repeats like "abcabcabc" are only slightly harder to guess than "abc"',
fc7c248f 3161 },
c6624d51
IC
3162 ];
3163 // use entropy
3164 page.evaluate(function() {
3165 $(".use-entropy").prop("checked", true).trigger("change");
3166 });
3167 var nextTest = function runNextTest(i) {
fb353f9d 3168 function getFeedbackError(expected, actual) {
391c7f26 3169 if ("filtered" in expected && actual.indexOf(expected.filtered) == -1) {
fb353f9d
IC
3170 return "Filtered value not in feedback";
3171 }
fc7c248f 3172 if ("type" in expected && actual.indexOf(expected.type) == -1) {
fb353f9d
IC
3173 return "Entropy type not in feedback";
3174 }
fc7c248f 3175 if ("events" in expected && actual.indexOf(expected.events) == -1) {
fb353f9d
IC
3176 return "Event count not in feedback";
3177 }
fc7c248f 3178 if ("bits" in expected && actual.indexOf(expected.bits) == -1) {
fb353f9d
IC
3179 return "Bit count not in feedback";
3180 }
fc7c248f 3181 if ("strength" in expected && actual.indexOf(expected.strength) == -1) {
fb353f9d
IC
3182 return "Strength not in feedback";
3183 }
fc7c248f
IC
3184 if ("bitsPerEvent" in expected && actual.indexOf(expected.bitsPerEvent) == -1) {
3185 return "bitsPerEvent not in feedback";
3186 }
fb353f9d
IC
3187 return false;
3188 }
c6624d51
IC
3189 test = tests[i];
3190 page.evaluate(function(e) {
3191 $(".addresses").empty();
057722b0 3192 $(".phrase").val("");
c6624d51
IC
3193 $(".entropy").val(e).trigger("input");
3194 }, test.entropy);
fb353f9d 3195 waitForEntropyFeedback(function() {
c6624d51
IC
3196 var mnemonic = page.evaluate(function() {
3197 return $(".phrase").val();
3198 });
fb353f9d 3199 // Check mnemonic length
fc7c248f 3200 if ("words" in test && test.words == 0) {
fb353f9d
IC
3201 if (mnemonic.length > 0) {
3202 console.log("Mnemonic length for " + test.strength + " strength is not " + test.words);
87ad2c6e 3203 console.log("Entropy: " + test.entropy);
fb353f9d
IC
3204 console.log("Mnemonic: " + mnemonic);
3205 fail();
3206 }
3207 }
fc7c248f 3208 else if ("words" in test) {
fb353f9d
IC
3209 if (mnemonic.split(" ").length != test.words) {
3210 console.log("Mnemonic length for " + test.strength + " strength is not " + test.words);
87ad2c6e 3211 console.log("Entropy: " + test.entropy);
fb353f9d
IC
3212 console.log("Mnemonic: " + mnemonic);
3213 fail();
3214 }
3215 }
3216 // check feedback
3217 var feedback = page.evaluate(function() {
dd944906 3218 return $(".entropy-container").text();
fb353f9d
IC
3219 });
3220 var feedbackError = getFeedbackError(test, feedback);
3221 if (feedbackError) {
3222 console.log("Entropy feedback for " + test.entropy + " returned error");
3223 console.log(feedbackError);
c6624d51
IC
3224 fail();
3225 }
fb353f9d 3226 // Run next test
c6624d51
IC
3227 var isLastTest = i == tests.length - 1;
3228 if (isLastTest) {
3229 next();
3230 }
3231 else {
3232 runNextTest(i+1);
3233 }
fb353f9d 3234 });
c6624d51
IC
3235 }
3236 nextTest(0);
3237});
3238},
3239
d6fd8ebf 3240// Entropy is truncated from the left
c6624d51
IC
3241function() {
3242page.open(url, function(status) {
d6fd8ebf 3243 var expected = "avocado zoo zone";
c6624d51
IC
3244 // use entropy
3245 page.evaluate(function() {
3246 $(".use-entropy").prop("checked", true).trigger("change");
3247 var entropy = "00000000 00000000 00000000 00000000";
d6fd8ebf 3248 entropy += "11111111 11111111 11111111 1111"; // Missing last byte
c6624d51
IC
3249 $(".entropy").val(entropy).trigger("input");
3250 });
3251 // check the entropy is truncated from the right
3252 waitForGenerate(function() {
3253 var actual = page.evaluate(function() {
3254 return $(".phrase").val();
3255 });
3256 if (actual != expected) {
3257 console.log("Entropy is not truncated from the right");
3258 console.log("Expected: " + expected);
3259 console.log("Got: " + actual);
3260 fail();
3261 }
3262 next();
3263 });
3264});
3265},
3266
3267// Very large entropy results in very long mnemonics
3268function() {
3269page.open(url, function(status) {
3270 // use entropy
3271 page.evaluate(function() {
3272 $(".use-entropy").prop("checked", true).trigger("change");
3273 var entropy = "";
3274 // Generate a very long entropy string
3275 for (var i=0; i<33; i++) {
3276 entropy += "AAAAAAAA"; // 3 words * 33 iterations = 99 words
3277 }
3278 $(".entropy").val(entropy).trigger("input");
3279 });
3280 // check the mnemonic is very long
3281 waitForGenerate(function() {
3282 var wordCount = page.evaluate(function() {
3283 return $(".phrase").val().split(" ").length;
3284 });
3285 if (wordCount != 99) {
3286 console.log("Large entropy does not generate long mnemonic");
3287 console.log("Expected 99 words, got " + wordCount);
3288 fail();
3289 }
3290 next();
3291 });
3292});
3293},
3294
3295// Is compatible with bip32jp entropy
3296// https://bip32jp.github.io/english/index.html
3297// NOTES:
3298// Is incompatible with:
c6624d51
IC
3299// base 20
3300function() {
3301page.open(url, function(status) {
0d0f07f9 3302 var expected = "train then jungle barely whip fiber purpose puppy eagle cloud clump hospital robot brave balcony utility detect estate old green desk skill multiply virus";
c6624d51
IC
3303 // use entropy
3304 page.evaluate(function() {
3305 $(".use-entropy").prop("checked", true).trigger("change");
0d0f07f9 3306 var entropy = "543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543";
c6624d51
IC
3307 $(".entropy").val(entropy).trigger("input");
3308 });
3309 // check the mnemonic matches the expected value from bip32jp
3310 waitForGenerate(function() {
3311 var actual = page.evaluate(function() {
3312 return $(".phrase").val();
3313 });
3314 if (actual != expected) {
3315 console.log("Mnemonic does not match bip32jp for base 6 entropy");
3316 console.log("Expected: " + expected);
3317 console.log("Got: " + actual);
3318 fail();
3319 }
3320 next();
3321 });
3322});
3323},
3324
057722b0
IC
3325// Blank entropy does not generate mnemonic or addresses
3326function() {
3327page.open(url, function(status) {
3328 // use entropy
3329 page.evaluate(function() {
3330 $(".use-entropy").prop("checked", true).trigger("change");
3331 $(".entropy").val("").trigger("input");
3332 });
3333 waitForFeedback(function() {
3334 // check there is no mnemonic
3335 var phrase = page.evaluate(function() {
3336 return $(".phrase").val();
3337 });
3338 if (phrase != "") {
3339 console.log("Blank entropy does not result in blank mnemonic");
3340 console.log("Got: " + phrase);
3341 fail();
3342 }
3343 // check there are no addresses displayed
3344 var addresses = page.evaluate(function() {
3345 return $(".address").length;
3346 });
3347 if (addresses != 0) {
3348 console.log("Blank entropy does not result in zero addresses");
3349 fail();
3350 }
3351 // Check the feedback says 'blank entropy'
3352 var feedback = page.evaluate(function() {
3353 return $(".feedback").text();
3354 });
3355 if (feedback != "Blank entropy") {
3356 console.log("Blank entropy does not show feedback message");
3357 fail();
3358 }
3359 next();
3360 });
3361});
3362},
3363
3599674d
IC
3364// Mnemonic length can be selected even for weak entropy
3365function() {
3366page.open(url, function(status) {
3367 // use entropy
3368 page.evaluate(function() {
3369 $(".use-entropy").prop("checked", true).trigger("change");
3370 $(".entropy").val("012345");
3371 $(".mnemonic-length").val("18").trigger("change");
3372 });
3373 // check the mnemonic is the correct length
3374 waitForGenerate(function() {
3375 var phrase = page.evaluate(function() {
3376 return $(".phrase").val();
3377 });
3378 var numberOfWords = phrase.split(/\s/g).length;
3379 if (numberOfWords != 18) {
3380 console.log("Weak entropy cannot be overridden to give 18 word mnemonic");
3381 console.log(phrase);
3382 fail();
3383 }
3384 next();
3385 });
3386});
3387},
3388
886f06ee
IC
3389// Github issue 33
3390// https://github.com/iancoleman/bip39/issues/33
3391// Final cards should contribute entropy
3392function() {
3393page.open(url, function(status) {
3394 // use entropy
3395 page.evaluate(function() {
3396 $(".use-entropy").prop("checked", true).trigger("change");
3397 $(".entropy").val("7S 9H 9S QH 8C KS AS 7D 7C QD 4S 4D TC 2D 5S JS 3D 8S 8H 4C 3C AC 3S QC 9C JC 7H AD TD JD 6D KH 5C QS 2S 6S 6H JH KD 9D-6C TS TH 4H KC 5H 2H AH 2C 8D 3H 5D").trigger("input");
3398 });
3399 // get the mnemonic
3400 waitForGenerate(function() {
3401 var originalPhrase = page.evaluate(function() {
3402 return $(".phrase").val();
3403 });
3404 // Set the last 12 cards to be AS
3405 page.evaluate(function() {
3406 $(".addresses").empty();
3407 $(".entropy").val("7S 9H 9S QH 8C KS AS 7D 7C QD 4S 4D TC 2D 5S JS 3D 8S 8H 4C 3C AC 3S QC 9C JC 7H AD TD JD 6D KH 5C QS 2S 6S 6H JH KD 9D-AS AS AS AS AS AS AS AS AS AS AS AS").trigger("input");
3408 });
3409 // get the new mnemonic
3410 waitForGenerate(function() {
3411 var newPhrase = page.evaluate(function() {
3412 return $(".phrase").val();
3413 });
92e73fd9 3414 // check the phrase has changed
886f06ee
IC
3415 if (newPhrase == originalPhrase) {
3416 console.log("Changing last 12 cards does not change mnemonic");
3417 console.log("Original:");
3418 console.log(originalPhrase);
3419 console.log("New:");
3420 console.log(newPhrase);
3421 fail();
3422 }
3423 next();
3424 });
3425 });
3426});
3427},
3428
e00964cc
IC
3429// Github issue 35
3430// https://github.com/iancoleman/bip39/issues/35
3431// QR Code support
3432function() {
3433page.open(url, function(status) {
3434 // use entropy
3435 page.evaluate(function() {
3436 $(".generate").click();
3437 });
3438 waitForGenerate(function() {
3439 var p = page.evaluate(function() {
3440 // get position of mnemonic element
3441 return $(".phrase").offset();
3442 });
3443 p.top = Math.ceil(p.top);
3444 p.left = Math.ceil(p.left);
3445 // check the qr code shows
3446 page.sendEvent("mousemove", p.left+4, p.top+4);
3447 var qrShowing = page.evaluate(function() {
3448 return $(".qr-container").find("canvas").length > 0;
3449 });
3450 if (!qrShowing) {
3451 console.log("QR Code does not show");
3452 fail();
3453 }
3454 // check the qr code hides
3455 page.sendEvent("mousemove", p.left-4, p.top-4);
3456 var qrHidden = page.evaluate(function() {
3457 return $(".qr-container").find("canvas").length == 0;
3458 });
3459 if (!qrHidden) {
3460 console.log("QR Code does not hide");
3461 fail();
3462 }
3463 next();
3464 });
3465});
3466},
3467
c554e6ff
IC
3468// BIP44 account extendend private key is shown
3469// github issue 37 - compatibility with electrum
3470function() {
3471page.open(url, function(status) {
3472 // set the phrase
3473 var expected = "xprv9yzrnt4zWVJUr1k2VxSPy9ettKz5PpeDMgaVG7UKedhqnw1tDkxP2UyYNhuNSumk2sLE5ctwKZs9vwjsq3e1vo9egCK6CzP87H2cVYXpfwQ";
3474 page.evaluate(function() {
3475 $(".phrase").val("abandon abandon ability");
3476 $(".phrase").trigger("input");
3477 });
3478 // check the BIP44 account extended private key
3479 waitForGenerate(function() {
3480 var actual = page.evaluate(function() {
684624b5 3481 return $("#bip44 .account-xprv").val();
c554e6ff
IC
3482 });
3483 if (actual != expected) {
3484 console.log("BIP44 account extended private key is incorrect");
3485 console.log("Expected: " + expected);
3486 console.log("Actual: " + actual);
3487 fail();
3488 }
3489 next();
3490 });
3491});
3492},
3493
3494// BIP44 account extendend public key is shown
3495// github issue 37 - compatibility with electrum
3496function() {
3497page.open(url, function(status) {
3498 // set the phrase
3499 var expected = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf";
3500 page.evaluate(function() {
3501 $(".phrase").val("abandon abandon ability");
3502 $(".phrase").trigger("input");
3503 });
3504 // check the BIP44 account extended public key
3505 waitForGenerate(function() {
3506 var actual = page.evaluate(function() {
684624b5 3507 return $("#bip44 .account-xpub").val();
c554e6ff
IC
3508 });
3509 if (actual != expected) {
3510 console.log("BIP44 account extended public key is incorrect");
3511 console.log("Expected: " + expected);
ba3cb9ec
IC
3512 console.log("Actual: " + actual);
3513 fail();
3514 }
3515 next();
3516 });
3517});
3518},
3519
3520// github issue 40
3521// BIP32 root key can be set as an xpub
3522function() {
3523page.open(url, function(status) {
3524 // set the phrase
3525 page.evaluate(function() {
3526 // set xpub for account 0 of bip44 for 'abandon abandon ability'
3527 var bip44AccountXpub = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf";
3528 $("#root-key").val(bip44AccountXpub);
3529 $("#root-key").trigger("input");
3530 });
3531 waitForFeedback(function() {
3532 page.evaluate(function() {
3533 // Use bip32 tab
3534 $("#bip32-tab a").click();
3535 });
3536 waitForGenerate(function() {
3537 page.evaluate(function() {
3538 // derive external addresses for this xpub
3539 var firstAccountDerivationPath = "m/0";
3540 $("#bip32-path").val(firstAccountDerivationPath);
3541 $("#bip32-path").trigger("input");
3542 });
3543 waitForGenerate(function() {
3544 // check the addresses are generated
3545 var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug";
3546 var actual = page.evaluate(function() {
3547 return $(".address:first").text();
3548 });
3549 if (actual != expected) {
3550 console.log("xpub key does not generate addresses in table");
3551 console.log("Expected: " + expected);
3552 console.log("Actual: " + actual);
3553 fail();
3554 }
3555 // check the xprv key is not set
3556 var expected = "NA";
3557 var actual = page.evaluate(function() {
3558 return $(".extended-priv-key").val();
3559 });
3560 if (actual != expected) {
3561 console.log("xpub key as root shows derived bip32 xprv key");
3562 console.log("Expected: " + expected);
3563 console.log("Actual: " + actual);
3564 fail();
3565 }
3566 // check the private key is not set
3567 var expected = "NA";
3568 var actual = page.evaluate(function() {
3569 return $(".privkey:first").text();
3570 });
3571 if (actual != expected) {
3572 console.log("xpub key generates private key in addresses table");
3573 console.log("Expected: " + expected);
3574 console.log("Actual: " + actual);
3575 fail();
3576 }
3577 next();
3578 });
3579 });
3580 });
3581});
3582},
3583
3584// github issue 40
3585// xpub for bip32 root key will not work with hardened derivation paths
3586function() {
3587page.open(url, function(status) {
3588 // set the phrase
3589 page.evaluate(function() {
3590 // set xpub for account 0 of bip44 for 'abandon abandon ability'
3591 var bip44AccountXpub = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf";
3592 $("#root-key").val(bip44AccountXpub);
3593 $("#root-key").trigger("input");
3594 });
3595 waitForFeedback(function() {
3596 // Check feedback is correct
3597 var expected = "Hardened derivation path is invalid with xpub key";
3598 var actual = page.evaluate(function() {
3599 return $(".feedback").text();
3600 });
3601 if (actual != expected) {
3602 console.log("xpub key with hardened derivation path does not show feedback");
3603 console.log("Expected: " + expected);
3604 console.log("Actual: " + actual);
3605 fail();
3606 }
3607 // Check no addresses are shown
3608 var expected = 0;
3609 var actual = page.evaluate(function() {
3610 return $(".addresses tr").length;
3611 });
3612 if (actual != expected) {
3613 console.log("addresses still show after setting xpub key with hardened derivation path");
3614 console.log("Expected: " + expected);
c554e6ff
IC
3615 console.log("Actual: " + actual);
3616 fail();
3617 }
3618 next();
3619 });
3620});
3621},
3622
0a1f0259
IC
3623// github issue 39
3624// no root key shows feedback
3625function() {
3626page.open(url, function(status) {
3627 // click the bip32 tab on fresh page
3628 page.evaluate(function() {
3629 $("#bip32-tab a").click();
3630 });
3631 waitForFeedback(function() {
3632 // Check feedback is correct
3633 var expected = "No root key";
3634 var actual = page.evaluate(function() {
3635 return $(".feedback").text();
3636 });
3637 if (actual != expected) {
3638 console.log("Blank root key not detected");
3639 console.log("Expected: " + expected);
3640 console.log("Actual: " + actual);
3641 fail();
3642 }
3643 next();
3644 });
3645});
3646},
886f06ee 3647
40892aba
IC
3648// Github issue 44
3649// display error switching tabs while addresses are generating
3650function() {
3651page.open(url, function(status) {
3652 // set the phrase
3653 page.evaluate(function() {
3654 $(".phrase").val("abandon abandon ability").trigger("input");
3655 });
3656 waitForGenerate(function() {
3657 // set to generate 500 more addresses
3658 // generate more addresses
3659 // change tabs which should cancel the previous generating
3660 page.evaluate(function() {
3661 $(".rows-to-add").val("100");
3662 $(".more").click();
3663 $("#bip32-tab a").click();
3664 });
3665 // check the derivation paths are in order and of the right quantity
3666 waitForGenerate(function() {
3667 var paths = page.evaluate(function() {
3668 return $(".index").map(function(i, e) {
3669 return $(e).text();
3670 });
3671 });
3672 for (var i=0; i<paths.length; i++) {
3673 var expected = "m/0/" + i;
3674 var actual = paths[i];
3675 if (actual != expected) {
3676 console.log("Path " + i + " is not in correct order");
3677 console.log("Expected: " + expected);
3678 console.log("Actual: " + actual);
3679 fail();
3680 }
3681 }
3682 if (paths.length != 20) {
3683 console.log("Generation was not cancelled by new action");
3684 fail();
3685 }
3686 next();
3687 });
3688 });
3689});
3690},
3691
53aaab27
IC
3692// Github issue 49
3693// padding for binary should give length with multiple of 256
3694// hashed entropy 1111 is length 252, so requires 4 leading zeros
3695// prior to issue 49 it would only generate 2 leading zeros, ie missing 2
3696function() {
3697page.open(url, function(status) {
3698 expected = "avocado valid quantum cross link predict excuse edit street able flame large galaxy ginger nuclear"
3699 // use entropy
3700 page.evaluate(function() {
3701 $(".use-entropy").prop("checked", true).trigger("change");
5ed50bd9 3702 $(".mnemonic-length").val("15");
53aaab27
IC
3703 $(".entropy").val("1111").trigger("input");
3704 });
3705 waitForGenerate(function() {
3706 // get the mnemonic
3707 var actual = page.evaluate(function() {
3708 return $(".phrase").val();
3709 });
3710 // check the mnemonic is correct
3711 if (actual != expected) {
3712 console.log("Left padding error for entropy");
3713 console.log("Expected: " + expected);
3714 console.log("Actual: " + actual);
3715 fail();
3716 }
3717 next();
3718 });
3719});
3720},
3721
cdfaaf00
IC
3722// Github pull request 55
3723// https://github.com/iancoleman/bip39/pull/55
3724// Client select
3725function() {
3726page.open(url, function(status) {
3727 // set mnemonic and select bip32 tab
3728 page.evaluate(function() {
3729 $("#bip32-tab a").click();
3730 $(".phrase").val("abandon abandon ability").trigger("input");
3731 });
3732 waitForGenerate(function() {
3733 // BITCOIN CORE
3734 // set bip32 client to bitcoin core
3735 page.evaluate(function() {
3736 var bitcoinCoreIndex = "0";
3737 $("#bip32-client").val(bitcoinCoreIndex).trigger("change");
3738 });
3739 waitForGenerate(function() {
3740 // get the derivation path
3741 var actual = page.evaluate(function() {
3742 return $("#bip32-path").val();
3743 });
3744 // check the derivation path is correct
3745 expected = "m/0'/0'"
3746 if (actual != expected) {
3747 console.log("Selecting Bitcoin Core client does not set correct derivation path");
3748 console.log("Expected: " + expected);
3749 console.log("Actual: " + actual);
3750 fail();
3751 }
3752 // get hardened addresses
3753 var usesHardenedAddresses = page.evaluate(function() {
3754 return $(".hardened-addresses").prop("checked");
3755 });
3756 // check hardened addresses is selected
3757 if(!usesHardenedAddresses) {
3758 console.log("Selecting Bitcoin Core client does not use hardened addresses");
3759 fail();
3760 }
3761 // check input is readonly
3762 var pathIsReadonly = page.evaluate(function() {
3763 return $("#bip32-path").prop("readonly");
3764 });
3765 if (!pathIsReadonly) {
3766 console.log("Selecting Bitcoin Core client does not set derivation path to readonly");
3767 fail();
3768 }
3769 // MULTIBIT
3770 // set bip32 client to multibit
3771 page.evaluate(function() {
3772 var multibitIndex = "2";
3773 $("#bip32-client").val(multibitIndex).trigger("change");
3774 });
3775 waitForGenerate(function() {
3776 // get the derivation path
3777 var actual = page.evaluate(function() {
3778 return $("#bip32-path").val();
3779 });
3780 // check the derivation path is correct
3781 expected = "m/0'/0"
3782 if (actual != expected) {
3783 console.log("Selecting Multibit client does not set correct derivation path");
3784 console.log("Expected: " + expected);
3785 console.log("Actual: " + actual);
3786 fail();
3787 }
3788 // get hardened addresses
3789 var usesHardenedAddresses = page.evaluate(function() {
3790 return $(".hardened-addresses").prop("checked");
3791 });
3792 // check hardened addresses is selected
3793 if(usesHardenedAddresses) {
3794 console.log("Selecting Multibit client does not uncheck hardened addresses");
3795 fail();
3796 }
3797 // CUSTOM DERIVATION PATH
3798 // check input is not readonly
3799 page.evaluate(function() {
3800 $("#bip32-client").val("custom").trigger("change");
3801 });
3802 // do not wait for generate, since there is no change to the
3803 // derivation path there is no new generation performed
3804 var pathIsReadonly = page.evaluate(function() {
3805 return $("#bip32-path").prop("readonly");
3806 });
3807 if (pathIsReadonly) {
3808 console.log("Selecting Custom Derivation Path does not allow derivation path input");
3809 fail();
3810 }
3811 next();
3812 });
3813 });
3814 });
3815});
3816},
3817
e6f08c6a
IC
3818// github issue 58
3819// https://github.com/iancoleman/bip39/issues/58
3820// bip32 derivation is correct, does not drop leading zeros
3821// see also
3822// https://medium.com/@alexberegszaszi/why-do-my-bip32-wallets-disagree-6f3254cc5846
3823function() {
3824page.open(url, function(status) {
3825 // set the phrase and passphrase
3826 var expected = "17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F";
3827 // Note that bitcore generates an incorrect address
3828 // 13EuKhffWkBE2KUwcbkbELZb1MpzbimJ3Y
3829 // see the medium.com link above for more details
3830 page.evaluate(function() {
3831 $(".phrase").val("fruit wave dwarf banana earth journey tattoo true farm silk olive fence");
3832 $(".passphrase").val("banana").trigger("input");
3833 });
3834 // check the address is generated correctly
3835 waitForGenerate(function() {
3836 var actual = page.evaluate(function() {
3837 return $(".address:first").text();
3838 });
3839 if (actual != expected) {
3840 console.log("BIP32 derivation is incorrect");
3841 console.log("Expected: " + expected);
d2d98ef7
IC
3842 console.log("Actual: " + actual);
3843 fail();
3844 }
3845 next();
3846 });
3847});
3848},
3849
3850
3851// github issue 60
3852// Japanese mnemonics generate incorrect bip32 seed
3853// BIP39 seed is set from phrase
3854function() {
3855page.open(url, function(status) {
3856 // set the phrase
3857 var expected = "a262d6fb6122ecf45be09c50492b31f92e9beb7d9a845987a02cefda57a15f9c467a17872029a9e92299b5cbdf306e3a0ee620245cbd508959b6cb7ca637bd55";
3858 page.evaluate(function() {
3859 $(".phrase").val("あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あおぞら");
3860 $("#passphrase").val("メートルガバヴァぱばぐゞちぢ十人十色");
3861 $("#passphrase").trigger("input");
3862 });
3863 // check the seed is generated correctly
3864 waitForGenerate(function() {
3865 var actual = page.evaluate(function() {
3866 return $(".seed").val();
3867 });
3868 if (actual != expected) {
3869 console.log("BIP39 seed is incorrectly generated from Japanese mnemonic");
3870 console.log("Expected: " + expected);
e6f08c6a
IC
3871 console.log("Actual: " + actual);
3872 fail();
3873 }
3874 next();
3875 });
3876});
3877},
3878
6c08f364
IC
3879// BIP49 official test vectors
3880// https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors
3881function() {
3882page.open(url, function(status) {
3883 // set the phrase and select bitcoin testnet
3884 var expected = "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2";
3885 page.evaluate(function() {
3886 $("#bip49-tab a").click();
3887 $(".phrase").val("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about");
3888 $(".network option[selected]").removeAttr("selected");
3889 $(".network option").filter(function() {
3890 return $(this).html() == "BTC - Bitcoin Testnet";
3891 }).prop("selected", true);
3892 $(".network").trigger("change");
3893 $(".phrase").trigger("input");
3894 });
3895 // check the first address
3896 waitForGenerate(function() {
3897 var actual = page.evaluate(function() {
3898 return $(".address:first").text();
3899 });
3900 if (actual != expected) {
3901 console.log("BIP49 address is incorrect");
3902 console.log("Expected: " + expected);
3903 console.log("Actual: " + actual);
3904 fail();
3905 }
3906 next();
3907 });
3908});
3909},
3910
3911// BIP49 derivation path is shown
3912function() {
3913page.open(url, function(status) {
3914 // set the phrase
3915 var expected = "m/49'/0'/0'/0";
3916 page.evaluate(function() {
3917 $("#bip49-tab a").click();
3918 $(".phrase").val("abandon abandon ability").trigger("input");
3919 });
3920 // check the derivation path of the first address
3921 waitForGenerate(function() {
3922 var actual = page.evaluate(function() {
3923 return $("#bip49 .path").val();
3924 });
3925 if (actual != expected) {
3926 console.log("BIP49 derivation path is incorrect");
3927 console.log("Expected: " + expected);
3928 console.log("Actual: " + actual);
3929 fail();
3930 }
3931 next();
3932 });
3933});
3934},
3935
3936// BIP49 extended private key is shown
3937function() {
3938page.open(url, function(status) {
3939 // set the phrase
3940 var expected = "xprvA1hukYsW7QfX9CVsaDAKde4eryajKa4DKWb6m9YjSnqkiZHrahFwwTJfEQTwBQ5kptWT5pZMkkusT1oK8dc1efQ8VFfq4SLSPAWd7Cpt423";
3941 page.evaluate(function() {
3942 $("#bip49-tab a").click();
3943 $(".phrase").val("abandon abandon ability").trigger("input");
3944 });
3945 // check the BIP49 extended private key
3946 waitForGenerate(function() {
3947 var actual = page.evaluate(function() {
3948 return $(".extended-priv-key").val();
3949 });
3950 if (actual != expected) {
3951 console.log("BIP49 extended private key is incorrect");
3952 console.log("Expected: " + expected);
3953 console.log("Actual: " + actual);
3954 fail();
3955 }
3956 next();
3957 });
3958});
3959},
3960
3961// BIP49 extended public key is shown
3962function() {
3963page.open(url, function(status) {
3964 // set the phrase
3965 var expected = "xpub6EhGA4QPwnDpMgaLgEhKzn1PR1RDj2n4gjWhZXxM18NjbMd18EaCVFd95gkLARJaBD2rXAYJED2gdkUbGn1KkrSzCKR554AdABUELoainnt";
3966 page.evaluate(function() {
3967 $("#bip49-tab a").click();
3968 $(".phrase").val("abandon abandon ability").trigger("input");
3969 });
3970 // check the BIP49 extended public key
3971 waitForGenerate(function() {
3972 var actual = page.evaluate(function() {
3973 return $(".extended-pub-key").val();
3974 });
3975 if (actual != expected) {
3976 console.log("BIP49 extended public key is incorrect");
3977 console.log("Expected: " + expected);
3978 console.log("Actual: " + actual);
3979 fail();
3980 }
3981 next();
3982 });
3983});
3984},
3985
3986// BIP49 account field changes address list
3987function() {
3988page.open(url, function(status) {
3989 // set the phrase
3990 var expected = "381wg1GGN4rP88rNC9v7QWsiww63yLVPsn";
3991 page.evaluate(function() {
3992 $("#bip49-tab a").click();
3993 $(".phrase").val("abandon abandon ability").trigger("input");
3994 });
3995 waitForGenerate(function() {
3996 // change the bip49 account field to 1
3997 page.evaluate(function() {
3998 $("#bip49 .account").val("1");
3999 $("#bip49 .account").trigger("input");
4000 });
4001 waitForGenerate(function() {
4002 // check the address for the new derivation path
4003 var actual = page.evaluate(function() {
4004 return $(".address:first").text();
4005 });
4006 if (actual != expected) {
4007 console.log("BIP49 account field generates incorrect address");
4008 console.log("Expected: " + expected);
4009 console.log("Actual: " + actual);
4010 fail();
4011 }
4012 next();
4013 });
4014 });
4015});
4016},
4017
4018// BIP49 change field changes address list
4019function() {
4020page.open(url, function(status) {
4021 // set the phrase
4022 var expected = "3PEM7MiKed5konBoN66PQhK8r3hjGhy9dT";
4023 page.evaluate(function() {
4024 $("#bip49-tab a").click();
4025 $(".phrase").val("abandon abandon ability").trigger("input");
4026 });
4027 waitForGenerate(function() {
4028 // change the bip49 change field to 1
4029 page.evaluate(function() {
4030 $("#bip49 .change").val("1");
4031 $("#bip49 .change").trigger("input");
4032 });
4033 waitForGenerate(function() {
4034 // check the address for the new derivation path
4035 var actual = page.evaluate(function() {
4036 return $(".address:first").text();
4037 });
4038 if (actual != expected) {
4039 console.log("BIP49 change field generates incorrect address");
4040 console.log("Expected: " + expected);
4041 console.log("Actual: " + actual);
4042 fail();
4043 }
4044 next();
4045 });
4046 });
4047});
4048},
4049
4050// BIP49 account extendend private key is shown
4051function() {
4052page.open(url, function(status) {
4053 // set the phrase
4054 var expected = "xprv9y3uhgQbfQZbj3o98nfgLDwGGuCJjUn7GKArSAZXjKgMjSdYHjQmTyf78s22g6jsGrxXvHB6HJeFyvFSPkuYZajeTGMZVXV6aNLWw2fagCn";
4055 page.evaluate(function() {
4056 $("#bip49-tab a").click();
4057 $(".phrase").val("abandon abandon ability");
4058 $(".phrase").trigger("input");
4059 });
4060 // check the BIP49 account extended private key
4061 waitForGenerate(function() {
4062 var actual = page.evaluate(function() {
4063 return $("#bip49 .account-xprv").val();
4064 });
4065 if (actual != expected) {
4066 console.log("BIP49 account extended private key is incorrect");
4067 console.log("Expected: " + expected);
4068 console.log("Actual: " + actual);
4069 fail();
4070 }
4071 next();
4072 });
4073});
4074},
4075
4076// BIP49 account extendend public key is shown
4077function() {
4078page.open(url, function(status) {
4079 // set the phrase
4080 var expected = "xpub6C3G7BwVVn7twXscEpCghMszpw2o8wVxdY6TEYy9HfDLcExgqGj21myazAiq6HSmW2F1cBiFqJa3D1cqcDpSh8pbZF5x4iqpd4PyJvd3gjB";
4081 page.evaluate(function() {
4082 $("#bip49-tab a").click();
4083 $(".phrase").val("abandon abandon ability");
4084 $(".phrase").trigger("input");
4085 });
4086 // check the BIP49 account extended public key
4087 waitForGenerate(function() {
4088 var actual = page.evaluate(function() {
4089 return $("#bip49 .account-xpub").val();
4090 });
4091 if (actual != expected) {
4092 console.log("BIP49 account extended public key is incorrect");
4093 console.log("Expected: " + expected);
4094 console.log("Actual: " + actual);
4095 fail();
4096 }
4097 next();
4098 });
4099});
4100},
4101
4102// Test selecting coin where bip49 is unavailable (eg CLAM)
4103function() {
4104page.open(url, function(status) {
4105 // set the phrase
4106 page.evaluate(function() {
4107 $("#bip49-tab a").click();
4108 $(".phrase").val("abandon abandon ability");
4109 $(".phrase").trigger("input");
4110 });
4111 waitForGenerate(function() {
4112 // select non-bip49 network, ie CLAM network
4113 page.evaluate(function() {
4114 $(".network option[selected]").removeAttr("selected");
4115 $(".network option").filter(function() {
4116 return $(this).html() == "CLAM - Clams";
4117 }).prop("selected", true);
4118 $(".network").trigger("change");
4119 });
4120 // check the BIP49 error is shown
4121 var bip49ErrorShown = page.evaluate(function() {
4122 var bip49hidden = $("#bip49 .available").hasClass("hidden");
4123 bip49hidden = bip49hidden && !($("#bip49 .unavailable").hasClass("hidden"));
4124 return bip49hidden;
4125 });
4126 if (!bip49ErrorShown) {
4127 console.log("BIP49 error not shown for non-bip49 network");
4128 fail();
4129 }
4130 // check there are no addresses shown
4131 var addressCount = page.evaluate(function() {
4132 return $(".address").length;
4133 });
4134 if (addressCount != 0) {
4135 console.log("BIP49 address count for non-bip49 network is " + addressCount);
4136 fail();
4137 }
4138 // check the derived keys are blank
4139 var areBlank = page.evaluate(function() {
4140 var prvKeyIsBlank = $(".extended-priv-key").val().length == 0;
4141 var pubKeyIsBlank = $(".extended-pub-key").val().length == 0;
4142 return prvKeyIsBlank && pubKeyIsBlank;
4143 });
4144 if (!areBlank) {
4145 console.log("BIP49 extended keys for non-bip49 network are not blank ");
4146 fail();
4147 }
4148 next();
4149 });
4150});
4151},
4152
ed6d9d39
IC
4153// github issue 43
4154// Cleared mnemonic and root key still allows addresses to be generated
4155// https://github.com/iancoleman/bip39/issues/43
4156function() {
4157page.open(url, function(status) {
4158 // set the phrase
4159 page.evaluate(function() {
4160 $("#bip49-tab a").click();
4161 $(".phrase").val("abandon abandon ability");
4162 $(".phrase").trigger("input");
4163 });
4164 waitForGenerate(function() {
4165 // clear the mnemonic and root key
4166 page.evaluate(function() {
4167 $(".phrase").val("");
4168 $(".phrase").trigger("input");
4169 $(".root-key").val("");
4170 $(".root-key").trigger("input");
4171 $(".more").click();
4172 });
4173 waitForFeedback(function() {
4174 // check there are no addresses shown
4175 var addressCount = page.evaluate(function() {
4176 return $(".address").length;
4177 });
4178 if (addressCount != 0) {
4179 console.log("Clearing mnemonic should not allow addresses to be generated");
4180 fail();
4181 }
4182 next();
4183 });
4184 });
4185});
4186},
4187
b18eb97a
IC
4188// Github issue 95
4189// error trying to generate addresses from xpub with hardened derivation
4190function() {
4191page.open(url, function(status) {
4192 // set the phrase
4193 page.evaluate(function() {
4194 // Use bip32 tab with hardened addresses
4195 $(".hardened-addresses").prop("checked", true);
4196 $("#bip32-tab a").click();
4197 // set xpub for account 0 of bip44 for 'abandon abandon ability'
4198 var bip44AccountXpub = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf";
4199 $("#root-key").val(bip44AccountXpub);
4200 $("#root-key").trigger("input");
4201 });
4202 waitForFeedback(function() {
4203 // check the error message shows
4204 var expected = "Hardened derivation path is invalid with xpub key";
4205 var actual = page.evaluate(function() {
4206 return $(".feedback").text();
4207 });
4208 if (actual != expected) {
4209 console.log("xpub key with hardened addresses does not show feedback");
4210 console.log("Expected: " + expected);
4211 console.log("Actual: " + actual);
4212 fail();
4213 }
4214 next();
4215 });
4216});
4217},
4218
3abab9b0
IC
4219// Litecoin uses xprv by default, and can optionally be set to ltpv
4220// github issue 96
4221// https://github.com/iancoleman/bip39/issues/96
4222// Issue with extended keys on Litecoin
4223function() {
4224page.open(url, function(status) {
4225 // set the phrase and coin
4226 page.evaluate(function() {
4227 $(".phrase").val("abandon abandon ability");
4228 $(".network option[selected]").removeAttr("selected");
4229 $(".network option").filter(function() {
4230 return $(this).html() == "LTC - Litecoin";
4231 }).prop("selected", true);
4232 $(".network").trigger("change");
4233 $(".phrase").trigger("input");
4234 });
4235 // check the extended key is generated correctly
4236 waitForGenerate(function() {
4237 var expected = "xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi";
4238 var actual = page.evaluate(function() {
4239 return $(".root-key").val();
4240 });
4241 if (actual != expected) {
4242 console.log("Litecoin root key does not default to xprv");
4243 console.log("Expected: " + expected);
4244 console.log("Actual: " + actual);
4245 fail();
4246 }
4247 // set litecoin to use ltub
4248 page.evaluate(function() {
4249 $(".addresses").empty();
4250 $(".litecoin-use-ltub").prop("checked", true);
4251 $(".litecoin-use-ltub").trigger("change");
4252 });
4253 waitForGenerate(function() {
4254 var expected = "Ltpv71G8qDifUiNesiPqf6h5V6eQ8ic77oxQiYtawiACjBEx3sTXNR2HGDGnHETYxESjqkMLFBkKhWVq67ey1B2MKQXannUqNy1RZVHbmrEjnEU";
4255 var actual = page.evaluate(function() {
4256 return $(".root-key").val();
4257 });
4258 if (actual != expected) {
4259 console.log("Litecoin root key cannot be set to use ltub");
4260 console.log("Expected: " + expected);
4261 console.log("Actual: " + actual);
4262 fail();
4263 }
4264 next();
4265 });
4266 });
4267});
4268},
4269
88311463
IC
4270// BIP32 tab can use P2WPKH Nested In P2SH
4271// github issue 91 part 2
4272// https://github.com/iancoleman/bip39/issues/91
4273// generate new addresses from xpub?
4274function() {
4275page.open(url, function(status) {
4276 // set the xpub and coin and select bip32 tab with p2wpkh addresses
4277 page.evaluate(function() {
4278 // use p2wpkh addresses
4279 $(".p2wpkh-nested-in-p2sh").prop("checked", true);
4280 // use bip32 tab
4281 $("#bip32-tab a").click();
4282 // use testnet
4283 $(".network option[selected]").removeAttr("selected");
4284 $(".network option").filter(function() {
4285 return $(this).html() == "BTC - Bitcoin Testnet";
4286 }).prop("selected", true);
4287 $(".network").trigger("change");
4288 // Set root xpub to BIP49 official test vector account 0
4289 $(".root-key").val("tpubDD7tXK8KeQ3YY83yWq755fHY2JW8Ha8Q765tknUM5rSvjPcGWfUppDFMpQ1ScziKfW3ZNtZvAD7M3u7bSs7HofjTD3KP3YxPK7X6hwV8Rk2");
4290 $(".root-key").trigger("input");
4291 });
4292 // check the address is generated correctly
4293 waitForGenerate(function() {
4294 var expected = "2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2";
4295 var actual = page.evaluate(function() {
4296 return $(".address:first").text();
4297 });
4298 if (actual != expected) {
4299 console.log("BIP32 tab cannot generate P2WPKH Nested In P2SH addresses");
4300 console.log("Expected: " + expected);
4301 console.log("Actual: " + actual);
4302 fail();
4303 }
4304 next();
4305 });
4306});
4307},
4308
b0fb45b9
IC
4309// If you wish to add more tests, do so here...
4310
4311// Here is a blank test template
4312/*
4313
4314function() {
4315page.open(url, function(status) {
4316 // Do something on the page
4317 page.evaluate(function() {
4318 $(".phrase").val("abandon abandon ability").trigger("input");
4319 });
4320 waitForGenerate(function() {
4321 // Check the result of doing the thing
4322 var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug";
4323 var actual = page.evaluate(function() {
4324 return $(".address:first").text();
4325 });
4326 if (actual != expected) {
4327 console.log("A specific message about what failed");
4328 console.log("Expected: " + expected);
4329 console.log("Actual: " + actual);
4330 fail();
4331 }
4332 // Run the next test
4333 next();
4334 });
4335});
4336},
4337
4338*/
4339
88e2cdaa
IC
4340];
4341
4342console.log("Running tests...");
fb372687 4343tests = shuffle(tests);
88e2cdaa 4344next();