Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple send e2e test #6669

Merged
merged 2 commits into from
Jul 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# End-to-end tests

**Fair warning:** this directory contains work in progress—this is where end-to-end tests will live once they are
updated to be more individually isolated and fixture-based.

See also:

- [How to run the e2e tests](./tests/README.md)
- [Fixture data documentation](./fixtures/README.md)
32 changes: 32 additions & 0 deletions e2e/fixtures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# End-to-end tests

This directory contains the fixture data used to bootstrap the individual e2e tests. Each sub-directory contains
two things:

1. A `state.json` file that represents a the saved state for the extension (see _Generating fixture data_ below)
2. A `db.js` file that exports a config for Ganache

The `db/` sub-sub-directory and its contents, should it exist, contains Ganache's state and a path to it is configured
in the `db.js` file.

## Generating fixture data

Fixture data can be generated by loading the unpacked extension, inspecting the background context,
dumping `chrome.storage.local`, and using [`copy`][1] to copy it to the clipboard, and manually pasting the contents into
a file on disk.

```js
chrome.storage.local.get(null, (x) => console.log(x))
// Store the value as a global (shown below)
copy(temp1)
```

Store the value as a global variable:

<img
width="840"
alt="Store as global variable"
src="https://user-images.githubusercontent.com/1623628/60987884-1a2c4a00-a31d-11e9-932e-b7fab452e6bd.png"
/>

[1]:https://developers.google.com/web/tools/chrome-devtools/console/utilities

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion e2e/fixtures/onboarded/state.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const path = require('path')

module.exports = {
port: 8545,
accounts: [{
balance: 12345,
}],
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","uncleHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0x0f349783484ca73cad640a476930e1a7f018de329c8e2073080f4fb1f320bc36","transactionsTrie":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptTrie":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x","number":"0x","gasLimit":"0x6691b7","gasUsed":"0x","timestamp":"0x5c89b962","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x"},"transactions":[],"uncleHeaders":[]}
{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","uncleHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0xd51801c3e9234174ee59ccd7314112e1711cb73a4c80b6ede7fedceafdb5b5b1","transactionsTrie":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptTrie":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x","number":"0x","gasLimit":"0x6691b7","gasUsed":"0x","timestamp":"0x5ceead06","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x"},"transactions":[],"uncleHeaders":[]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"0xf866943ecf4659ab223cf48a9b082eba8041c5f4b1d45eb84ff84d80890246ddf97976680000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"0xf86694385c30949c92df7a0bd42e0f3e3d539ece98db24b84ff84d80890246ddf97976680000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"0xf851a04ef305cd67b97b743669faa6b70fab3c29d545df173e5798da1a3bef0efeb5d98080808080808080a0b8624db45edd70931d98cc8e2ba8671e8ce23d8b8a8086d8367a65e923432e1680808080808080"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"0xf871a04ef305cd67b97b743669faa6b70fab3c29d545df173e5798da1a3bef0efeb5d9808080808080a08180082a4ae6ecc7ef893160ae2cacf0992cee785262027924cc9707fa0b65ad80a0b8624db45edd70931d98cc8e2ba8671e8ce23d8b8a8086d8367a65e923432e1680808080808080"
1 change: 1 addition & 0 deletions e2e/fixtures/simple-send/state.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion e2e/ganache/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const getPort = require('get-port')

class Ganache {
async start (options) {
const port = await getPort()
const port = options.port || await getPort()
this._server = ganache.server(options)
return new Promise((resolve, reject) => {
this._server.listen(port, (err, blockchain) => {
Expand Down
4 changes: 3 additions & 1 deletion e2e/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ const ReferenceCounter = require('./rc')
const {buildWebDriver, Driver} = require('./webdriver')

const fixtureServer = new fixtures.FixtureServer()
const rc = new ReferenceCounter(async () => fixtureServer.start(), async () => fixtureServer.stop())
const rc = new ReferenceCounter(() => fixtureServer.start(), () => fixtureServer.stop())

// TODO Exit if either Ganache or the browser fail to start correctly

const withFixtures = async function load (fixturesDirectory, callback) {
await rc.tick(async () => {
Expand Down
17 changes: 17 additions & 0 deletions e2e/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# End-to-end tests

# Quick start

To run the tests in Firefox:

```bash
BROWSER=firefox npx mocha --no-timeouts e2e/tests/**/*.spec.js
```

To run the tests in Chrome:

```bash
BROWSER=chrome npx mocha --no-timeouts e2e/tests/**/*.spec.js
```

Both commands listed above assume a current working directory of the project root.
19 changes: 0 additions & 19 deletions e2e/tests/example.spec.js

This file was deleted.

18 changes: 18 additions & 0 deletions e2e/tests/simple-send/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const {Key} = require('selenium-webdriver')
const {withFixtures} = require('../../')

describe('MetaMask Browser Extension', function () {
it('can send a simple transaction from one account to another', async () => {
await withFixtures('simple-send', async ({driver}) => {
await driver.findElement('#password').sendKeys('password')
await driver.findElement('#password').sendKeys(Key.ENTER)
await driver.clickElement('#app-content > div > div.main-container-wrapper > div > div > div.transaction-view > div.transaction-view__balance-wrapper > div > div.transaction-view-balance__buttons > button:nth-child(2)')
await driver.findElement('input[placeholder="Recipient Address"]').sendKeys('0x985c30949c92df7a0bd42e0f3e3d539ece98db24')
await driver.findElement('.unit-input__input').sendKeys('1')
await driver.delay(1000)
await driver.clickElement('#app-content > div > div.main-container-wrapper > div > div.page-container__footer > header > button.button.btn-primary.btn--large.page-container__footer-button')
await driver.clickElement('#app-content > div > div.main-container-wrapper > div > div.page-container__footer > header > button.button.btn-confirm.btn--large.page-container__footer-button')
await driver.findElement('.transaction-list-item')
})
})
})
24 changes: 23 additions & 1 deletion e2e/webdriver/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Driver {
* @param {!ThenableWebDriver} driver a {@code WebDriver} instance
* @param {number} timeout
*/
constructor (driver, timeout = 5000) {
constructor (driver, timeout = 10000) {
this.driver = driver
this.timeout = timeout
}
Expand All @@ -17,6 +17,28 @@ class Driver {
findElement (selector) {
return this.driver.wait(until.elementLocated(By.css(selector)), this.timeout)
}

/**
* @param {string} selector the CSS selector to use
* @return {Promise<void>}
*/
async clickElement (selector) {
const element = await this.findElement(selector)
await element.click()
}

/**
* @param {string} query the XPath selector to use
* @return {Promise<void>}
*/
async clickElementXPath (query) {
const element = await this.driver.wait(until.elementLocated(By.xpath(query)), this.timeout)
await element.click()
}

delay (time) {
return new Promise(resolve => setTimeout(resolve, time))
}
}

module.exports = Driver