Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Detox: Address Book Tests #1441

Merged
merged 3 commits into from
Mar 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions app/components/UI/Navbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export function getNavigationOptionsTitle(title, navigation) {
},
headerTintColor: colors.blue,
headerLeft: (
<TouchableOpacity onPress={navigationPop} style={styles.backButton}>
<TouchableOpacity onPress={navigationPop} style={styles.backButton} testID={'title-back-arrow-button'}>
<IonicIcon
name={Device.isAndroid() ? 'md-arrow-back' : 'ios-arrow-back'}
size={Device.isAndroid() ? 24 : 28}
Expand Down Expand Up @@ -221,7 +221,7 @@ export function getEditableOptions(title, navigation) {
},
headerTintColor: colors.blue,
headerLeft: (
<TouchableOpacity onPress={navigationPop} style={styles.backButton}>
<TouchableOpacity onPress={navigationPop} style={styles.backButton} testID={'edit-contact-back-button'}>
<IonicIcon
name={Device.isAndroid() ? 'md-arrow-back' : 'ios-arrow-back'}
size={Device.isAndroid() ? 24 : 28}
Expand Down Expand Up @@ -358,13 +358,13 @@ export function getSendFlowTitle(title, navigation) {
headerTitle: <NavbarTitle title={title} disableNetwork />,
headerRight: (
// eslint-disable-next-line react/jsx-no-bind
<TouchableOpacity onPress={rightAction} style={styles.closeButton}>
<TouchableOpacity onPress={rightAction} style={styles.closeButton} testID={'send-cancel-button'}>
<Text style={styles.closeButtonText}>{'Cancel'}</Text>
</TouchableOpacity>
),
headerLeft: canGoBack ? (
// eslint-disable-next-line react/jsx-no-bind
<TouchableOpacity onPress={leftAction} style={styles.closeButton}>
<TouchableOpacity onPress={leftAction} style={styles.closeButton} testID={'send-back-button'}>
<Text style={styles.closeButtonText}>{'Back'}</Text>
</TouchableOpacity>
) : (
Expand Down Expand Up @@ -708,7 +708,7 @@ export function getNetworkNavbarOptions(title, translate, navigation) {
headerTitle: <NavbarTitle title={title} translate={translate} />,
headerLeft: (
// eslint-disable-next-line react/jsx-no-bind
<TouchableOpacity onPress={() => navigation.pop()} style={styles.backButton}>
<TouchableOpacity onPress={() => navigation.pop()} style={styles.backButton} testID={'asset-back-button'}>
<IonicIcon
name={Device.isAndroid() ? 'md-arrow-back' : 'ios-arrow-back'}
size={Device.isAndroid() ? 24 : 28}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ exports[`ErrorMessage should render correctly 1`] = `
"padding": 15,
}
}
testID="error-message-warning"
>
<Text
style={
Expand Down
2 changes: 1 addition & 1 deletion app/components/Views/SendFlow/ErrorMessage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const styles = StyleSheet.create({
export default function ErrorMessage(props) {
const { errorMessage } = props;
return (
<View style={styles.wrapper}>
<View style={styles.wrapper} testID={'error-message-warning'}>
<Text style={styles.errorMessage}>{errorMessage}</Text>
</View>
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/Views/SendFlow/SendTo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ class SendFlow extends PureComponent {
</Text>
</TouchableOpacity>
)}
<View style={styles.footerContainer}>
<View style={styles.footerContainer} testID={'no-eth-message'}>
{balanceIsZero && (
<View style={styles.warningContainer}>
<WarningMessage warningMessage={strings('transaction.not_enough_for_gas')} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ exports[`ContactForm should render correctly 1`] = `
"flexDirection": "column",
}
}
testID="add-contact-screen"
>
<KeyboardAwareScrollViewMock
enableAutomaticScroll={true}
Expand Down Expand Up @@ -76,6 +77,7 @@ exports[`ContactForm should render correctly 1`] = `
Object {},
]
}
testID="contact-name-input"
underlineColorAndroid="transparent"
/>
<Text
Expand Down Expand Up @@ -142,6 +144,7 @@ exports[`ContactForm should render correctly 1`] = `
Object {},
]
}
testID="contact-address-input"
underlineColorAndroid="transparent"
/>
</View>
Expand Down Expand Up @@ -232,6 +235,7 @@ exports[`ContactForm should render correctly 1`] = `
Object {},
]
}
testID="contact-memo-input"
underlineColorAndroid="transparent"
/>
</View>
Expand Down Expand Up @@ -275,6 +279,7 @@ exports[`ContactForm should render correctly 1`] = `
"opacity": 0.6,
}
}
testID="contact-add-contact-button"
type="confirm"
>
Add contact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ class ContactForm extends PureComponent {
render = () => {
const { address, addressError, toEnsName, name, mode, addressReady, memo, editable, inputWidth } = this.state;
return (
<SafeAreaView style={styles.wrapper}>
<SafeAreaView style={styles.wrapper} testID={'add-contact-screen'}>
<KeyboardAwareScrollView style={styles.informationWrapper}>
<View style={styles.scrollWrapper}>
<Text style={styles.label}>{strings('address_book.name')}</Text>
Expand All @@ -272,6 +272,7 @@ class ContactForm extends PureComponent {
]}
value={name}
onSubmitEditing={this.jumpToAddressInput}
testID={'contact-name-input'}
/>

<Text style={styles.label}>{strings('address_book.address')}</Text>
Expand All @@ -290,6 +291,7 @@ class ContactForm extends PureComponent {
value={toEnsName || address}
ref={this.addressInput}
onSubmitEditing={this.jumpToMemoInput}
testID={'contact-address-input'}
/>
{toEnsName && <Text style={styles.resolvedInput}>{renderShortAddress(address)}</Text>}
</View>
Expand Down Expand Up @@ -317,6 +319,7 @@ class ContactForm extends PureComponent {
style={[styles.textInput, inputWidth ? { width: inputWidth } : {}]}
value={memo}
ref={this.memoInput}
testID={'contact-memo-input'}
/>
</View>
</View>
Expand All @@ -332,6 +335,7 @@ class ContactForm extends PureComponent {
type={'confirm'}
disabled={!addressReady || !name || !!addressError}
onPress={this.saveContact}
testID={'contact-add-contact-button'}
>
{strings(`address_book.${mode}_contact`)}
</StyledButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exports[`Contacts should render correctly 1`] = `
"flex": 1,
}
}
testID="contacts-screen"
>
<Connect(AddressList)
onAccountLongPress={[Function]}
Expand All @@ -33,6 +34,7 @@ exports[`Contacts should render correctly 1`] = `
"opacity": 0.6,
}
}
testID="add-contact-button"
type="confirm"
>
Add contact
Expand Down
9 changes: 7 additions & 2 deletions app/components/Views/Settings/Contacts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,19 @@ class Contacts extends PureComponent {
render = () => {
const { reloadAddressList } = this.state;
return (
<SafeAreaView style={styles.wrapper}>
<SafeAreaView style={styles.wrapper} testID={'contacts-screen'}>
<AddressList
onlyRenderAddressBook
reloadAddressList={reloadAddressList}
onAccountPress={this.onAddressPress}
onAccountLongPress={this.onAddressLongPress}
/>
<StyledButton type={'confirm'} containerStyle={styles.addContact} onPress={this.goToAddContact}>
<StyledButton
type={'confirm'}
containerStyle={styles.addContact}
onPress={this.goToAddContact}
testID={'add-contact-button'}
>
{strings('address_book.add_contact')}
</StyledButton>
<ActionSheet
Expand Down
182 changes: 182 additions & 0 deletions e2e/addressbook-tests.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
'use strict';
import TestHelpers from './helpers';

const INVALID_ADDRESS = '0xB8B4EE5B1b693971eB60bDa15211570df2dB221L';
const MYTH_ADDRESS = '0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6';
const MEMO = 'Test adding ENS';

describe('Addressbook Tests', () => {
beforeEach(() => {
jest.setTimeout(150000);
});

it('should create new wallet and dismiss tutorial', async () => {
// Check that we are on the onboarding carousel screen
await TestHelpers.checkIfVisible('onboarding-carousel-screen');
// Check that Get started CTA is visible & tap it
await TestHelpers.waitAndTap('onboarding-get-started-button');
// Check that we are on the onboarding screen
await TestHelpers.checkIfVisible('onboarding-screen');
// Check that Start Exploring CTA is visible & tap it
await TestHelpers.waitAndTap('start-exploring-button');
// Check that we are on the metametrics optIn screen
await TestHelpers.checkIfVisible('metaMetrics-OptIn');
// Check that I Agree CTA is visible and tap it
await TestHelpers.waitAndTap('agree-button');
// Check that we are on the wallet screen
if (!device.getPlatform() === 'android') {
// Check that we are on the wallet screen
await TestHelpers.checkIfExists('wallet-screen');
}
// Check that the onboarding wizard is present
await TestHelpers.checkIfVisible('onboarding-wizard-step1-view');
// Check that No thanks CTA is visible and tap it
await TestHelpers.waitAndTap('onboarding-wizard-back-button');
// Check that the onboarding wizard is gone
await TestHelpers.checkIfNotVisible('onboarding-wizard-step1-view');
});

it('should go to send view', async () => {
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Tap on ETH asset
await TestHelpers.waitAndTap('eth-logo');
// Check that we are on the token overview screen
await TestHelpers.checkIfVisible('token-asset-overview');
// Tap on Send button
await TestHelpers.tapByText('SEND');
// Check that we are on the send screen
await TestHelpers.checkIfVisible('send-screen');
// Make sure view with my accounts visible
await TestHelpers.checkIfExists('my-accounts-button');
});

it('should input a valid address to send to', async () => {
// Input incorrect address
await TestHelpers.typeTextAndHideKeyboard('txn-to-address-input', INVALID_ADDRESS);
// Check that the error is displayed
await TestHelpers.checkIfVisible('address-error');
// Clear text
await TestHelpers.clearField('txn-to-address-input');
// Input valid myth address
await TestHelpers.typeTextAndHideKeyboard('txn-to-address-input', MYTH_ADDRESS);
// Check that the warning appears at the bottom of the screen
await TestHelpers.checkIfVisible('no-eth-message');
});

it('should add a new address to address book via send flow', async () => {
// Tap on add this address to your address book
await TestHelpers.waitAndTap('add-address-button');
// Make sure address book modal is displayed
await TestHelpers.checkIfExists('add-address-modal');
// Input alias
await TestHelpers.typeTextAndHideKeyboard('address-alias-input', 'Myth');
// Save contact
await TestHelpers.tapByText('Save');
// Clear address
await TestHelpers.tap('clear-address-button');
// Check that the new account is on the address list
await TestHelpers.checkIfElementWithTextIsVisible('Myth');
});

it('should go to settings then select contacts', async () => {
// Tap on cancel button
await TestHelpers.tap('send-cancel-button');
// Tap on back button to proceed to wallet view
await TestHelpers.tap('asset-back-button');
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Open Drawer
await TestHelpers.tap('hamburger-menu-button-wallet');
// Check that the drawer is visbile
await TestHelpers.checkIfVisible('drawer-screen');
// Tap on settings
await TestHelpers.tap('settings-button');
// Tap on the "Contacts" option
await TestHelpers.tapByText('Contacts');
// Check that we are on the contacts screen
await TestHelpers.checkIfVisible('contacts-screen');
// Check that Myth address is saved in the address book
await TestHelpers.checkIfElementWithTextIsVisible('Myth');
});

it('should add an address via the contacts view', async () => {
// Tap on add contact button
await TestHelpers.tap('add-contact-button');
// Check that we are on the add contact screen
await TestHelpers.checkIfVisible('add-contact-screen');
// Input a name
await TestHelpers.typeTextAndHideKeyboard('contact-name-input', 'Ibrahim');
// Input invalid address
await TestHelpers.replaceTextInField('contact-address-input', INVALID_ADDRESS);
// Check that warning is shown
await TestHelpers.checkIfVisible('error-message-warning');
// Check warning is for the right reason
await TestHelpers.checkIfElementHasString('error-message-warning', 'Invalid address');
// Clear address input field
await TestHelpers.clearField('contact-address-input');
// Replace address with valid ENS address
await TestHelpers.replaceTextInField('contact-address-input', 'ibrahim.team.mask.eth');
// Add a memo
await TestHelpers.typeTextAndHideKeyboard('contact-memo-input', MEMO);
// Tap add contact button
await TestHelpers.tap('contact-add-contact-button');
// Tap add contact button
await TestHelpers.tap('contact-add-contact-button');
// Check that we are on the contacts screen
await TestHelpers.checkIfVisible('contacts-screen');
// Check that Ibrahim address is saved in the address book
await TestHelpers.checkIfElementWithTextIsVisible('Ibrahim');
});

it('should edit a contact', async () => {
// Tap on Myth address
await TestHelpers.tapByText('Myth');
// Tap on edit
await TestHelpers.tapByText('Edit');
// Change name from Myth to Moon
await TestHelpers.replaceTextInField('contact-name-input', 'Moon');
// Tap on Edit contact button
await TestHelpers.tapByText('Edit contact');
// Check that we are on the contacts screen
await TestHelpers.checkIfVisible('contacts-screen');
// Check that Ibrahim address is saved in the address book
await TestHelpers.checkIfElementWithTextIsVisible('Moon');
// Ensure Myth is not visible
await TestHelpers.checkIfElementWithTextIsNotVisible('Myth');
});

it('should remove a contact', async () => {
// Tap on Moon address
await TestHelpers.tapByText('Moon');
// Tap on edit
await TestHelpers.tapByText('Edit');
// Tap on Delete
await TestHelpers.tapByText('Delete');
// Tap on Delete
await TestHelpers.tapByText('Delete');
// Ensure Moon is not visible
await TestHelpers.checkIfElementWithTextIsNotVisible('Moon');
});

it('should go back to send flow to validate newly added address is displayed', async () => {
// tap on the back arrow
await TestHelpers.tap('title-back-arrow-button');
// tap to get out of settings view
if (device.getPlatform() === 'android') {
await device.pressBack();
} else {
await TestHelpers.tapByText('Close');
}
// check we are on wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Open Drawer
await TestHelpers.tap('hamburger-menu-button-wallet');
// Check that the drawer is visbile
await TestHelpers.checkIfVisible('drawer-screen');
// Tap on send
await TestHelpers.tapByText('Send');
// Check that the new account is on the address list
await TestHelpers.checkIfElementWithTextIsVisible('Ibrahim');
});
});
4 changes: 4 additions & 0 deletions e2e/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export default class TestHelpers {
.withTimeout(10000);
}

static checkIfElementWithTextIsNotVisible(text) {
return expect(element(by.text(text)).atIndex(0)).toBeNotVisible();
}

static checkIfExists(elementId) {
return expect(element(by.id(elementId))).toExist();
}
Expand Down