diff --git a/appium/tests/data/index.ts b/appium/tests/data/index.ts index 6cd7329f6..16fd4ad3a 100644 --- a/appium/tests/data/index.ts +++ b/appium/tests/data/index.ts @@ -3,8 +3,22 @@ import * as path from 'path'; export const CommonData = { account: { email: 'e2e.enterprise.test@flowcrypt.com', - password: process.env.ACCOUNT_PASSWORD, - passPhrase: 'London blueBARREY capi' + password: process.env.E2E_ENTERPRISE_TESTS_GOOGLE_PASSWORD, + passPhrase: 'London blueBARREY capi', + folder: 'Gmail enterprise folder', + name: 'e2e' + }, + outlookAccount: { + email: 'e2e.consumer.tests@outlook.com', + password: process.env.E2E_CONSUMER_TESTS_OUTLOOK_PASSWORD, + passPhrase: 'flowcrypt compatibility accounts o', + name: 'e2e.consumer.tests', + outlookFolder: 'Outlook consumer folder' + }, + outlookEmail: { + subject: 'outlook account inbox email', + message: 'test email from gmail', + sender: 'e2e.enterprise.test@flowcrypt.com' }, sender: { email: 'dmitry@flowcrypt.com', @@ -115,7 +129,9 @@ export const CommonData = { '\n' + 'One or more of your recipients have revoked public keys (marked in red).\n' + '\n' + - 'Please ask them to send you a new public key. If this is an enterprise installation, please ask your systems admin.' + 'Please ask them to send you a new public key. If this is an enterprise installation, please ask your systems admin.', + wrongPassPhraseOnLogin: 'Error\n' + + 'Wrong pass phrase, please try again' }, decryptErrorBadge: { badgeText: 'decrypt error' diff --git a/appium/tests/screenobjects/all-screens.ts b/appium/tests/screenobjects/all-screens.ts index ccafd7778..7ca7f303a 100644 --- a/appium/tests/screenobjects/all-screens.ts +++ b/appium/tests/screenobjects/all-screens.ts @@ -12,6 +12,7 @@ import AttachmentScreen from './attachment.screen'; import MailFolderScreen from './mail-folder.screen'; import SearchScreen from './search.screen'; import OldVersionAppScreen from './old-version-app.screen'; +import EmailProviderScreen from './email-provider.screen'; export { SplashScreen, @@ -27,5 +28,6 @@ export { ContactPublicKeyScreen, MailFolderScreen, SearchScreen, - OldVersionAppScreen + OldVersionAppScreen, + EmailProviderScreen }; diff --git a/appium/tests/screenobjects/email-provider.screen.ts b/appium/tests/screenobjects/email-provider.screen.ts new file mode 100644 index 000000000..0a1a49ca2 --- /dev/null +++ b/appium/tests/screenobjects/email-provider.screen.ts @@ -0,0 +1,69 @@ +import BaseScreen from './base.screen'; +import ElementHelper from "../helpers/ElementHelper"; +import TouchHelper from "../helpers/TouchHelper"; + +const SELECTORS = { + BACK_BTN: '~aid-back-button', + EMAIL_PROVIDER_HEADER: '~navigationItemEmail Provider', + CONNECT_BUTTON: '~Connect', + EMAIL_FIELD: '-ios class chain:**/XCUIElementTypeTextField[`name == "Email"`]', + PASSWORD_FIELD: '-ios class chain:**/XCUIElementTypeSecureTextField[`name == "Password"`]', + RETURN_BUTTON: '~Return', +}; + +class EmailProviderScreen extends BaseScreen { + constructor() { + super(SELECTORS.BACK_BTN); + } + + get backButton() { + return $(SELECTORS.BACK_BTN); + } + + get emailProviderHeader() { + return $(SELECTORS.EMAIL_PROVIDER_HEADER); + } + + get connectButton() { + return $(SELECTORS.CONNECT_BUTTON); + } + + get emailField() { + return $(SELECTORS.EMAIL_FIELD); + } + + get passwordField() { + return $(SELECTORS.PASSWORD_FIELD) + } + + get returnButton() { + return $(SELECTORS.RETURN_BUTTON) + } + + checkEmailProviderScreen = async () => { + await expect(this.backButton).toBeDisplayed(); + await expect(this.emailProviderHeader).toBeDisplayed(); + await expect(this.connectButton).toBeDisplayed(); + } + + fillEmail = async (email: string) => { + await ElementHelper.waitClickAndType(await this.emailField, email); + await browser.pause(500); + } + + fillPassword = async (password: string) => { + await ElementHelper.waitClickAndType(await this.passwordField, password); + await browser.pause(500); // stability sleep + } + + clickConnectBtn = async () => { + await TouchHelper.scrollUp(); + await ElementHelper.waitAndClick(await this.connectButton); + } + + clickReturnBtn = async () => { + await ElementHelper.waitAndClick(await this.returnButton); + } +} + +export default new EmailProviderScreen(); diff --git a/appium/tests/screenobjects/menu-bar.screen.ts b/appium/tests/screenobjects/menu-bar.screen.ts index a3163c4a8..eccbada66 100644 --- a/appium/tests/screenobjects/menu-bar.screen.ts +++ b/appium/tests/screenobjects/menu-bar.screen.ts @@ -9,6 +9,7 @@ const SELECTORS = { INBOX_BTN: '~menuBarItemInbox', SENT_BTN: '~menuBarItemSent', TRASH_BTN: '~menuBarItemTrash', + ADD_ACCOUNT_BUTTON: '~Add account' }; class MenuBarScreen extends BaseScreen { @@ -40,6 +41,10 @@ class MenuBarScreen extends BaseScreen { return $(SELECTORS.TRASH_BTN) } + get addAccountButton() { + return $(SELECTORS.ADD_ACCOUNT_BUTTON); + } + clickMenuIcon = async () => { await ElementHelper.waitAndClick(await this.menuIcon, 1000); await this.checkMenuBar(); @@ -50,6 +55,15 @@ class MenuBarScreen extends BaseScreen { await el.waitForDisplayed(); } + clickOnUserEmail = async (email: string = CommonData.account.email) => { + const el = await $(`~${email}`); + await ElementHelper.waitAndClick(await el); + } + + clickAddAccountButton = async() => { + await ElementHelper.waitAndClick(await this.addAccountButton); + } + checkMenuBar = async () => { await ElementHelper.waitElementVisible(await this.logoutButton); await ElementHelper.waitElementVisible(await this.settingsButton); @@ -77,6 +91,16 @@ class MenuBarScreen extends BaseScreen { clickTrashButton = async () => { await ElementHelper.waitAndClick(await this.trashButton); } + + checkMenuBarItem = async (menuItem: string) => { + const menuBarItem = await $(`~menuBarItem${menuItem}`); + await menuBarItem.waitForDisplayed(); + } + + selectAccount = async (order: number) => { + const ele = await $(`~aid-account-email-${order-1}`); + await ElementHelper.waitAndClick(await ele); + } } export default new MenuBarScreen(); diff --git a/appium/tests/screenobjects/search.screen.ts b/appium/tests/screenobjects/search.screen.ts index 653b6cfa7..6cfd730b7 100644 --- a/appium/tests/screenobjects/search.screen.ts +++ b/appium/tests/screenobjects/search.screen.ts @@ -31,6 +31,13 @@ class SearchScreen extends BaseScreen { const selector = `~${subject}`; await ElementHelper.waitAndClick(await $(selector), 500); } + + searchAndClickEmailForOutlook = async (subject: string) => { + await (await this.searchField).setValue(subject); + + const selector = `~${subject}`; + await ElementHelper.waitAndClick(await $(selector), 500); + } } export default new SearchScreen(); diff --git a/appium/tests/screenobjects/setup-key.screen.ts b/appium/tests/screenobjects/setup-key.screen.ts index 93480df4d..c1f178c93 100644 --- a/appium/tests/screenobjects/setup-key.screen.ts +++ b/appium/tests/screenobjects/setup-key.screen.ts @@ -4,9 +4,11 @@ import ElementHelper from "../helpers/ElementHelper"; const SELECTORS = { SET_PASS_PHRASE_BUTTON: '~Set pass phrase', - ENTER_YOUR_PASS_PHRASE_FIELD: '-ios class chain:**/XCUIElementTypeSecureTextField[`value == "Enter your pass phrase"`]', + ENTER_YOUR_PASS_PHRASE_FIELD: '-ios class chain:**/XCUIElementTypeSecureTextField', OK_BUTTON: '~Ok', CONFIRM_PASS_PHRASE_FIELD: '~textField', + LOAD_ACCOUNT_BUTTON: '~load_account', + CREATE_NEW_KEY_BUTTON: '~Create a new key' }; class SetupKeyScreen extends BaseScreen { @@ -18,6 +20,10 @@ class SetupKeyScreen extends BaseScreen { return $(SELECTORS.SET_PASS_PHRASE_BUTTON); } + get loadAccountButton() { + return $(SELECTORS.LOAD_ACCOUNT_BUTTON) + } + get enterPassPhraseField() { return $(SELECTORS.ENTER_YOUR_PASS_PHRASE_FIELD); } @@ -30,6 +36,10 @@ class SetupKeyScreen extends BaseScreen { return $(SELECTORS.CONFIRM_PASS_PHRASE_FIELD) } + get createNewKeyButton () { + return $(SELECTORS.CREATE_NEW_KEY_BUTTON) + } + setPassPhrase = async (text: string = CommonData.account.passPhrase) => { // retrying several times because following login, we switch // from webview to our own view and then to another one several @@ -46,6 +56,32 @@ class SetupKeyScreen extends BaseScreen { await this.confirmPassPhrase(text); } + setPassPhraseForOtherProviderEmail = async (text: string = CommonData.outlookAccount.passPhrase) => { + + // retrying several times because following login, we switch + // from webview to our own view and then to another one several + // times, which was causing flaky tests. Originally we did a 10s + // delay but now instead we're retrying once per second until + // we see what we expect. + + let count = 0; + do { + await browser.pause(1000); + count++; + } while ((await (await this.loadAccountButton).isDisplayed() !== true && await (await this.createNewKeyButton).isDisplayed() !== true) && count <= 15); + + if(await (await this.enterPassPhraseField).isDisplayed() !== true) { + await this.clickCreateNewKeyButton(); + await this.fillPassPhrase(text); + await this.clickSetPassPhraseBtn(); + await this.confirmPassPhrase(text); + } else { + await this.fillPassPhrase(text); + await this.clickLoadAccountButton(); + } + } + + fillPassPhrase = async (passPhrase: string) => { await ElementHelper.waitClickAndType(await this.enterPassPhraseField, passPhrase); } @@ -54,10 +90,18 @@ class SetupKeyScreen extends BaseScreen { await ElementHelper.waitAndClick(await this.setPassPhraseButton); } + clickLoadAccountButton = async () => { + await ElementHelper.waitAndClick(await this.loadAccountButton); + } + confirmPassPhrase = async (passPhrase: string) => { await ElementHelper.waitClickAndType(await this.confirmPassPhraseField, passPhrase); await ElementHelper.waitAndClick(await this.okButton); } + + clickCreateNewKeyButton = async () => { + await ElementHelper.waitAndClick(await this.createNewKeyButton); + } } export default new SetupKeyScreen(); diff --git a/appium/tests/screenobjects/splash.screen.ts b/appium/tests/screenobjects/splash.screen.ts index 2c8800322..0ec5f25d1 100644 --- a/appium/tests/screenobjects/splash.screen.ts +++ b/appium/tests/screenobjects/splash.screen.ts @@ -1,6 +1,9 @@ import BaseScreen from './base.screen'; import { CommonData } from "../data"; import ElementHelper from "../helpers/ElementHelper"; +import { + EmailProviderScreen +} from '../screenobjects/all-screens'; const SELECTORS = { PRIVACY_TAB: '~privacy', @@ -98,6 +101,10 @@ class SplashScreen extends BaseScreen { await ElementHelper.waitAndClick(await this.continueWithGmailBtn); } + clickOtherEmailProvider = async () => { + await ElementHelper.waitAndClick(await this.otherEmailProviderButton) ; + } + clickContinueBtn = async () => { // expect(await this.continueButton).toBeDisplayed(); // expect(await this.cancelButton).toBeDisplayed(); @@ -135,7 +142,7 @@ class SplashScreen extends BaseScreen { } gmailLogin = async (email: string, password: string) => { - const emailSelector = `-ios class chain:**/XCUIElementTypeStaticText[\`label == "${email}"\`]`; + const emailSelector = `-ios class chain:**/XCUIElementTypeLink/XCUIElementTypeStaticText[\`label == "${email}"\`]`; await (await this.signInAsGoogleAccounLabel).waitForDisplayed(); await browser.pause(1000); // stability sleep for language change if (await (await $(emailSelector)).isDisplayed()) { @@ -160,6 +167,14 @@ class SplashScreen extends BaseScreen { await this.gmailLogin(email, password); await ElementHelper.waitElementInvisible(await this.signInAsGoogleAccounLabel); } + + loginToOtherEmailProvider = async (email: string = CommonData.outlookAccount.email, password: string = CommonData.outlookAccount.password!) => { + await this.clickOtherEmailProvider(); + await EmailProviderScreen.checkEmailProviderScreen(); + await EmailProviderScreen.fillEmail(email); + await EmailProviderScreen.fillPassword(password); + await EmailProviderScreen.clickConnectBtn(); + } } export default new SplashScreen(); diff --git a/appium/tests/specs/live/login/LoginToMultipleAccounts.spec.ts b/appium/tests/specs/live/login/LoginToMultipleAccounts.spec.ts new file mode 100644 index 000000000..3a353ae51 --- /dev/null +++ b/appium/tests/specs/live/login/LoginToMultipleAccounts.spec.ts @@ -0,0 +1,92 @@ +import { + SplashScreen, + SetupKeyScreen, + MailFolderScreen, + SearchScreen, + EmailScreen, + MenuBarScreen +} from '../../../screenobjects/all-screens'; +import {CommonData} from "../../../data"; +import BaseScreen from "../../../screenobjects/base.screen"; + + +describe('LOGIN: ', () => { + + it('user should be able login to multiple accounts', async () => { + + const senderOutlook = CommonData.outlookEmail.sender; + const subjectOutlook = CommonData.outlookEmail.subject; + const messageOutlook = CommonData.outlookEmail.message; + const outlookEmail = CommonData.outlookAccount.email; + const outlookFolder = CommonData.outlookAccount.outlookFolder; + + const senderGmail = CommonData.recipientsListEmail.sender; + const subjectGmail = CommonData.recipientsListEmail.subject; + const messageGmail = CommonData.recipientsListEmail.message; + const gmailFolder = CommonData.account.folder; + const wrongPassPhraseError = CommonData.errors.wrongPassPhraseOnLogin; + + await SplashScreen.loginToOtherEmailProvider(); + await SetupKeyScreen.setPassPhraseForOtherProviderEmail('wrong'); + await BaseScreen.checkModalMessage(wrongPassPhraseError); + await BaseScreen.clickOkButtonOnError(); + await SetupKeyScreen.setPassPhraseForOtherProviderEmail(); + await MailFolderScreen.checkInboxScreen(); + + await MailFolderScreen.clickSearchButton(); + + await SearchScreen.searchAndClickEmailForOutlook(subjectOutlook); + await EmailScreen.checkOpenedEmail(senderOutlook, subjectOutlook, messageOutlook); + + await EmailScreen.clickBackButton(); + + await SearchScreen.clickBackButton(); + + await MenuBarScreen.clickMenuIcon(); + await MenuBarScreen.checkUserEmail(outlookEmail); + await MenuBarScreen.checkMenuBarItem(outlookFolder); + + await MenuBarScreen.clickOnUserEmail(outlookEmail); + + await MenuBarScreen.clickAddAccountButton(); + + await SplashScreen.checkLoginPage(); + + await SplashScreen.login(); + + await SetupKeyScreen.setPassPhrase(); + await MailFolderScreen.checkInboxScreen(); + + await MailFolderScreen.clickSearchButton(); + + await SearchScreen.searchAndClickEmailForOutlook(subjectGmail); + await EmailScreen.checkOpenedEmail(senderGmail, subjectGmail, messageGmail); + + await EmailScreen.clickBackButton(); + + await SearchScreen.clickBackButton(); + + await MenuBarScreen.clickMenuIcon(); + await MenuBarScreen.checkUserEmail(); + await MenuBarScreen.checkMenuBarItem(gmailFolder); + + await MenuBarScreen.clickOnUserEmail(); + + await MenuBarScreen.selectAccount(1); + + await MailFolderScreen.checkInboxScreen(); + + await MailFolderScreen.clickSearchButton(); + + await SearchScreen.searchAndClickEmailForOutlook(subjectOutlook); + await EmailScreen.checkOpenedEmail(senderOutlook, subjectOutlook, messageOutlook); + + await EmailScreen.clickBackButton(); + + await SearchScreen.clickBackButton(); + + await MenuBarScreen.clickMenuIcon(); + await MenuBarScreen.checkUserEmail(outlookEmail); + await MenuBarScreen.checkMenuBarItem(outlookFolder); + }); +});