diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d9dc1b93fec..64aaa26742ed 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,456 +4,456 @@ workflows: version: 2 full_test: jobs: - - prep-deps-npm - - prep-deps-firefox - - prep-build: - requires: - - prep-deps-npm - - prep-docs: - requires: - - prep-deps-npm - - prep-scss: - requires: - - prep-deps-npm - - test-lint: - requires: - - prep-deps-npm - - test-deps: - requires: - - prep-deps-npm - - test-e2e-chrome: - requires: - - prep-deps-npm - - prep-build - - test-e2e-firefox: - requires: - - prep-deps-npm - - prep-deps-firefox - - prep-build - - test-unit: - requires: - - prep-deps-npm - - test-integration-mascara-chrome: - requires: - - prep-deps-npm - - prep-scss - - test-integration-mascara-firefox: - requires: - - prep-deps-npm - - prep-deps-firefox - - prep-scss - - test-integration-flat-chrome: - requires: - - prep-deps-npm - - prep-scss - - test-integration-flat-firefox: - requires: - - prep-deps-npm - - prep-deps-firefox - - prep-scss - - all-tests-pass: - requires: - - test-lint - - test-unit - - test-e2e-chrome - - test-e2e-firefox - - test-integration-mascara-chrome - - test-integration-mascara-firefox - - test-integration-flat-chrome - - test-integration-flat-firefox - - job-screens: - requires: - - prep-deps-npm - - prep-build -# - all-tests-pass - - job-publish-prerelease: - requires: - - prep-deps-npm - - prep-build - - job-screens -# - all-tests-pass - - job-publish-release: - filters: - branches: - only: master - requires: - - prep-deps-npm - - prep-build - - prep-docs - - job-screens -# - all-tests-pass - - job-publish-postrelease: - filters: - branches: - only: master - requires: - - prep-deps-npm - - prep-build - - prep-docs - - job-screens + - prep-deps-npm + - prep-deps-firefox + - prep-build: + requires: + - prep-deps-npm + - prep-docs: + requires: + - prep-deps-npm + - prep-scss: + requires: + - prep-deps-npm + - test-lint: + requires: + - prep-deps-npm + - test-deps: + requires: + - prep-deps-npm + - test-e2e-chrome: + requires: + - prep-deps-npm + - prep-build + - test-e2e-firefox: + requires: + - prep-deps-npm + - prep-deps-firefox + - prep-build + - test-unit: + requires: + - prep-deps-npm + - test-integration-mascara-chrome: + requires: + - prep-deps-npm + - prep-scss + - test-integration-mascara-firefox: + requires: + - prep-deps-npm + - prep-deps-firefox + - prep-scss + - test-integration-flat-chrome: + requires: + - prep-deps-npm + - prep-scss + - test-integration-flat-firefox: + requires: + - prep-deps-npm + - prep-deps-firefox + - prep-scss + - all-tests-pass: + requires: + - test-lint + - test-unit + - test-e2e-chrome + - test-e2e-firefox + - test-integration-mascara-chrome + - test-integration-mascara-firefox + - test-integration-flat-chrome + - test-integration-flat-firefox + - job-screens: + requires: + - prep-deps-npm + - prep-build + # - all-tests-pass + - job-publish-prerelease: + requires: + - prep-deps-npm + - prep-build + - job-screens + # - all-tests-pass + - job-publish-release: + filters: + branches: + only: master + requires: + - prep-deps-npm + - prep-build + - prep-docs + - job-screens + # - all-tests-pass + - job-publish-postrelease: + filters: + branches: + only: master + requires: + - prep-deps-npm + - prep-build + - prep-docs + - job-screens # - all-tests-pass jobs: prep-deps-npm: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Install npm 6 + deps via npm - command: | - sudo npm install -g npm@6.1.0 && npm install --no-save - - save_cache: - key: dependency-cache-{{ .Revision }} - paths: - - node_modules + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Install npm 6 + deps via npm + command: | + sudo npm install -g npm@6.1.0 && npm install --no-save + - save_cache: + key: dependency-cache-{{ .Revision }} + paths: + - node_modules prep-deps-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-firefox-{{ .Revision }} - - run: - name: Download Firefox - command: ./.circleci/scripts/firefox-download.sh - - save_cache: - key: dependency-cache-firefox-{{ .Revision }} - paths: - - firefox + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Download Firefox + command: ./.circleci/scripts/firefox-download.sh + - save_cache: + key: dependency-cache-firefox-{{ .Revision }} + paths: + - firefox prep-build: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: build:dist - command: NODE_ENV='production' npm run dist - - run: - name: build:debug - command: find dist/ -type f -exec md5sum {} \; | sort -k 2 - - save_cache: - key: build-cache-{{ .Revision }} - paths: - - dist - - builds + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: build:dist + command: NODE_ENV='production' npm run dist + - run: + name: build:debug + command: find dist/ -type f -exec md5sum {} \; | sort -k 2 + - save_cache: + key: build-cache-{{ .Revision }} + paths: + - dist + - builds prep-docs: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: build:dist - command: npm run doc - - save_cache: - key: docs-cache-{{ .Revision }} - paths: - - docs/jsdoc + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: build:dist + command: npm run doc + - save_cache: + key: docs-cache-{{ .Revision }} + paths: + - docs/jsdoc prep-scss: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Get Scss Cache key - # this allows us to checksum against a whole directory - command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum - - run: - name: Build for integration tests - command: npm run test:integration:build - - save_cache: - key: scss-cache-{{ checksum "scss_checksum" }} - paths: - - ui/app/css/output + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - run: + name: Build for integration tests + command: npm run test:integration:build + - save_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + paths: + - ui/app/css/output test-lint: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Test - command: npm run lint + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Test + command: npm run lint test-deps: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Test - command: npx nsp check + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Test + command: npx nsp check test-e2e-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - run: - name: test:e2e:chrome - command: npm run test:e2e:chrome - - store_artifacts: - path: test-artifacts - destination: test-artifacts + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:chrome + command: npm run test:e2e:chrome + - store_artifacts: + path: test-artifacts + destination: test-artifacts test-e2e-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-firefox-{{ .Revision }} - - run: - name: Install firefox - command: ./.circleci/scripts/firefox-install.sh - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - run: - name: test:e2e:firefox - command: npm run test:e2e:firefox - - store_artifacts: - path: test-artifacts - destination: test-artifacts + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Install firefox + command: ./.circleci/scripts/firefox-install.sh + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:firefox + command: npm run test:e2e:firefox + - store_artifacts: + path: test-artifacts + destination: test-artifacts test-e2e-beta-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - run: - name: test:e2e:chrome:beta - command: npm run test:e2e:chrome:beta - - store_artifacts: - path: test-artifacts - destination: test-artifacts + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:chrome:beta + command: npm run test:e2e:chrome:beta + - store_artifacts: + path: test-artifacts + destination: test-artifacts test-e2e-beta-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-firefox-{{ .Revision }} - - run: - name: Install firefox - command: ./.circleci/scripts/firefox-install.sh - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - run: - name: test:e2e:firefox:beta - command: npm run test:e2e:firefox:beta - - store_artifacts: - path: test-artifacts - destination: test-artifacts + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Install firefox + command: ./.circleci/scripts/firefox-install.sh + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: test:e2e:firefox:beta + command: npm run test:e2e:firefox:beta + - store_artifacts: + path: test-artifacts + destination: test-artifacts job-screens: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - run: - name: Test - command: npm run test:screens - - save_cache: - key: job-screens-{{ .Revision }} - paths: - - test-artifacts + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - run: + name: Test + command: npm run test:screens + - save_cache: + key: job-screens-{{ .Revision }} + paths: + - test-artifacts job-publish-prerelease: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - restore_cache: - key: job-screens-{{ .Revision }} - - store_artifacts: - path: dist/mascara - destination: builds/mascara - - store_artifacts: - path: dist/sourcemaps - destination: builds/sourcemaps - - store_artifacts: - path: builds - destination: builds - - store_artifacts: - path: test-artifacts - destination: test-artifacts - - run: - name: build:announce - command: ./development/metamaskbot-build-announce.js + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - restore_cache: + key: job-screens-{{ .Revision }} + - store_artifacts: + path: dist/mascara + destination: builds/mascara + - store_artifacts: + path: dist/sourcemaps + destination: builds/sourcemaps + - store_artifacts: + path: builds + destination: builds + - store_artifacts: + path: test-artifacts + destination: test-artifacts + - run: + name: build:announce + command: ./development/metamaskbot-build-announce.js job-publish-release: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: + - checkout + - restore_cache: key: dependency-cache-{{ .Revision }} - - restore_cache: + - restore_cache: key: build-cache-{{ .Revision }} - - run: - name: build:release - command: node ./development/publish-release.js + - run: + name: build:release + command: node ./development/publish-release.js job-publish-postrelease: - docker: - - image: circleci/node:8.11.4-browsers - steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - restore_cache: - key: build-cache-{{ .Revision }} - - restore_cache: - key: docs-cache-{{ .Revision }} - - restore_cache: - key: job-screens-{{ .Revision }} - - run: - name: sentry sourcemaps upload - command: npm run sentry:publish -# - run: -# name: github gh-pages docs publish -# command: > -# git config user.name metamaskbot -# git config user.email admin@metamask.io -# gh-pages -d docs/jsdocs + docker: + - image: circleci/node:8.11.4-browsers + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - restore_cache: + key: build-cache-{{ .Revision }} + - restore_cache: + key: docs-cache-{{ .Revision }} + - restore_cache: + key: job-screens-{{ .Revision }} + - run: + name: sentry sourcemaps upload + command: npm run sentry:publish + # - run: + # name: github gh-pages docs publish + # command: > + # git config user.name metamaskbot + # git config user.email admin@metamask.io + # gh-pages -d docs/jsdocs test-unit: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: test:coverage - command: npm run test:coverage + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: test:coverage + command: npm run test:coverage test-integration-flat-firefox: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-firefox-{{ .Revision }} - - run: - name: Install firefox - command: ./.circleci/scripts/firefox-install.sh - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Get Scss Cache key - # this allows us to checksum against a whole directory - command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum - - restore_cache: - key: scss-cache-{{ checksum "scss_checksum" }} - - run: - name: test:integration:flat - command: npm run test:flat + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Install firefox + command: ./.circleci/scripts/firefox-install.sh + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:flat + command: npm run test:flat test-integration-flat-chrome: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Get Scss Cache key - # this allows us to checksum against a whole directory - command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum - - restore_cache: - key: scss-cache-{{ checksum "scss_checksum" }} - - run: - name: test:integration:flat - command: npm run test:flat + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:flat + command: npm run test:flat test-integration-mascara-firefox: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-firefox-{{ .Revision }} - - run: - name: Install firefox - command: ./.circleci/scripts/firefox-install.sh - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Get Scss Cache key - # this allows us to checksum against a whole directory - command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum - - restore_cache: - key: scss-cache-{{ checksum "scss_checksum" }} - - run: - name: test:integration:mascara - command: npm run test:mascara + - checkout + - restore_cache: + key: dependency-cache-firefox-{{ .Revision }} + - run: + name: Install firefox + command: ./.circleci/scripts/firefox-install.sh + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:mascara + command: npm run test:mascara test-integration-mascara-chrome: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - checkout - - restore_cache: - key: dependency-cache-{{ .Revision }} - - run: - name: Get Scss Cache key - # this allows us to checksum against a whole directory - command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum - - restore_cache: - key: scss-cache-{{ checksum "scss_checksum" }} - - run: - name: test:integration:mascara - command: npm run test:mascara + - checkout + - restore_cache: + key: dependency-cache-{{ .Revision }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:mascara + command: npm run test:mascara all-tests-pass: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.11.4-browsers steps: - - run: - name: All Tests Passed - command: echo 'weew - everything passed!' + - run: + name: All Tests Passed + command: echo 'weew - everything passed!' \ No newline at end of file diff --git a/test/e2e/elements.js b/test/e2e/elements.js index 7c5de0654899..9e810c1d6a51 100644 --- a/test/e2e/elements.js +++ b/test/e2e/elements.js @@ -11,7 +11,8 @@ module.exports = { logOut: By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)'), textLogOut: 'Log Out', textSettings: 'Settings', - }, + info: By.css('li.dropdown-menu-item:nth-child(4)'), + }, account: { menu: By.css('#app-content > div > div.full-width > div > div:nth-child(2) > span > div'), delete: By.css('#app-content > div > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(4) > div.remove'), @@ -29,6 +30,17 @@ module.exports = { }, }, screens: { + addToken: { + title: By.className('page-subtitle'), + titleText: 'Add Token', + fields: { + contractAddress: By.id('token-address'), + tokenSymbol: By.id('token_symbol'), + decimals: By.id('token_decimals'), + }, + buttonAdd: By.css('.flex-space-around > button:nth-child(7)'), + + }, deleteCustomRPC: { buttons: { yes: By.css('#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-right > button:nth-child(2)'), @@ -111,34 +123,44 @@ module.exports = { address: By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div'), tokens: { remove: By.className('trash'), - menu: 'activeForm right', + menu: By.className('inactiveForm pointer'), token: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li'), balance: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > h3'), amount: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > div > span'), textNoTokens: 'No tokens found', textYouOwn1token: 'You own 1 token', - buttonAdd: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > div > button'), + buttonAdd: By.css('div.full-flex-height:nth-child(2) > div:nth-child(1) > button:nth-child(2)'), + buttonAddText: 'Add Token', }, }, + info: { + title: By.className('section-title flex-row flex-center'), + titleText: 'Info', + label: By.className('info'), + }, + removeToken: { + title: By.className('page-subtitle'), + titleText: 'Remove Token', + label: By.className('confirm-label'), + labelText: 'Are you sure you want to remove token', + buttons: { + back: By.className('fa fa-arrow-left fa-lg cursor-pointer'), + no: By.className('btn-violet'), + yes: By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button:nth-child(2)'), + }, + }, + changePassword: { title: By.className('page-subtitle'), titleText: 'Change Password', - ById: { - fieldOldPassword: 'old-password-box', - fieldNewPassword: 'new-password-box', - fieldConfirmNewPassword: 'password-box-confirm', - }, - ByCss: { - buttonNo: '#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-right > button.btn-violet', - buttonYes: '#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-right > button:nth-child(2)', - subtitle: '#app-content > div > div.app-primary.from-right > div > div.section-title.flex-row.flex-center > h2', - label: '#app-content > div > div.app-primary.from-right > div > p', - }, - ByClassName: { - label: 'confirm-label', - arrowLeft: 'fa fa-arrow-left fa-lg cursor-pointer', - error: 'error', - }, + fieldOldPassword: By.id('old-password-box'), + fieldNewPassword: By.id('new-password-box'), + fieldConfirmNewPassword: By.id('password-box-confirm'), + buttonNo: By.css('#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-right > button.btn-violet'), + buttonYes: By.css('#app-content > div > div.app-primary.from-right > div > div.flex-row.flex-right > button:nth-child(2)'), + label: By.className('confirm-label'), + arrowLeft: By.className('fa fa-arrow-left fa-lg cursor-pointer'), + error: By.className('error'), labelText: 'Are you sure you want to change the password for unlocking of your wallet?', errorText: { differ: 'New password should differ from the current one', @@ -150,21 +172,19 @@ module.exports = { lock: { fieldPassword: By.id('password-box'), error: By.className('error'), - errorText: 'Incorrect password', + errorText: 'Incorrect password. Try again.', buttonLogin: By.className('cursor-pointer'), linkRestore: By.css('#app-content > div > div.app-primary.from-left > div > div.flex-row.flex-center.flex-grow > p'), linkRestoreText: 'Restore from seed phrase', }, - addToken: { - fieldTokenContractAddress: By.id('token-address'), - fieldTokenSymbol: By.id('token_symbol'), - fieldDecimals: By.id('token_decimals'), - buttonAdd: By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button'), - }, + TOU: { - titleText: 'Nifty Wallet', - header: By.className('terms-header'), + agreement: By.className('notice-box'), + titleText: 'Terms of Use', + title: By.className('terms-header'), button: By.css('button'), + linkTerms: By.linkText('Terms of Service'), + linkTermsText: 'Terms of Service', }, create: { fieldPassword: By.id('password-box'), diff --git a/test/e2e/func.js b/test/e2e/func.js index 0ac228afca98..70935757809a 100644 --- a/test/e2e/func.js +++ b/test/e2e/func.js @@ -6,7 +6,7 @@ const path = require('path') const webdriver = require('selenium-webdriver') const Command = require('selenium-webdriver/lib/command').Command -const { By, Key } = webdriver +const { By } = webdriver module.exports = { delay, @@ -15,8 +15,7 @@ module.exports = { installWebExt, getExtensionIdChrome, getExtensionIdFirefox, - clearField, - } +} function delay (time) { return new Promise(resolve => setTimeout(resolve, time)) @@ -63,11 +62,3 @@ async function installWebExt (driver, extension) { return await driver.execute(cmd, 'installWebExt(' + extension + ')') } - -async function clearField (field, number) { - await field.click() - if (number === undefined) number = 40 - for (let i = 0; i < number; i++) { - await field.sendKeys(Key.BACK_SPACE) - } -} diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index ff6311557b51..e0b965d0be01 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -4,8 +4,8 @@ const path = require('path') const assert = require('assert') const pify = require('pify') const webdriver = require('selenium-webdriver') -const { By, Key, until } = webdriver -const { clearField, delay, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, getExtensionIdChrome, getExtensionIdFirefox } = require('./func') +const { By, Key } = webdriver +const { delay, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, getExtensionIdChrome, getExtensionIdFirefox } = require('./func') const { menus, screens, elements, NETWORKS } = require('./elements') describe('Metamask popup page', async function () { @@ -50,406 +50,412 @@ describe('Metamask popup page', async function () { }) after(async function () { - // await driver.quit() + await driver.quit() }) describe('Setup', async function () { - it('switches to Chrome extensions list', async function () { + it('switches to extensions list', async function () { await delay(300) const windowHandles = await driver.getAllWindowHandles() await driver.switchTo().window(windowHandles[0]) }) - - it('sets provider type to localhost', async function () { - await delay(300) - await setProviderType('localhost') - }) }) describe('Account Creation', async () => { - it('matches Nifty Wallet title', async () => { + it('title is \'Nifty Wallet\'', async () => { const title = await driver.getTitle() - assert.equal(title, screens.TOU.titleText, 'title matches Nifty Wallet') - await delay(300) + assert.equal(title, 'Nifty Wallet', 'title is incorrect') }) - it('show terms of use', async () => { - const terms = await driver.findElement(screens.TOU.header).getText() - assert.equal(terms, 'Terms of Use', 'shows terms of use') - delay(300) + it('screen \'Terms of Use\' has not empty agreement', async () => { + const terms = await waitUntilShowUp(screens.TOU.agreement) + const text = await terms.getText() + assert.equal(text.length > 400, true, 'agreement is too short') }) - it('checks if the TOU button is enabled', async () => { - const button = await driver.findElement(screens.TOU.button).isEnabled() - assert.equal(button, true, 'enabled continue button') - const element = await driver.findElement(By.linkText('Terms of Service')) - await driver.executeScript('arguments[0].scrollIntoView(true)', element) - await delay(700) + it('screen \'Terms of Use\' has correct title', async () => { + const terms = await waitUntilShowUp(screens.TOU.title) + assert.equal(await terms.getText(), screens.TOU.titleText, 'title is incorrect') }) - it('allows the button to be clicked when scrolled to the bottom of TOU', async () => { - const button = await driver.findElement(screens.TOU.button) - await button.click() + it('checks if the TOU contains link \'Terms of service\'', async () => { + const element = await driver.findElement(screens.TOU.linkTerms) + await scrollTo(screens.TOU.linkTerms) + assert.notEqual(element, null, ' link \'Terms of service\' isn\'t present') + assert.equal(await element.getText(), screens.TOU.linkTermsText, 'incorrect name of link \'Terms of service\'') }) - it('accepts password with length of eight', async () => { - const passwordBox = await driver.findElement(screens.create.fieldPassword) - const passwordBoxConfirm = await driver.findElement(screens.create.fieldPasswordConfirm) - const button = await driver.findElements(screens.create.button) + it('checks if the button \'Accept\' is present and enabled', async () => { + const button = await waitUntilShowUp(screens.TOU.button) + assert.notEqual(button, false, 'button isn\'t present') + assert.equal(await button.isEnabled(), true, 'button isn\'t enabled') + await click(button) + }) + it('accepts password with length of eight', async () => { + const passwordBox = await waitUntilShowUp(screens.create.fieldPassword) + const passwordBoxConfirm = await waitUntilShowUp(screens.create.fieldPasswordConfirm) + const button = await waitUntilShowUp(screens.create.button) await passwordBox.sendKeys(password) await passwordBoxConfirm.sendKeys(password) - await button[0].click() - await delay(500) + await click(button) }) it('shows vault was created and seed phrase', async () => { await delay(300) - const element = await driver.findElement(screens.seedPhrase.fieldPhrase) + const element = await waitUntilShowUp(screens.seedPhrase.fieldPhrase) const seedPhrase = await element.getText() assert.equal(seedPhrase.split(' ').length, 12) - const continueAfterSeedPhrase = await driver.findElement(screens.seedPhrase.buttonIveCopied) + const continueAfterSeedPhrase = await waitUntilShowUp(screens.seedPhrase.buttonIveCopied) assert.equal(await continueAfterSeedPhrase.getText(), screens.seedPhrase.textButtonIveCopied) - await continueAfterSeedPhrase.click() - await delay(300) + await click(continueAfterSeedPhrase) + }) + + it('sets provider type to localhost', async function () { + await setProvider(NETWORKS.LOCALHOST) }) it('adds a second account', async function () { - // throw('sf') - await driver.findElement(menus.account.menu).click() - await delay(300) - await driver.findElement(menus.account.createAccount).click() + const accountMenu = await waitUntilShowUp(menus.account.menu) + await accountMenu.click() + const item = await waitUntilShowUp(menus.account.createAccount) + await item.click() }) it('shows account address', async function () { await delay(300) - accountAddress = await driver.findElement(screens.main.address).getText() - }) + const account = await waitUntilShowUp(screens.main.address) + accountAddress = await account.getText() + }) it('logs out of the vault', async () => { - await driver.findElement(menus.sandwich.menu).click() + const menu = await waitUntilShowUp(menus.sandwich.menu) + await menu.click() await delay(500) - const logoutButton = await driver.findElement(menus.sandwich.logOut) + const logoutButton = await waitUntilShowUp(menus.sandwich.logOut) assert.equal(await logoutButton.getText(), 'Log Out') await logoutButton.click() }) it('accepts account password after lock', async () => { - await delay(500) - await driver.findElement(screens.lock.fieldPassword).sendKeys(password) - await driver.findElement(screens.lock.fieldPassword).sendKeys(Key.ENTER) - await delay(500) + const box = await waitUntilShowUp(screens.lock.fieldPassword) + await box.sendKeys(password) + const button = await waitUntilShowUp(screens.lock.buttonLogin) + await click(button) }) it('shows QR code option', async () => { - await delay(300) - await driver.findElement(menus.dot.menu).click() - await driver.findElement(menus.dot.showQRcode).click() - await delay(300) + const menu = await waitUntilShowUp(menus.dot.menu) + await menu.click() + const item = await waitUntilShowUp(menus.dot.showQRcode) + await item.click() + }) it('checks QR code address is the same as account details address', async () => { - const QRaccountAddress = await driver.findElement(screens.QRcode.address).getText() - assert.equal(accountAddress.toLowerCase(), QRaccountAddress) - await driver.findElement(screens.QRcode.buttonArrow).click() - await delay(500) + const field = await waitUntilShowUp(screens.QRcode.address) + const text = await field.getText() + assert.equal(text.toLowerCase(), accountAddress.toLowerCase(), 'QR addres doesn\'t match') + }) + + it('close QR code screen by clicking button arrow', async () => { + const button = await waitUntilShowUp(screens.QRcode.buttonArrow) + await click(button) + }) + + it('user is able to open \'Info\' screen', async function () { + const accountMenu = await waitUntilShowUp(menus.sandwich.menu) + await accountMenu.click() + const item = await waitUntilShowUp(menus.sandwich.info) + await item.click() + }) + + it('screen \'Info\' has correct title', async function () { + const title = await waitUntilShowUp(screens.info.title) + assert.equal(await title.getText(), screens.info.titleText, 'title is incorrect') }) }) - // it doesn't work for Firefox in Circle CI - if (process.env.SELENIUM_BROWSER === 'chrome') { - describe('Change password', async () => { - const newPassword = { - correct: 'abcDEF123!@#', - short: '123', - incorrect: '1234567890', - } - let fieldNewPassword - let fieldConfirmNewPassword - let fieldOldPassword - let buttonYes - - describe('Check screen "Settings" -> "Change password" ', async () => { - - it('checks if "Change password" button is present and enabled', async () => { - await driver.findElement(By.css(menus.sandwich.menu)).click() - await delay(500) - await driver.findElement(By.css(menus.sandwich.settings)).click() - await delay(500) - const buttons = await driver.findElements(By.css(screens.settings.buttons.changePassword)) - assert.equal(buttons.length, 1, 'Button "Change password" is not present') - assert.equal(await buttons[0].isEnabled(), true, 'Button "Change password" is disabled') - }) - - it('screen contains correct title', async () => { - const button = await driver.findElement(By.css(screens.settings.buttons.changePassword)) - await delay(500) - await driver.executeScript('arguments[0].scrollIntoView(true)', button) - await delay(700) - await button.click() - await delay(500) - const title = await driver.findElement(By.css(screens.changePassword.ByCss.subtitle)) - assert.equal(await title.getText(), screens.changePassword.titleText, '"Change password" screen contains incorrect title') - }) - - it('screen contains correct label', async () => { - const labels = await driver.findElements(By.css(screens.changePassword.ByCss.label)) - assert.equal(labels.length, 1, 'screen "Change password" doesn\'t contain label') - assert.equal(await labels[0].getText(), screens.changePassword.labelText, 'label contains incorrect title') - }) - - it('clicking the button "No" bring back to "Setting" screen ', async () => { - const button = await driver.findElement(By.css(screens.changePassword.ByCss.buttonNo)) - await button.click() - const title = await driver.findElement(By.css(screens.settings.title)) - assert.equal(await title.getText(), screens.settings.titleText, 'button "No" doesnt open settings screen') - const buttonChangePass = await driver.findElement(By.css(screens.settings.buttons.changePassword)) - await buttonChangePass.click() - }) + describe('Change password', async () => { + const newPassword = { + correct: 'abcDEF123!@#', + short: '123', + incorrect: '1234567890', + } + let fieldNewPassword + let fieldConfirmNewPassword + let fieldOldPassword + let buttonYes + + describe('Check screen "Settings" -> "Change password" ', async () => { + + it('checks if "Change password" button is present and enabled', async () => { + const menu = await waitUntilShowUp(menus.sandwich.menu) + await menu.click() + const settings = await waitUntilShowUp(menus.sandwich.settings) + await settings.click() + await waitUntilShowUp(screens.settings.fieldNewRPC) + const buttons = await driver.findElements(screens.settings.buttons.changePassword) + await scrollTo(buttons[0]) + assert.equal(buttons.length, 1, 'Button "Change password" is not present') + assert.equal(await buttons[0].isEnabled(), true, 'Button "Change password" is disabled') + await click(buttons[0]) + }) + + it('screen has correct title', async () => { + const title = await waitUntilShowUp(screens.changePassword.title) + assert.equal(await title.getText(), screens.changePassword.titleText, '"Change password" screen contains incorrect title') }) - describe('Validation of errors ', async () => { - - before(async () => { - fieldOldPassword = await driver.findElement(By.id(screens.changePassword.ById.fieldOldPassword)) - await fieldOldPassword.sendKeys(password) - fieldNewPassword = await driver.findElement(By.id(screens.changePassword.ById.fieldNewPassword)) - fieldConfirmNewPassword = await driver.findElement(By.id(screens.changePassword.ById.fieldConfirmNewPassword)) - buttonYes = await driver.findElement(By.css(screens.changePassword.ByCss.buttonYes)) - }) - - it('error if new password shorter than 8 digits', async () => { - await fieldNewPassword.sendKeys(newPassword.short) - await fieldConfirmNewPassword.sendKeys(newPassword.short) - await buttonYes.click() - const errors = await driver.findElements(By.className(screens.changePassword.ByClassName.error)) - assert.equal(errors.length > 0, true, 'error isn\'t displayed') - assert.equal(await errors[0].getText(), screens.changePassword.error.notLong, 'Error\'s text incorrect') - }) - - it('error if new password doesn\'t match confirmation', async () => { - await clearField(fieldNewPassword) - await clearField(fieldConfirmNewPassword) - await fieldNewPassword.sendKeys(newPassword.correct) - await fieldConfirmNewPassword.sendKeys(newPassword.incorrect) - await buttonYes.click() - const errors = await driver.findElements(By.className(screens.changePassword.ByClassName.error)) - assert.equal(errors.length > 0, true, 'error isn\'t displayed') - assert.equal(await errors[0].getText(), screens.changePassword.error.dontMatch, 'Error\'s text incorrect') - }) - - it('error if new password match old password', async () => { - await clearField(fieldNewPassword) - await clearField(fieldConfirmNewPassword) - await fieldNewPassword.sendKeys(password) - await fieldConfirmNewPassword.sendKeys(password) - await buttonYes.click() - const errors = await driver.findElements(By.className(screens.changePassword.ByClassName.error)) - assert.equal(errors.length > 0, true, 'error isn\'t displayed') - assert.equal(await errors[0].getText(), screens.changePassword.error.differ, 'Error\'s text incorrect') - }) - - it.skip('error if old password incorrect, https://github.com/poanetwork/metamask-extension/issues/86 ', async () => { - await clearField(fieldOldPassword) - await fieldOldPassword.sendKeys(newPassword.incorrect) - await buttonYes.click() - const errors = await driver.findElements(By.className(screens.changePassword.ByClassName.error)) - assert.equal(errors.length > 0, true, 'error isn\'t displayed') - assert.equal(await errors[0].getText(), screens.changePassword.error.incorrectPassword, 'Error\'s text incorrect') - }) - - it('no errors if old, new, confirm new passwords are correct; user can change password', async () => { - await clearField(fieldNewPassword) - await clearField(fieldOldPassword) - await clearField(fieldConfirmNewPassword) - - await fieldOldPassword.sendKeys(password) - await fieldNewPassword.sendKeys(newPassword.correct) - await fieldConfirmNewPassword.sendKeys(newPassword.correct) - await buttonYes.click() - - await driver.wait(until.elementLocated(By.css(screens.settings.buttons.changePassword))) - const buttons = await driver.findElements(By.css(screens.settings.buttons.changePassword)) - assert.equal(buttons.length, 1, 'Button "Change password" is not present') - assert.equal(await buttons[0].isEnabled(), true, 'Button "Change password" is disabled') - }) + it('screen contains correct label', async () => { + await waitUntilShowUp(screens.changePassword.label) + const labels = await driver.findElements(screens.changePassword.label) + assert.equal(labels.length, 1, 'screen "Change password" doesn\'t contain label') + assert.equal(await labels[0].getText(), screens.changePassword.labelText, 'label contains incorrect title') }) - describe('Check if new password is accepted', async () => { - - it('user can log out', async () => { - await driver.findElement(By.css(menus.sandwich.menu)).click() - await delay(500) - await driver.wait(until.elementLocated(By.css(menus.sandwich.logOut))) - const itemLogOut = await driver.findElement(By.css(menus.sandwich.logOut)) - await driver.wait(until.elementIsVisible(itemLogOut)) - itemLogOut.click() - await driver.wait(until.elementLocated(By.id(screens.lock.fieldPassword))) - const fields = await driver.findElements(By.id(screens.lock.fieldPassword)) - assert.equal(fields.length, 1, 'password box isn\'t present after logout') - }) - it.skip('can\'t login with old password', async () => { - const field = await driver.findElement(By.id(screens.lock.fieldPassword)) - await field.sendKeys(password) - await driver.findElement(By.className(screens.lock.buttonLogin)).click() - const errors = await driver.findElements(By.className(screens.lock.error)) - assert.equal(errors.length, 1, 'error isn\'t displayed if password incorrect') - assert.equal(await errors[0].getText(), screens.lock.errorText, 'error\'s text incorrect') - }) - it('accepts new password after lock', async () => { - const field = await driver.findElement(By.id(screens.lock.fieldPassword)) - await field.sendKeys(newPassword.correct) - await driver.findElement(By.className(screens.lock.buttonLogin)).click() - - await driver.wait(until.elementLocated(By.css(screens.main.buttons.buy))) - const buttons = await driver.findElements(By.css(screens.main.buttons.buy)) - assert.equal(buttons.length, 1, 'main screen isn\'t displayed') - password = newPassword.correct - }) + it('clicking the button "No" bring back to "Setting" screen ', async () => { + const button = await waitUntilShowUp(screens.changePassword.buttonNo) + await click(button) + const title = await waitUntilShowUp(screens.settings.title) + assert.equal(await title.getText(), screens.settings.titleText, 'button "No" doesnt open settings screen') + const buttonChangePass = await driver.findElement(screens.settings.buttons.changePassword) + await scrollTo(buttonChangePass) + await click(buttonChangePass) }) }) - } - // it doesn't work for Firefox in Circle CI - if (process.env.SELENIUM_BROWSER === 'chrome') { - describe('Import Account', () => { - - it('opens import account menu', async function () { - await driver.wait(until.elementLocated(By.css(menus.account.menu))) - await driver.findElement(By.css(menus.account.menu)).click() - await delay(500) - await driver.findElement(By.css(menus.account.import)).click() - await delay(500) - const importAccountTitle = await driver.findElement(By.css(screens.importAccounts.title)) - assert.equal(await importAccountTitle.getText(), screens.importAccounts.textTitle) + describe('Validation of errors ', async () => { + + before(async () => { + fieldOldPassword = await waitUntilShowUp(screens.changePassword.fieldOldPassword) + await fieldOldPassword.sendKeys(password) + fieldNewPassword = await waitUntilShowUp(screens.changePassword.fieldNewPassword) + fieldConfirmNewPassword = await waitUntilShowUp(screens.changePassword.fieldConfirmNewPassword) + buttonYes = await waitUntilShowUp(screens.changePassword.buttonYes) }) - it('imports account', async function () { - const privateKeyBox = await driver.findElement(By.css(screens.importAccounts.fieldPrivateKey)) - const importButton = await driver.findElement(By.css(screens.importAccounts.buttonImport)) - await privateKeyBox.sendKeys('c6b81c1252415d1acfda94474ab8f662a44c045f96749c805ff12a6074081586')// demo private key - importButton.click() - await delay(500) - // check, that account is added - await driver.findElement(By.css(menus.account.menu)).click() - await delay(500) - const importedLabel = await driver.findElement(By.css(menus.account.labelImported)) - assert.equal(await importedLabel.getText(), 'IMPORTED') + it('error if new password shorter than 8 digits', async () => { + await fieldNewPassword.sendKeys(newPassword.short) + await fieldConfirmNewPassword.sendKeys(newPassword.short) + await click(buttonYes) + await delay(2000) + const errors = await driver.findElements(screens.changePassword.error) + assert.equal(errors.length > 0, true, 'error isn\'t displayed') + assert.equal(await errors[0].getText(), screens.changePassword.errorText.notLong, 'Error\'s text incorrect') }) - it('opens delete imported account screen', async function () { - await driver.findElement(By.css(menus.account.delete)).click() - await delay(200) - const deleteImportedAccountTitle = await driver.findElement(By.css(screens.deleteImportedAccount.title)) - assert.equal(await deleteImportedAccountTitle.getText(), screens.deleteImportedAccount.titleText) + it('error if new password doesn\'t match confirmation', async () => { + await clearField(fieldNewPassword) + await clearField(fieldConfirmNewPassword) + await fieldNewPassword.sendKeys(newPassword.correct) + await fieldConfirmNewPassword.sendKeys(newPassword.incorrect) + await click(buttonYes) + await delay(2000) + const errors = await driver.findElements(screens.changePassword.error) + assert.equal(errors.length > 0, true, 'error isn\'t displayed') + assert.equal(await errors[0].getText(), screens.changePassword.errorText.dontMatch, 'Error\'s text incorrect') }) - it('doesn\'t remove imported account with \'No\' button', async function () { - const NoButton = await driver.findElement(By.css(screens.deleteImportedAccount.buttons.no)) - NoButton.click() - await delay(500) - const settingsTitle = await driver.findElement(By.css(screens.settings.title)) - assert.equal(await settingsTitle.getText(), 'Settings') - - // check, that imported account still exists - await driver.findElement(By.css(menus.account.menu)).click() - await delay(500) - const importedLabel = await driver.findElement(By.css(menus.account.labelImported)) - assert.equal(await importedLabel.getText(), 'IMPORTED') + it('error if new password match old password', async () => { + await clearField(fieldNewPassword) + await clearField(fieldConfirmNewPassword) + await fieldNewPassword.sendKeys(password) + await fieldConfirmNewPassword.sendKeys(password) + await click(buttonYes) + await delay(2000) + const errors = await driver.findElements(screens.changePassword.error) + assert.equal(errors.length > 0, true, 'error isn\'t displayed') + assert.equal(await errors[0].getText(), screens.changePassword.errorText.differ, 'Error\'s text incorrect') }) - it('opens delete imported account screen again', async function () { - await driver.findElement(By.css(menus.account.delete)).click() - await delay(500) + it('error if old password incorrect', async () => { + await clearField(fieldOldPassword) + await fieldOldPassword.sendKeys(newPassword.incorrect) + await click(buttonYes) + await click(buttonYes) + await delay(2000) + const errors = await driver.findElements(screens.changePassword.error) + assert.equal(errors.length > 0, true, 'error isn\'t displayed') + assert.equal(await errors[0].getText(), screens.changePassword.errorText.incorrectPassword, 'Error\'s text incorrect') }) - it('removes imported account with \'Yes\' button', async function () { - const YesButton = await driver.findElement(By.css(screens.deleteImportedAccount.buttons.yes)) - YesButton.click() - await delay(500) - const settingsTitle = await driver.findElement(By.css(screens.settings.title)) - assert.equal(await settingsTitle.getText(), 'Settings') - - // check, that imported account is removed - await driver.findElement(By.css(menus.account.menu)).click() - await delay(500) - const importedAccounts = await driver.findElements(By.css(menus.account.labelImported)) - assert.ok(importedAccounts.length === 0) - await driver.findElement(By.css(menus.account.menu)).click() - await delay(500) + it('no errors if old, new, confirm new passwords are correct; user can change password', async () => { + await clearField(fieldNewPassword) + await clearField(fieldOldPassword) + await clearField(fieldConfirmNewPassword) + + await fieldOldPassword.sendKeys(password) + await fieldNewPassword.sendKeys(newPassword.correct) + await fieldConfirmNewPassword.sendKeys(newPassword.correct) + await click(buttonYes) + await waitUntilShowUp(screens.settings.buttons.changePassword, 25) + const buttons = await driver.findElements(screens.settings.buttons.changePassword) + assert.equal(buttons.length, 1, 'Button "Change password" is not present') + assert.equal(await buttons[0].isEnabled(), true, 'Button "Change password" is disabled') }) }) - } + + describe('Check if new password is accepted', async () => { + + it('user can log out', async () => { + const menu = await waitUntilShowUp(menus.sandwich.menu) + await menu.click() + const itemLogOut = await waitUntilShowUp(menus.sandwich.logOut) + await itemLogOut.click() + const field = await waitUntilShowUp(screens.lock.fieldPassword) + assert.notEqual(field, false, 'password box isn\'t present after logout') + }) + it('can\'t login with old password', async () => { + const field = await waitUntilShowUp(screens.lock.fieldPassword) + await field.sendKeys(password) + const button = await waitUntilShowUp(screens.lock.buttonLogin) + await click(button) + const error = await waitUntilShowUp(screens.lock.error) + assert.notEqual(error, false, 'error isn\'t displayed if password incorrect') + assert.equal(await error.getText(), screens.lock.errorText, 'error\'s text incorrect') + }) + it('accepts new password after lock', async () => { + const field = await waitUntilShowUp(screens.lock.fieldPassword) + await clearField(field) + await field.sendKeys(newPassword.correct) + const button = await waitUntilShowUp(screens.lock.buttonLogin) + await click(button) + + await waitUntilShowUp(screens.main.buttons.buy) + const buttons = await driver.findElements(screens.main.buttons.buy) + assert.equal(buttons.length, 1, 'main screen isn\'t displayed') + password = newPassword.correct + }) + }) + }) + + describe('Import Account', () => { + + it('opens import account menu', async function () { + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + const item = await waitUntilShowUp(menus.account.import) + await item.click() + const importAccountTitle = await waitUntilShowUp(screens.importAccounts.title) + assert.equal(await importAccountTitle.getText(), screens.importAccounts.textTitle) + }) + + it('imports account', async function () { + const privateKeyBox = await waitUntilShowUp(screens.importAccounts.fieldPrivateKey) + await privateKeyBox.sendKeys('c6b81c1252415d1acfda94474ab8f662a44c045f96749c805ff12a6074081586')// demo private key + const importButton = await waitUntilShowUp(screens.importAccounts.buttonImport) + await click(importButton) + + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + + const importedLabel = await waitUntilShowUp(menus.account.labelImported) + assert.equal(await importedLabel.getText(), 'IMPORTED') + }) + + it('opens delete imported account screen', async function () { + const menu = await waitUntilShowUp(menus.account.delete) + await menu.click() + const deleteImportedAccountTitle = await waitUntilShowUp(screens.deleteImportedAccount.title) + assert.equal(await deleteImportedAccountTitle.getText(), screens.deleteImportedAccount.titleText) + }) + + it('doesn\'t remove imported account with \'No\' button', async function () { + const NoButton = await waitUntilShowUp(screens.deleteImportedAccount.buttons.no) + await click(NoButton) + const settingsTitle = await waitUntilShowUp(screens.settings.title) + assert.equal(await settingsTitle.getText(), 'Settings') + + // check, that imported account still exists + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + const importedLabel = await waitUntilShowUp(menus.account.labelImported) + assert.equal(await importedLabel.getText(), 'IMPORTED') + }) + + it('opens delete imported account screen again', async function () { + const menu = await waitUntilShowUp(menus.account.delete) + await menu.click() + }) + + it('removes imported account with \'Yes\' button', async function () { + const YesButton = await waitUntilShowUp(screens.deleteImportedAccount.buttons.yes) + await click(YesButton) + const settingsTitle = await waitUntilShowUp(screens.settings.title) + assert.equal(await settingsTitle.getText(), 'Settings') + + // check, that imported account is removed + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + await waitUntilShowUp(menus.account.labelImported, 25) + const importedAccounts = await driver.findElements(menus.account.labelImported) + assert.ok(importedAccounts.length === 0) + await menu.click() + }) + }) describe('Import Ganache seed phrase', function () { it('logs out', async function () { - await driver.findElement(menus.sandwich.menu).click() - await delay(200) - const logOut = await driver.findElement(menus.sandwich.logOut) + const menu = await waitUntilShowUp(menus.sandwich.menu) + await menu.click() + const logOut = await waitUntilShowUp(menus.sandwich.logOut) assert.equal(await logOut.getText(), menus.sandwich.textLogOut) await logOut.click() - await delay(300) }) it('restores from seed phrase', async function () { - const restoreSeedLink = await driver.findElement(screens.lock.linkRestore) + const restoreSeedLink = await waitUntilShowUp(screens.lock.linkRestore) assert.equal(await restoreSeedLink.getText(), screens.lock.linkRestoreText) await restoreSeedLink.click() - await delay(100) }) it('adds seed phrase', async function () { const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' - const seedTextArea = await driver.findElement(screens.restoreVault.textArea) + const seedTextArea = await waitUntilShowUp(screens.restoreVault.textArea) await seedTextArea.sendKeys(testSeedPhrase) - await driver.findElement(screens.restoreVault.fieldPassword).sendKeys(password) - await driver.findElement(screens.restoreVault.fieldPasswordConfirm).sendKeys(password) - await driver.findElement(screens.restoreVault.buttos.ok).click() - await delay(500) + let field = await driver.findElement(screens.restoreVault.fieldPassword) + await field.sendKeys(password) + field = await driver.findElement(screens.restoreVault.fieldPasswordConfirm) + await field.sendKeys(password) + field = await waitUntilShowUp(screens.restoreVault.buttos.ok) + await click(field) }) it('balance renders', async function () { - await delay(200) - const balance = await driver.findElement(screens.main.balance) + const balance = await waitUntilShowUp(screens.main.balance) assert.equal(await balance.getText(), '100.000') - await delay(200) }) it('sends transaction', async function () { - const sendButton = await driver.findElement(screens.main.buttons.send) + const sendButton = await waitUntilShowUp(screens.main.buttons.send) assert.equal(await sendButton.getText(), screens.main.buttons.sendText) - await sendButton.click() - await delay(200) + await click(sendButton) }) it('adds recipient address and amount', async function () { - const sendTranscationScreen = await driver.findElement(screens.sendTransaction.title).getText() - assert.equal(sendTranscationScreen, screens.sendTransaction.titleText) - const inputAddress = await driver.findElement(screens.sendTransaction.fields.address) - const inputAmmount = await driver.findElement(screens.sendTransaction.fields.amount) + const sendTranscationScreen = await waitUntilShowUp(screens.sendTransaction.title) + assert.equal(await sendTranscationScreen.getText(), screens.sendTransaction.titleText, 'Transaction screen has incorrect titlr') + const inputAddress = await waitUntilShowUp(screens.sendTransaction.fields.address) + const inputAmmount = await waitUntilShowUp(screens.sendTransaction.fields.amount) await inputAddress.sendKeys('0x2f318C334780961FB129D2a6c30D0763d9a5C970') await inputAmmount.sendKeys('10') - await driver.findElement(screens.sendTransaction.buttonNext).click() - await delay(300) + const button = await waitUntilShowUp(screens.sendTransaction.buttonNext) + await click(button) }) it('confirms transaction', async function () { - await delay(300) - const bySubmitButton = screens.confirmTransaction.buttons.submit - const submitButton = await driver.wait(until.elementLocated(bySubmitButton)) - - submitButton.click() - - await delay(1500) + const submitButton = await waitUntilShowUp(screens.confirmTransaction.buttons.submit) + await click(submitButton) }) it('finds the transaction in the transactions list', async function () { - const tranasactionAmount = await driver.findElement(screens.main.transactionList) - assert.equal(await tranasactionAmount.getText(), '10.0') + const transactionAmount = await waitUntilShowUp(screens.main.transactionList) + assert.equal(await transactionAmount.getText(), '10.0') }) }) @@ -460,22 +466,22 @@ describe('Metamask popup page', async function () { }) it('navigates to create token contract link', async function () { - const createToken = await driver.findElement(By.css('#bs-example-navbar-collapse-1 > ul > li:nth-child(3) > a')) + const createToken = await waitUntilShowUp(By.css('#bs-example-navbar-collapse-1 > ul > li:nth-child(3) > a')) await createToken.click() }) it('adds input for token', async function () { - const totalSupply = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(5) > input')) - const tokenName = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(6) > input')) - const tokenDecimal = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(7) > input')) - const tokenSymbol = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(8) > input')) - const createToken = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > div > button')) + const totalSupply = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(5) > input')) + const tokenName = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(6) > input')) + const tokenDecimal = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(7) > input')) + const tokenSymbol = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > div > div:nth-child(8) > input')) + const createToken = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > div > button')) await totalSupply.sendKeys('100') await tokenName.sendKeys('Test') await tokenDecimal.sendKeys('0') await tokenSymbol.sendKeys('TST') - await createToken.click() + await click(createToken) await delay(1000) }) @@ -483,16 +489,14 @@ describe('Metamask popup page', async function () { it('confirms transaction in MetaMask popup', async function () { const windowHandles = await driver.getAllWindowHandles() await driver.switchTo().window(windowHandles[windowHandles.length - 1]) - 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) + const buttonSubmit = await waitUntilShowUp(screens.confirmTransaction.buttons.submit) + await click(buttonSubmit) }) it('switches back to Token Factory to grab the token contract address', async function () { const windowHandles = await driver.getAllWindowHandles() await driver.switchTo().window(windowHandles[0]) - const tokenContactAddress = await driver.findElement(By.css('#main > div > div > div > div:nth-child(2) > span:nth-child(3)')) + const tokenContactAddress = await waitUntilShowUp(By.css('#main > div > div > div > div:nth-child(2) > span:nth-child(3)')) tokenAddress = await tokenContactAddress.getText() await delay(500) }) @@ -510,33 +514,32 @@ describe('Metamask popup page', async function () { describe('Add Token', function () { it('switches to the add token screen', async function () { - const tokensTab = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div > div.inactiveForm.pointer')) + await waitUntilShowUp(screens.main.buttons.send) + const tokensTab = await driver.findElement(screens.main.tokens.menu) assert.equal(await tokensTab.getText(), 'Tokens') await tokensTab.click() - await delay(300) }) it('navigates to the add token screen', async function () { - const addTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > section > div.full-flex-height > div > button')) - assert.equal(await addTokenButton.getText(), 'Add Token') - await addTokenButton.click() + const addTokenButton = await waitUntilShowUp(screens.main.tokens.buttonAdd) + assert.equal(await addTokenButton.getText(), screens.main.tokens.buttonAddText) + await click(addTokenButton) }) - it('checks add token screen rendered', async function () { - const addTokenScreen = await driver.findElement(screens.settings.title) - assert.equal(await addTokenScreen.getText(), 'Add Token') + it('checks add token screen has correct title', async function () { + const addTokenScreen = await waitUntilShowUp(By.className('page-subtitle')) + assert.equal(await addTokenScreen.getText(), screens.addToken.titleText) }) it('adds token parameters', async function () { - const tokenContractAddress = await driver.findElement(By.css('#token-address')) + const tokenContractAddress = await waitUntilShowUp(screens.addToken.fields.contractAddress) await tokenContractAddress.sendKeys(tokenAddress) - await delay(300) - await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button')).click() - await delay(200) + const button = await waitUntilShowUp(screens.addToken.buttonAdd) + await click(button) }) it('checks the token balance', async function () { - const tokenBalance = await driver.findElement(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.equal(await tokenBalance.getText(), '100 TST') }) }) @@ -584,42 +587,42 @@ describe('Metamask popup page', async function () { it('adds token with the same address to POA network', async function () { await setProvider(NETWORKS.POA) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) it('adds token with the same address to SOKOL network', async function () { await setProvider(NETWORKS.SOKOL) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) it('adds token with the same address to MAINNET network', async function () { await setProvider(NETWORKS.MAINNET) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) it('adds token with the same address to ROPSTEN network', async function () { await setProvider(NETWORKS.ROPSTEN) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) it('adds token with the same address to KOVAN network', async function () { await setProvider(NETWORKS.KOVAN) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) it('adds token with the same address to RINKEBY network', async function () { await setProvider(NETWORKS.RINKEBY) await addToken(tokenAddress, tokenName, tokenDecimals) - const tokenBalance = await await waitUntilShowUp(screens.main.tokens.balance) + const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.notEqual(await tokenBalance.getText(), '') }) @@ -635,43 +638,40 @@ describe('Metamask popup page', async function () { }) describe('Remove Token', function () { - it('navigates to the remove token screen and goes back', async function () { - // Click to remove first token + it('button \'Remove token\' displayed', async function () { await setProvider(NETWORKS.LOCALHOST) - const removeTokenButton = await driver.findElement(screens.main.tokens.remove) + const removeTokenButton = await waitUntilShowUp(screens.main.tokens.remove) + assert.notEqual(removeTokenButton, false, 'button isn\'t displayed') await removeTokenButton.click() - const removeTokenTitle = await driver.findElement(screens.settings.title) - - // Check that the correct page is opened - assert.equal(await removeTokenTitle.getText(), 'Remove Token') - - // Go back - await delay(500) - await driver.findElement(By.className('fa fa-arrow-left fa-lg cursor-pointer')).click() + }) + it('screen \'Remove token\' has correct title', async function () { + const title = await waitUntilShowUp(screens.removeToken.title) + assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') + }) - await delay(300) + it('button "No" bring back to "Main" screen', async function () { + const title = await waitUntilShowUp(screens.removeToken.title) + assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') - // Check that the token was not deleted - const tokens = await driver.findElements(By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li')) - assert.equal(tokens.length, 1, 'There should be 1 token') + const button = await waitUntilShowUp(screens.removeToken.buttons.no) + assert.notEqual(button, false, 'button \'No\' isn\'t displayed ') + assert.equal(await button.getText(), 'No', 'button \'No\' has incorrect name') + await click(button) + const token = await waitUntilShowUp(screens.main.tokens.balance) + assert.notEqual(await token.getText(), '', 'token is disapeared after return from remove token screen ') }) - it('navigates to the remove token screen and removes the token from LOCALHOST', async function () { - // Click to remove first token - const removeTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > .trash')) + it('button "Yes" delete token', async function () { + const removeTokenButton = await waitUntilShowUp(screens.main.tokens.remove) + assert.notEqual(removeTokenButton, false, 'button isn\'t displayed') await removeTokenButton.click() - const removeTokenTitle = await driver.findElement(screens.settings.title) + const title = await waitUntilShowUp(screens.removeToken.title) + assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') - // Check that the correct page is opened - assert.equal(await removeTokenTitle.getText(), 'Remove Token') - - // Confirm the removal - const confirmRemoveTokenButton = await driver.findElement(By.css('#app-content > div > div.app-primary.from-right > div > div.flex-column.flex-justify-center.flex-grow.select-none > div > button:nth-child(2)')) - assert.equal(await confirmRemoveTokenButton.getText(), 'Yes') - await confirmRemoveTokenButton.click() - await delay(300) - - // Check that the token was deleted + const button = await waitUntilShowUp(screens.removeToken.buttons.yes) + assert.notEqual(button, false, 'button \'Yes\' isn\'t displayed ') + assert.equal(await button.getText(), 'Yes', 'button \'Yes\' has incorrect name') + await click(button) assert.equal(await assertTokensNotDisplayed(), true, 'tokens are displayed') }) @@ -713,15 +713,17 @@ describe('Metamask popup page', async function () { const correctRpcUrl = 'https://poa.infura.io/test1' it('switches to settings screen through menu \'Network -> Custom RPC\'', async function () { - await setProvider(NETWORKS.CUSTOM) - const settings = await driver.findElement(screens.settings.title) + const settings = await waitUntilShowUp(screens.settings.title) assert.equal(await settings.getText(), screens.settings.titleText, 'inappropriate screen is opened') }) it('error message if new Rpc url is invalid', async function () { - await driver.findElement(screens.settings.fieldNewRPC).sendKeys(invalidStringUrl) - await driver.findElement(screens.settings.buttonSave).click() + const field = await waitUntilShowUp(screens.settings.fieldNewRPC) + await field.sendKeys(invalidStringUrl) + const button = await waitUntilShowUp(screens.settings.buttonSave) + await click(button) + await delay(1000) assert.equal(await waitUntilShowUp(screens.settings.buttons.delete, 5), false, 'invalid Rpc was added') const errors = await driver.findElements(screens.settings.error) assert.equal(errors.length, 1, 'error isn\'t displayed if Rpc url incorrect') @@ -733,7 +735,9 @@ describe('Metamask popup page', async function () { await clearField(fieldRpc) await clearField(fieldRpc) await fieldRpc.sendKeys(urlWithoutHttp) - await driver.findElement(screens.settings.buttonSave).click() + const button = await waitUntilShowUp(screens.settings.buttonSave) + await click(button) + await delay(1000) assert.equal(await waitUntilShowUp(screens.settings.buttons.delete, 5), false, 'invalid Rpc was added') const errors = await driver.findElements(screens.settings.error) assert.equal(errors.length, 1, 'error isn\'t displayed if Rpc url incorrect') @@ -745,7 +749,9 @@ describe('Metamask popup page', async function () { await clearField(fieldRpc) await clearField(fieldRpc) await fieldRpc.sendKeys(invalidEndpoint) - await driver.findElement(screens.settings.buttonSave).click() + const button = await waitUntilShowUp(screens.settings.buttonSave) + await click(button) + await delay(1000) assert.equal(await waitUntilShowUp(screens.settings.buttons.delete, 5), false, 'invalid Rpc was added') const errors = await driver.findElements(screens.settings.error) assert.equal(errors.length, 1, 'error isn\'t displayed if Rpc url incorrect') @@ -766,17 +772,19 @@ describe('Metamask popup page', async function () { }) it('new added Rpc displayed in network dropdown menu', async function () { - await driver.findElement(screens.main.network).click() + let menu = await waitUntilShowUp(screens.main.network) + await menu.click() const item = await waitUntilShowUp(menus.networks.addedCustomRpc) - await driver.findElement(screens.main.network).click() - assert.equal(await item.getText(), correctRpcUrl, 'Added custom Url aren\'t displayed ') + assert.equal(await item.getText(), correctRpcUrl, 'Added custom Url isn\'t displayed ') + menu = await waitUntilShowUp(screens.main.network) + await menu.click() }) it('click button \'Delete\' opens screen \'Delete Custom RPC\'', async function () { await delay(1000) const buttonDelete = await waitUntilShowUp(screens.settings.buttons.delete, 10) assert.equal(await buttonDelete.getText(), 'Delete') - await buttonDelete.click() + await click(buttonDelete) const title = await waitUntilShowUp(screens.settings.title) assert.equal(await title.getText(), screens.deleteCustomRPC.titleText, 'inappropriate screen is opened') }) @@ -784,17 +792,17 @@ describe('Metamask popup page', async function () { it('click button \'No\' opens screen \'Settings\'', async function () { const buttonNo = await waitUntilShowUp(screens.deleteCustomRPC.buttons.no) assert.equal(await buttonNo.getText(), 'No') - await buttonNo.click() + await click(buttonNo) const title = await waitUntilShowUp(screens.settings.title) assert.equal(await title.getText(), screens.settings.titleText, 'inappropriate screen is opened') }) it('user able to delete custom rpc', async function () { - const buttonDelete = await waitUntilShowUp(screens.settings.buttons.delete, 10) - await buttonDelete.click() + const buttonDelete = await waitUntilShowUp(screens.settings.buttons.delete, 25) + await click(buttonDelete) const yesButton = await waitUntilShowUp(screens.deleteCustomRPC.buttons.yes) assert.equal(await yesButton.getText(), 'Yes') - await yesButton.click() + await click(yesButton) const title = await waitUntilShowUp(screens.settings.title) assert.equal(await title.getText(), screens.settings.titleText, 'inappropriate screen is opened') }) @@ -805,20 +813,19 @@ describe('Metamask popup page', async function () { }) it('deleted custom rpc isn\'t displayed in network dropdown menu', async function () { - const menu = await waitUntilShowUp(screens.main.network) - await menu.click() + let menu = await waitUntilShowUp(screens.main.network) + await menu.click() const item = await waitUntilShowUp(menus.networks.addedCustomRpc, 20) - await driver.findElement(screens.main.network).click() + menu = await waitUntilShowUp(screens.main.network) + await menu.click() assert.equal(item, false, 'deleted custom rpc is displayed in network dropdown menu ') }) }) - async function setProviderType (type) { - await driver.executeScript('window.metamask.setProviderType(arguments[0])', type) - } - async function setProvider (network) { - await driver.findElement(screens.main.network).click() + await delay(300) + const menu = await waitUntilShowUp(screens.main.network) + await menu.click() let counter switch (network) { case NETWORKS.POA: @@ -851,10 +858,35 @@ describe('Metamask popup page', async function () { await driver.executeScript("document.getElementsByClassName('dropdown-menu-item')[" + counter + '].click();') } + async function scrollTo (element) { + try { + await driver.executeScript('arguments[0].scrollIntoView();', element) + return true + } catch (err) { + return false + } + } + + async function click (element) { + try { + await element.sendKeys(Key.RETURN) + return true + } catch (err) { + return false + } + } + + async function clearField (field, number) { + await click(field) + if (number === undefined) number = 40 + for (let i = 0; i < number; i++) { + await field.sendKeys(Key.BACK_SPACE) + } + } + async function waitUntilDisappear (by, Twait) { if (Twait === undefined) Twait = 10 do { - await delay(100) if (!await isElementDisplayed(by)) return true } while (Twait-- > 0) @@ -862,7 +894,7 @@ describe('Metamask popup page', async function () { } async function waitUntilShowUp (by, Twait) { - if (Twait === undefined) Twait = 2000 + if (Twait === undefined) Twait = 200 do { await delay(100) if (await isElementDisplayed(by)) return await driver.findElement(by) @@ -892,22 +924,22 @@ describe('Metamask popup page', async function () { assert.equal(tokens.length, 0, 'Unexpected token presents') return true } catch (err) { - return err + return false } } async function addToken (tokenAddress, tokenName, tokenDecimals) { try { const button = await waitUntilShowUp(screens.main.tokens.buttonAdd) - await button.click() - const field = await waitUntilShowUp(screens.addToken.fieldTokenContractAddress) + await click(button) + const field = await waitUntilShowUp(screens.addToken.fields.contractAddress) await field.sendKeys(tokenAddress) await delay(500) - await driver.findElement(screens.addToken.fieldTokenSymbol).sendKeys(tokenName) + await driver.findElement(screens.addToken.fields.tokenSymbol).sendKeys(tokenName) await delay(500) - await driver.findElement(screens.addToken.fieldDecimals).sendKeys(tokenDecimals) + await driver.findElement(screens.addToken.fields.decimals).sendKeys(tokenDecimals) const buttonAdd = await waitUntilShowUp(screens.addToken.buttonAdd) - await buttonAdd.click() + await click(buttonAdd) return true } catch (err) { return false