X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=tests.js;h=6d4702aa0e5a207210f8a90e35c0b7423e94ce63;hb=81ee6e893229013d38d3a231ffbadb1e61576ba6;hp=c6fa59460bb7800595dbae6c6b3a11dd6c78829d;hpb=9eb72cdfcf76cd6f8b57409f322e3c4e83ffdeec;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FBIP39.git diff --git a/tests.js b/tests.js index c6fa594..6d4702a 100644 --- a/tests.js +++ b/tests.js @@ -4,7 +4,12 @@ var page = require('webpage').create(); var url = 'src/index.html'; -var testMaxTime = 5000; +var testMaxTime = 20000; + +page.viewportSize = { + width: 1024, + height: 720 +}; page.onResourceError = function(e) { console.log("Error loading " + e.url); @@ -44,6 +49,67 @@ function waitForGenerate(fn, maxTime) { wait(); } +function waitForFeedback(fn, maxTime) { + if (!maxTime) { + maxTime = testMaxTime; + } + var start = new Date().getTime(); + var wait = function keepWaiting() { + var now = new Date().getTime(); + var hasTimedOut = now - start > maxTime; + if (hasTimedOut) { + console.log("Test timed out"); + fn(); + return; + } + var feedback = page.evaluate(function() { + var feedback = $(".feedback"); + if (feedback.css("display") == "none") { + return ""; + } + return feedback.text(); + }); + var hasFinished = feedback.length > 0 && feedback != "Calculating..."; + if (hasFinished) { + fn(); + } + else { + setTimeout(keepWaiting, 100); + } + } + wait(); +} + +function waitForEntropyFeedback(fn, maxTime) { + if (!maxTime) { + maxTime = testMaxTime; + } + var origFeedback = page.evaluate(function() { + return $(".entropy-container").text(); + }); + var start = new Date().getTime(); + var wait = function keepWaiting() { + var now = new Date().getTime(); + var hasTimedOut = now - start > maxTime; + if (hasTimedOut) { + console.log("Test timed out"); + fn(); + return; + } + var feedback = page.evaluate(function() { + return $(".entropy-container").text(); + }); + var hasFinished = feedback != origFeedback; + if (hasFinished) { + fn(); + } + else { + setTimeout(keepWaiting, 100); + } + } + wait(); +} + function next() { if (tests.length > 0) { var testsStr = tests.length == 1 ? "test" : "tests"; @@ -101,18 +167,17 @@ page.open(url, function(status) { // Entering mnemonic generates addresses function() { page.open(url, function(status) { - var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug"; // set the phrase page.evaluate(function() { $(".phrase").val("abandon abandon ability").trigger("input"); }); // get the address waitForGenerate(function() { - var actual = page.evaluate(function() { - return $(".address:first").text(); + var addressCount = page.evaluate(function() { + return $(".address").length; }); - if (actual != expected) { - console.log("Mnemonic did not generate address"); + if (addressCount != 20) { + console.log("Mnemonic did not generate addresses"); console.log("Expected: " + expected); console.log("Got: " + actual); fail(); @@ -215,7 +280,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=1]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Bitcoin Testnet"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -243,7 +310,39 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=2]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Litecoin"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Litecoin address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to ripple +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "rLTFnqbmCVPGx6VfaygdtuKWJgcN4v1zRS"; + page.evaluate(function() { + $(".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"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Ripple"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -271,7 +370,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=3]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Dogecoin"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -299,7 +400,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=4]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "ShadowCash"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -327,7 +430,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=5]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "ShadowCash Testnet"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -355,7 +460,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=6]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Viacoin"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -383,7 +490,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=7]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Viacoin Testnet"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -411,7 +520,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=8]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "Jumbucks"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -439,7 +550,9 @@ page.open(url, function(status) { $(".phrase").val("abandon abandon ability"); $(".phrase").trigger("input"); $(".network option[selected]").removeAttr("selected"); - $(".network option[value=9]").prop("selected", true); + $(".network option").filter(function() { + return $(this).html() == "CLAM"; + }).prop("selected", true); $(".network").trigger("change"); }); // check the address is generated correctly @@ -458,6 +571,248 @@ page.open(url, function(status) { }); }, +// Network can be set to dash +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "XdbhtMuGsPSkE6bPdNTHoFSszQKmK4S5LT"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "DASH"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("DASH address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to game +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "GSMY9bAp36cMR4zyT4uGVS7GFjpdXbao5Q"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "GAME"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("GAME address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to namecoin +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "Mw2vK2Bvex1yYtYF6sfbEg2YGoUc98YUD2"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Namecoin"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Namecoin address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to peercoin +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "PVAiioTaK2eDHSEo3tppT9AVdBYqxRTBAm"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Peercoin"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Peercoin address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to ethereum +function() { + +page.open(url, function(status) { + + // set the phrase and coin + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Ethereum"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + waitForGenerate(function() { + // check the address is generated correctly + // this value comes from + // https://www.myetherwallet.com/#view-wallet-info + // Unusual capitalization is due to checksum + var expected = "0xe5815d5902Ad612d49283DEdEc02100Bd44C2772"; + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Ethereum address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + // check the private key is correct + // this private key can be imported into + // https://www.myetherwallet.com/#view-wallet-info + // and it should correlate to the address above + var expected = "8f253078b73d7498302bb78c171b23ce7a8fb511987d2b2702b731638a4a15e7"; + var actual = page.evaluate(function() { + return $(".privkey:first").text(); + }); + if (actual != expected) { + console.log("Ethereum privkey is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + // check the public key is correct + // TODO + // don't have any third-party source to generate the expected value + //var expected = "?"; + //var actual = page.evaluate(function() { + // return $(".pubkey:first").text(); + //}); + //if (actual != expected) { + // console.log("Ethereum privkey is incorrect"); + // console.log("Expected: " + expected); + // console.log("Actual: " + actual); + // fail(); + //} + next(); + }); +}); +}, + +// Network can be set to Slimcoin +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "SNzPi1CafHFm3WWjRo43aMgiaEEj3ogjww"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Slimcoin"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Slimcoin address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + +// Network can be set to Slimcointn +function() { +page.open(url, function(status) { + // set the phrase and coin + var expected = "n3nMgWufTek5QQAr6uwMhg5xbzj8xqc4Dq"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + $(".network option[selected]").removeAttr("selected"); + $(".network option").filter(function() { + return $(this).html() == "Slimcoin Testnet"; + }).prop("selected", true); + $(".network").trigger("change"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Slimcoin testnet address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + // BIP39 seed is set from phrase function() { page.open(url, function(status) { @@ -679,48 +1034,2733 @@ page.open(url, function(status) { }, // BIP44 account field changes address list -// BIP44 external/internal field changes address list - -// BIP32 derivation path can be set -// BIP32 can use hardened derivation paths -// BIP32 extended private key is shown +function() { +page.open(url, function(status) { + // set the phrase + var expected = "1Nq2Wmu726XHCuGhctEtGmhxo3wzk5wZ1H"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + waitForGenerate(function() { + // change the bip44 purpose field to 45 + page.evaluate(function() { + $("#bip44 .account").val("1"); + $("#bip44 .account").trigger("input"); + }); + waitForGenerate(function() { + // check the address for the new derivation path + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("BIP44 account field generates incorrect address"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); +}); +}, + +// BIP44 change field changes address list +function() { +page.open(url, function(status) { + // set the phrase + var expected = "1KAGfWgqfVbSSXY56fNQ7YnhyKuoskHtYo"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + waitForGenerate(function() { + // change the bip44 purpose field to 45 + page.evaluate(function() { + $("#bip44 .change").val("1"); + $("#bip44 .change").trigger("input"); + }); + waitForGenerate(function() { + // check the address for the new derivation path + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("BIP44 change field generates incorrect address"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); +}); +}, + +// BIP32 derivation path can be set +function() { +page.open(url, function(status) { + // set the phrase + var expected = "16pYQQdLD1hH4hwTGLXBaZ9Teboi1AGL8L"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // change tabs + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32-tab a").click(); + }); + // set the derivation path to m/1 + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32 .path").val("m/1"); + $("#bip32 .path").trigger("input"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Custom BIP32 path generates incorrect address"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); + }); +}); +}, + +// BIP32 can use hardened derivation paths +function() { +page.open(url, function(status) { + // set the phrase + var expected = "14aXZeprXAE3UUKQc4ihvwBvww2LuEoHo4"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // change tabs + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32-tab a").click(); + }); + // set the derivation path to m/0' + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32 .path").val("m/0'"); + $("#bip32 .path").trigger("input"); + }); + // check the address is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Hardened BIP32 path generates incorrect address"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); + }); +}); +}, + +// BIP32 extended private key is shown +function() { +page.open(url, function(status) { + // set the phrase + var expected = "xprv9va99uTVE5aLiutUVLTyfxfe8v8aaXjSQ1XxZbK6SezYVuikA9MnjQVTA8rQHpNA5LKvyQBpLiHbBQiiccKiBDs7eRmBogsvq3THFeLHYbe"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // change tabs + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32-tab a").click(); + }); + // check the extended private key is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".extended-priv-key").val(); + }); + if (actual != expected) { + console.log("BIP32 extended private key is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); +}); +}, + // BIP32 extended public key is shown +function() { +page.open(url, function(status) { + // set the phrase + var expected = "xpub69ZVZQzP4T8dwPxwbMzz36cNgwy4yzTHmETZMyihzzXXNi3thgg3HCow1RtY252wdw5rS8369xKnraN5Q93y3FkFfJp2XEHWUrkyXsjS93P"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // change tabs + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32-tab a").click(); + }); + // check the extended public key is generated correctly + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".extended-pub-key").val(); + }); + if (actual != expected) { + console.log("BIP32 extended public key is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); +}); +}, // Derivation path is shown in table +function() { +page.open(url, function(status) { + // set the phrase + var expected = "m/44'/0'/0'/0/0"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // check for derivation path in table + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".index:first").text(); + }); + if (actual != expected) { + console.log("Derivation path shown incorrectly in table"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); +}); +}, + // Derivation path for address can be hardened +function() { +page.open(url, function(status) { + // set the phrase + var expected = "18exLzUv7kfpiXRzmCjFDoC9qwNLFyvwyd"; + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + // change tabs + waitForGenerate(function() { + page.evaluate(function() { + $("#bip32-tab a").click(); + }); + waitForGenerate(function() { + // select the hardened addresses option + page.evaluate(function() { + $(".hardened-addresses").prop("checked", true); + $(".hardened-addresses").trigger("change"); + }); + waitForGenerate(function() { + // check the generated address is hardened + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Hardened address is incorrect"); + console.log("Expected: " + expected); + console.log("Actual: " + actual); + fail(); + } + next(); + }); + }); + }); +}); +}, + // Derivation path visibility can be toggled +function() { +page.open(url, function(status) { + // set the phrase + page.evaluate(function() { + $(".phrase").val("abandon abandon ability"); + $(".phrase").trigger("input"); + }); + waitForGenerate(function() { + // toggle path visibility + page.evaluate(function() { + $(".index-toggle").click(); + }); + // check the path is not visible + var isInvisible = page.evaluate(function() { + return $(".index:first span").hasClass("invisible"); + }); + if (!isInvisible) { + console.log("Toggled derivation path is visible"); + fail(); + } + next(); + }); +}); +}, + // Address is shown -// Addresses are shown in order of derivation path -// Address visibility can be toggled -// Private key is shown -// Private key visibility can be toggled +function() { +page.open(url, function(status) { + var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug"; + // set the phrase + page.evaluate(function() { + $(".phrase").val("abandon abandon ability").trigger("input"); + }); + // get the address + waitForGenerate(function() { + var actual = page.evaluate(function() { + return $(".address:first").text(); + }); + if (actual != expected) { + console.log("Address is not shown"); + console.log("Expected: " + expected); + console.log("Got: " + actual); + fail(); + } + next(); + }); +}); +}, -// More addresses can be generated -// A custom number of additional addresses can be generated -// Additional addresses are shown in order of derivation path +// Addresses are shown in order of derivation path +function() { +page.open(url, function(status) { + // set the phrase + page.evaluate(function() { + $(".phrase").val("abandon abandon ability").trigger("input"); + }); + // get the derivation paths + waitForGenerate(function() { + var paths = page.evaluate(function() { + return $(".index").map(function(i, e) { + return $(e).text(); + }); + }); + if (paths.length != 20) { + console.log("Total paths is less than expected: " + paths.length); + fail(); + } + for (var i=0; i