diff options
Merge branch 'develop' of github.com:MetaMask/metamask-extension into network-remove-provider-engine
Diffstat (limited to 'test')
-rw-r--r-- | test/e2e/beta/contract-test/contract.js | 61 | ||||
-rw-r--r-- | test/e2e/beta/contract-test/index.html | 8 | ||||
-rw-r--r-- | test/e2e/beta/from-import-beta-ui.spec.js | 84 | ||||
-rw-r--r-- | test/e2e/beta/helpers.js | 14 | ||||
-rw-r--r-- | test/e2e/beta/metamask-beta-ui.spec.js | 533 | ||||
-rwxr-xr-x | test/e2e/beta/run-all.sh | 4 | ||||
-rw-r--r-- | test/e2e/func.js | 2 | ||||
-rw-r--r-- | test/e2e/metamask.spec.js | 34 | ||||
-rw-r--r-- | test/integration/lib/send-new-ui.js | 4 | ||||
-rw-r--r-- | test/unit/app/account-import-strategies.spec.js | 62 | ||||
-rw-r--r-- | test/unit/app/controllers/notice-controller-test.js | 50 | ||||
-rw-r--r-- | test/unit/test-utils.js | 17 |
12 files changed, 666 insertions, 207 deletions
diff --git a/test/e2e/beta/contract-test/contract.js b/test/e2e/beta/contract-test/contract.js new file mode 100644 index 000000000..19c29e5c1 --- /dev/null +++ b/test/e2e/beta/contract-test/contract.js @@ -0,0 +1,61 @@ +/* +The `piggybankContract` is compiled from: + + pragma solidity ^0.4.0; + contract PiggyBank { + + uint private balance; + address public owner; + + function PiggyBank() public { + owner = msg.sender; + balance = 0; + } + + function deposit() public payable returns (uint) { + balance += msg.value; + return balance; + } + + function withdraw(uint withdrawAmount) public returns (uint remainingBal) { + require(msg.sender == owner); + balance -= withdrawAmount; + + msg.sender.transfer(withdrawAmount); + + return balance; + } + } +*/ + +var piggybankContract = web3.eth.contract([{"constant":false,"inputs":[{"name":"withdrawAmount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"remainingBal","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]); + +deployButton.addEventListener('click', function (event) { + + var piggybank = piggybankContract.new( + { + from: web3.eth.accounts[0], + data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029', + gas: '4700000' + }, function (e, contract){ + console.log(e, contract); + if (typeof contract.address !== 'undefined') { + console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); + + console.log(`contract`, contract); + + depositButton.addEventListener('click', function (event) { + contract.deposit({ from: web3.eth.accounts[0], value: '0x29a2241af62c0000' }, function (result) { + console.log(result) + }) + }) + + withdrawButton.addEventListener('click', function (event) { + contract.withdraw('0xde0b6b3a7640000', { from: web3.eth.accounts[0] }, function (result) { + console.log(result) + }) + }) + } + }) + +})
\ No newline at end of file diff --git a/test/e2e/beta/contract-test/index.html b/test/e2e/beta/contract-test/index.html new file mode 100644 index 000000000..0868633f7 --- /dev/null +++ b/test/e2e/beta/contract-test/index.html @@ -0,0 +1,8 @@ +<html> +<body> + <button id="deployButton">Deploy Contract</button> + <button id="depositButton">Deposit</button> + <button id="withdrawButton">Withdraw</button> +</body> +<script src="contract.js"></script> +</html>
\ No newline at end of file diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js index f2feefa49..2470d1eef 100644 --- a/test/e2e/beta/from-import-beta-ui.spec.js +++ b/test/e2e/beta/from-import-beta-ui.spec.js @@ -23,6 +23,7 @@ describe('Using MetaMask with an existing account', function () { const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' const testAddress = '0xE18035BF8712672935FDB4e5e431b1a0183d2DFC' + const testPrivateKey2 = '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6' const regularDelayMs = 1000 const largeDelayMs = regularDelayMs * 2 const waitingNewPageDelayMs = regularDelayMs * 10 @@ -109,27 +110,39 @@ describe('Using MetaMask with an existing account', function () { await delay(regularDelayMs) }) + it('clicks through the ToS', async () => { + // terms of use + const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled() + assert.equal(canClickThrough, false, 'disabled continue button') + const bottomOfTos = await findElement(driver, By.linkText('Attributions')) + await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos) + await delay(regularDelayMs) + const acceptTos = await findElement(driver, By.css('.tou button')) + await acceptTos.click() + await delay(regularDelayMs) + }) + it('clicks through the privacy notice', async () => { - const [nextScreen] = await findElements(driver, By.css('.tou button')) + // privacy notice + const nextScreen = await findElement(driver, By.css('.tou button')) await nextScreen.click() await delay(regularDelayMs) + }) - const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled() - assert.equal(canClickThrough, false, 'disabled continue button') - const element = await findElement(driver, By.linkText('Attributions')) - await driver.executeScript('arguments[0].scrollIntoView(true)', element) + it('clicks through the phishing notice', async () => { + // phishing notice + const noticeElement = await driver.findElement(By.css('.markdown')) + await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement) await delay(regularDelayMs) - - const acceptTos = await findElement(driver, By.xpath(`//button[contains(text(), 'Accept')]`)) - await acceptTos.click() + const nextScreen = await findElement(driver, By.css('.tou button')) + await nextScreen.click() await delay(regularDelayMs) }) }) describe('Show account information', () => { it('shows the correct account address', async () => { - const detailsButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Details')]`)) - detailsButton.click() + await driver.findElement(By.css('.wallet-view__details-button')).click() await driver.findElement(By.css('.qr-wrapper')).isDisplayed() await delay(regularDelayMs) @@ -225,8 +238,10 @@ describe('Using MetaMask with an existing account', function () { await configureGas.click() await delay(regularDelayMs) + const gasModal = await driver.findElement(By.css('span .modal')) const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() + await driver.wait(until.stalenessOf(gasModal)) await delay(regularDelayMs) // Continue to next screen @@ -303,15 +318,8 @@ describe('Using MetaMask with an existing account', function () { await nextScreen.click() await delay(regularDelayMs) - const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) - await addTokens.click() - await delay(largeDelayMs) - }) - - it('renders the balance for the new token', async () => { - const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) - const tokenAmount = await balance.getText() - assert.equal(tokenAmount, '0BAT') + const [importAccount] = await findElements(driver, By.xpath(`//div[contains(text(), 'Import Account')]`)) + await importAccount.click() await delay(regularDelayMs) }) }) @@ -343,8 +351,9 @@ describe('Using MetaMask with an existing account', function () { await driver.get(extensionUri) await delay(regularDelayMs) - const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) - await confirmButton.click() + it('enter private key', async () => { + const privateKeyInput = await findElement(driver, By.css('#private-key-box')) + await privateKeyInput.sendKeys(testPrivateKey2) await delay(regularDelayMs) await driver.switchTo().window(tokenFactory) @@ -357,36 +366,17 @@ describe('Using MetaMask with an existing account', function () { await delay(regularDelayMs) }) - it('clicks on the Add Token button', async () => { - const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) - await addToken.click() - await delay(regularDelayMs) - }) - - it('picks the new Test token', async () => { - const addCustomToken = await findElement(driver, By.xpath("//div[contains(text(), 'Custom Token')]")) - await addCustomToken.click() - await delay(regularDelayMs) - - const newTokenAddress = await findElement(driver, By.css('#custom-address')) - await newTokenAddress.sendKeys(tokenAddress) - await delay(regularDelayMs) - - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() - await delay(regularDelayMs) - - const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) - await addTokens.click() + it('should show the correct account name', async () => { + const [accountName] = await findElements(driver, By.css('.account-name')) + assert.equal(await accountName.getText(), 'Account 3') await delay(regularDelayMs) }) - it('renders the balance for the new token', async () => { - const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) - await driver.wait(until.elementTextIs(balance, '100TST')) - const tokenAmount = await balance.getText() - assert.equal(tokenAmount, '100TST') + it('should show the imported label', async () => { + const [importedLabel] = await findElements(driver, By.css('.wallet-view__keyring-label')) + assert.equal(await importedLabel.getText(), 'IMPORTED') await delay(regularDelayMs) }) }) + }) diff --git a/test/e2e/beta/helpers.js b/test/e2e/beta/helpers.js index eaf2e0ade..35015ab9c 100644 --- a/test/e2e/beta/helpers.js +++ b/test/e2e/beta/helpers.js @@ -1,9 +1,11 @@ +const { delay } = require('../func') const { until } = require('selenium-webdriver') module.exports = { checkBrowserForConsoleErrors, findElement, findElements, + openNewPage, } async function checkBrowserForConsoleErrors (driver) { @@ -31,3 +33,15 @@ async function findElement (driver, by, timeout = 10000) { async function findElements (driver, by, timeout = 10000) { return driver.wait(until.elementsLocated(by), timeout) } + +async function openNewPage (driver, url) { + await driver.executeScript('window.open()') + await delay(1000) + + const handles = await driver.getAllWindowHandles() + const secondHandle = handles[1] + await driver.switchTo().window(secondHandle) + + await driver.get(url) + await delay(1000) +} diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index afd0e9496..50998fd5d 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -12,6 +12,9 @@ const { findElement, findElements, checkBrowserForConsoleErrors, + loadExtension, + verboseReportOnFailure, + openNewPage, } = require('./helpers') describe('MetaMask', function () { @@ -50,8 +53,7 @@ describe('MetaMask', function () { } } if (this.currentTest.state === 'failed') { - await verboseReportOnFailure({ browser, driver, title: this.currentTest.title }) - await delay(1000000) + await verboseReportOnFailure(driver, this.currentTest) } }) @@ -60,10 +62,26 @@ describe('MetaMask', function () { }) describe('New UI setup', async function () { + let networkSelector it('switches to first tab', async function () { const [firstTab] = await driver.getAllWindowHandles() await driver.switchTo().window(firstTab) await delay(regularDelayMs) + try { + networkSelector = await findElement(driver, By.css('#network_component')) + } catch (e) { + await loadExtension(driver, extensionId) + } + await delay(regularDelayMs) + }) + + it('use the local network', async function () { + await networkSelector.click() + await delay(regularDelayMs) + + const localhost = await findElement(driver, By.xpath(`//li[contains(text(), 'Localhost')]`)) + await localhost.click() + await delay(regularDelayMs) }) it('selects the new UI option', async () => { @@ -72,15 +90,21 @@ describe('MetaMask', function () { await delay(regularDelayMs) // Close all other tabs - let [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() - newUi = newUi || infoPage + let [oldUi, tab1, tab2] = await driver.getAllWindowHandles() await driver.switchTo().window(oldUi) await driver.close() - if (infoPage !== newUi) { - await driver.switchTo().window(infoPage) + + await driver.switchTo().window(tab1) + const tab1Url = await driver.getCurrentUrl() + if (tab1Url.match(/metamask.io/)) { + await driver.switchTo().window(tab1) await driver.close() + await driver.switchTo().window(tab2) + } else if (tab2) { + await driver.switchTo().window(tab2) + await driver.close() + await driver.switchTo().window(tab1) } - await driver.switchTo().window(newUi) await delay(regularDelayMs) const continueBtn = await findElement(driver, By.css('.welcome-screen__button')) @@ -107,27 +131,43 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) - it('clicks through the privacy notice', async () => { - const nextScreen = await findElement(driver, By.css('.tou button')) - await nextScreen.click() - await delay(regularDelayMs) - + it('clicks through the ToS', async () => { + // terms of use const canClickThrough = await driver.findElement(By.css('.tou button')).isEnabled() assert.equal(canClickThrough, false, 'disabled continue button') const bottomOfTos = await findElement(driver, By.linkText('Attributions')) await driver.executeScript('arguments[0].scrollIntoView(true)', bottomOfTos) await delay(regularDelayMs) - const acceptTos = await findElement(driver, By.css('.tou button')) + driver.wait(until.elementIsEnabled(acceptTos)) await acceptTos.click() await delay(regularDelayMs) }) + it('clicks through the privacy notice', async () => { + // privacy notice + const nextScreen = await findElement(driver, By.css('.tou button')) + await nextScreen.click() + await delay(regularDelayMs) + }) + + it('clicks through the phishing notice', async () => { + // phishing notice + const noticeElement = await driver.findElement(By.css('.markdown')) + await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', noticeElement) + await delay(regularDelayMs) + const nextScreen = await findElement(driver, By.css('.tou button')) + await nextScreen.click() + await delay(regularDelayMs) + }) + let seedPhrase it('reveals the seed phrase', async () => { - const revealSeedPhrase = await findElement(driver, By.css('.backup-phrase__secret-blocker')) - await revealSeedPhrase.click() + const byRevealButton = By.css('.backup-phrase__secret-blocker .backup-phrase__reveal-button') + await driver.wait(until.elementLocated(byRevealButton, 10000)) + const revealSeedPhraseButton = await findElement(driver, byRevealButton, 10000) + await revealSeedPhraseButton.click() await delay(regularDelayMs) seedPhrase = await driver.findElement(By.css('.backup-phrase__secret-words')).getText() @@ -139,56 +179,76 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) - it('can retype the seed phrase', async () => { - const words = seedPhrase.split(' ') + async function retypeSeedPhrase (words) { + try { + const word0 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[0]}')]`), 10000) - const word0 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[0]}')]`)) - await word0.click() - await delay(tinyDelayMs) + await word0.click() + await delay(tinyDelayMs) - const word1 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[1]}')]`)) - await word1.click() - await delay(tinyDelayMs) + const word1 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[1]}')]`), 10000) - const word2 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[2]}')]`)) - await word2.click() - await delay(tinyDelayMs) + await word1.click() + await delay(tinyDelayMs) - const word3 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[3]}')]`)) - await word3.click() - await delay(tinyDelayMs) + const word2 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[2]}')]`), 10000) - const word4 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[4]}')]`)) - await word4.click() - await delay(tinyDelayMs) + await word2.click() + await delay(tinyDelayMs) - const word5 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[5]}')]`)) - await word5.click() - await delay(tinyDelayMs) + const word3 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[3]}')]`), 10000) - const word6 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[6]}')]`)) - await word6.click() - await delay(tinyDelayMs) + await word3.click() + await delay(tinyDelayMs) - const word7 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[7]}')]`)) - await word7.click() - await delay(tinyDelayMs) + const word4 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[4]}')]`), 10000) - const word8 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[8]}')]`)) - await word8.click() - await delay(tinyDelayMs) + await word4.click() + await delay(tinyDelayMs) - const word9 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[9]}')]`)) - await word9.click() - await delay(tinyDelayMs) + const word5 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[5]}')]`), 10000) - const word10 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[10]}')]`)) - await word10.click() - await delay(tinyDelayMs) + await word5.click() + await delay(tinyDelayMs) - const word11 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[11]}')]`)) - await word11.click() - await delay(tinyDelayMs) + const word6 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[6]}')]`), 10000) + + await word6.click() + await delay(tinyDelayMs) + + const word7 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[7]}')]`), 10000) + + await word7.click() + await delay(tinyDelayMs) + + const word8 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[8]}')]`), 10000) + + await word8.click() + await delay(tinyDelayMs) + + const word9 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[9]}')]`), 10000) + + await word9.click() + await delay(tinyDelayMs) + + const word10 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[10]}')]`), 10000) + + await word10.click() + await delay(tinyDelayMs) + + const word11 = await findElement(driver, By.xpath(`//button[contains(text(), '${words[11]}')]`), 10000) + await word11.click() + await delay(tinyDelayMs) + } catch (e) { + await loadExtension(driver, extensionId) + await retypeSeedPhrase(words) + } + } + + it('can retype the seed phrase', async () => { + const words = seedPhrase.split(' ') + + await retypeSeedPhrase(words) const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirm.click() @@ -196,7 +256,8 @@ describe('MetaMask', function () { }) it('clicks through the deposit modal', async () => { - const buyModal = await driver.findElement(By.css('span .modal')) + const byBuyModal = By.css('span .modal') + const buyModal = await driver.wait(until.elementLocated(byBuyModal)) const closeModal = await findElement(driver, By.css('.page-container__header-close')) await closeModal.click() await driver.wait(until.stalenessOf(buyModal)) @@ -210,8 +271,12 @@ describe('MetaMask', function () { await driver.findElement(By.css('.qr-wrapper')).isDisplayed() await delay(regularDelayMs) + let accountModal = await driver.findElement(By.css('span .modal')) + await driver.executeScript("document.querySelector('.account-modal-close').click()") - await delay(regularDelayMs * 4) + + await driver.wait(until.stalenessOf(accountModal)) + await delay(regularDelayMs) }) }) @@ -311,8 +376,11 @@ describe('MetaMask', function () { await configureGas.click() await delay(regularDelayMs) + const gasModal = await driver.findElement(By.css('span .modal')) + const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) await save.click() + await driver.wait(until.stalenessOf(gasModal)) await delay(regularDelayMs) // Continue to next screen @@ -331,19 +399,20 @@ describe('MetaMask', function () { const transactions = await findElements(driver, By.css('.tx-list-item')) assert.equal(transactions.length, 1) - const txValues = await findElements(driver, By.css('.tx-list-value')) - assert.equal(txValues.length, 1) - assert.equal(await txValues[0].getText(), '1 ETH') + const txValues = await findElement(driver, By.css('.tx-list-value')) + await driver.wait(until.elementTextMatches(txValues, /1\sETH/), 10000) }) }) describe('Send ETH from Faucet', () => { it('starts a send transaction inside Faucet', async () => { - await driver.executeScript('window.open("https://faucet.metamask.io")') - await delay(waitingNewPageDelayMs) + await openNewPage(driver, 'https://faucet.metamask.io') const [extension, faucet] = await driver.getAllWindowHandles() await driver.switchTo().window(faucet) + + const faucetPageTitle = await findElement(driver, By.css('.container-fluid')) + await driver.wait(until.elementTextMatches(faucetPageTitle, /MetaMask/)) await delay(regularDelayMs) const send1eth = await findElement(driver, By.xpath(`//button[contains(text(), '10 ether')]`), 14000) @@ -369,47 +438,133 @@ describe('MetaMask', function () { }) }) - describe('Add existing token using search', () => { - it('clicks on the Add Token button', async () => { - const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) - await addToken.click() + describe('Deploy contract and call contract methods', () => { + let extension + let contractTestPage + it('confirms a deploy contract transaction', async () => { + await openNewPage(driver, 'http://127.0.0.1:8080/'); + + [extension, contractTestPage] = await driver.getAllWindowHandles() + await delay(regularDelayMs) + + const deployContractButton = await findElement(driver, By.css('#deployButton')) + await deployContractButton.click() await delay(regularDelayMs) + + await driver.switchTo().window(extension) + await delay(regularDelayMs) + + const txListItem = await findElement(driver, By.css('.tx-list-item')) + await txListItem.click() + await delay(regularDelayMs) + + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + + const txAccounts = await findElements(driver, By.css('.tx-list-account')) + assert.equal(await txAccounts[0].getText(), 'Contract Deployment') }) - it('can pick a token from the existing options', async () => { - const tokenSearch = await findElement(driver, By.css('#search-tokens')) - await tokenSearch.sendKeys('BAT') + it('calls and confirms a contract method where ETH is sent', async () => { + await driver.switchTo().window(contractTestPage) await delay(regularDelayMs) - const token = await findElement(driver, By.xpath("//span[contains(text(), 'BAT')]")) - await token.click() + const depositButton = await findElement(driver, By.css('#depositButton')) + await depositButton.click() await delay(regularDelayMs) - const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) - await nextScreen.click() + await driver.switchTo().window(extension) await delay(regularDelayMs) - const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) - await addTokens.click() - await delay(largeDelayMs) + const txListItem = await findElement(driver, By.css('.tx-list-item')) + await txListItem.click() + await delay(regularDelayMs) + + // Set the gas limit + const configureGas = await findElement(driver, By.css('.sliders-icon-container')) + await configureGas.click() + await delay(regularDelayMs) + + let gasModal = await driver.findElement(By.css('span .modal')) + await driver.wait(until.elementLocated(By.css('.send-v2__customize-gas__title'))) + + const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input')) + await gasPriceInput.clear() + await gasPriceInput.sendKeys('10') + await gasLimitInput.clear() + await gasLimitInput.sendKeys('60001') + + const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + await save.click() + await delay(regularDelayMs) + + await driver.wait(until.stalenessOf(gasModal)) + + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + + const txValues = await findElement(driver, By.css('.tx-list-value')) + await driver.wait(until.elementTextMatches(txValues, /3\sETH/), 10000) + + const txAccounts = await findElements(driver, By.css('.tx-list-account')) + const firstTxAddress = await txAccounts[0].getText() + assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/)) }) - it('renders the balance for the chosen token', async () => { + it('calls and confirms a contract method where ETH is received', async () => { + await driver.switchTo().window(contractTestPage) + await delay(regularDelayMs) + + const withdrawButton = await findElement(driver, By.css('#withdrawButton')) + await withdrawButton.click() + await delay(regularDelayMs) + + await driver.switchTo().window(extension) + await delay(regularDelayMs) + + const txListItem = await findElement(driver, By.css('.tx-list-item')) + await txListItem.click() + await delay(regularDelayMs) + + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + + const txValues = await findElement(driver, By.css('.tx-list-value')) + await driver.wait(until.elementTextMatches(txValues, /0\sETH/), 10000) + + await driver.switchTo().window(contractTestPage) + await driver.close() + await driver.switchTo().window(extension) + }) + + it('renders the correct ETH balance', async () => { const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) - await driver.wait(until.elementTextIs(balance, '0BAT')) + await driver.wait(until.elementTextMatches(balance, /^86.*ETH.*$/), 10000) const tokenAmount = await balance.getText() - assert.equal(tokenAmount, '0BAT') + assert.ok(/^86.*ETH.*$/.test(tokenAmount)) await delay(regularDelayMs) }) }) describe('Add a custom token from TokenFactory', () => { it('creates a new token', async () => { - await driver.executeScript('window.open("https://tokenfactory.surge.sh/#/factory")') - await delay(waitingNewPageDelayMs) + openNewPage(driver, 'https://tokenfactory.surge.sh/#/factory') + await delay(regularDelayMs * 10) const [extension, tokenFactory] = await driver.getAllWindowHandles() - await driver.switchTo().window(tokenFactory) + const [ totalSupply, tokenName, @@ -436,12 +591,16 @@ describe('MetaMask', function () { await driver.switchTo().window(tokenFactory) await delay(regularDelayMs) + const tokenContactAddress = await driver.findElement(By.css('div > div > div:nth-child(2) > span:nth-child(3)')) tokenAddress = await tokenContactAddress.getText() + await driver.close() await driver.switchTo().window(extension) - await driver.get(extensionUri) + await loadExtension(driver, extensionId) + await driver.switchTo().window(extension) await delay(regularDelayMs) + }) it('clicks on the Add Token button', async () => { @@ -470,9 +629,217 @@ describe('MetaMask', function () { it('renders the balance for the new token', async () => { const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) - await driver.wait(until.elementTextIs(balance, '100TST')) + await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/)) const tokenAmount = await balance.getText() - assert.equal(tokenAmount, '100TST') + assert.ok(/^100\s*TST\s*$/.test(tokenAmount)) + await delay(regularDelayMs) + }) + }) + + describe('Send token from inside MetaMask', () => { + let gasModal + it('starts to send a transaction', async function () { + const sendButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Send')]`)) + await sendButton.click() + await delay(regularDelayMs) + + const inputAddress = await findElement(driver, By.css('input[placeholder="Recipient Address"]')) + const inputAmount = await findElement(driver, By.css('.currency-display__input')) + await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + await inputAmount.sendKeys('50') + + // Set the gas limit + const configureGas = await findElement(driver, By.css('.send-v2__gas-fee-display button')) + await configureGas.click() + await delay(regularDelayMs) + + gasModal = await driver.findElement(By.css('span .modal')) + }) + + it('customizes gas', async () => { + await driver.wait(until.elementLocated(By.css('.send-v2__customize-gas__title'))) + const save = await findElement(driver, By.xpath(`//button[contains(text(), 'Save')]`)) + await save.click() + await delay(regularDelayMs) + }) + + it('transitions to the confirm screen', async () => { + await driver.wait(until.stalenessOf(gasModal)) + + // Continue to next screen + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + await nextScreen.click() + await delay(regularDelayMs) + }) + + it('submits the transaction', async function () { + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + }) + + it('finds the transaction in the transactions list', async function () { + const transactions = await findElements(driver, By.css('.tx-list-item')) + assert.equal(transactions.length, 1) + + const txValues = await findElements(driver, By.css('.tx-list-value')) + assert.equal(txValues.length, 1) + + // test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, + // or possibly until we use latest version of firefox in the tests + if (process.env.SELENIUM_BROWSER !== 'firefox') { + await driver.wait(until.elementTextMatches(txValues[0], /50\sTST/), 10000) + } + + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + const tx = await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed|Failed/), 10000) + assert.equal(await tx.getText(), 'Confirmed') + }) + }) + + describe('Send a custom token from TokenFactory', () => { + let gasModal + it('sends an already created token', async () => { + openNewPage(driver, `https://tokenfactory.surge.sh/#/token/${tokenAddress}`) + + const [extension, tokenFactory] = await driver.getAllWindowHandles() + + const [ + transferToAddress, + transferToAmount, + ] = await findElements(driver, By.css('.form-control')) + + await transferToAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') + await transferToAmount.sendKeys('26') + + const transferAmountButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Transfer Amount')]`)) + await transferAmountButton.click() + await delay(regularDelayMs) + + const [,, popup] = await driver.getAllWindowHandles() + await driver.switchTo().window(popup) + await driver.close() + await driver.switchTo().window(extension) + await delay(regularDelayMs) + + const [txListItem] = await findElements(driver, By.css('.tx-list-item')) + await txListItem.click() + await delay(regularDelayMs) + + // Set the gas limit + const configureGas = await driver.wait(until.elementLocated(By.css('.send-v2__gas-fee-display button'))) + await configureGas.click() + await delay(regularDelayMs) + + gasModal = await driver.findElement(By.css('span .modal')) + }) + + it('customizes gas', async () => { + await driver.wait(until.elementLocated(By.css('.send-v2__customize-gas__title'))) + + const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.customize-gas-input')) + await gasPriceInput.clear() + await delay(tinyDelayMs) + await gasPriceInput.sendKeys('10') + await delay(tinyDelayMs) + await gasLimitInput.clear() + await delay(tinyDelayMs) + await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'a')) + await gasLimitInput.sendKeys('60000') + await gasLimitInput.sendKeys(Key.chord(Key.CONTROL, 'e')) + + // Needed for different behaviour of input in different versions of firefox + const gasLimitInputValue = await gasLimitInput.getAttribute('value') + if (gasLimitInputValue === '600001') { + await gasLimitInput.sendKeys(Key.BACK_SPACE) + } + + const save = await findElement(driver, By.css('.send-v2__customize-gas__save')) + await save.click() + await driver.wait(until.stalenessOf(gasModal)) + + const gasFeeInput = await findElement(driver, By.css('.currency-display__input')) + assert.equal(await gasFeeInput.getAttribute('value'), 0.0006) + }) + + it('submits the transaction', async function () { + const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) + await confirmButton.click() + await delay(regularDelayMs) + }) + + it('finds the transaction in the transactions list', async function () { + const transactions = await findElements(driver, By.css('.tx-list-item')) + assert.equal(transactions.length, 2) + + const txValues = await findElements(driver, By.css('.tx-list-value')) + await driver.wait(until.elementTextMatches(txValues[0], /26\sTST/)) + const txStatuses = await findElements(driver, By.css('.tx-list-status')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + + const walletBalance = await findElement(driver, By.css('.wallet-balance')) + await walletBalance.click() + + const tokenListItems = await findElements(driver, By.css('.token-list-item')) + await tokenListItems[0].click() + + // test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, + // or possibly until we use latest version of firefox in the tests + if (process.env.SELENIUM_BROWSER !== 'firefox') { + const tokenBalanceAmount = await findElement(driver, By.css('.token-balance__amount')) + assert.equal(await tokenBalanceAmount.getText(), '24') + } + }) + }) + + describe('Hide token', () => { + it('hides the token when clicked', async () => { + const [hideTokenEllipsis] = await findElements(driver, By.css('.token-list-item__ellipsis')) + await hideTokenEllipsis.click() + + const byTokenMenuDropdownOption = By.css('.menu__item--clickable') + const tokenMenuDropdownOption = await driver.wait(until.elementLocated(byTokenMenuDropdownOption)) + + await tokenMenuDropdownOption.click() + + const confirmHideModal = await findElement(driver, By.css('span .modal')) + + const byHideTokenConfirmationButton = By.css('.hide-token-confirmation__button') + const hideTokenConfirmationButton = await driver.wait(until.elementLocated(byHideTokenConfirmationButton)) + await hideTokenConfirmationButton.click() + + await driver.wait(until.stalenessOf(confirmHideModal)) + }) + }) + + describe('Add existing token using search', () => { + it('clicks on the Add Token button', async () => { + const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) + await addToken.click() + await delay(regularDelayMs) + }) + + it('can pick a token from the existing options', async () => { + const tokenSearch = await findElement(driver, By.css('#search-tokens')) + await tokenSearch.sendKeys('BAT') + await delay(regularDelayMs) + + const token = await findElement(driver, By.xpath("//span[contains(text(), 'BAT')]")) + await token.click() + await delay(regularDelayMs) + + const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`)) + await nextScreen.click() + await delay(regularDelayMs) + + const addTokens = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Tokens')]`)) + await addTokens.click() + await delay(largeDelayMs) + }) + + it('renders the balance for the chosen token', async () => { + const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + await driver.wait(until.elementTextMatches(balance, /0\sBAT/)) await delay(regularDelayMs) }) }) diff --git a/test/e2e/beta/run-all.sh b/test/e2e/beta/run-all.sh index 5916d5614..493e1360a 100755 --- a/test/e2e/beta/run-all.sh +++ b/test/e2e/beta/run-all.sh @@ -6,5 +6,5 @@ set -o pipefail export PATH="$PATH:./node_modules/.bin" -shell-parallel -s 'npm run ganache:start' -x 'sleep 5 && mocha test/e2e/beta/metamask-beta-ui.spec' -shell-parallel -s 'npm run ganache:start' -x 'sleep 5 && mocha test/e2e/beta/from-import-beta-ui.spec' +shell-parallel -s 'npm run ganache:start' -x 'sleep 5 && superstatic test/e2e/beta/contract-test/ --port 8080 --host 127.0.0.1' -x 'sleep 5 && mocha test/e2e/beta/metamask-beta-ui.spec' +shell-parallel -s 'npm run ganache:start -- -d' -x 'sleep 5 && superstatic test/e2e/beta/contract-test/ --port 8080 --host 127.0.0.1' -x 'sleep 5 && mocha test/e2e/beta/from-import-beta-ui.spec' diff --git a/test/e2e/func.js b/test/e2e/func.js index 34c64709a..700552658 100644 --- a/test/e2e/func.js +++ b/test/e2e/func.js @@ -57,7 +57,7 @@ async function setupBrowserAndExtension ({ browser, extPath }) { } function buildChromeWebDriver (extPath) { - const tmpProfile = path.join(os.tmpdir(), fs.mkdtempSync('mm-chrome-profile')); + const tmpProfile = fs.mkdtempSync(path.join(os.tmpdir(), 'mm-chrome-profile')) return new webdriver.Builder() .withCapabilities({ chromeOptions: { diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index 30b077cde..d80fc9430 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -59,13 +59,6 @@ describe('Metamask popup page', function () { it('matches MetaMask title', async () => { const title = await driver.getTitle() assert.equal(title, 'MetaMask', 'title matches MetaMask') - }) - - it('shows privacy notice', async () => { - await delay(300) - const privacy = await driver.findElement(By.css('.terms-header')).getText() - assert.equal(privacy, 'PRIVACY NOTICE', 'shows privacy notice') - await driver.findElement(By.css('button')).click() await delay(300) }) @@ -88,6 +81,24 @@ describe('Metamask popup page', function () { await button.click() }) + it('shows privacy notice', async () => { + const privacy = await driver.findElement(By.css('.terms-header')).getText() + assert.equal(privacy, 'PRIVACY NOTICE', 'shows privacy notice') + await driver.findElement(By.css('button')).click() + await delay(300) + }) + + it('shows phishing notice', async () => { + await delay(300) + const noticeHeader = await driver.findElement(By.css('.terms-header')).getText() + assert.equal(noticeHeader, 'PHISHING WARNING', 'shows phishing warning') + const element = await driver.findElement(By.css('.markdown')) + await driver.executeScript('arguments[0].scrollTop = arguments[0].scrollHeight', element) + await delay(300) + await driver.findElement(By.css('button')).click() + await delay(300) + }) + it('accepts password with length of eight', async () => { const passwordBox = await driver.findElement(By.id('password-box')) const passwordBoxConfirm = await driver.findElement(By.id('password-box-confirm')) @@ -206,7 +217,11 @@ describe('Metamask popup page', function () { it('confirms transaction', async function () { await delay(300) - await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')).click() + const bySubmitButton = By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input') + const submitButton = await driver.wait(until.elementLocated(bySubmitButton)) + + submitButton.click() + await delay(500) }) @@ -246,7 +261,8 @@ describe('Metamask popup page', function () { it('confirms transaction in MetaMask popup', async function () { const windowHandles = await driver.getAllWindowHandles() await driver.switchTo().window(windowHandles[windowHandles.length - 1]) - const metamaskSubmit = await driver.findElement(By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input')) + const byMetamaskSubmit = By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input') + const metamaskSubmit = await driver.wait(until.elementLocated(byMetamaskSubmit)) await metamaskSubmit.click() await delay(1000) }) diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 4d2ea2ea4..72e4a8cb1 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -117,12 +117,12 @@ async function runSendFlowTest(assert, done) { const sendGasField = await queryAsync($, '.send-v2__gas-fee-display') assert.equal( sendGasField.find('.currency-display__input-wrapper > input').val(), - '0.000198264', + '0.000021', 'send gas field should show estimated gas total' ) assert.equal( sendGasField.find('.currency-display__converted-value')[0].textContent, - '$0.24 USD', + '$0.03 USD', 'send gas field should show estimated gas total converted to USD' ) diff --git a/test/unit/app/account-import-strategies.spec.js b/test/unit/app/account-import-strategies.spec.js index 83cfaeb3e..216c2f698 100644 --- a/test/unit/app/account-import-strategies.spec.js +++ b/test/unit/app/account-import-strategies.spec.js @@ -1,31 +1,59 @@ const assert = require('assert') const path = require('path') -const accountImporter = require('../../../app/scripts/account-import-strategies/index') const ethUtil = require('ethereumjs-util') +const accountImporter = require('../../../app/scripts/account-import-strategies/index') +const { assertRejects } = require('../test-utils') describe('Account Import Strategies', function () { const privkey = '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553' const json = '{"version":3,"id":"dbb54385-0a99-437f-83c0-647de9f244c3","address":"a7f92ce3fba24196cf6f4bd2e1eb3db282ba998c","Crypto":{"ciphertext":"bde13d9ade5c82df80281ca363320ce254a8a3a06535bbf6ffdeaf0726b1312c","cipherparams":{"iv":"fbf93718a57f26051b292f072f2e5b41"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"7ffe00488319dec48e4c49a120ca49c6afbde9272854c64d9541c83fc6acdffe","n":8192,"r":8,"p":1},"mac":"2adfd9c4bc1cdac4c85bddfb31d9e21a684e0e050247a70c5698facf6b7d4681"}}' - it('imports a private key and strips 0x prefix', async function () { - const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ]) - assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)) - }) + describe('private key import', function () { + it('imports a private key and strips 0x prefix', async function () { + const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ]) + assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey)) + }) - it('fails when password is incorrect for keystore', async function () { - const wrongPassword = 'password2' + it('throws an error for empty string private key', async () => { + assertRejects(async function() { + await accountImporter.importAccount('Private Key', [ '' ]) + }, Error, 'no empty strings') + }) - try { - await accountImporter.importAccount('JSON File', [ json, wrongPassword]) - } catch (error) { - assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase') - } - }) + it('throws an error for undefined string private key', async () => { + assertRejects(async function () { + await accountImporter.importAccount('Private Key', [ undefined ]) + }) + }) - it('imports json string and password to return a private key', async function () { - const fileContentsPassword = 'password1' - const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword]) - assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7') + it('throws an error for undefined string private key', async () => { + assertRejects(async function () { + await accountImporter.importAccount('Private Key', []) + }) + }) + + it('throws an error for invalid private key', async () => { + assertRejects(async function () { + await accountImporter.importAccount('Private Key', [ 'popcorn' ]) + }) + }) }) + describe('JSON keystore import', function () { + it('fails when password is incorrect for keystore', async function () { + const wrongPassword = 'password2' + + try { + await accountImporter.importAccount('JSON File', [ json, wrongPassword]) + } catch (error) { + assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase') + } + }) + + it('imports json string and password to return a private key', async function () { + const fileContentsPassword = 'password1' + const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword]) + assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7') + }) + }) }) diff --git a/test/unit/app/controllers/notice-controller-test.js b/test/unit/app/controllers/notice-controller-test.js index e78b69623..b3ae75080 100644 --- a/test/unit/app/controllers/notice-controller-test.js +++ b/test/unit/app/controllers/notice-controller-test.js @@ -14,18 +14,6 @@ describe('notice-controller', function () { }) describe('notices', function () { - describe('#getNoticesList', function () { - it('should return an empty array when new', function (done) { - // const testList = [{ - // id: 0, - // read: false, - // title: 'Futuristic Notice', - // }] - var result = noticeController.getNoticesList() - assert.equal(result.length, 0) - done() - }) - }) describe('#setNoticesList', function () { it('should set data appropriately', function (done) { @@ -41,36 +29,6 @@ describe('notice-controller', function () { }) }) - describe('#updateNoticeslist', function () { - it('should integrate the latest changes from the source', function (done) { - var testList = [{ - id: 55, - read: false, - title: 'Futuristic Notice', - }] - noticeController.setNoticesList(testList) - noticeController.updateNoticesList().then(() => { - var newList = noticeController.getNoticesList() - assert.ok(newList[0].id === 55) - assert.ok(newList[1]) - done() - }) - }) - it('should not overwrite any existing fields', function (done) { - var testList = [{ - id: 0, - read: false, - title: 'Futuristic Notice', - }] - noticeController.setNoticesList(testList) - var newList = noticeController.getNoticesList() - assert.equal(newList[0].id, 0) - assert.equal(newList[0].title, 'Futuristic Notice') - assert.equal(newList.length, 1) - done() - }) - }) - describe('#markNoticeRead', function () { it('should mark a notice as read', function (done) { var testList = [{ @@ -86,7 +44,7 @@ describe('notice-controller', function () { }) }) - describe('#getLatestUnreadNotice', function () { + describe('#getNextUnreadNotice', function () { it('should retrieve the latest unread notice', function (done) { var testList = [ {id: 0, read: true, title: 'Past Notice'}, @@ -94,8 +52,8 @@ describe('notice-controller', function () { {id: 2, read: false, title: 'Future Notice'}, ] noticeController.setNoticesList(testList) - var latestUnread = noticeController.getLatestUnreadNotice() - assert.equal(latestUnread.id, 2) + var latestUnread = noticeController.getNextUnreadNotice() + assert.equal(latestUnread.id, 1) done() }) it('should return undefined if no unread notices exist.', function (done) { @@ -105,7 +63,7 @@ describe('notice-controller', function () { {id: 2, read: true, title: 'Future Notice'}, ] noticeController.setNoticesList(testList) - var latestUnread = noticeController.getLatestUnreadNotice() + var latestUnread = noticeController.getNextUnreadNotice() assert.ok(!latestUnread) done() }) diff --git a/test/unit/test-utils.js b/test/unit/test-utils.js new file mode 100644 index 000000000..7d0ae4d91 --- /dev/null +++ b/test/unit/test-utils.js @@ -0,0 +1,17 @@ +const assert = require('assert') + +module.exports = { + assertRejects, +} + +// assert.rejects added in node v10 +async function assertRejects (asyncFn, regExp) { + let f = () => {} + try { + await asyncFn() + } catch (error) { + f = () => { throw error } + } finally { + assert.throws(f, regExp) + } +} |