diff --git a/.eslintignore b/.eslintignore
index 23fdd0c543..10c9718f18 100755
--- a/.eslintignore
+++ b/.eslintignore
@@ -5,8 +5,9 @@ main.js
logs
node_modules
translations
-./tests
-features/tests/e2e/documents/*
+tests
+tests/paper-wallets/e2e/documents/*
+tests/wallets/e2e/documents/*
mainnet-genesis-dryrun-with-stakeholders.json
source/renderer/app/i18n/locales
nodemon.json
diff --git a/.gitignore b/.gitignore
index 889975bc75..1727a3e3ac 100755
--- a/.gitignore
+++ b/.gitignore
@@ -62,8 +62,8 @@ translations/messages
translations/reports
# 'Screenshots' and 'Paper wallet ceritifcate PDF file' generated by acceptance tests
-features/tests/e2e/documents/paper_wallet_certificates/paper-wallet-certificate.pdf
-features/tests/e2e/screenshots
+tests/paper-wallets/e2e/documents/paper-wallet-certificate.pdf
+tests/screenshots/
# Webpack
.cache
diff --git a/.prettierignore b/.prettierignore
index 583be1c748..4c9d735a7b 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -20,4 +20,5 @@
# Ignore the following special folders and files
source/renderer/app/i18n/locales/
-features/tests/e2e/documents/*
+tests/paper-wallets/e2e/documents/*
+tests/wallets/e2e/documents/*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2ac1a4755..b966e4def3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
Changelog
=========
+## vNext
+
+### Chores
+
+- Reorganized tests directories by domain and added flow support to all tests JS files ([PR 1540](https://github.com/input-output-hk/daedalus/pull/1540))
+
## 0.15.0
### Features
diff --git a/features/.eslintrc b/features/.eslintrc
deleted file mode 100644
index 0eed3f6a3f..0000000000
--- a/features/.eslintrc
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "rules": {
- "func-names": 0,
- "max-len": 0,
- "new-cap": [2, {
- "capIsNewExceptions": [
- "After",
- "AfterAll",
- "BeforeAll",
- "Before",
- "Given",
- "When",
- "Then"
- ]
- }]
- },
- "globals": {
- "daedalus": true
- }
-}
diff --git a/features/README.md b/features/README.md
deleted file mode 100644
index 14523556d2..0000000000
--- a/features/README.md
+++ /dev/null
@@ -1,62 +0,0 @@
-
-Document maintainer: Nikola Glumac
Document status: Active
-
-
-# Install Daedalus
-
-1. Make sure you have node and yarn installed on your machine
-2. Clone Daedalus repository to your machine (`git clone git@github.com:input-output-hk/daedalus.git`)
-3. Install dependencies from within Daedalus directory:
-
-```bash
-$ yarn install
-```
-
-# Run unit tests
-
-Make sure Daedalus is properly installed (see above).
-
-```bash
-$ yarn test:unit
-```
-
-## Unbound tests
-
-Unbound tests run as long as you keep them running
-(never end except if an error occurs).
-
-Example:
-`yarn test:unit:unbound --tags @mnemonics`
-generates and validates mnemonics as long as you keep it
-running (the number of executions is updated in the terminal)
-
-# Run end-to-end tests
-
-1. Make sure Daedalus is properly installed (see above).
-2. Build and run the backend (Cardano SL) following the instructions from [Daedalus](https://github.com/input-output-hk/daedalus/blob/master/README.md#development---with-cardano-wallet) README file.
-3. Run Daedalus frontend tests:
-
-```bash
-$ cd daedalus/
-$ yarn nix:dev XXX # XXX = cardano system startup time
-$ yarn build
-$ yarn test:e2e
-```
-
-# Run all tests
-
-```bash
-$ yarn test
-```
-
-Once tests are complete you will get a summary of passed/failed tests in the Terminal window.
-
-## Keeping Daedalus alive after end-to-end tests
-
-While working on the tests it's often useful to keep Daedalus alive after the tests have run
-(e.g: to inspect the app state). You can pass a special environment var to tell the test script
-not to close the app:
-
-````bash
-$ KEEP_APP_AFTER_TESTS=true yarn test:e2e
-````
diff --git a/features/tests/e2e/documents/default-wallet.json b/features/tests/e2e/documents/default-wallet.json
deleted file mode 100644
index bad1f6d5b4..0000000000
--- a/features/tests/e2e/documents/default-wallet.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "wallet": {
- "accounts": [{ "name": "Genesis account", "index": 2147483648 }],
- "walletSecretKey": "WIAwbsQgbz9X0WhvOnVeH+yRs7Ri93ESTdMspBHzeLnPUR6hLZL/NazfB40z2x8FZhLwNIt83DCuMR1nGG+ZqvsD/ouyzg3ec729fnrqEMO4A+qPTJmpiRgQZfYO2KDJDRxLtMyofXl90VVZOEke/QddnZ8CGHoR/lCemJgZuvzBpw==",
- "walletMeta": {
- "name": "Imported Wallet",
- "assurance": "normal",
- "unit": "ADA"
- },
- "passwordHash": "WGQxNHw4fDF8V0NERGRHY0JGcThzelVyeFdza00wM1VjYnloeVBBQXBvdWtwdWFsUTExNGVFdz09fFJXMk5kUmVJYmg2REtsa2lsWG8rQ1lvTStRZmJkMzRmRVd0MG4rSy82YUU9"
- },
- "fileType": "WALLETS_EXPORT",
- "fileVersion": "1.0.0"
-}
diff --git a/features/tests/e2e/documents/paper_wallet_certificates/paper-wallet-certificate.pdf b/features/tests/e2e/documents/paper_wallet_certificates/paper-wallet-certificate.pdf
deleted file mode 100644
index 64c339b4ba..0000000000
Binary files a/features/tests/e2e/documents/paper_wallet_certificates/paper-wallet-certificate.pdf and /dev/null differ
diff --git a/features/tests/e2e/helpers/add-wallet-page-helpers.js b/features/tests/e2e/helpers/add-wallet-page-helpers.js
deleted file mode 100644
index 58a956403b..0000000000
--- a/features/tests/e2e/helpers/add-wallet-page-helpers.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { waitAndClick } from './shared-helpers';
-
-const ADD_WALLET = '.WalletAdd';
-const IMPORT_WALLET_BUTTON = '.importWalletButton';
-
-export default {
- waitForVisible: (client, { isHidden } = {}) =>
- client.waitForVisible(ADD_WALLET, null, isHidden),
- clickImportButton: client =>
- waitAndClick(client, `${ADD_WALLET} ${IMPORT_WALLET_BUTTON}`),
-};
diff --git a/features/tests/e2e/helpers/app-helpers.js b/features/tests/e2e/helpers/app-helpers.js
deleted file mode 100644
index 0adca54379..0000000000
--- a/features/tests/e2e/helpers/app-helpers.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// @flow
-import type { WebdriverClient } from '../setup/global-types';
-import { getProcessesByName } from '../../../../source/main/utils/processes';
-
-export const waitForDaedalusToExit = async (
- client: WebdriverClient,
- timeout: number = 61000
-) => {
- const daedalusProcessName =
- process.platform === 'linux' ? 'electron' : 'Electron';
- return client.waitUntil(
- async () => (await getProcessesByName(daedalusProcessName)).length === 0,
- timeout
- );
-};
-
-export const refreshClient = async (client: WebdriverClient) => {
- await client.url(`file://${__dirname}/../../../../dist/renderer/index.html`);
-};
diff --git a/features/tests/e2e/helpers/cardano-node-helpers.js b/features/tests/e2e/helpers/cardano-node-helpers.js
deleted file mode 100644
index c4075450aa..0000000000
--- a/features/tests/e2e/helpers/cardano-node-helpers.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// @flow
-import type { Daedalus, WebdriverClient } from '../setup/global-types';
-import { getProcessesByName } from '../../../../source/main/utils/processes';
-
-declare var daedalus: Daedalus;
-
-export const getCardanoNodeState = async (client: WebdriverClient) =>
- (await client.execute(() => daedalus.stores.networkStatus.cardanoNodeState))
- .value;
-
-export const waitForCardanoNodeToExit = async (client: WebdriverClient) =>
- client.waitUntil(
- async () => (await getProcessesByName('cardano-node')).length === 0,
- 61000
- );
diff --git a/features/tests/e2e/helpers/data-layer-migration-helpers.js b/features/tests/e2e/helpers/data-layer-migration-helpers.js
deleted file mode 100644
index 0981959da1..0000000000
--- a/features/tests/e2e/helpers/data-layer-migration-helpers.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT =
- '.DataLayerMigrationForm_component';
-
-const dataLayerMigration = {
- waitForVisible: async (client, { isHidden } = {}) =>
- client.waitForVisible(
- DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT,
- null,
- isHidden
- ),
- acceptMigration: async client => {
- await client.execute(() => {
- daedalus.actions.profile.acceptDataLayerMigration.trigger();
- });
- await dataLayerMigration.waitForVisible(client, { isHidden: true });
- },
-};
-
-export default dataLayerMigration;
diff --git a/features/tests/e2e/helpers/dialogs/import-wallet-dialog-helpers.js b/features/tests/e2e/helpers/dialogs/import-wallet-dialog-helpers.js
deleted file mode 100644
index f8d9afa72e..0000000000
--- a/features/tests/e2e/helpers/dialogs/import-wallet-dialog-helpers.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { expectTextInSelector, waitAndClick } from '../shared-helpers';
-
-const IMPORT_WALLET_DIALOG = '.WalletFileImportDialog';
-
-export default {
- waitForDialog: (client, { isHidden } = {}) =>
- client.waitForVisible(IMPORT_WALLET_DIALOG, null, isHidden),
- selectFile: (client, { filePath }) =>
- client.chooseFile(
- `${IMPORT_WALLET_DIALOG} .FileUploadWidget_dropZone input`,
- filePath
- ),
- clickImport: client =>
- waitAndClick(client, `${IMPORT_WALLET_DIALOG} .primary`),
- expectError: (client, { error }) =>
- expectTextInSelector(client, {
- selector: `${IMPORT_WALLET_DIALOG}_error`,
- text: error,
- }),
-};
diff --git a/features/tests/e2e/helpers/i18n-helpers.js b/features/tests/e2e/helpers/i18n-helpers.js
deleted file mode 100644
index d331cf4e17..0000000000
--- a/features/tests/e2e/helpers/i18n-helpers.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const DEFAULT_LANGUAGE = 'en-US';
-
-export default {
- formatMessage: async (client, { id, values }) => {
- const translation = await client.execute(
- (translationId, translationValues) => {
- const IntlProvider = require('react-intl').IntlProvider; // eslint-disable-line
- const locale = daedalus.stores.profile.currentLocale;
- const messages = daedalus.translations;
- const intlProvider = new IntlProvider(
- { locale, messages: messages[locale] },
- {}
- );
- return intlProvider
- .getChildContext()
- .intl.formatMessage({ id: translationId }, translationValues);
- },
- id,
- values || {}
- );
- return translation.value;
- },
- setActiveLanguage: async (client, { language } = {}) =>
- client.execute(locale => {
- daedalus.actions.profile.updateLocale.trigger({ locale });
- }, language || DEFAULT_LANGUAGE),
-};
diff --git a/features/tests/e2e/helpers/language-selection-helpers.js b/features/tests/e2e/helpers/language-selection-helpers.js
deleted file mode 100644
index bc53148a9d..0000000000
--- a/features/tests/e2e/helpers/language-selection-helpers.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import i18n from './i18n-helpers';
-
-const LANGUAGE_SELECTION_FORM = '.LanguageSelectionForm_component';
-
-const languageSelection = {
- waitForVisible: async (client, { isHidden } = {}) =>
- client.waitForVisible(LANGUAGE_SELECTION_FORM, null, isHidden),
- ensureLanguageIsSelected: async (client, { language } = {}) => {
- await i18n.setActiveLanguage(client, { language });
- await languageSelection.waitForVisible(client, { isHidden: true });
- },
-};
-
-export default languageSelection;
diff --git a/features/tests/e2e/helpers/notifications-helpers.js b/features/tests/e2e/helpers/notifications-helpers.js
deleted file mode 100644
index 70aea2d1b9..0000000000
--- a/features/tests/e2e/helpers/notifications-helpers.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { WalletSyncStateTags } from '../../../../source/renderer/app/domains/Wallet';
-
-export const isActiveWalletBeingRestored = async client => {
- const result = await client.execute(
- expectedSyncTag =>
- daedalus.stores.wallets.active.syncState.tag === expectedSyncTag,
- WalletSyncStateTags.RESTORING
- );
- return result.value;
-};
-
-export const waitForActiveRestoreNotification = (client, { isHidden } = {}) =>
- client.waitForVisible('.ActiveRestoreNotification', null, isHidden);
diff --git a/features/tests/e2e/helpers/route-helpers.js b/features/tests/e2e/helpers/route-helpers.js
deleted file mode 100644
index 4da5b90c22..0000000000
--- a/features/tests/e2e/helpers/route-helpers.js
+++ /dev/null
@@ -1,18 +0,0 @@
-export const getCurrentAppRoute = async function() {
- const url = (await this.client.url()).value;
- return url.substring(url.indexOf('#/') + 1); // return without the hash
-};
-
-export const waitUntilUrlEquals = function(expectedUrl) {
- const context = this;
- return context.client.waitUntil(async () => {
- const url = await getCurrentAppRoute.call(context);
- return url === expectedUrl;
- });
-};
-
-export const navigateTo = function(requestedRoute) {
- return this.client.execute(route => {
- daedalus.actions.router.goToRoute.trigger({ route });
- }, requestedRoute);
-};
diff --git a/features/tests/e2e/helpers/screenshot.js b/features/tests/e2e/helpers/screenshot.js
deleted file mode 100644
index ab615a1599..0000000000
--- a/features/tests/e2e/helpers/screenshot.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import { generateFileNameWithTimestamp } from '../../../../source/common/utils/files';
-import ensureDirectoryExists from '../../../../source/main/utils/ensureDirectoryExists';
-
-export const generateScreenshotFilePath = prefix => {
- const filePath = path.resolve(__dirname, '../screenshots', prefix);
- const extension = 'png';
- const fileName = generateFileNameWithTimestamp({ prefix, extension });
- ensureDirectoryExists(filePath);
- return `${filePath}/${fileName}`;
-};
-
-export const getTestNameFromTestFile = testFile =>
- testFile.replace('features/', '').replace('.feature', '');
-
-export const saveScreenshot = async (context, file) => {
- await context.browserWindow
- .capturePage()
- .then(imageBuffer => fs.writeFile(file, imageBuffer))
- .catch(err => {
- // eslint-disable-next-line no-console
- console.log(err);
- });
-};
diff --git a/features/tests/e2e/helpers/shared-helpers.js b/features/tests/e2e/helpers/shared-helpers.js
deleted file mode 100644
index 5e4813b619..0000000000
--- a/features/tests/e2e/helpers/shared-helpers.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { expect } from 'chai';
-
-export const waitAndClick = async (client, selector, ...waitArgs) => {
- await client.waitForVisible(selector, ...waitArgs);
- await client.waitForEnabled(selector, ...waitArgs);
- return client.click(selector);
-};
-
-export const expectTextInSelector = async (client, { selector, text }) => {
- await client.waitForText(selector);
- let textOnScreen = await client.getText(selector);
- // The selector could exist multiple times in the DOM
- if (typeof textOnScreen === 'string') textOnScreen = [textOnScreen];
- // We only compare the first result
- expect(textOnScreen[0]).to.equal(text);
-};
-
-export const waitUntilTextInSelector = async (client, { selector, text }) =>
- client.waitUntil(async () => {
- await client.waitForText(selector);
- let textOnScreen = await client.getText(selector);
- // The selector could exist multiple times in the DOM
- if (typeof textOnScreen === 'string') textOnScreen = [textOnScreen];
- // We only compare the first result
- return textOnScreen[0] === text;
- });
-
-export const getVisibleElementsForSelector = async (
- client,
- selectSelector,
- waitSelector = selectSelector,
- ...waitArgs
-) => {
- await client.waitForVisible(waitSelector, ...waitArgs);
- return client.elements(selectSelector);
-};
-
-export const getVisibleElementsCountForSelector = async (
- client,
- selectSelector,
- waitSelector = selectSelector,
- ...waitArgs
-) => {
- const elements = await getVisibleElementsForSelector(
- client,
- selectSelector,
- waitSelector,
- ...waitArgs
- );
- return elements.value ? elements.value.length : 0;
-};
-
-export const getVisibleTextsForSelector = async (client, selector) => {
- await client.waitForVisible(selector);
- const texts = await client.getText(selector);
- return [].concat(texts);
-};
diff --git a/features/tests/e2e/helpers/sidebar-helpers.js b/features/tests/e2e/helpers/sidebar-helpers.js
deleted file mode 100644
index 4981919339..0000000000
--- a/features/tests/e2e/helpers/sidebar-helpers.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { waitAndClick } from './shared-helpers';
-
-export default {
- activateCategory: async (client, { category }) => {
- await client.execute(cat => {
- daedalus.actions.sidebar.activateSidebarCategory.trigger({
- category: cat,
- showSubMenu: true,
- });
- }, `/${category}`);
- return client.waitForVisible(`.SidebarCategory_active.${category}`);
- },
- clickAddWalletButton: client =>
- waitAndClick(client, '.SidebarWalletsMenu_addWalletButton'),
-};
diff --git a/features/tests/e2e/helpers/terms-of-use-helpers.js b/features/tests/e2e/helpers/terms-of-use-helpers.js
deleted file mode 100644
index e387b7c923..0000000000
--- a/features/tests/e2e/helpers/terms-of-use-helpers.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const TERMS_OF_USE_FORM = '.TermsOfUseForm_component';
-
-const termsOfUse = {
- waitForVisible: async (client, { isHidden } = {}) =>
- client.waitForVisible(TERMS_OF_USE_FORM, null, isHidden),
- acceptTerms: async client => {
- await client.execute(() => {
- daedalus.actions.profile.acceptTermsOfUse.trigger();
- });
- await termsOfUse.waitForVisible(client, { isHidden: true });
- },
-};
-
-export default termsOfUse;
diff --git a/features/tests/e2e/setup/global-types.js b/features/tests/e2e/setup/global-types.js
deleted file mode 100644
index e573d4a542..0000000000
--- a/features/tests/e2e/setup/global-types.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// @flow
-import type { Api } from '../../../../source/renderer/app/api';
-import type { ActionsMap } from '../../../../source/renderer/app/actions';
-import type { StoresMap } from '../../../../source/renderer/app/stores';
-
-export type Daedalus = {
- api: Api,
- environment: Object,
- actions: ActionsMap,
- stores: StoresMap,
- translations: Object,
- reset: Function,
-};
-
-export type WebdriverExecuteResult = { value: T };
-
-export type WebdriverClient = {
- execute: (script: Function) => WebdriverExecuteResult,
- waitUntil: (script: Function, timeout?: number) => Promise,
- url: (url: string) => Promise,
-};
diff --git a/features/tests/e2e/setup/i18n.js b/features/tests/e2e/setup/i18n.js
deleted file mode 100644
index f9afc7b852..0000000000
--- a/features/tests/e2e/setup/i18n.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Before } from 'cucumber';
-
-Before(function() {
- this.intl = async (translationId, translationValues = {}) => {
- const translation = await this.client.execute(
- (id, values) => {
- const IntlProvider = require('react-intl').IntlProvider; // eslint-disable-line
- const locale = daedalus.stores.profile.currentLocale;
- const messages = daedalus.translations;
- const intlProvider = new IntlProvider(
- { locale, messages: messages[locale] },
- {}
- );
- return intlProvider
- .getChildContext()
- .intl.formatMessage({ id }, values);
- },
- translationId,
- translationValues
- );
- return translation.value;
- };
-});
diff --git a/features/tests/e2e/setup/webdriver.js b/features/tests/e2e/setup/webdriver.js
deleted file mode 100644
index 33d9b85225..0000000000
--- a/features/tests/e2e/setup/webdriver.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { Before } from 'cucumber';
-
-Before(function() {
- this.waitAndClick = async (selector, ...waitArgs) => {
- await this.client.waitForVisible(selector, ...waitArgs);
- return this.client.click(selector);
- };
-});
diff --git a/features/tests/e2e/steps/helper-steps.js b/features/tests/e2e/steps/helper-steps.js
deleted file mode 100644
index d0141ace1a..0000000000
--- a/features/tests/e2e/steps/helper-steps.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { When } from 'cucumber';
-import {
- generateScreenshotFilePath,
- saveScreenshot,
-} from '../helpers/screenshot';
-
-const oneHour = 60 * 60 * 1000;
-// Helper step to pause execution for up to an hour ;)
-When(/^I freeze$/, { timeout: oneHour }, callback => {
- setTimeout(callback, oneHour);
-});
-
-When(/^I take a screenshot named "([^"]*)"$/, async function(testName) {
- const file = generateScreenshotFilePath(testName);
- await saveScreenshot(this, file);
-});
-
-When(/^I inject fault named "([^"]*)"$/, async function(faultName) {
- await this.client.executeAsync((name, done) => {
- daedalus.api.ada
- .setCardanoNodeFault([name, true])
- .then(done)
- .catch(e => {
- throw e;
- });
- }, faultName);
-});
-
-When(/^I trigger the apply-update endpoint$/, async function() {
- await this.client.executeAsync(done => {
- daedalus.api.ada
- .applyUpdate()
- .then(done)
- .catch(e => {
- throw e;
- });
- });
-});
-
-When(/^I set next update version to "([^"]*)"$/, async function(
- applicationVersion
-) {
- await this.client.executeAsync((version, done) => {
- daedalus.api.ada
- .setNextUpdate(parseInt(version, 10))
- .then(done)
- .catch(e => {
- throw e;
- });
- }, applicationVersion);
-});
diff --git a/features/tests/e2e/steps/setup-steps.js b/features/tests/e2e/steps/setup-steps.js
deleted file mode 100644
index 370a5ebccc..0000000000
--- a/features/tests/e2e/steps/setup-steps.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Given } from 'cucumber';
-import termsOfUse from '../helpers/terms-of-use-helpers';
-import languageSelection from '../helpers/language-selection-helpers';
-import dataLayerMigration from '../helpers/data-layer-migration-helpers';
-
-Given(/^I have completed the basic setup$/, async function() {
- await languageSelection.ensureLanguageIsSelected(this.client, {
- language: 'en-US',
- });
- await termsOfUse.acceptTerms(this.client);
- await dataLayerMigration.acceptMigration(this.client);
-});
diff --git a/features/tests/unit/setup/context.js b/features/tests/unit/setup/context.js
deleted file mode 100644
index 8fa1261dbe..0000000000
--- a/features/tests/unit/setup/context.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Before } from 'cucumber';
-
-Before(function() {
- this.context = {};
-});
diff --git a/features/tests/unit/setup/parameter-types.js b/features/tests/unit/setup/parameter-types.js
deleted file mode 100644
index 9aad9bd47f..0000000000
--- a/features/tests/unit/setup/parameter-types.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { defineParameterType } from 'cucumber';
-
-// Add {bool} parameter type
-defineParameterType({
- name: 'bool',
- regexp: /true|false/,
- transformer: b => b === 'true',
-});
diff --git a/gulpfile.js b/gulpfile.js
index 3ceec80513..53a480bd9f 100755
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -182,7 +182,7 @@ gulp.task('build:themes', gulp.series('clean:dist', 'prepare:themes'));
gulp.task(
'test:e2e:nodemon',
shell.task(
- 'nodemon --watch dist --watch features --exec "yarn test:e2e --tags \'@e2e and @watch\'"'
+ 'nodemon --watch dist --watch tests --exec "yarn test:e2e --tags \'@e2e and @watch\'"'
)
);
diff --git a/package.json b/package.json
index b389074c01..3dab01472b 100644
--- a/package.json
+++ b/package.json
@@ -10,18 +10,18 @@
"start:dev": "NODE_ENV=development gulp start",
"dev": "IS_WATCH_MODE=true gulp dev",
"test": "NODE_ENV=test yarn build && yarn test:unit && yarn test:e2e",
- "test:unit": "yarn cucumber --require 'features/tests/unit/**/*.js' --tags '@unit and not @skip and not @wip'",
- "test:unit:watch": "nodemon --watch source --watch features --exec \"yarn test:unit --tags '@unit and @watch'\"",
- "test:unit:unbound": "yarn cucumber --require 'features/tests/unit/**/*.js' --tags '@unbound and not @skip and not @wip'",
- "test:e2e": "yarn cucumber --require 'features/tests/e2e/**/*.js' --tags '@e2e and not @skip and not @wip'",
+ "test:unit": "yarn cucumber --require 'tests/**/unit/*.js' --tags '@unit and not @skip and not @wip'",
+ "test:unit:watch": "nodemon --watch source --watch tests --exec \"yarn test:unit --tags '@unit and @watch'\"",
+ "test:unit:unbound": "yarn cucumber --require 'tests/**/unit/*.js' --tags '@unbound and not @skip and not @wip'",
+ "test:e2e": "yarn cucumber --require 'tests/**/e2e/*.js' --tags '@e2e and not @skip and not @wip'",
"test:e2e:watch": "gulp test:e2e:watch",
+ "cucumber": "cross-env NODE_ENV=test cucumber-js tests --require 'tests/**/*.js' --require-module @babel/register -f node_modules/cucumber-pretty --format-options '{\"snippetInterface\": \"async-await\"}'",
"test:e2e:watch:once": "KEEP_APP_AFTER_TESTS=true yarn test:e2e --tags '@e2e and @watch'",
- "cucumber": "cross-env NODE_ENV=test cucumber-js --require-module @babel/register -f node_modules/cucumber-pretty --format-options '{\"snippetInterface\": \"async-await\"}'",
"debug": "gulp debug",
"package": "gulp build && cross-env NODE_ENV=production node -r @babel/register -r @babel/polyfill scripts/package.js",
"package:all": "yarn package --all",
"cleanup": "mop -v",
- "lint": "eslint --format=node_modules/eslint-formatter-pretty source features storybook *.js",
+ "lint": "eslint --format=node_modules/eslint-formatter-pretty source tests storybook *.js",
"flow:test": "flow; test $? -eq 0 -o $? -eq 2",
"prettier": "./node_modules/.bin/prettier \"**/*.*\"",
"prettier:check": "yarn prettier --check",
diff --git a/scripts/package.js b/scripts/package.js
index 4ce3fe1d2e..c9956287dd 100755
--- a/scripts/package.js
+++ b/scripts/package.js
@@ -27,7 +27,7 @@ const DEFAULT_OPTS = {
ignore: [
/^\/.buildkite($|\/)/,
/^\/.storybook($|\/)/,
- /^\/features($|\/)/,
+ /^\/tests($|\/)/,
/^\/flow($|\/)/,
/^\/node_modules($|\/)/,
/^\/scripts($|\/)/,
diff --git a/source/renderer/app/api/index.js b/source/renderer/app/api/index.js
index 7ac262bcb4..ab532ed216 100644
--- a/source/renderer/app/api/index.js
+++ b/source/renderer/app/api/index.js
@@ -5,6 +5,7 @@ import LocalStorageApi from './utils/localStorage';
export type Api = {
ada: AdaApi,
localStorage: LocalStorageApi,
+ setFaultyNodeSettingsApi?: boolean,
};
export const setupApi = (isTest: boolean, network: string): Api => ({
diff --git a/tests/.eslintrc b/tests/.eslintrc
new file mode 100644
index 0000000000..4e788345ec
--- /dev/null
+++ b/tests/.eslintrc
@@ -0,0 +1,20 @@
+{
+ "rules": {
+ "func-names": 0,
+ "max-len": 0,
+ "new-cap": [2, {
+ "capIsNewExceptions": [
+ "After",
+ "AfterAll",
+ "BeforeAll",
+ "Before",
+ "Given",
+ "When",
+ "Then"
+ ]
+ }]
+ },
+ "globals": {
+ "daedalus": true
+ }
+}
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000000..45ef7c502e
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,78 @@
+
+Document maintainer: Nikola Glumac, Marcus Hurney
Document status: Active
+
+
+# Daedalus Acceptance Tests Overview
+
+### File types and Cucumber syntax
+
+- Cucumber looks for files with a `.feature` file extension as the starting point for executing `scenarios` defined within a given `.feature` file. Each `scenario` contains one or more `steps`. `scenarios` describe the broader context or purpose of a given set of steps while the `steps` themselves describe the intended functionality of the Javascript test executables. Together, the collective `scenarios` within a `.feature` file comprise test coverage of at least one feature within the Daedalus UI.
+
+### JavaScript Executables
+
+- Each `step` in a `.feature` file will match a JavaScript `string` passed as the first parameter to a `step-definition` function within a separate `.js` file. A `step-definition` also contains the executable JavaScript function(s) that run the test logic itself. The `step`'s name written as text within a `.feature` file must exactly match the associated JavaScript `string` within a `step-definition` in order for the executable to run.
+
+### File Structure
+
+- All the files comprising the Daedalus acceptance tests are divided into directories by domain. A test belongs to a domain depending on the category of functionality it's meant to test. Within Daedalus the domains `wallets`, `paper-wallets`, `addresses`, `transactions`, `navigation`, `nodes`, `settings`, and `common`. These domains also constitute the top level directories of the Daedalus acceptance tests.
+
+# Running Daedalus Acceptance Tests
+
+### Install Daedalus
+
+1. Make sure you have node and yarn installed on your machine
+2. Clone Daedalus repository to your machine (`git clone git@github.com:input-output-hk/daedalus.git`)
+3. Install dependencies from within Daedalus directory:
+
+```bash
+$ yarn install
+```
+
+### Run unit tests
+
+Make sure Daedalus is properly installed (see above).
+
+```bash
+$ yarn test:unit
+```
+
+### Unbound tests
+
+Unbound tests run as long as you keep them running
+(never end except if an error occurs).
+
+Example:
+`yarn test:unit:unbound --tags @mnemonics`
+generates and validates mnemonics as long as you keep it
+running (the number of executions is updated in the terminal)
+
+### Run end-to-end tests
+
+1. Make sure Daedalus is properly installed (see above).
+2. Build and run the backend (Cardano SL) following the instructions from [Daedalus](https://github.com/input-output-hk/daedalus/blob/master/README.md#development---with-cardano-wallet) README file.
+3. Run Daedalus frontend tests:
+
+```bash
+$ cd daedalus/
+$ yarn nix:dev XXX # XXX = cardano system startup time
+$ yarn build
+$ yarn test:e2e
+```
+
+### Run all tests
+
+```bash
+$ yarn test
+```
+
+Once tests are complete you will get a summary of passed/failed tests in the Terminal window.
+
+### Keeping Daedalus alive after end-to-end tests
+
+While working on the tests it's often useful to keep Daedalus alive after the tests have run
+(e.g: to inspect the app state). You can pass a special environment var to tell the test script
+not to close the app:
+
+````bash
+$ KEEP_APP_AFTER_TESTS=true yarn test:e2e
+````
\ No newline at end of file
diff --git a/features/receive-money.feature b/tests/addresses/e2e/features/receive-money.feature
similarity index 100%
rename from features/receive-money.feature
rename to tests/addresses/e2e/features/receive-money.feature
diff --git a/features/wallet-address-generate.feature b/tests/addresses/e2e/features/wallet-address-generate.feature
similarity index 100%
rename from features/wallet-address-generate.feature
rename to tests/addresses/e2e/features/wallet-address-generate.feature
diff --git a/features/tests/e2e/steps/receive-steps.js b/tests/addresses/e2e/steps/addresses.js
similarity index 58%
rename from features/tests/e2e/steps/receive-steps.js
rename to tests/addresses/e2e/steps/addresses.js
index 51d1c15f9c..1b28dd45ea 100644
--- a/features/tests/e2e/steps/receive-steps.js
+++ b/tests/addresses/e2e/steps/addresses.js
@@ -1,21 +1,32 @@
-import { Given, When, Then } from 'cucumber';
+// @flow
+import { Given, Then, When } from 'cucumber';
import { expect } from 'chai';
import {
- waitAndClick,
getVisibleElementsCountForSelector,
-} from '../helpers/shared-helpers';
+ waitAndClick,
+} from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
+const SELECTORS = {
+ ADDRESS_ACTIVE: '.WalletReceive_hash',
+ ADDRESS_COMPONENT: '.Address_component',
+ ADDRESS_USED: '.Address_usedWalletAddress',
+ GENERATE_ADDRESS_BTN: '.generateAddressButton:not(.WalletReceive_spinning)',
+ SHOW_USED_SWITCH: '.SimpleSwitch_switch',
+};
Given('I generate {int} addresses', async function(numberOfAddresses) {
for (let i = 0; i < numberOfAddresses; i++) {
await waitAndClick(
this.client,
- '.generateAddressButton:not(.WalletReceive_spinning)'
+ SELECTORS.GENERATE_ADDRESS_BTN
);
}
});
When('I click the ShowUsed switch', async function() {
- await waitAndClick(this.client, '.SimpleSwitch_switch');
+ await waitAndClick(this.client, SELECTORS.SHOW_USED_SWITCH);
});
Then('I should see {int} used addresses', { timeout: 60000 }, async function(
@@ -23,8 +34,8 @@ Then('I should see {int} used addresses', { timeout: 60000 }, async function(
) {
const addressesFound = await getVisibleElementsCountForSelector(
this.client,
- '.Address_usedWalletAddress',
- '.Address_usedWalletAddress',
+ SELECTORS.ADDRESS_USED,
+ SELECTORS.ADDRESS_USED,
60000
);
expect(addressesFound).to.equal(numberOfAddresses);
@@ -33,7 +44,7 @@ Then('I should see {int} used addresses', { timeout: 60000 }, async function(
Then('I should see {int} addresses', async function(numberOfAddresses) {
const addressesFound = await getVisibleElementsCountForSelector(
this.client,
- '.Address_component'
+ SELECTORS.ADDRESS_COMPONENT
);
expect(addressesFound).to.equal(numberOfAddresses);
});
@@ -42,12 +53,14 @@ Then('I should see the following addresses:', async function(table) {
const expectedAdresses = table.hashes();
let addresses;
await this.client.waitUntil(async () => {
- addresses = await this.client.getAttribute('.Address_component', 'class');
+ addresses = await this.client.getAttribute(SELECTORS.ADDRESS_COMPONENT, 'class');
return addresses.length === expectedAdresses.length;
});
- addresses.forEach((address, index) =>
- expect(address).to.include(expectedAdresses[index].ClassName)
- );
+ if (addresses) {
+ addresses.forEach((address, index) =>
+ expect(address).to.include(expectedAdresses[index].ClassName)
+ );
+ }
});
Then('The active address should be the newest one', async function() {
@@ -56,6 +69,6 @@ Then('The active address should be the newest one', async function() {
} = await this.client.execute(
() => daedalus.stores.addresses.lastGeneratedAddress
);
- const activeAddress = await this.client.getText('.WalletReceive_hash');
+ const activeAddress = await this.client.getText(SELECTORS.ADDRESS_ACTIVE);
expect(lastGeneratedAddress).to.equal(activeAddress);
});
diff --git a/tests/common/e2e/steps/helpers.js b/tests/common/e2e/steps/helpers.js
new file mode 100644
index 0000000000..4e7afd06ff
--- /dev/null
+++ b/tests/common/e2e/steps/helpers.js
@@ -0,0 +1,100 @@
+// @flow
+import fs from 'fs';
+import path from 'path';
+import { expect } from 'chai';
+import { generateFileNameWithTimestamp } from '../../../../source/common/utils/files';
+import ensureDirectoryExists from '../../../../source/main/utils/ensureDirectoryExists';
+import type { WebdriverClient } from '../../../types';
+
+export const expectTextInSelector = async (
+ client: WebdriverClient,
+ { selector, text }: { selector: string, text: string }
+) => {
+ await client.waitForText(selector);
+ let textOnScreen = await client.getText(selector);
+ // The selector could exist multiple times in the DOM
+ if (typeof textOnScreen === 'string') textOnScreen = [textOnScreen];
+ // We only compare the first result
+ expect(textOnScreen[0]).to.equal(text);
+};
+
+export const generateScreenshotFilePath = (prefix: string) => {
+ const prefixParts = prefix.split('/');
+ const testName = prefixParts.pop();
+ const testPath = prefixParts.slice(1).join('/');
+ const filePath = path.resolve(__dirname, '../../../screenshots/', testPath);
+ const extension = 'png';
+ const fileName = generateFileNameWithTimestamp({ prefix: testName, extension });
+ ensureDirectoryExists(filePath);
+ return `${filePath}/${fileName}`;
+};
+
+export const getTestNameFromTestFile = (testFile: string) => testFile.split('.feature').join('');
+
+export const getVisibleElementsCountForSelector = async (
+ client: WebdriverClient,
+ selectSelector: string,
+ waitSelector: string = selectSelector,
+ ...waitArgs: Array<*>
+) => {
+ const elements = await getVisibleElementsForSelector(
+ client,
+ selectSelector,
+ waitSelector,
+ ...waitArgs
+ );
+ return elements.value ? elements.value.length : 0;
+};
+
+export const getVisibleElementsForSelector = async (
+ client: WebdriverClient,
+ selectSelector: string,
+ waitSelector: string = selectSelector,
+ ...waitArgs: Array<*>
+) => {
+ await client.waitForVisible(waitSelector, ...waitArgs);
+ return client.elements(selectSelector);
+};
+
+export const getVisibleTextsForSelector = async (
+ client: WebdriverClient,
+ selector: string
+): Promise> => {
+ await client.waitForVisible(selector);
+ const texts = await client.getText(selector);
+ return [].concat(texts);
+};
+
+export const saveScreenshot = async (
+ context: Object,
+ file: any
+) => await context.browserWindow
+ .capturePage()
+ .then(imageBuffer => fs.writeFile(file, imageBuffer))
+ .catch(err => {
+ // eslint-disable-next-line no-console
+ console.log(err);
+ });
+
+export const waitAndClick = async (
+ client: WebdriverClient,
+ selector: string,
+ ...waitArgs: Array<*>
+) => {
+ await client.waitForVisible(selector, ...waitArgs);
+ await client.waitForEnabled(selector, ...waitArgs);
+ return client.click(selector);
+};
+
+export const waitUntilTextInSelector = async (
+ client: WebdriverClient,
+ { selector, text }: { selector: string, text: string }
+) =>
+ client.waitUntil(async () => {
+ await client.waitForText(selector);
+ let textOnScreen = await client.getText(selector);
+ // The selector could exist multiple times in the DOM
+ if (typeof textOnScreen === 'string') textOnScreen = [textOnScreen];
+ // We only compare the first result
+ return textOnScreen[0] === text;
+ });
diff --git a/features/navigate-general-settings-menu.feature b/tests/navigation/e2e/features/navigate-general-settings-menu.feature
similarity index 100%
rename from features/navigate-general-settings-menu.feature
rename to tests/navigation/e2e/features/navigate-general-settings-menu.feature
diff --git a/features/navigate-sidebar-categories.feature b/tests/navigation/e2e/features/navigate-sidebar-categories.feature
similarity index 100%
rename from features/navigate-sidebar-categories.feature
rename to tests/navigation/e2e/features/navigate-sidebar-categories.feature
diff --git a/features/navigate-wallet-tabs.feature b/tests/navigation/e2e/features/navigate-wallet-tabs.feature
similarity index 100%
rename from features/navigate-wallet-tabs.feature
rename to tests/navigation/e2e/features/navigate-wallet-tabs.feature
diff --git a/features/switching-between-wallets.feature b/tests/navigation/e2e/features/switching-between-wallets.feature
similarity index 100%
rename from features/switching-between-wallets.feature
rename to tests/navigation/e2e/features/switching-between-wallets.feature
diff --git a/features/toggle-sidebar-submenus.feature b/tests/navigation/e2e/features/toggle-sidebar-submenus.feature
similarity index 100%
rename from features/toggle-sidebar-submenus.feature
rename to tests/navigation/e2e/features/toggle-sidebar-submenus.feature
diff --git a/tests/navigation/e2e/steps/general-settings.js b/tests/navigation/e2e/steps/general-settings.js
new file mode 100644
index 0000000000..e7de37b64f
--- /dev/null
+++ b/tests/navigation/e2e/steps/general-settings.js
@@ -0,0 +1,15 @@
+// @flow
+import { Given, Then } from 'cucumber';
+import { navigateTo, waitUntilUrlEquals } from './helpers';
+
+Given(/^I am on the General Settings "([^"]*)" screen$/, async function(
+ screen
+) {
+ await navigateTo.call(this, `/settings/${screen}`);
+});
+
+Then(/^I should see General Settings "([^"]*)" screen$/, async function(
+ screenName
+) {
+ return waitUntilUrlEquals.call(this, `/settings/${screenName}`);
+});
\ No newline at end of file
diff --git a/tests/navigation/e2e/steps/helpers.js b/tests/navigation/e2e/steps/helpers.js
new file mode 100644
index 0000000000..bd9861f95f
--- /dev/null
+++ b/tests/navigation/e2e/steps/helpers.js
@@ -0,0 +1,45 @@
+// @flow
+import { waitAndClick } from '../../../common/e2e/steps/helpers';
+import type { Daedalus, WebdriverClient } from '../../../types';
+
+declare var daedalus: Daedalus;
+const SELECTORS = {
+ ACTIVE_CATEGORY: '.SidebarCategory_active',
+ ADD_WALLET_BTN: '.SidebarWalletsMenu_addWalletButton',
+};
+
+export const getCurrentAppRoute = async function() {
+ const url = (await this.client.url()).value;
+ return url.substring(url.indexOf('#/') + 1); // return without the hash
+};
+
+export const waitUntilUrlEquals = function(expectedUrl: string) {
+ const context = this;
+ return context.client.waitUntil(async () => {
+ const url = await getCurrentAppRoute.call(context);
+ return url === expectedUrl;
+ });
+};
+
+export const navigateTo = function(requestedRoute: string) {
+ return this.client.execute(route => {
+ daedalus.actions.router.goToRoute.trigger({ route });
+ }, requestedRoute);
+};
+
+export const sidebarHelpers = {
+ activateCategory: async (
+ client: WebdriverClient,
+ { category }: { category: string }
+ ) => {
+ await client.execute(cat => {
+ daedalus.actions.sidebar.activateSidebarCategory.trigger({
+ category: cat,
+ showSubMenu: true,
+ });
+ }, `/${category}`);
+ return client.waitForVisible(`${SELECTORS.ACTIVE_CATEGORY}.${category}`);
+ },
+ clickAddWalletButton: (client: WebdriverClient) =>
+ waitAndClick(client, SELECTORS.ADD_WALLET_BTN),
+};
\ No newline at end of file
diff --git a/features/tests/e2e/steps/sidebar-steps.js b/tests/navigation/e2e/steps/sidebar.js
similarity index 54%
rename from features/tests/e2e/steps/sidebar-steps.js
rename to tests/navigation/e2e/steps/sidebar.js
index 82f3ad22fd..177fe8c21b 100644
--- a/features/tests/e2e/steps/sidebar-steps.js
+++ b/tests/navigation/e2e/steps/sidebar.js
@@ -1,10 +1,24 @@
+// @flow
import { Given, When, Then } from 'cucumber';
-import sidebar from '../helpers/sidebar-helpers';
+import { sidebarHelpers } from './helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
+const SELECTORS = {
+ CATEGORY_ACTIVE: '.SidebarCategory_active',
+ CATEGORY_COMPONENT: '.SidebarCategory_component',
+ LAYOUT_COMPONENT: '.SidebarLayout_component',
+ MENU_COMPONENT: '.SidebarMenu_component',
+ MENU_VISIBLE: '.SidebarMenu_visible',
+ SIDEBAR_COMPONENT: '.Sidebar_component',
+ TOP_BAR: '.SidebarLayout_topbar',
+ TOP_BAR_LEFT_ICON: '.TopBar_leftIcon',
+};
Given(/^the sidebar submenu is (hidden|visible)/, async function(state) {
const isVisible = state === 'visible';
- await this.client.waitForVisible('.Sidebar_component');
- await this.client.executeAsync((visible, done) => {
+ await this.client.waitForVisible(SELECTORS.SIDEBAR_COMPONENT);
+ await this.client.executeAsync((visible, SELECTORS, done) => {
const { isShowingSubMenus } = daedalus.stores.sidebar;
let sidebarWillAnimate = false;
if (isShowingSubMenus !== visible) {
@@ -13,7 +27,7 @@ Given(/^the sidebar submenu is (hidden|visible)/, async function(state) {
}
if (sidebarWillAnimate) {
// Wait until the sidebar transition is finished -> otherwise webdriver click error!
- const sidebarElement = document.querySelectorAll('.Sidebar_component')[0];
+ const sidebarElement = document.querySelectorAll(SELECTORS.SIDEBAR_COMPONENT)[0];
const onTransitionFinished = () => {
sidebarElement.removeEventListener(
'transitioned',
@@ -25,24 +39,24 @@ Given(/^the sidebar submenu is (hidden|visible)/, async function(state) {
} else {
done();
}
- }, isVisible);
- return this.client.waitForExist('.SidebarMenu_visible', null, !isVisible);
+ }, isVisible, SELECTORS);
+ return this.client.waitForExist(SELECTORS.MENU_VISIBLE, null, !isVisible);
});
Given(/^The sidebar shows the "([^"]*)" category$/, function(category) {
- return sidebar.activateCategory(this.client, { category });
+ return sidebarHelpers.activateCategory(this.client, { category });
});
When(/^I click on the sidebar toggle button$/, function() {
- return this.waitAndClick('.SidebarLayout_topbar .TopBar_leftIcon');
+ return this.waitAndClick(`${SELECTORS.TOP_BAR} ${SELECTORS.TOP_BAR_LEFT_ICON}`);
});
When(/^I click on the "([^"]*)" category in the sidebar$/, function(category) {
- return this.waitAndClick(`.SidebarCategory_component.${category}`);
+ return this.waitAndClick(`${SELECTORS.CATEGORY_COMPONENT}.${category}`);
});
When(/^I click on the add wallet button in the sidebar$/, function() {
- return sidebar.clickAddWalletButton(this.client);
+ return sidebarHelpers.clickAddWalletButton(this.client);
});
When(/^I click on the "([^"]*)" wallet in the sidebar$/, function(walletName) {
@@ -54,12 +68,16 @@ When(/^I click on the "([^"]*)" wallet in the sidebar$/, function(walletName) {
Then(/^the sidebar submenu should be (hidden|visible)/, function(state) {
const waitForHidden = state === 'hidden';
return this.client.waitForVisible(
- '.SidebarMenu_component',
+ SELECTORS.MENU_COMPONENT,
null,
waitForHidden
);
});
Then(/^The "([^"]*)" category should be active$/, function(category) {
- return this.client.waitForVisible(`.SidebarCategory_active.${category}`);
+ return this.client.waitForVisible(`${SELECTORS.CATEGORY_ACTIVE}.${category}`);
+});
+
+Then(/^I should see the initial screen$/, function() {
+ return this.client.waitForVisible(SELECTORS.LAYOUT_COMPONENT);
});
diff --git a/features/tests/e2e/documents/dummy-news.json b/tests/news/e2e/documents/dummy-news.json
similarity index 100%
rename from features/tests/e2e/documents/dummy-news.json
rename to tests/news/e2e/documents/dummy-news.json
diff --git a/features/newsfeed.feature b/tests/news/e2e/features/newsfeed.feature
similarity index 100%
rename from features/newsfeed.feature
rename to tests/news/e2e/features/newsfeed.feature
diff --git a/features/tests/e2e/steps/newsfeed-steps.js b/tests/news/e2e/steps/newsfeed-steps.js
similarity index 95%
rename from features/tests/e2e/steps/newsfeed-steps.js
rename to tests/news/e2e/steps/newsfeed-steps.js
index 6385d25d58..eda98ba111 100644
--- a/features/tests/e2e/steps/newsfeed-steps.js
+++ b/tests/news/e2e/steps/newsfeed-steps.js
@@ -7,7 +7,7 @@ import newsDummyJson from '../documents/dummy-news.json';
import {
expectTextInSelector,
getVisibleElementsCountForSelector,
-} from '../helpers/shared-helpers';
+} from '../../../common/e2e/steps/helpers';
async function prepareFakeNews(context, fakeNews, preparation, ...args) {
// Run custom preparation logic
@@ -64,7 +64,8 @@ async function prepareNewsOfType(
);
}
-function setNewsFeedIsOpen(client, flag) {
+// Set newsfeed to open before each newsfeed step
+export function setNewsFeedIsOpen(client, flag) {
return client.execute(desiredState => {
if (daedalus.stores.app.newsFeedIsOpen !== desiredState) {
daedalus.actions.app.toggleNewsFeed.trigger();
@@ -72,8 +73,8 @@ function setNewsFeedIsOpen(client, flag) {
}, flag);
}
-// Reset the fake news
-function resetTestNews(client) {
+// Reset the fake news before each newsfeed step
+export function resetTestNews(client) {
return client.executeAsync(done => {
daedalus.api.ada.setFakeNewsFeedJsonForTesting({
updatedAt: Date.now(),
@@ -83,13 +84,6 @@ function resetTestNews(client) {
});
}
-// SCENARIO HOOKS
-
-Before({ tags: '@newsfeed' }, async function() {
- setNewsFeedIsOpen(this.client, false);
- resetTestNews(this.client);
-});
-
// GIVEN STEPS
Given(/^there (?:are|is)\s?(\d+)? (read|unread) (\w+?)s?$/, async function(
@@ -142,6 +136,8 @@ Given('the latest alert will cover the screen', async function() {
});
});
+// WHEN STEPS
+
When('I click on the newsfeed icon', async function() {
await this.waitAndClick('.NewsFeedIcon_component');
});
@@ -164,6 +160,8 @@ When('I click on the alert in the newsfeed', async function() {
await this.waitAndClick('.NewsItem_alert.NewsItem_isRead');
});
+// THEN STEPS
+
Then('i should see the newsfeed icon', async function() {
await this.client.waitForVisible('.NewsFeedIcon_component');
});
diff --git a/features/about-dialog.feature b/tests/nodes/e2e/features/about-dialog.feature
similarity index 100%
rename from features/about-dialog.feature
rename to tests/nodes/e2e/features/about-dialog.feature
diff --git a/features/app-version-difference.feature b/tests/nodes/e2e/features/app-version-difference.feature
similarity index 100%
rename from features/app-version-difference.feature
rename to tests/nodes/e2e/features/app-version-difference.feature
diff --git a/features/block-consolidation-page.feature b/tests/nodes/e2e/features/block-consolidation-page.feature
similarity index 100%
rename from features/block-consolidation-page.feature
rename to tests/nodes/e2e/features/block-consolidation-page.feature
diff --git a/features/data-layer-migration.feature b/tests/nodes/e2e/features/data-layer-migration.feature
similarity index 100%
rename from features/data-layer-migration.feature
rename to tests/nodes/e2e/features/data-layer-migration.feature
diff --git a/features/local-time-difference.feature b/tests/nodes/e2e/features/local-time-difference.feature
similarity index 100%
rename from features/local-time-difference.feature
rename to tests/nodes/e2e/features/local-time-difference.feature
diff --git a/features/no-disk-space.feature b/tests/nodes/e2e/features/no-disk-space.feature
similarity index 100%
rename from features/no-disk-space.feature
rename to tests/nodes/e2e/features/no-disk-space.feature
diff --git a/features/node-update-exit.feature b/tests/nodes/e2e/features/node-update-exit.feature
similarity index 100%
rename from features/node-update-exit.feature
rename to tests/nodes/e2e/features/node-update-exit.feature
diff --git a/features/node-update-notification.feature b/tests/nodes/e2e/features/node-update-notification.feature
similarity index 100%
rename from features/node-update-notification.feature
rename to tests/nodes/e2e/features/node-update-notification.feature
diff --git a/features/quit-app.feature b/tests/nodes/e2e/features/quit-app.feature
similarity index 100%
rename from features/quit-app.feature
rename to tests/nodes/e2e/features/quit-app.feature
diff --git a/features/trouble-connecting-notification.feature b/tests/nodes/e2e/features/trouble-connecting-notification.feature
similarity index 100%
rename from features/trouble-connecting-notification.feature
rename to tests/nodes/e2e/features/trouble-connecting-notification.feature
diff --git a/features/trouble-syncing-notification.feature b/tests/nodes/e2e/features/trouble-syncing-notification.feature
similarity index 100%
rename from features/trouble-syncing-notification.feature
rename to tests/nodes/e2e/features/trouble-syncing-notification.feature
diff --git a/features/wallet-settings-recovery-phrase-verification.feature b/tests/nodes/e2e/features/wallet-settings-recovery-phrase-verification.feature
similarity index 99%
rename from features/wallet-settings-recovery-phrase-verification.feature
rename to tests/nodes/e2e/features/wallet-settings-recovery-phrase-verification.feature
index e327ad01bf..d46f309074 100644
--- a/features/wallet-settings-recovery-phrase-verification.feature
+++ b/tests/nodes/e2e/features/wallet-settings-recovery-phrase-verification.feature
@@ -1,4 +1,4 @@
-@e2e @watch
+@e2e
Feature: Wallet Settings - Recovery Phrase Verification
Background:
diff --git a/features/tests/e2e/steps/about-dialog.js b/tests/nodes/e2e/steps/about-dialog.js
similarity index 68%
rename from features/tests/e2e/steps/about-dialog.js
rename to tests/nodes/e2e/steps/about-dialog.js
index a356577a5c..2c5d8097fc 100644
--- a/features/tests/e2e/steps/about-dialog.js
+++ b/tests/nodes/e2e/steps/about-dialog.js
@@ -1,6 +1,14 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
import packageJson from '../../../../package.json';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
+const SELECTORS = {
+ CONTAINER: '.About_container',
+ VERSION: '.About_daedalusVersion',
+};
Given(/^I open the About dialog$/, async function() {
this.client.execute(() => daedalus.actions.app.openAboutDialog.trigger());
@@ -12,14 +20,14 @@ When(/^I close the About dialog$/, function() {
Then(/^the About dialog is (hidden|visible)/, async function(state) {
const isVisible = state === 'visible';
- return this.client.waitForVisible('.About_container', null, !isVisible);
+ return this.client.waitForVisible(SELECTORS.CONTAINER, null, !isVisible);
});
Then(
/^the About dialog and package.json show the same Daedalus version/,
async function() {
const { version: packageJsonVersion } = packageJson;
- const aboutVersion = await this.client.getText('.About_daedalusVersion');
+ const aboutVersion = await this.client.getText(SELECTORS.VERSION);
expect(aboutVersion).to.equal(packageJsonVersion);
}
);
diff --git a/features/tests/e2e/steps/app-version-difference.js b/tests/nodes/e2e/steps/app-version-difference.js
similarity index 61%
rename from features/tests/e2e/steps/app-version-difference.js
rename to tests/nodes/e2e/steps/app-version-difference.js
index 2c7e789bbb..c9567fc35e 100644
--- a/features/tests/e2e/steps/app-version-difference.js
+++ b/tests/nodes/e2e/steps/app-version-difference.js
@@ -1,21 +1,25 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
import { environment } from '../../../../source/main/environment';
-import { getVisibleTextsForSelector } from '../helpers/shared-helpers';
-import i18n from '../helpers/i18n-helpers';
-
-const SELECTORS = {
- MANUAL_UPDATE_VERSION_INFO:
- '.ManualUpdate_content .ManualUpdate_description p:nth-child(2)',
-};
+import { getVisibleTextsForSelector } from '../../../common/e2e/steps/helpers';
+import { i18nHelpers } from '../../../settings/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+declare var daedalus: Daedalus;
const currentAppVersion = environment.version;
const currentAppVersionChunks = currentAppVersion.split('.');
+const { formatMessage } = i18nHelpers;
const nextAppVersion = [
currentAppVersionChunks[0],
parseInt(currentAppVersionChunks[1], 10) + 1,
currentAppVersionChunks[2],
].join('.');
+const SELECTORS = {
+ DESCRIPTION: 'manualUpdate.description2',
+ OVERLAY: '.ManualUpdate_content',
+ VERSION_INFO: '.ManualUpdate_content .ManualUpdate_description p:nth-child(2)',
+};
Given(/^There is a newer application version available$/, async function() {
await this.client.execute(version => {
@@ -28,7 +32,7 @@ When(/^Daedalus is stuck in connecting state$/, async function() {
});
Then(/^I should see the "Manual Update" overlay$/, function() {
- return this.client.waitForVisible('.ManualUpdate_content');
+ return this.client.waitForVisible(SELECTORS.OVERLAY);
});
Then(
@@ -36,11 +40,11 @@ Then(
async function() {
const [renderedText] = await getVisibleTextsForSelector(
this.client,
- SELECTORS.MANUAL_UPDATE_VERSION_INFO
+ SELECTORS.VERSION_INFO
);
- let expectedText = await i18n.formatMessage(this.client, {
- id: 'manualUpdate.description2',
+ let expectedText = await formatMessage(this.client, {
+ id: SELECTORS.DESCRIPTION,
values: {
currentAppVersion,
availableAppVersion: nextAppVersion,
@@ -52,3 +56,14 @@ Then(
expect(renderedText).to.equal(expectedText);
}
);
+
+When(/^I trigger the apply-update endpoint$/, async function() {
+ await this.client.executeAsync(done => {
+ daedalus.api.ada
+ .applyUpdate()
+ .then(done)
+ .catch(e => {
+ throw e;
+ });
+ });
+});
diff --git a/features/tests/e2e/steps/block-consolidation-page-steps.js b/tests/nodes/e2e/steps/block-consolidation-page.js
similarity index 91%
rename from features/tests/e2e/steps/block-consolidation-page-steps.js
rename to tests/nodes/e2e/steps/block-consolidation-page.js
index 7807b861aa..a2a9fa2823 100644
--- a/features/tests/e2e/steps/block-consolidation-page-steps.js
+++ b/tests/nodes/e2e/steps/block-consolidation-page.js
@@ -1,21 +1,23 @@
+// @flow
import { When, Then } from 'cucumber';
import { expect } from 'chai';
-import { getVisibleTextsForSelector } from '../helpers/shared-helpers';
-import i18n from '../helpers/i18n-helpers';
+import { getVisibleTextsForSelector } from '../../../common/e2e/steps/helpers';
+import { i18nHelpers } from '../../../settings/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const SELECTORS = {
BLOCK_CONSOLIDATION_COMPONENT: '.BlockConsolidationStatus_component',
- BLOCK_CONSOLIDATION_EXPLANATION:
- '.BlockConsolidationStatus_content p:nth-child(3)',
+ BLOCK_CONSOLIDATION_EXPLANATION: '.BlockConsolidationStatus_content p:nth-child(3)',
+ EPOCHS_CONSOLIDATED: '.BlockConsolidationStatus_indicatorEpochsConsolidated p',
EPOCHS_CONSOLIDATION_STATUS: '.BlockConsolidationStatus_epochs p span b',
- EPOCHS_CONSOLIDATED:
- '.BlockConsolidationStatus_indicatorEpochsConsolidated p',
- TRAILING_BY_2_EPOCH: '.BlockConsolidationStatus_indicatorEpochsBehind p',
MAXIMUM_EPOCH: '.BlockConsolidationStatus_fullEpoch',
SYNC_PROGRESS: '.BlockConsolidationStatus_indicatorEpochsSynced p span',
- SYNC_PROGRESS_LOADING_STATE:
- '.BlockConsolidationStatus_indicatorContainerNoCurrentEpochs',
+ SYNC_PROGRESS_LOADING_STATE: '.BlockConsolidationStatus_indicatorContainerNoCurrentEpochs',
+ TRAILING_BY_2_EPOCH: '.BlockConsolidationStatus_indicatorEpochsBehind p',
};
+const { formatMessage } = i18nHelpers;
When(/^I open the Block Consolidation Status Dialog$/, async function() {
await this.client.execute(() =>
@@ -66,7 +68,7 @@ Then(
currentEpochBehind = `(${Math.max(currentEpochValue - 1, 0)})`;
}
- let expectedText = await i18n.formatMessage(this.client, {
+ let expectedText = await formatMessage(this.client, {
id: consolidationText.message,
values: {
currentEpoch,
@@ -195,7 +197,7 @@ Then(
.catch(error => done(error));
});
const [expectedTextData] = data.hashes();
- const expectedText = await i18n.formatMessage(this.client, {
+ const expectedText = await formatMessage(this.client, {
id: expectedTextData.message,
values: { epochsSynced },
});
diff --git a/features/tests/e2e/steps/cardano-steps.js b/tests/nodes/e2e/steps/cardano-node.js
similarity index 82%
rename from features/tests/e2e/steps/cardano-steps.js
rename to tests/nodes/e2e/steps/cardano-node.js
index 496ba03065..376f811eae 100644
--- a/features/tests/e2e/steps/cardano-steps.js
+++ b/tests/nodes/e2e/steps/cardano-node.js
@@ -1,10 +1,7 @@
// @flow
import { Given, Then } from 'cucumber';
import { CardanoNodeStates } from '../../../../source/common/types/cardano-node.types';
-import {
- getCardanoNodeState,
- waitForCardanoNodeToExit,
-} from '../helpers/cardano-node-helpers';
+import { getCardanoNodeState, waitForCardanoNodeToExit } from './helpers';
Given(/^cardano-node is running$/, async function() {
await this.client.waitUntil(
diff --git a/features/tests/e2e/steps/app-steps.js b/tests/nodes/e2e/steps/daedalus-process.js
similarity index 83%
rename from features/tests/e2e/steps/app-steps.js
rename to tests/nodes/e2e/steps/daedalus-process.js
index 8015c1246d..808925846e 100644
--- a/features/tests/e2e/steps/app-steps.js
+++ b/tests/nodes/e2e/steps/daedalus-process.js
@@ -1,12 +1,12 @@
// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
-import type { Daedalus } from '../setup/global-types';
-import { waitUntilTextInSelector } from '../helpers/shared-helpers';
-import { waitForCardanoNodeToExit } from '../helpers/cardano-node-helpers';
-import { refreshClient, waitForDaedalusToExit } from '../helpers/app-helpers';
+import { waitUntilTextInSelector } from '../../../common/e2e/steps/helpers';
+import { refreshClient, waitForCardanoNodeToExit, waitForDaedalusToExit } from './helpers';
+import type { Daedalus } from '../../../types';
declare var daedalus: Daedalus;
+const CONNECTING_TITLE = '.SyncingConnectingTitle_connecting h1';
Given(/^Daedalus is running$/, function() {
expect(this.app.isRunning()).to.equal(true);
@@ -53,7 +53,7 @@ Then(/^I should see the loading screen with "([^"]*)"$/, async function(
message
) {
await waitUntilTextInSelector(this.client, {
- selector: '.SyncingConnectingTitle_connecting h1',
+ selector: CONNECTING_TITLE,
text: message,
});
});
diff --git a/features/tests/e2e/steps/data-layer-migration.js b/tests/nodes/e2e/steps/data-layer-migration.js
similarity index 60%
rename from features/tests/e2e/steps/data-layer-migration.js
rename to tests/nodes/e2e/steps/data-layer-migration.js
index 82b1f487f8..65a4376eb7 100644
--- a/features/tests/e2e/steps/data-layer-migration.js
+++ b/tests/nodes/e2e/steps/data-layer-migration.js
@@ -1,7 +1,13 @@
+// @flow
import { Given, When, Then } from 'cucumber';
+import type { Daedalus } from '../../../types';
-const DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT =
- '.DataLayerMigrationForm_component';
+declare var daedalus: Daedalus;
+
+const SELECTORS = {
+ COMPONENT: '.DataLayerMigrationForm_component',
+ SUBMIT_BTN: '.DataLayerMigrationForm_submitButton',
+};
Given(/^I haven't accepted the data layer migration$/, async function() {
await this.client.execute(() => {
@@ -10,12 +16,12 @@ Given(/^I haven't accepted the data layer migration$/, async function() {
});
Then(/^I should see the Data Layer Migration screen$/, function() {
- return this.client.waitForVisible(DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT);
+ return this.client.waitForVisible(SELECTORS.COMPONENT);
});
Then(/^I should not see the Data Layer Migration screen$/, function() {
return this.client.waitForVisible(
- DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT,
+ SELECTORS.COMPONENT,
null,
true
);
@@ -23,6 +29,6 @@ Then(/^I should not see the Data Layer Migration screen$/, function() {
When(/^I click the migration button$/, function() {
return this.waitAndClick(
- `${DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT} .DataLayerMigrationForm_submitButton`
+ `${SELECTORS.COMPONENT} ${SELECTORS.SUBMIT_BTN}`
);
});
diff --git a/tests/nodes/e2e/steps/helpers.js b/tests/nodes/e2e/steps/helpers.js
new file mode 100644
index 0000000000..cb204b9b12
--- /dev/null
+++ b/tests/nodes/e2e/steps/helpers.js
@@ -0,0 +1,42 @@
+// @flow
+import { getProcessesByName } from '../../../../source/main/utils/processes';
+import type { Daedalus, WebdriverClient } from '../../../types';
+
+declare var daedalus: Daedalus;
+
+const ACTIVE_RESTORE_NOTIFICATION = '.ActiveRestoreNotification';
+
+export const getCardanoNodeState = async (client: WebdriverClient) =>
+ (await client.execute(() => daedalus.stores.networkStatus.cardanoNodeState)).value;
+
+export const refreshClient = async (client: WebdriverClient) => {
+ await client.url(`file://${__dirname}/../../../../dist/renderer/index.html`);
+};
+
+export const waitForActiveRestoreNotification = (
+ client: WebdriverClient,
+ { isHidden } : { isHidden: boolean } = {}
+) =>
+ client.waitForVisible(
+ ACTIVE_RESTORE_NOTIFICATION,
+ null,
+ isHidden
+ );
+
+export const waitForCardanoNodeToExit = async (client: WebdriverClient) =>
+ client.waitUntil(
+ async () => (await getProcessesByName('cardano-node')).length === 0,
+ 61000
+ );
+
+export const waitForDaedalusToExit = async (
+ client: WebdriverClient,
+ timeout: number = 61000
+) => {
+ const daedalusProcessName =
+ process.platform === 'linux' ? 'electron' : 'Electron';
+ return client.waitUntil(
+ async () => (await getProcessesByName(daedalusProcessName)).length === 0,
+ timeout
+ );
+};
diff --git a/tests/nodes/e2e/steps/inject-fault.js b/tests/nodes/e2e/steps/inject-fault.js
new file mode 100644
index 0000000000..9029269e56
--- /dev/null
+++ b/tests/nodes/e2e/steps/inject-fault.js
@@ -0,0 +1,16 @@
+// @flow
+import { When } from 'cucumber';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
+
+When(/^I inject fault named "([^"]*)"$/, async function(faultName) {
+ await this.client.executeAsync((name, done) => {
+ daedalus.api.ada
+ .setCardanoNodeFault([name, true])
+ .then(done)
+ .catch(e => {
+ throw e;
+ });
+ }, faultName);
+});
\ No newline at end of file
diff --git a/features/tests/e2e/steps/local-time-difference-steps.js b/tests/nodes/e2e/steps/local-time-difference.js
similarity index 71%
rename from features/tests/e2e/steps/local-time-difference-steps.js
rename to tests/nodes/e2e/steps/local-time-difference.js
index 344be30a33..325c95e6e1 100644
--- a/features/tests/e2e/steps/local-time-difference-steps.js
+++ b/tests/nodes/e2e/steps/local-time-difference.js
@@ -1,7 +1,13 @@
+// @flow
import { Given, Then } from 'cucumber';
-import { expectTextInSelector } from '../helpers/shared-helpers';
+import { expectTextInSelector } from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
-const selector = '.time-off';
+declare var daedalus: Daedalus;
+const SELECTORS = {
+ ERROR_COMPONENT: '.SystemTimeError_component',
+ TIME_OFF: '.time-off',
+};
Given('I set the local time difference to be {int} seconds', async function(
seconds
@@ -21,12 +27,13 @@ Then(/^the system time error overlay should be (hidden|visible)$/, function(
) {
const isVisible = state === 'visible';
return this.client.waitForVisible(
- '.SystemTimeError_component',
+ SELECTORS.ERROR_COMPONENT,
null,
!isVisible
);
});
Then('the system time difference should be {string}', async function(text) {
+ let selector = SELECTORS.TIME_OFF;
await expectTextInSelector(this.client, { selector, text });
});
diff --git a/features/tests/e2e/steps/no-disk-space.js b/tests/nodes/e2e/steps/no-disk-space.js
similarity index 90%
rename from features/tests/e2e/steps/no-disk-space.js
rename to tests/nodes/e2e/steps/no-disk-space.js
index 9d6d4ab5f2..59549e0c92 100644
--- a/features/tests/e2e/steps/no-disk-space.js
+++ b/tests/nodes/e2e/steps/no-disk-space.js
@@ -1,9 +1,12 @@
+// @flow
import { Given, When, Then } from 'cucumber';
+import type { Daedalus } from '../../../types';
+declare var daedalus: Daedalus;
let diskSpaceRequired;
const HUNDRED_TB = 100 * 1e12; // 100 TB | unit: bytes
-const ONE_KB = 1 * 1000; // 1 KB | unit: bytes
const NO_DISK_SPACE_COMPONENT = '.NoDiskSpaceError_component';
+const ONE_KB = 1 * 1000; // 1 KB | unit: bytes
Given(/^I set the required space to 100 TB$/, () => {
diskSpaceRequired = HUNDRED_TB;
diff --git a/features/tests/e2e/steps/node-update-notification-steps.js b/tests/nodes/e2e/steps/node-update-notification.js
similarity index 58%
rename from features/tests/e2e/steps/node-update-notification-steps.js
rename to tests/nodes/e2e/steps/node-update-notification.js
index 45fb725191..718b9bd1c8 100644
--- a/features/tests/e2e/steps/node-update-notification-steps.js
+++ b/tests/nodes/e2e/steps/node-update-notification.js
@@ -1,7 +1,10 @@
import { When, Then } from 'cucumber';
import { expect } from 'chai';
import { environment } from '../../../../source/main/environment';
-import { getVisibleTextsForSelector } from '../helpers/shared-helpers';
+import { getVisibleTextsForSelector } from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const currentAppVersion = environment.version;
@@ -10,10 +13,25 @@ const SELECTORS = {
'.AutomaticUpdateNotification_description p span b:nth-child(1)',
newAppVersionInfo:
'.AutomaticUpdateNotification_description p span b:nth-child(2)',
+ acceptButton: '.AutomaticUpdateNotification_acceptButton',
+ postponeButton: '.AutomaticUpdateNotification_postponeButton',
+ nodeUpdateOverlay: '.AutomaticUpdateNotification_dialog',
+ nodeUpdateComponent: '.AutomaticUpdateNotification_overlay',
};
Then('I should see the node update notification overlay', async function() {
- return this.client.waitForVisible('.AutomaticUpdateNotification_dialog');
+ return this.client.waitForVisible(SELECTORS.nodeUpdateOverlay);
+});
+
+When(/^I set next update version to "([^"]*)"$/, async function(applicationVersion) {
+ await this.client.executeAsync((applicationVersion, done) => {
+ daedalus.api.ada
+ .setNextUpdate(parseInt(applicationVersion))
+ .then(done)
+ .catch(e => {
+ throw e;
+ });
+ }, applicationVersion);
});
When(
@@ -29,8 +47,8 @@ When(
);
expect(newAppVersionInfo.replace('v ', '')).to.equal(nextVersion);
expect(currentAppVersionInfo.replace('v ', '')).to.equal(currentAppVersion);
- this.client.waitForVisible('.AutomaticUpdateNotification_acceptButton');
- this.client.waitForVisible('.AutomaticUpdateNotification_postponeButton');
+ this.client.waitForVisible(SELECTORS.acceptButton);
+ this.client.waitForVisible(SELECTORS.postponeButton);
}
);
@@ -43,16 +61,16 @@ When(/^I set next application version to "([^"]*)"$/, async function(
});
When(/^I click the postpone update button$/, function() {
- return this.waitAndClick('.AutomaticUpdateNotification_postponeButton');
+ return this.waitAndClick(SELECTORS.postponeButton);
});
When(/^I click the accept update button$/, function() {
- return this.waitAndClick('.AutomaticUpdateNotification_acceptButton');
+ return this.waitAndClick(SELECTORS.acceptButton);
});
Then(/^I should not see the notification component anymore$/, function() {
return this.client.waitForVisible(
- '.AutomaticUpdateNotification_overlay',
+ SELECTORS.nodeUpdateComponent,
null,
true
);
diff --git a/features/tests/e2e/steps/trouble-connecting-notification-steps.js b/tests/nodes/e2e/steps/trouble-connecting-notification.js
similarity index 81%
rename from features/tests/e2e/steps/trouble-connecting-notification-steps.js
rename to tests/nodes/e2e/steps/trouble-connecting-notification.js
index 0b1867d48c..3faef6089a 100644
--- a/features/tests/e2e/steps/trouble-connecting-notification-steps.js
+++ b/tests/nodes/e2e/steps/trouble-connecting-notification.js
@@ -1,10 +1,14 @@
+// @flow
import { Then, When } from 'cucumber';
-import { waitUntilTextInSelector } from '../helpers/shared-helpers';
+import { waitUntilTextInSelector } from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const SELECTORS = {
+ REPORT_ISSUE_BTN: '.ReportIssue_actionButton.reportIssueButton',
+ REPORT_ISSUE_HEADER: '.ReportIssue_reportIssueText',
SYNCING_CONNECTING_COMPONENT: '.SyncingConnecting_component',
- REPORT_ISSUE_TEXT_H1: '.ReportIssue_reportIssueText',
- REPORT_ISSUE_BUTTON: '.ReportIssue_actionButton.reportIssueButton',
};
Then(/^I should not see the loading screen$/, async function() {
@@ -19,14 +23,14 @@ Then(
/^I should see the report issue notification displaying "([^"]*)"$/,
async function(text) {
await waitUntilTextInSelector(this.client, {
- selector: SELECTORS.REPORT_ISSUE_TEXT_H1,
+ selector: SELECTORS.REPORT_ISSUE_HEADER,
text,
});
}
);
Then(/^I should not see the report issue notification$/, async function() {
- await this.client.waitForVisible(SELECTORS.REPORT_ISSUE_TEXT_H1, null, true);
+ await this.client.waitForVisible(SELECTORS.REPORT_ISSUE_HEADER, null, true);
});
Then(/^The report issue button should be (hidden|visible)$/, async function(
@@ -34,7 +38,7 @@ Then(/^The report issue button should be (hidden|visible)$/, async function(
) {
const waitForHidden = state === 'hidden';
await this.client.waitForVisible(
- SELECTORS.REPORT_ISSUE_BUTTON,
+ SELECTORS.REPORT_ISSUE_BTN,
null,
waitForHidden
);
diff --git a/features/tests/e2e/steps/trouble-syncing-notification-steps.js b/tests/nodes/e2e/steps/trouble-syncing-notification.js
similarity index 66%
rename from features/tests/e2e/steps/trouble-syncing-notification-steps.js
rename to tests/nodes/e2e/steps/trouble-syncing-notification.js
index f68180537b..a6e95aad7a 100644
--- a/features/tests/e2e/steps/trouble-syncing-notification-steps.js
+++ b/tests/nodes/e2e/steps/trouble-syncing-notification.js
@@ -1,5 +1,11 @@
+// @flow
import { When, Then } from 'cucumber';
-import { waitUntilTextInSelector } from '../helpers/shared-helpers';
+import { waitUntilTextInSelector } from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
+
+const SYNCING_STATUS_HEADER = '.SyncingConnectingTitle_syncing h1';
When(
/^I arbitrarily set the local block height to half the network block height$/,
@@ -16,7 +22,7 @@ When(
Then(/^I should see the syncing status with "([^"]*)"$/, async function(text) {
await waitUntilTextInSelector(this.client, {
- selector: '.SyncingConnectingTitle_syncing h1',
+ selector: SYNCING_STATUS_HEADER,
text,
});
});
diff --git a/features/tests/e2e/steps/wallet-recovery-phrase-verification-steps.js b/tests/nodes/e2e/steps/wallet-recovery-phrase-verification-steps.js
similarity index 100%
rename from features/tests/e2e/steps/wallet-recovery-phrase-verification-steps.js
rename to tests/nodes/e2e/steps/wallet-recovery-phrase-verification-steps.js
diff --git a/features/tests/e2e/documents/paper_wallet_certificates/.gitkeep b/tests/paper-wallets/e2e/documents/.gitkeep
similarity index 100%
rename from features/tests/e2e/documents/paper_wallet_certificates/.gitkeep
rename to tests/paper-wallets/e2e/documents/.gitkeep
diff --git a/features/paper-wallets-certificate.feature b/tests/paper-wallets/e2e/features/paper-wallets-certificate.feature
similarity index 100%
rename from features/paper-wallets-certificate.feature
rename to tests/paper-wallets/e2e/features/paper-wallets-certificate.feature
diff --git a/features/tests/e2e/steps/paper-wallets-certificate-steps.js b/tests/paper-wallets/e2e/steps/paper-wallets-certificate.js
similarity index 95%
rename from features/tests/e2e/steps/paper-wallets-certificate-steps.js
rename to tests/paper-wallets/e2e/steps/paper-wallets-certificate.js
index 5868f8eef5..3e9cec58a7 100644
--- a/features/tests/e2e/steps/paper-wallets-certificate-steps.js
+++ b/tests/paper-wallets/e2e/steps/paper-wallets-certificate.js
@@ -1,12 +1,16 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
import path from 'path';
-import { fillOutWalletSendForm } from '../helpers/wallets-helpers';
-import { waitUntilTextInSelector } from '../helpers/shared-helpers';
+import { fillOutWalletSendForm } from '../../../wallets/e2e/steps/helpers';
+import { waitUntilTextInSelector } from '../../../common/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const paperWalletCertificatePath = path.resolve(
__dirname,
- '../documents/paper_wallet_certificates/paper-wallet-certificate.pdf'
+ '../documents/paper-wallet-certificate.pdf'
);
Given(/^I see the "Certificate Generation Instructions" dialog$/, function() {
diff --git a/features/accept-terms-of-use.feature b/tests/settings/e2e/features/accept-terms-of-use.feature
similarity index 100%
rename from features/accept-terms-of-use.feature
rename to tests/settings/e2e/features/accept-terms-of-use.feature
diff --git a/features/select-language.feature b/tests/settings/e2e/features/select-language.feature
similarity index 100%
rename from features/select-language.feature
rename to tests/settings/e2e/features/select-language.feature
diff --git a/features/wallet-settings.feature b/tests/settings/e2e/features/wallet-settings.feature
similarity index 100%
rename from features/wallet-settings.feature
rename to tests/settings/e2e/features/wallet-settings.feature
diff --git a/tests/settings/e2e/steps/basic-setup.js b/tests/settings/e2e/steps/basic-setup.js
new file mode 100644
index 0000000000..29790a233a
--- /dev/null
+++ b/tests/settings/e2e/steps/basic-setup.js
@@ -0,0 +1,15 @@
+// @flow
+import { Given } from 'cucumber';
+import { languageSelectionHelpers, migrationHelpers, termsOfUseHelpers } from './helpers';
+
+const { acceptMigration } = migrationHelpers;
+const { acceptTerms } = termsOfUseHelpers;
+const { ensureLanguageIsSelected } = languageSelectionHelpers;
+
+Given(/^I have completed the basic setup$/, async function() {
+ await ensureLanguageIsSelected(this.client, {
+ language: 'en-US',
+ });
+ await acceptTerms(this.client);
+ await acceptMigration(this.client);
+});
diff --git a/features/tests/e2e/steps/general-settings-steps.js b/tests/settings/e2e/steps/general-settings.js
similarity index 70%
rename from features/tests/e2e/steps/general-settings-steps.js
rename to tests/settings/e2e/steps/general-settings.js
index cbaf03b380..8efc3ea9be 100644
--- a/features/tests/e2e/steps/general-settings-steps.js
+++ b/tests/settings/e2e/steps/general-settings.js
@@ -1,15 +1,9 @@
-import { Given, When, Then } from 'cucumber';
-import _ from 'lodash';
-import { navigateTo, waitUntilUrlEquals } from '../helpers/route-helpers';
-
-Given(/^I am on the General Settings "([^"]*)" screen$/, async function(
- screen
-) {
- await navigateTo.call(this, `/settings/${screen}`);
-});
+// @flow
+import { When, Then } from 'cucumber';
+import { camelCase } from 'lodash';
When(/^I click on secondary menu (.*) item$/, async function(buttonName) {
- const buttonSelector = `.SettingsMenuItem_component.${_.camelCase(
+ const buttonSelector = `.SettingsMenuItem_component.${camelCase(
buttonName
)}`;
await this.client.waitForVisible(buttonSelector);
@@ -24,12 +18,6 @@ When(/^I open General Settings language selection dropdown$/, async function() {
await this.client.click('.GeneralSettings_component .SimpleInput_input');
});
-Then(/^I should see General Settings "([^"]*)" screen$/, async function(
- screenName
-) {
- return waitUntilUrlEquals.call(this, `/settings/${screenName}`);
-});
-
Then(/^I should see Japanese language as selected$/, async function() {
return this.client.waitUntil(async () => {
const selectedLanguage = await this.client.getValue(
diff --git a/tests/settings/e2e/steps/helpers.js b/tests/settings/e2e/steps/helpers.js
new file mode 100644
index 0000000000..b9e92bee06
--- /dev/null
+++ b/tests/settings/e2e/steps/helpers.js
@@ -0,0 +1,88 @@
+// @flow
+import type { Daedalus, WebdriverClient } from '../../../types';
+
+const DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT = '.DataLayerMigrationForm_component';
+const DEFAULT_LANGUAGE = 'en-US';
+const LANGUAGE_SELECTION_FORM = '.LanguageSelectionForm_component';
+const TERMS_OF_USE_FORM = '.TermsOfUseForm_component';
+
+declare var daedalus: Daedalus;
+
+export const i18nHelpers = {
+ formatMessage: async (
+ client: WebdriverClient,
+ { id, values }: { id: string, values?: Object }
+ ) => {
+ const translation = await client.execute(
+ (translationId, translationValues) => {
+ const IntlProvider = require('react-intl').IntlProvider; // eslint-disable-line
+ const locale = daedalus.stores.profile.currentLocale;
+ const messages = daedalus.translations;
+ const intlProvider = new IntlProvider(
+ { locale, messages: messages[locale] },
+ {}
+ );
+ return intlProvider
+ .getChildContext()
+ .intl.formatMessage({ id: translationId }, translationValues);
+ },
+ id,
+ values || {}
+ );
+ return translation.value;
+ },
+ setActiveLanguage: async (
+ client: WebdriverClient,
+ { language }: { language: string } = {}
+ ) =>
+ client.execute(locale => {
+ daedalus.actions.profile.updateLocale.trigger({ locale });
+ }, language || DEFAULT_LANGUAGE),
+};
+
+export const languageSelectionHelpers = {
+ waitForVisible: async (
+ client: WebdriverClient,
+ { isHidden }: { isHidden: boolean } = {}
+ ) =>
+ client.waitForVisible(LANGUAGE_SELECTION_FORM, null, isHidden),
+ ensureLanguageIsSelected: async (
+ client: WebdriverClient,
+ { language }: { language: string } = {}
+ ) => {
+ await i18nHelpers.setActiveLanguage(client, { language });
+ await languageSelectionHelpers.waitForVisible(client, { isHidden: true });
+ },
+};
+
+export const migrationHelpers = {
+ waitForVisible: async (
+ client: WebdriverClient,
+ { isHidden } : { isHidden: boolean } = {}
+ ) =>
+ client.waitForVisible(
+ DATA_LAYER_MIGRATION_ACCEPTANCE_COMPONENT,
+ null,
+ isHidden
+ ),
+ acceptMigration: async (client: WebdriverClient) => {
+ await client.execute(() => {
+ daedalus.actions.profile.acceptDataLayerMigration.trigger();
+ });
+ await migrationHelpers.waitForVisible(client, { isHidden: true });
+ },
+};
+
+export const termsOfUseHelpers = {
+ waitForVisible: async (
+ client: WebdriverClient,
+ { isHidden } : { isHidden: boolean } = {}
+ ) =>
+ client.waitForVisible(TERMS_OF_USE_FORM, null, isHidden),
+ acceptTerms: async (client: WebdriverClient) => {
+ await client.execute(() => {
+ daedalus.actions.profile.acceptTermsOfUse.trigger();
+ });
+ await termsOfUseHelpers.waitForVisible(client, { isHidden: true });
+ },
+};
diff --git a/features/tests/e2e/steps/select-language-steps.js b/tests/settings/e2e/steps/select-language.js
similarity index 84%
rename from features/tests/e2e/steps/select-language-steps.js
rename to tests/settings/e2e/steps/select-language.js
index ad55213a70..b3029a2df8 100644
--- a/features/tests/e2e/steps/select-language-steps.js
+++ b/tests/settings/e2e/steps/select-language.js
@@ -1,11 +1,15 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
-import languageSelection from '../helpers/language-selection-helpers';
+import { languageSelectionHelpers } from './helpers';
+import type { Daedalus } from '../../../types';
+declare var daedalus: Daedalus;
+const { ensureLanguageIsSelected } = languageSelectionHelpers;
const LANGUAGE_SELECTION_FORM = '.LanguageSelectionForm_component';
Given(/^I have selected English language$/, async function() {
- await languageSelection.ensureLanguageIsSelected(this.client, {
+ await ensureLanguageIsSelected(this.client, {
language: 'en-US',
});
});
diff --git a/features/tests/e2e/steps/settings-steps.js b/tests/settings/e2e/steps/settings.js
similarity index 95%
rename from features/tests/e2e/steps/settings-steps.js
rename to tests/settings/e2e/steps/settings.js
index 324b65d81d..82cc8f0b9a 100644
--- a/features/tests/e2e/steps/settings-steps.js
+++ b/tests/settings/e2e/steps/settings.js
@@ -1,10 +1,14 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
-import { navigateTo } from '../helpers/route-helpers';
+import { navigateTo } from '../../../navigation/e2e/steps/helpers';
import {
waitUntilWaletNamesEqual,
getNameOfActiveWalletInSidebar,
-} from '../helpers/wallets-helpers';
+} from '../../../wallets/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
Given(/^I am on the settings screen$/, async function() {
await navigateTo.call(this, '/settings');
diff --git a/features/tests/e2e/steps/accept-terms-of-use-steps.js b/tests/settings/e2e/steps/terms-of-use.js
similarity index 84%
rename from features/tests/e2e/steps/accept-terms-of-use-steps.js
rename to tests/settings/e2e/steps/terms-of-use.js
index 08e612a560..acb9fffcec 100644
--- a/features/tests/e2e/steps/accept-terms-of-use-steps.js
+++ b/tests/settings/e2e/steps/terms-of-use.js
@@ -1,11 +1,16 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
-import termsOfUse from '../helpers/terms-of-use-helpers';
+import { termsOfUseHelpers } from './helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const TERMS_OF_USE_FORM = '.TermsOfUseForm_component';
+const { acceptTerms } = termsOfUseHelpers;
Given(/^I have accepted "Terms of use"$/, async function() {
- await termsOfUse.acceptTerms(this.client);
+ await acceptTerms(this.client);
});
Given(/^I didnt accept "Terms of use"$/, async function() {
diff --git a/features/generate-filename-with-timestamp.feature b/tests/settings/unit/features/generate-filename-with-timestamp.feature
similarity index 100%
rename from features/generate-filename-with-timestamp.feature
rename to tests/settings/unit/features/generate-filename-with-timestamp.feature
diff --git a/features/tests/unit/steps/generate-filename-with-timestamp-steps.js b/tests/settings/unit/steps/file-names.js
similarity index 85%
rename from features/tests/unit/steps/generate-filename-with-timestamp-steps.js
rename to tests/settings/unit/steps/file-names.js
index b1ba200d24..74307084cb 100644
--- a/features/tests/unit/steps/generate-filename-with-timestamp-steps.js
+++ b/tests/settings/unit/steps/file-names.js
@@ -8,9 +8,14 @@ import {
const getDataFromFunction = props => {
const filename = generateFileNameWithTimestamp(props);
- const prefix = filename.match(/^[^-]*[^ -]/i)[0];
- const extension = filename.match(/\.[0-9a-z]+$/i)[0].replace('.', '');
- const isUTC = !!filename.match(`Z.${extension}`);
+ let prefix = filename.match(/^[^-]*[^ -]/i);
+ let extension = filename.match(/\.[0-9a-z]+$/i);
+ let isUTC = false;
+
+ if (prefix) { prefix = prefix[0]; }
+ if (extension) { extension = extension[0].replace('.', ''); }
+ if (extension) { isUTC = !!filename.match(`Z.${extension}`); }
+
return {
filename,
prefix,
diff --git a/features/tests/e2e/setup/electron.js b/tests/setup.js
similarity index 75%
rename from features/tests/e2e/setup/electron.js
rename to tests/setup.js
index 70e53d00f4..cb4adb3f46 100644
--- a/features/tests/e2e/setup/electron.js
+++ b/tests/setup.js
@@ -1,3 +1,4 @@
+// @flow
import path from 'path';
import { Application } from 'spectron';
import {
@@ -9,16 +10,19 @@ import {
} from 'cucumber';
import electronPath from 'electron';
import fakeDialog from 'spectron-fake-dialog';
-import { TEST } from '../../../../source/common/types/environment.types';
import {
generateScreenshotFilePath,
getTestNameFromTestFile,
saveScreenshot,
-} from '../helpers/screenshot';
-import { refreshClient } from '../helpers/app-helpers';
+} from './common/e2e/steps/helpers';
+import { setNewsFeedIsOpen, resetTestNews } from './news/e2e/steps/newsfeed-steps';
+import { refreshClient } from './nodes/e2e/steps/helpers';
+import { TEST } from '../source/common/types/environment.types';
+import type { Daedalus } from './types';
/* eslint-disable consistent-return */
+declare var daedalus: Daedalus;
const context = {};
const DEFAULT_TIMEOUT = 20000;
let scenariosCount = 0;
@@ -36,7 +40,7 @@ const printMainProcessLogs = () =>
const defaultWalletKeyFilePath = path.resolve(
__dirname,
- '../documents/default-wallet.key'
+ './wallets/e2e/documents/default-wallet.key'
);
const startApp = async () => {
@@ -50,9 +54,9 @@ const startApp = async () => {
waitTimeout: DEFAULT_TIMEOUT,
chromeDriverLogPath: path.join(
__dirname,
- '../../../../logs/chrome-driver.log'
+ '../logs/chrome-driver.log'
),
- webdriverLogPath: path.join(__dirname, '../../../../logs/webdriver'),
+ webdriverLogPath: path.join(__dirname, '../logs/webdriver'),
});
fakeDialog.apply(app);
await app.start();
@@ -130,6 +134,48 @@ Before({ timeout: DEFAULT_TIMEOUT * 2 }, async function(testCase) {
});
});
+// adds context object to webdriver
+Before(function() {
+ this.context = {};
+});
+
+Before({ tags: '@newsfeed' }, function() {
+ setNewsFeedIsOpen(this.client, false);
+ resetTestNews(this.client);
+});
+
+// adds waitAndClick method to webdriver
+Before(function() {
+ this.waitAndClick = async (selector, ...waitArgs) => {
+ await this.client.waitForVisible(selector, ...waitArgs);
+ return this.client.click(selector);
+ };
+});
+
+// ads intl method to webdriver
+Before(function() {
+ this.intl = async (translationId, translationValues = {}) => {
+ const translation = await this.client.execute(
+ (id, values) => {
+ const IntlProvider = require('react-intl').IntlProvider; // eslint-disable-line
+ const locale = daedalus.stores.profile.currentLocale;
+ const messages = daedalus.translations;
+ const intlProvider = new IntlProvider(
+ { locale, messages: messages[locale] },
+ {}
+ );
+ return intlProvider
+ .getChildContext()
+ .intl.formatMessage({ id }, values);
+ },
+ translationId,
+ translationValues
+ );
+ return translation.value;
+ };
+});
+
+
// this ensures that the spectron instance of the app restarts
// after the node update acceptance test shuts it down via 'kill-process'
// eslint-disable-next-line prefer-arrow-callback
diff --git a/features/send-money-to-receiver.feature b/tests/transactions/e2e/features/send-money-to-receiver.feature
similarity index 100%
rename from features/send-money-to-receiver.feature
rename to tests/transactions/e2e/features/send-money-to-receiver.feature
diff --git a/features/transactions-display.feature b/tests/transactions/e2e/features/transactions-display.feature
similarity index 100%
rename from features/transactions-display.feature
rename to tests/transactions/e2e/features/transactions-display.feature
diff --git a/features/wallet-utxos.feature b/tests/transactions/e2e/features/wallet-utxos.feature
similarity index 100%
rename from features/wallet-utxos.feature
rename to tests/transactions/e2e/features/wallet-utxos.feature
diff --git a/features/tests/e2e/steps/transactions-steps.js b/tests/transactions/e2e/steps/transactions.js
similarity index 93%
rename from features/tests/e2e/steps/transactions-steps.js
rename to tests/transactions/e2e/steps/transactions.js
index cea7a72da8..c54052b8b8 100644
--- a/features/tests/e2e/steps/transactions-steps.js
+++ b/tests/transactions/e2e/steps/transactions.js
@@ -1,3 +1,4 @@
+// @flow
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
import BigNumber from 'bignumber.js/bignumber';
@@ -5,8 +6,11 @@ import {
DECIMAL_PLACES_IN_ADA,
LOVELACES_PER_ADA,
} from '../../../../source/renderer/app/config/numbersConfig';
-import { getVisibleTextsForSelector } from '../helpers/shared-helpers';
-import { getWalletByName } from '../helpers/wallets-helpers';
+import { getVisibleTextsForSelector } from '../../../common/e2e/steps/helpers';
+import { getWalletByName } from '../../../wallets/e2e/steps/helpers';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
// This step ensures sequential creation of given transactions
// use only when the order is important because it's slower!
diff --git a/features/tests/e2e/steps/wallets-utxos-steps.js b/tests/transactions/e2e/steps/utxos.js
similarity index 81%
rename from features/tests/e2e/steps/wallets-utxos-steps.js
rename to tests/transactions/e2e/steps/utxos.js
index e72488dd9a..43c07041de 100644
--- a/features/tests/e2e/steps/wallets-utxos-steps.js
+++ b/tests/transactions/e2e/steps/utxos.js
@@ -1,7 +1,11 @@
+// @flow
import { Then } from 'cucumber';
import { expect } from 'chai';
-import { getVisibleTextsForSelector } from '../helpers/shared-helpers';
+import { getVisibleTextsForSelector } from '../../../common/e2e/steps/helpers';
import { getWalletUtxosTotalAmount } from '../../../../source/renderer/app/utils/utxoUtils';
+import type { Daedalus } from '../../../types';
+
+declare var daedalus: Daedalus;
const container = '.WalletUtxo_container';
@@ -38,18 +42,18 @@ Then(
this.client,
selectors.walletUtxosAmount
);
-
const {
value: { expextedWalletAmount, histogram },
- } = await this.client.executeAsync(done =>
+ } = await this.client.executeAsync(done => {
+ const histogram = daedalus.stores.walletSettings.walletUtxos
+ ? daedalus.stores.walletSettings.walletUtxos.histogram
+ : null;
done({
expextedWalletAmount: daedalus.stores.wallets.activeValue,
- histogram: daedalus.stores.walletSettings.walletUtxos.histogram,
- })
- );
-
+ histogram,
+ });
+ });
const expectedWalletUtxosAmount = getWalletUtxosTotalAmount(histogram);
-
expect(expextedWalletAmount).to.equal(renderedWalletAmount);
expect(expectedWalletUtxosAmount).to.equal(
parseInt(renderedWalletUtxosAmount, 10)
diff --git a/features/utxos-chart.feature b/tests/transactions/unit/features/utxos-chart.feature
similarity index 100%
rename from features/utxos-chart.feature
rename to tests/transactions/unit/features/utxos-chart.feature
diff --git a/features/tests/unit/setup/utxo-helpers.js b/tests/transactions/unit/steps/helpers.js
similarity index 62%
rename from features/tests/unit/setup/utxo-helpers.js
rename to tests/transactions/unit/steps/helpers.js
index 477ef2f6a0..707dbc37e4 100644
--- a/features/tests/unit/setup/utxo-helpers.js
+++ b/tests/transactions/unit/steps/helpers.js
@@ -1,5 +1,6 @@
-export const getHistogramFromTable = data => {
- const histogram = {};
+// @flow
+export const getHistogramFromTable = (data: Object) => {
+ let histogram = {};
data.hashes().forEach(({ walletAmount, walletUtxosAmount }) => {
histogram[walletAmount] = walletUtxosAmount;
});
diff --git a/features/tests/unit/steps/utxos-chart-steps.js b/tests/transactions/unit/steps/utxos-chart.js
similarity index 98%
rename from features/tests/unit/steps/utxos-chart-steps.js
rename to tests/transactions/unit/steps/utxos-chart.js
index a7a93147ef..69eb1d4d3e 100644
--- a/features/tests/unit/steps/utxos-chart-steps.js
+++ b/tests/transactions/unit/steps/utxos-chart.js
@@ -9,7 +9,7 @@ import {
getUtxoWalletPrettyAmount,
getWalletUtxosTotalAmount,
} from '../../../../source/renderer/app/utils/utxoUtils';
-import { getHistogramFromTable } from '../setup/utxo-helpers';
+import { getHistogramFromTable } from './helpers';
/* eslint-disable no-unused-expressions */
Given('the `getUtxoChartData` function receives the following props:', function(
diff --git a/tests/types.js b/tests/types.js
new file mode 100644
index 0000000000..cc09c76a2d
--- /dev/null
+++ b/tests/types.js
@@ -0,0 +1,41 @@
+// @flow
+import { defineParameterType } from 'cucumber';
+import type { Api } from '../source/renderer/app/api';
+import type { ActionsMap } from '../source/renderer/app/actions';
+import type { StoresMap } from '../source/renderer/app/stores';
+
+// Add {bool} parameter type
+defineParameterType({
+ name: 'bool',
+ regexp: /true|false/,
+ transformer: b => b === 'true',
+});
+
+export type Daedalus = {
+ actions: ActionsMap,
+ api: Api,
+ environment: Object,
+ reset: Function,
+ stores: StoresMap,
+ translations: Object,
+ utils: {
+ crypto: {
+ generateMnemonic: Function
+ }
+ },
+};
+
+export type WebdriverExecuteResult = { value: T };
+
+export type WebdriverClient = {
+ click: (selector: string) => Promise,
+ elements: (selector: string) => Promise