]>
git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blob - tests.js
2800e6cf073b4ee6cc0f8a1dbcac9480eed55f63
2 // $ phantomjs tests.js
5 var page
= require('webpage').create();
6 var url
= 'src/index.html';
7 var testMaxTime
= 5000;
9 page
.onResourceError = function(e
) {
10 console
.log("Error loading " + e
.url
);
15 console
.log("Failed");
19 function waitForGenerate(fn
, maxTime
) {
21 maxTime
= testMaxTime
;
23 var start
= new Date().getTime();
24 var prevAddressCount
= -1;
25 var wait
= function keepWaiting() {
26 var now
= new Date().getTime();
27 var hasTimedOut
= now
- start
> maxTime
;
28 var addressCount
= page
.evaluate(function() {
29 return $(".address").length
;
31 var hasFinished
= addressCount
> 0 && addressCount
== prevAddressCount
;
32 prevAddressCount
= addressCount
;
36 else if (hasTimedOut
) {
37 console
.log("Test timed out");
41 setTimeout(keepWaiting
, 100);
48 if (tests
.length
> 0) {
49 var testsStr
= tests
.length
== 1 ? "test" : "tests";
50 console
.log(tests
.length
+ " " + testsStr
+ " remaining");
54 console
.log("Finished with 0 failures");
60 * Randomize array element order in-place.
61 * Using Durstenfeld shuffle algorithm.
62 * See http://stackoverflow.com/a/12646864
64 function shuffle(array
) {
65 for (var i
= array
.length
- 1; i
> 0; i
--) {
66 var j
= Math
.floor(Math
.random() * (i
+ 1));
76 // Page loads with status of 'success'
78 page
.open(url
, function(status
) {
79 if (status
!= "success") {
80 console
.log("Page did not load with status 'success'");
89 page
.open(url
, function(status
) {
90 var content
= page
.evaluate(function() {
91 return document
.body
.textContent
.trim();
94 console
.log("Page does not have text");
101 // Entering mnemonic generates addresses
103 page
.open(url
, function(status
) {
105 page
.evaluate(function() {
106 $(".phrase").val("abandon abandon ability").trigger("input");
109 waitForGenerate(function() {
110 var addressCount
= page
.evaluate(function() {
111 return $(".address").length
;
113 if (addressCount
!= 20) {
114 console
.log("Mnemonic did not generate addresses");
115 console
.log("Expected: " + expected
);
116 console
.log("Got: " + actual
);
124 // Random button generates random mnemonic
126 page
.open(url
, function(status
) {
127 // check initial phrase is empty
128 var phrase
= page
.evaluate(function() {
129 return $(".phrase").text();
132 console
.log("Initial phrase is not blank");
135 // press the 'generate' button
136 page
.evaluate(function() {
137 $(".generate").click();
139 // get the new phrase
140 waitForGenerate(function() {
141 var phrase
= page
.evaluate(function() {
142 return $(".phrase").val();
144 if (phrase
.length
<= 0) {
145 console
.log("Phrase not generated by pressing button");
153 // Mnemonic length can be customized
155 page
.open(url
, function(status
) {
156 // set the length to 6
157 var expectedLength
= "6";
158 page
.evaluate(function() {
159 $(".strength option[selected]").removeAttr("selected");
160 $(".strength option[value=6]").prop("selected", true);
162 // press the 'generate' button
163 page
.evaluate(function() {
164 $(".generate").click();
166 // check the new phrase is six words long
167 waitForGenerate(function() {
168 var actualLength
= page
.evaluate(function() {
169 var words
= $(".phrase").val().split(" ");
172 if (actualLength
!= expectedLength
) {
173 console
.log("Phrase not generated with correct length");
174 console
.log("Expected: " + expectedLength
);
175 console
.log("Actual: " + actualLength
);
183 // Passphrase can be set
185 page
.open(url
, function(status
) {
186 // set the phrase and passphrase
187 var expected
= "15pJzUWPGzR7avffV9nY5by4PSgSKG9rba";
188 page
.evaluate(function() {
189 $(".phrase").val("abandon abandon ability");
190 $(".passphrase").val("secure_passphrase").trigger("input");
192 // check the address is generated correctly
193 waitForGenerate(function() {
194 var actual
= page
.evaluate(function() {
195 return $(".address:first").text();
197 if (actual
!= expected
) {
198 console
.log("Passphrase results in wrong address");
199 console
.log("Expected: " + expected
);
200 console
.log("Actual: " + actual
);
208 // Network can be set to bitcoin testnet
210 page
.open(url
, function(status
) {
211 // set the phrase and coin
212 var expected
= "mucaU5iiDaJDb69BHLeDv8JFfGiyg2nJKi";
213 page
.evaluate(function() {
214 $(".phrase").val("abandon abandon ability");
215 $(".phrase").trigger("input");
216 $(".network option[selected]").removeAttr("selected");
217 $(".network option[value=1]").prop("selected", true);
218 $(".network").trigger("change");
220 // check the address is generated correctly
221 waitForGenerate(function() {
222 var actual
= page
.evaluate(function() {
223 return $(".address:first").text();
225 if (actual
!= expected
) {
226 console
.log("Bitcoin testnet address is incorrect");
227 console
.log("Expected: " + expected
);
228 console
.log("Actual: " + actual
);
236 // Network can be set to litecoin
238 page
.open(url
, function(status
) {
239 // set the phrase and coin
240 var expected
= "LQ4XU8RX2ULPmPq9FcUHdVmPVchP9nwXdn";
241 page
.evaluate(function() {
242 $(".phrase").val("abandon abandon ability");
243 $(".phrase").trigger("input");
244 $(".network option[selected]").removeAttr("selected");
245 $(".network option[value=2]").prop("selected", true);
246 $(".network").trigger("change");
248 // check the address is generated correctly
249 waitForGenerate(function() {
250 var actual
= page
.evaluate(function() {
251 return $(".address:first").text();
253 if (actual
!= expected
) {
254 console
.log("Litecoin address is incorrect");
255 console
.log("Expected: " + expected
);
256 console
.log("Actual: " + actual
);
264 // Network can be set to dogecoin
266 page
.open(url
, function(status
) {
267 // set the phrase and coin
268 var expected
= "DPQH2AtuzkVSG6ovjKk4jbUmZ6iXLpgbJA";
269 page
.evaluate(function() {
270 $(".phrase").val("abandon abandon ability");
271 $(".phrase").trigger("input");
272 $(".network option[selected]").removeAttr("selected");
273 $(".network option[value=3]").prop("selected", true);
274 $(".network").trigger("change");
276 // check the address is generated correctly
277 waitForGenerate(function() {
278 var actual
= page
.evaluate(function() {
279 return $(".address:first").text();
281 if (actual
!= expected
) {
282 console
.log("Dogecoin address is incorrect");
283 console
.log("Expected: " + expected
);
284 console
.log("Actual: " + actual
);
292 // Network can be set to shadowcash
294 page
.open(url
, function(status
) {
295 // set the phrase and coin
296 var expected
= "SiSZtfYAXEFvMm3XM8hmtkGDyViRwErtCG";
297 page
.evaluate(function() {
298 $(".phrase").val("abandon abandon ability");
299 $(".phrase").trigger("input");
300 $(".network option[selected]").removeAttr("selected");
301 $(".network option[value=4]").prop("selected", true);
302 $(".network").trigger("change");
304 // check the address is generated correctly
305 waitForGenerate(function() {
306 var actual
= page
.evaluate(function() {
307 return $(".address:first").text();
309 if (actual
!= expected
) {
310 console
.log("Shadowcash address is incorrect");
311 console
.log("Expected: " + expected
);
312 console
.log("Actual: " + actual
);
320 // Network can be set to shadowcash testnet
322 page
.open(url
, function(status
) {
323 // set the phrase and coin
324 var expected
= "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe";
325 page
.evaluate(function() {
326 $(".phrase").val("abandon abandon ability");
327 $(".phrase").trigger("input");
328 $(".network option[selected]").removeAttr("selected");
329 $(".network option[value=5]").prop("selected", true);
330 $(".network").trigger("change");
332 // check the address is generated correctly
333 waitForGenerate(function() {
334 var actual
= page
.evaluate(function() {
335 return $(".address:first").text();
337 if (actual
!= expected
) {
338 console
.log("Shadowcash testnet address is incorrect");
339 console
.log("Expected: " + expected
);
340 console
.log("Actual: " + actual
);
348 // Network can be set to viacoin
350 page
.open(url
, function(status
) {
351 // set the phrase and coin
352 var expected
= "Vq9Eq4N5SQnjqZvxtxzo7hZPW5XnyJsmXT";
353 page
.evaluate(function() {
354 $(".phrase").val("abandon abandon ability");
355 $(".phrase").trigger("input");
356 $(".network option[selected]").removeAttr("selected");
357 $(".network option[value=6]").prop("selected", true);
358 $(".network").trigger("change");
360 // check the address is generated correctly
361 waitForGenerate(function() {
362 var actual
= page
.evaluate(function() {
363 return $(".address:first").text();
365 if (actual
!= expected
) {
366 console
.log("Viacoin address is incorrect");
367 console
.log("Expected: " + expected
);
368 console
.log("Actual: " + actual
);
376 // Network can be set to viacoin testnet
378 page
.open(url
, function(status
) {
379 // set the phrase and coin
380 var expected
= "tM2EDpVKaTiEg2NZg3yKg8eqjLr55BErHe";
381 page
.evaluate(function() {
382 $(".phrase").val("abandon abandon ability");
383 $(".phrase").trigger("input");
384 $(".network option[selected]").removeAttr("selected");
385 $(".network option[value=7]").prop("selected", true);
386 $(".network").trigger("change");
388 // check the address is generated correctly
389 waitForGenerate(function() {
390 var actual
= page
.evaluate(function() {
391 return $(".address:first").text();
393 if (actual
!= expected
) {
394 console
.log("Viacoin testnet address is incorrect");
395 console
.log("Expected: " + expected
);
396 console
.log("Actual: " + actual
);
404 // Network can be set to jumbucks
406 page
.open(url
, function(status
) {
407 // set the phrase and coin
408 var expected
= "JLEXccwDXADK4RxBPkRez7mqsHVoJBEUew";
409 page
.evaluate(function() {
410 $(".phrase").val("abandon abandon ability");
411 $(".phrase").trigger("input");
412 $(".network option[selected]").removeAttr("selected");
413 $(".network option[value=8]").prop("selected", true);
414 $(".network").trigger("change");
416 // check the address is generated correctly
417 waitForGenerate(function() {
418 var actual
= page
.evaluate(function() {
419 return $(".address:first").text();
421 if (actual
!= expected
) {
422 console
.log("Jumbucks address is incorrect");
423 console
.log("Expected: " + expected
);
424 console
.log("Actual: " + actual
);
432 // Network can be set to clam
434 page
.open(url
, function(status
) {
435 // set the phrase and coin
436 var expected
= "xCp4sakjVx4pUAZ6cBCtuin8Ddb6U1sk9y";
437 page
.evaluate(function() {
438 $(".phrase").val("abandon abandon ability");
439 $(".phrase").trigger("input");
440 $(".network option[selected]").removeAttr("selected");
441 $(".network option[value=9]").prop("selected", true);
442 $(".network").trigger("change");
444 // check the address is generated correctly
445 waitForGenerate(function() {
446 var actual
= page
.evaluate(function() {
447 return $(".address:first").text();
449 if (actual
!= expected
) {
450 console
.log("CLAM address is incorrect");
451 console
.log("Expected: " + expected
);
452 console
.log("Actual: " + actual
);
460 // Network can be set to dash
462 page
.open(url
, function(status
) {
463 // set the phrase and coin
464 var expected
= "XdbhtMuGsPSkE6bPdNTHoFSszQKmK4S5LT";
465 page
.evaluate(function() {
466 $(".phrase").val("abandon abandon ability");
467 $(".phrase").trigger("input");
468 $(".network option[selected]").removeAttr("selected");
469 $(".network option[value=10]").prop("selected", true);
470 $(".network").trigger("change");
472 // check the address is generated correctly
473 waitForGenerate(function() {
474 var actual
= page
.evaluate(function() {
475 return $(".address:first").text();
477 if (actual
!= expected
) {
478 console
.log("DASH address is incorrect");
479 console
.log("Expected: " + expected
);
480 console
.log("Actual: " + actual
);
488 // Network can be set to namecoin
490 page
.open(url
, function(status
) {
491 // set the phrase and coin
492 var expected
= "Mw2vK2Bvex1yYtYF6sfbEg2YGoUc98YUD2";
493 page
.evaluate(function() {
494 $(".phrase").val("abandon abandon ability");
495 $(".phrase").trigger("input");
496 $(".network option[selected]").removeAttr("selected");
497 $(".network option[value=11]").prop("selected", true);
498 $(".network").trigger("change");
500 // check the address is generated correctly
501 waitForGenerate(function() {
502 var actual
= page
.evaluate(function() {
503 return $(".address:first").text();
505 if (actual
!= expected
) {
506 console
.log("Namecoin address is incorrect");
507 console
.log("Expected: " + expected
);
508 console
.log("Actual: " + actual
);
516 // Network can be set to peercoin
518 page
.open(url
, function(status
) {
519 // set the phrase and coin
520 var expected
= "PVAiioTaK2eDHSEo3tppT9AVdBYqxRTBAm";
521 page
.evaluate(function() {
522 $(".phrase").val("abandon abandon ability");
523 $(".phrase").trigger("input");
524 $(".network option[selected]").removeAttr("selected");
525 $(".network option[value=12]").prop("selected", true);
526 $(".network").trigger("change");
528 // check the address is generated correctly
529 waitForGenerate(function() {
530 var actual
= page
.evaluate(function() {
531 return $(".address:first").text();
533 if (actual
!= expected
) {
534 console
.log("Peercoin address is incorrect");
535 console
.log("Expected: " + expected
);
536 console
.log("Actual: " + actual
);
544 // BIP39 seed is set from phrase
546 page
.open(url
, function(status
) {
548 var expected
= "20da140d3dd1df8713cefcc4d54ce0e445b4151027a1ab567b832f6da5fcc5afc1c3a3f199ab78b8e0ab4652efd7f414ac2c9a3b81bceb879a70f377aa0a58f3";
549 page
.evaluate(function() {
550 $(".phrase").val("abandon abandon ability");
551 $(".phrase").trigger("input");
553 // check the address is generated correctly
554 waitForGenerate(function() {
555 var actual
= page
.evaluate(function() {
556 return $(".seed").val();
558 if (actual
!= expected
) {
559 console
.log("BIP39 seed is incorrectly generated from mnemonic");
560 console
.log("Expected: " + expected
);
561 console
.log("Actual: " + actual
);
569 // BIP32 root key is set from phrase
571 page
.open(url
, function(status
) {
573 var expected
= "xprv9s21ZrQH143K2jkGDCeTLgRewT9F2pH5JZs2zDmmjXes34geVnFiuNa8KTvY5WoYvdn4Ag6oYRoB6cXtc43NgJAEqDXf51xPm6fhiMCKwpi";
574 page
.evaluate(function() {
575 $(".phrase").val("abandon abandon ability");
576 $(".phrase").trigger("input");
578 // check the address is generated correctly
579 waitForGenerate(function() {
580 var actual
= page
.evaluate(function() {
581 return $(".root-key").val();
583 if (actual
!= expected
) {
584 console
.log("Root key is incorrectly generated from mnemonic");
585 console
.log("Expected: " + expected
);
586 console
.log("Actual: " + actual
);
594 // Tabs show correct addresses when changed
596 page
.open(url
, function(status
) {
598 var expected
= "17uQ7s2izWPwBmEVFikTmZUjbBKWYdJchz";
599 page
.evaluate(function() {
600 $(".phrase").val("abandon abandon ability");
601 $(".phrase").trigger("input");
604 waitForGenerate(function() {
605 page
.evaluate(function() {
606 $("#bip32-tab a").click();
608 // check the address is generated correctly
609 waitForGenerate(function() {
610 var actual
= page
.evaluate(function() {
611 return $(".address:first").text();
613 if (actual
!= expected
) {
614 console
.log("Clicking tab generates incorrect address");
615 console
.log("Expected: " + expected
);
616 console
.log("Actual: " + actual
);
625 // BIP44 derivation path is shown
627 page
.open(url
, function(status
) {
629 var expected
= "m/44'/0'/0'/0";
630 page
.evaluate(function() {
631 $(".phrase").val("abandon abandon ability");
632 $(".phrase").trigger("input");
634 // check the derivation path of the first address
635 waitForGenerate(function() {
636 var actual
= page
.evaluate(function() {
637 return $("#bip44 .path").val();
639 if (actual
!= expected
) {
640 console
.log("BIP44 derivation path is incorrect");
641 console
.log("Expected: " + expected
);
642 console
.log("Actual: " + actual
);
650 // BIP44 extended private key is shown
652 page
.open(url
, function(status
) {
654 var expected
= "xprvA2DxxvPZcyRvYgZMGS53nadR32mVDeCyqQYyFhrCVbJNjPoxMeVf7QT5g7mQASbTf9Kp4cryvcXnu2qurjWKcrdsr91jXymdCDNxKgLFKJG";
655 page
.evaluate(function() {
656 $(".phrase").val("abandon abandon ability");
657 $(".phrase").trigger("input");
659 // check the BIP44 extended private key
660 waitForGenerate(function() {
661 var actual
= page
.evaluate(function() {
662 return $(".extended-priv-key").val();
664 if (actual
!= expected
) {
665 console
.log("BIP44 extended private key is incorrect");
666 console
.log("Expected: " + expected
);
667 console
.log("Actual: " + actual
);
675 // BIP44 extended public key is shown
677 page
.open(url
, function(status
) {
679 var expected
= "xpub6FDKNRvTTLzDmAdpNTc49ia9b4byd6vqCdUa46Fp3vqMcC96uBoufCmZXQLiN5AK3iSCJMhf9gT2sxkpyaPepRuA7W3MujV5tGmF5VfbueM";
680 page
.evaluate(function() {
681 $(".phrase").val("abandon abandon ability");
682 $(".phrase").trigger("input");
684 // check the BIP44 extended public key
685 waitForGenerate(function() {
686 var actual
= page
.evaluate(function() {
687 return $(".extended-pub-key").val();
689 if (actual
!= expected
) {
690 console
.log("BIP44 extended public key is incorrect");
691 console
.log("Expected: " + expected
);
692 console
.log("Actual: " + actual
);
700 // BIP44 purpose field changes address list
702 page
.open(url
, function(status
) {
704 var expected
= "1JbDzRJ2cDT8aat2xwKd6Pb2zzavow5MhF";
705 page
.evaluate(function() {
706 $(".phrase").val("abandon abandon ability");
707 $(".phrase").trigger("input");
709 waitForGenerate(function() {
710 // change the bip44 purpose field to 45
711 page
.evaluate(function() {
712 $("#bip44 .purpose").val("45");
713 $("#bip44 .purpose").trigger("input");
715 waitForGenerate(function() {
716 // check the address for the new derivation path
717 var actual
= page
.evaluate(function() {
718 return $(".address:first").text();
720 if (actual
!= expected
) {
721 console
.log("BIP44 purpose field generates incorrect address");
722 console
.log("Expected: " + expected
);
723 console
.log("Actual: " + actual
);
732 // BIP44 coin field changes address list
734 page
.open(url
, function(status
) {
736 var expected
= "1F6dB2djQYrxoyfZZmfr6D5voH8GkJTghk";
737 page
.evaluate(function() {
738 $(".phrase").val("abandon abandon ability");
739 $(".phrase").trigger("input");
741 waitForGenerate(function() {
742 // change the bip44 purpose field to 45
743 page
.evaluate(function() {
744 $("#bip44 .coin").val("1");
745 $("#bip44 .coin").trigger("input");
747 waitForGenerate(function() {
748 // check the address for the new derivation path
749 var actual
= page
.evaluate(function() {
750 return $(".address:first").text();
752 if (actual
!= expected
) {
753 console
.log("BIP44 coin field generates incorrect address");
754 console
.log("Expected: " + expected
);
755 console
.log("Actual: " + actual
);
764 // BIP44 account field changes address list
766 page
.open(url
, function(status
) {
768 var expected
= "1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H";
769 page
.evaluate(function() {
770 $(".phrase").val("abandon abandon ability");
771 $(".phrase").trigger("input");
773 waitForGenerate(function() {
774 // change the bip44 purpose field to 45
775 page
.evaluate(function() {
776 $("#bip44 .account").val("1");
777 $("#bip44 .account").trigger("input");
779 waitForGenerate(function() {
780 // check the address for the new derivation path
781 var actual
= page
.evaluate(function() {
782 return $(".address:first").text();
784 if (actual
!= expected
) {
785 console
.log("BIP44 account field generates incorrect address");
786 console
.log("Expected: " + expected
);
787 console
.log("Actual: " + actual
);
796 // BIP44 change field changes address list
798 page
.open(url
, function(status
) {
800 var expected
= "1KAGfWgqfVbSSXY56fNQ7YnhyKuoskHtYo";
801 page
.evaluate(function() {
802 $(".phrase").val("abandon abandon ability");
803 $(".phrase").trigger("input");
805 waitForGenerate(function() {
806 // change the bip44 purpose field to 45
807 page
.evaluate(function() {
808 $("#bip44 .change").val("1");
809 $("#bip44 .change").trigger("input");
811 waitForGenerate(function() {
812 // check the address for the new derivation path
813 var actual
= page
.evaluate(function() {
814 return $(".address:first").text();
816 if (actual
!= expected
) {
817 console
.log("BIP44 change field generates incorrect address");
818 console
.log("Expected: " + expected
);
819 console
.log("Actual: " + actual
);
828 // BIP32 derivation path can be set
830 page
.open(url
, function(status
) {
832 var expected
= "16pYQQdLD1hH4hwTGLXBaZ9Teboi1AGL8L";
833 page
.evaluate(function() {
834 $(".phrase").val("abandon abandon ability");
835 $(".phrase").trigger("input");
838 waitForGenerate(function() {
839 page
.evaluate(function() {
840 $("#bip32-tab a").click();
842 // set the derivation path to m/1
843 waitForGenerate(function() {
844 page
.evaluate(function() {
845 $("#bip32 .path").val("m/1");
846 $("#bip32 .path").trigger("input");
848 // check the address is generated correctly
849 waitForGenerate(function() {
850 var actual
= page
.evaluate(function() {
851 return $(".address:first").text();
853 if (actual
!= expected
) {
854 console
.log("Custom BIP32 path generates incorrect address");
855 console
.log("Expected: " + expected
);
856 console
.log("Actual: " + actual
);
866 // BIP32 can use hardened derivation paths
868 page
.open(url
, function(status
) {
870 var expected
= "14aXZeprXAE3UUKQc4ihvwBvww2LuEoHo4";
871 page
.evaluate(function() {
872 $(".phrase").val("abandon abandon ability");
873 $(".phrase").trigger("input");
876 waitForGenerate(function() {
877 page
.evaluate(function() {
878 $("#bip32-tab a").click();
880 // set the derivation path to m/0'
881 waitForGenerate(function() {
882 page
.evaluate(function() {
883 $("#bip32 .path").val("m/0'");
884 $("#bip32 .path").trigger("input");
886 // check the address is generated correctly
887 waitForGenerate(function() {
888 var actual
= page
.evaluate(function() {
889 return $(".address:first").text();
891 if (actual
!= expected
) {
892 console
.log("Hardened BIP32 path generates incorrect address");
893 console
.log("Expected: " + expected
);
894 console
.log("Actual: " + actual
);
904 // BIP32 extended private key is shown
906 page
.open(url
, function(status
) {
908 var expected
= "xprv9va99uTVE5aLiutUVLTyfxfe8v8aaXjSQ1XxZbK6SezYVuikA9MnjQVTA8rQHpNA5LKvyQBpLiHbBQiiccKiBDs7eRmBogsvq3THFeLHYbe";
909 page
.evaluate(function() {
910 $(".phrase").val("abandon abandon ability");
911 $(".phrase").trigger("input");
914 waitForGenerate(function() {
915 page
.evaluate(function() {
916 $("#bip32-tab a").click();
918 // check the extended private key is generated correctly
919 waitForGenerate(function() {
920 var actual
= page
.evaluate(function() {
921 return $(".extended-priv-key").val();
923 if (actual
!= expected
) {
924 console
.log("BIP32 extended private key is incorrect");
925 console
.log("Expected: " + expected
);
926 console
.log("Actual: " + actual
);
935 // BIP32 extended public key is shown
937 page
.open(url
, function(status
) {
939 var expected
= "xpub69ZVZQzP4T8dwPxwbMzz36cNgwy4yzTHmETZMyihzzXXNi3thgg3HCow1RtY252wdw5rS8369xKnraN5Q93y3FkFfJp2XEHWUrkyXsjS93P";
940 page
.evaluate(function() {
941 $(".phrase").val("abandon abandon ability");
942 $(".phrase").trigger("input");
945 waitForGenerate(function() {
946 page
.evaluate(function() {
947 $("#bip32-tab a").click();
949 // check the extended public key is generated correctly
950 waitForGenerate(function() {
951 var actual
= page
.evaluate(function() {
952 return $(".extended-pub-key").val();
954 if (actual
!= expected
) {
955 console
.log("BIP32 extended public key is incorrect");
956 console
.log("Expected: " + expected
);
957 console
.log("Actual: " + actual
);
966 // Derivation path is shown in table
968 page
.open(url
, function(status
) {
970 var expected
= "m/44'/0'/0'/0/0";
971 page
.evaluate(function() {
972 $(".phrase").val("abandon abandon ability");
973 $(".phrase").trigger("input");
975 // check for derivation path in table
976 waitForGenerate(function() {
977 var actual
= page
.evaluate(function() {
978 return $(".index:first").text();
980 if (actual
!= expected
) {
981 console
.log("Derivation path shown incorrectly in table");
982 console
.log("Expected: " + expected
);
983 console
.log("Actual: " + actual
);
991 // Derivation path for address can be hardened
993 page
.open(url
, function(status
) {
995 var expected
= "18exLzUv7kfpiXRzmCjFDoC9qwNLFyvwyd";
996 page
.evaluate(function() {
997 $(".phrase").val("abandon abandon ability");
998 $(".phrase").trigger("input");
1001 waitForGenerate(function() {
1002 page
.evaluate(function() {
1003 $("#bip32-tab a").click();
1005 waitForGenerate(function() {
1006 // select the hardened addresses option
1007 page
.evaluate(function() {
1008 $(".hardened-addresses").prop("checked", true);
1009 $(".hardened-addresses").trigger("change");
1011 waitForGenerate(function() {
1012 // check the generated address is hardened
1013 var actual
= page
.evaluate(function() {
1014 return $(".address:first").text();
1016 if (actual
!= expected
) {
1017 console
.log("Hardened address is incorrect");
1018 console
.log("Expected: " + expected
);
1019 console
.log("Actual: " + actual
);
1029 // Derivation path visibility can be toggled
1031 page
.open(url
, function(status
) {
1033 page
.evaluate(function() {
1034 $(".phrase").val("abandon abandon ability");
1035 $(".phrase").trigger("input");
1037 waitForGenerate(function() {
1038 // toggle path visibility
1039 page
.evaluate(function() {
1040 $(".index-toggle").click();
1042 // check the path is not visible
1043 var isInvisible
= page
.evaluate(function() {
1044 return $(".index:first span").hasClass("invisible");
1047 console
.log("Toggled derivation path is visible");
1057 page
.open(url
, function(status
) {
1058 var expected
= "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug";
1060 page
.evaluate(function() {
1061 $(".phrase").val("abandon abandon ability").trigger("input");
1064 waitForGenerate(function() {
1065 var actual
= page
.evaluate(function() {
1066 return $(".address:first").text();
1068 if (actual
!= expected
) {
1069 console
.log("Address is not shown");
1070 console
.log("Expected: " + expected
);
1071 console
.log("Got: " + actual
);
1079 // Addresses are shown in order of derivation path
1081 page
.open(url
, function(status
) {
1083 page
.evaluate(function() {
1084 $(".phrase").val("abandon abandon ability").trigger("input");
1086 // get the derivation paths
1087 waitForGenerate(function() {
1088 var paths
= page
.evaluate(function() {
1089 return $(".index").map(function(i
, e
) {
1093 if (paths
.length
!= 20) {
1094 console
.log("Total paths is less than expected: " + paths
.length
);
1097 for (var i
=0; i
<paths
.length
; i
++) {
1098 var expected
= "m/44'/0'/0'/0/" + i
;
1099 var actual
= paths
[i
];
1100 if (actual
!= expected
) {
1101 console
.log("Path " + i
+ " is incorrect");
1102 console
.log("Expected: " + expected
);
1103 console
.log("Actual: " + actual
);
1112 // Address visibility can be toggled
1114 page
.open(url
, function(status
) {
1116 page
.evaluate(function() {
1117 $(".phrase").val("abandon abandon ability");
1118 $(".phrase").trigger("input");
1120 waitForGenerate(function() {
1121 // toggle address visibility
1122 page
.evaluate(function() {
1123 $(".address-toggle").click();
1125 // check the address is not visible
1126 var isInvisible
= page
.evaluate(function() {
1127 return $(".address:first span").hasClass("invisible");
1130 console
.log("Toggled address is visible");
1138 // Private key is shown
1140 page
.open(url
, function(status
) {
1141 var expected
= "L26cVSpWFkJ6aQkPkKmTzLqTdLJ923e6CzrVh9cmx21QHsoUmrEE";
1143 page
.evaluate(function() {
1144 $(".phrase").val("abandon abandon ability").trigger("input");
1147 waitForGenerate(function() {
1148 var actual
= page
.evaluate(function() {
1149 return $(".privkey:first").text();
1151 if (actual
!= expected
) {
1152 console
.log("Private key is not shown");
1153 console
.log("Expected: " + expected
);
1154 console
.log("Got: " + actual
);
1162 // Private key visibility can be toggled
1164 page
.open(url
, function(status
) {
1166 page
.evaluate(function() {
1167 $(".phrase").val("abandon abandon ability");
1168 $(".phrase").trigger("input");
1170 waitForGenerate(function() {
1171 // toggle private key visibility
1172 page
.evaluate(function() {
1173 $(".private-key-toggle").click();
1175 // check the private key is not visible
1176 var isInvisible
= page
.evaluate(function() {
1177 return $(".privkey:first span").hasClass("invisible");
1180 console
.log("Toggled private key is visible");
1188 // More addresses can be generated
1190 page
.open(url
, function(status
) {
1192 page
.evaluate(function() {
1193 $(".phrase").val("abandon abandon ability");
1194 $(".phrase").trigger("input");
1196 waitForGenerate(function() {
1197 // generate more addresses
1198 page
.evaluate(function() {
1201 waitForGenerate(function() {
1202 // check there are more addresses
1203 var addressCount
= page
.evaluate(function() {
1204 return $(".address").length
;
1206 if (addressCount
!= 40) {
1207 console
.log("More addresses cannot be generated");
1216 // A custom number of additional addresses can be generated
1218 page
.open(url
, function(status
) {
1220 page
.evaluate(function() {
1221 $(".phrase").val("abandon abandon ability");
1222 $(".phrase").trigger("input");
1224 waitForGenerate(function() {
1225 // get the current number of addresses
1226 var oldAddressCount
= page
.evaluate(function() {
1227 return $(".address").length
;
1229 // set a custom number of additional addresses
1230 page
.evaluate(function() {
1231 $(".rows-to-add").val(1);
1233 // generate more addresses
1234 page
.evaluate(function() {
1237 waitForGenerate(function() {
1238 // check there are the correct number of addresses
1239 var newAddressCount
= page
.evaluate(function() {
1240 return $(".address").length
;
1242 if (newAddressCount
- oldAddressCount
!= 1) {
1243 console
.log("Number of additional addresses cannot be customized");
1244 console
.log(newAddressCount
)
1245 console
.log(oldAddressCount
)
1254 // Additional addresses are shown in order of derivation path
1256 page
.open(url
, function(status
) {
1258 page
.evaluate(function() {
1259 $(".phrase").val("abandon abandon ability").trigger("input");
1261 waitForGenerate(function() {
1262 // generate more addresses
1263 page
.evaluate(function() {
1266 // get the derivation paths
1267 waitForGenerate(function() {
1268 var paths
= page
.evaluate(function() {
1269 return $(".index").map(function(i
, e
) {
1273 if (paths
.length
!= 40) {
1274 console
.log("Total additional paths is less than expected: " + paths
.length
);
1277 for (var i
=0; i
<paths
.length
; i
++) {
1278 var expected
= "m/44'/0'/0'/0/" + i
;
1279 var actual
= paths
[i
];
1280 if (actual
!= expected
) {
1281 console
.log("Path " + i
+ " is not in correct order");
1282 console
.log("Expected: " + expected
);
1283 console
.log("Actual: " + actual
);
1293 // BIP32 root key can be set by the user
1294 // Setting BIP32 root key clears the existing phrase, passphrase and seed
1295 // Clearing of phrase, passphrase and seed can be cancelled by user
1296 // Custom BIP32 root key is used when changing the derivation path
1298 // Incorrect mnemonic shows error
1299 // Incorrect word shows suggested replacement
1300 // Incorrect BIP32 root key shows error
1301 // Derivation path not starting with m shows error
1302 // Derivation path containing invalid characters shows useful error
1304 // Github Issue 11: Default word length is 15
1305 // https://github.com/dcpos/bip39/issues/11
1307 // Github Issue 12: Generate more rows with private keys hidden
1308 // https://github.com/dcpos/bip39/issues/12
1310 // Github Issue 19: Mnemonic is not sensitive to whitespace
1311 // https://github.com/dcpos/bip39/issues/19
1313 // Github Issue 23: Use correct derivation path when changing tabs
1314 // https://github.com/dcpos/bip39/issues/23
1316 // Github Issue 26: When using a Root key derrived altcoins are incorrect
1317 // https://github.com/dcpos/bip39/issues/26
1321 console
.log("Running tests...");
1322 tests
= shuffle(tests
);