diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 07b890a36..d6dcf92de 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -5,7 +5,7 @@ agent: type: a1-standard-4 os_image: macos-xcode13 execution_time_limit: - minutes: 90 + minutes: 120 auto_cancel: running: when: branch != 'master' @@ -15,7 +15,7 @@ blocks: run: when: 'change_in(''/'', {exclude: [''/Core/package.json'', ''/Core/package-lock.json'']})' execution_time_limit: - minutes: 85 + minutes: 115 task: secrets: - name: flowcrypt-ios-ci-secrets diff --git a/FlowCrypt.xcworkspace/xcshareddata/swiftpm/Package.resolved b/FlowCrypt.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6528023d1..9b379cb07 100644 --- a/FlowCrypt.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/FlowCrypt.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -87,8 +87,8 @@ "repositoryURL": "https://github.com/realm/realm-cocoa", "state": { "branch": null, - "revision": "39177714b95bb5b1b29fffe28f1c7da77eef8e8b", - "version": "10.21.1" + "revision": "9dff9f2862240d521ad6ad599541269177ddb993", + "version": "10.22.0" } }, { @@ -96,8 +96,8 @@ "repositoryURL": "https://github.com/realm/realm-core", "state": { "branch": null, - "revision": "f1976f0d96d9b06fbe0afbd60090b1c3966b1e23", - "version": "11.8.0" + "revision": "6b81f1a7a2d421f9e0b9e7f04e76bcf736a54409", + "version": "11.9.0" } }, { diff --git a/FlowCrypt/Controllers/Compose/ComposeViewController.swift b/FlowCrypt/Controllers/Compose/ComposeViewController.swift index db952f904..8e572e692 100644 --- a/FlowCrypt/Controllers/Compose/ComposeViewController.swift +++ b/FlowCrypt/Controllers/Compose/ComposeViewController.swift @@ -124,7 +124,9 @@ final class ComposeViewController: TableNodeViewController { self.composeMessageService = composeMessageService ?? ComposeMessageService( clientConfiguration: clientConfiguration, encryptedStorage: appContext.encryptedStorage, - messageGateway: appContext.getRequiredMailProvider().messageSender + messageGateway: appContext.getRequiredMailProvider().messageSender, + passPhraseService: appContext.passPhraseService, + sender: email ) self.filesManager = filesManager self.photosManager = photosManager @@ -271,7 +273,6 @@ extension ComposeViewController { let sendableMsg = try await composeMessageService.validateAndProduceSendableMsg( input: input, contextToSend: contextToSend, - email: email, includeAttachments: false, signingPrv: signingPrv ) @@ -507,7 +508,6 @@ extension ComposeViewController { let sendableMsg = try await self.composeMessageService.validateAndProduceSendableMsg( input: self.input, contextToSend: self.contextToSend, - email: self.email, signingPrv: signingKey ) UIApplication.shared.isIdleTimerDisabled = true @@ -527,8 +527,17 @@ extension ComposeViewController { DispatchQueue.main.asyncAfter(deadline: .now() + hideSpinnerAnimationDuration) { [weak self] in guard let self = self else { return } - if case MessageValidationError.noPubRecipients = error, self.isMessagePasswordSupported { - self.setMessagePassword() + if self.isMessagePasswordSupported { + switch error { + case MessageValidationError.noPubRecipients: + self.setMessagePassword() + case MessageValidationError.notUniquePassword, + MessageValidationError.subjectContainsPassword, + MessageValidationError.weakPassword: + self.showAlert(message: error.errorMessage) + default: + self.showAlert(message: "compose_error".localized + "\n\n" + error.errorMessage) + } } else { self.showAlert(message: "compose_error".localized + "\n\n" + error.errorMessage) } @@ -1107,7 +1116,9 @@ extension ComposeViewController { } @objc private func messagePasswordTextFieldDidChange(_ sender: UITextField) { - messagePasswordAlertController?.actions[1].isEnabled = (sender.text ?? "").isNotEmpty + let password = sender.text ?? "" + let isPasswordStrong = composeMessageService.isMessagePasswordStrong(pwd: password) + messagePasswordAlertController?.actions[1].isEnabled = isPasswordStrong } } diff --git a/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift b/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift index ea0988f16..96a21ac13 100644 --- a/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift +++ b/FlowCrypt/Functionality/Error Handling/ErrorHandler.swift @@ -34,7 +34,7 @@ private struct ComposedErrorHandler: ErrorHandler { static let shared: ComposedErrorHandler = ComposedErrorHandler( handlers: [ KeyServiceErrorHandler(), - BackupServiceErrorHandler(), + BackupServiceErrorHandler() ] ) diff --git a/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageError.swift b/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageError.swift index c464947aa..e8eda540c 100644 --- a/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageError.swift +++ b/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageError.swift @@ -12,7 +12,10 @@ enum MessageValidationError: Error, CustomStringConvertible, Equatable { case emptyRecipient case emptySubject case emptyMessage - case missedPublicKey + case weakPassword + case subjectContainsPassword + case notUniquePassword + case missingPublicKey case noPubRecipients case revokedKeyRecipients case expiredKeyRecipients @@ -27,7 +30,13 @@ enum MessageValidationError: Error, CustomStringConvertible, Equatable { return "compose_enter_subject".localized case .emptyMessage: return "compose_enter_secure".localized - case .missedPublicKey: + case .weakPassword: + return "compose_password_weak".localized + case .subjectContainsPassword: + return "compose_password_subject_error".localized + case .notUniquePassword: + return "compose_password_passphrase_error".localized + case .missingPublicKey: return "compose_no_pub_sender".localized case .noPubRecipients: return "compose_recipient_no_pub".localized diff --git a/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageService.swift b/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageService.swift index b36bca7e4..2b2141ba7 100644 --- a/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageService.swift +++ b/FlowCrypt/Functionality/Services/Compose Message Service/ComposeMessageService.swift @@ -22,6 +22,7 @@ protocol CoreComposeMessageType { final class ComposeMessageService { private let messageGateway: MessageGateway + private let passPhraseService: PassPhraseServiceType private let storage: EncryptedStorageType private let contactsService: ContactsServiceType private let core: CoreComposeMessageType & KeyParser @@ -29,6 +30,8 @@ final class ComposeMessageService { private let draftGateway: DraftGateway? private lazy var logger: Logger = Logger.nested(Self.self) + private let sender: String + private struct ReplyInfo: Encodable { let sender: String let recipient: [String] @@ -40,12 +43,15 @@ final class ComposeMessageService { clientConfiguration: ClientConfiguration, encryptedStorage: EncryptedStorageType, messageGateway: MessageGateway, + passPhraseService: PassPhraseServiceType, draftGateway: DraftGateway? = nil, contactsService: ContactsServiceType? = nil, + sender: String, core: CoreComposeMessageType & KeyParser = Core.shared, enterpriseServer: EnterpriseServerApiType = EnterpriseServerApi() ) { self.messageGateway = messageGateway + self.passPhraseService = passPhraseService self.draftGateway = draftGateway self.storage = encryptedStorage self.contactsService = contactsService ?? ContactsService( @@ -54,6 +60,7 @@ final class ComposeMessageService { ) self.core = core self.enterpriseServer = enterpriseServer + self.sender = sender self.logger = Logger.nested(in: Self.self, with: "ComposeMessageService") } @@ -66,7 +73,6 @@ final class ComposeMessageService { func validateAndProduceSendableMsg( input: ComposeMessageInput, contextToSend: ComposeMessageContext, - email: String, includeAttachments: Bool = true, signingPrv: PrvKeyInfo? ) async throws -> SendableMsg { @@ -98,8 +104,8 @@ final class ComposeMessageService { let subject = contextToSend.subject ?? "(no subject)" - guard let myPubKey = storage.getKeypairs(by: email).map(\.public).first else { - throw MessageValidationError.missedPublicKey + guard let myPubKey = storage.getKeypairs(by: sender).map(\.public).first else { + throw MessageValidationError.missingPublicKey } let sendableAttachments: [SendableMsg.Attachment] = includeAttachments @@ -114,13 +120,24 @@ final class ComposeMessageService { let replyToMimeMsg = input.replyToMime .flatMap { String(data: $0, encoding: .utf8) } + if let password = contextToSend.messagePassword, password.isNotEmpty { + if subject.lowercased().contains(password.lowercased()) { + throw MessageValidationError.subjectContainsPassword + } + + let allAvailablePassPhrases = passPhraseService.getPassPhrases().map(\.value) + if allAvailablePassPhrases.contains(password) { + throw MessageValidationError.notUniquePassword + } + } + return SendableMsg( text: text, html: nil, to: recipients.map(\.email), cc: [], bcc: [], - from: email, + from: sender, subject: subject, replyToMimeMsg: replyToMimeMsg, atts: sendableAttachments, @@ -338,4 +355,27 @@ extension ComposeMessageService { return SendableMsgBody(text: text, html: html) } + + func isMessagePasswordStrong(pwd: String) -> Bool { + let minLength = 8 + + // currently password-protected messages are supported only with FES on iOS + // guard enterpriseServer.isFesUsed else { + // // consumers - just 8 chars requirement + // return pwd.count >= minLength + // } + + // enterprise FES - use common corporate password rules + let predicate = NSPredicate( + format: "SELF MATCHES %@ ", [ + "(?=.*[a-z])", // 1 lowercase character + "(?=.*[A-Z])", // 1 uppercase character + "(?=.*[0-9])", // 1 number + "(?=.*[\\-@$#!%*?&_,;:'()\"])", // 1 special symbol + ".{\(minLength),}$" // minimum 8 characters + ].joined() + ) + + return predicate.evaluate(with: pwd) + } } diff --git a/FlowCrypt/Resources/en.lproj/Localizable.strings b/FlowCrypt/Resources/en.lproj/Localizable.strings index 53f27ab1b..d4d9b4842 100644 --- a/FlowCrypt/Resources/en.lproj/Localizable.strings +++ b/FlowCrypt/Resources/en.lproj/Localizable.strings @@ -82,10 +82,13 @@ "compose_recipient_revoked" = "One or more of your recipients have revoked public keys (marked in red).\n\nPlease ask them to send you a new public key. If this is an enterprise installation, please ask your systems admin."; "compose_recipient_expired" = "One or more of your recipients have expired public keys (marked in orange).\n\nPlease ask them to send you updated public key. If this is an enterprise installation, please ask your systems admin."; "compose_recipient_invalid_email" = "One or more of your recipients have invalid email address (marked in red)"; +"compose_password_weak" = "Password didn't comply with company policy, which requires at least:\n\n- one uppercase\n- one lowercase\n- one number\n- one special character eg &/#\"-'_%-@,;:!*()\n- 8 characters length\n\nPlease update the password and re-send."; +"compose_password_passphrase_error" = "Please do not use your private key pass phrase as a password for this message.\n\nYou should come up with some other unique password that you can share with recipient."; +"compose_password_subject_error" = "Please do not include the password in the email subject. Sharing password over email undermines password based encryption.\n\nYou can ask the recipient to also install FlowCrypt, messages between FlowCrypt users don't need a password."; "compose_password_placeholder" = "Tap to add password for recipients who don't have encryption set up."; "compose_password_set_message" = "Web portal password added"; "compose_password_modal_title" = "Set web portal password"; -"compose_password_modal_message" = "The recipients will receive a link to read your message on a web portal, where they will need to enter this password.\n\nYou are responsible for sharing this password with recipients (use other medium to share the password - not email)"; +"compose_password_modal_message" = "The recipients will receive a link to read your message on a web portal, where they will need to enter this password.\n\nYou are responsible for sharing this password with recipients (use other medium to share the password - not email)\n\nPassword should include:\n- one uppercase\n- one lowercase\n- one number\n- one special character eg &/#\"-'_%-@,;:!*()\n- min 8 characters length"; "compose_error" = "Could not compose message"; "compose_reply_successful" = "Reply successfully sent"; "compose_quote_from" = "On %@ at %@ %@ wrote:"; // Date, time, sender diff --git a/FlowCryptAppTests/ExtensionTests.swift b/FlowCryptAppTests/ExtensionTests.swift index 87d9c0f89..22a12e6c7 100644 --- a/FlowCryptAppTests/ExtensionTests.swift +++ b/FlowCryptAppTests/ExtensionTests.swift @@ -82,11 +82,12 @@ extension ExtensionTests { dateFormatter.dateFormat = "HH:mm" let today = Date() - let year = Calendar.current.dateComponents([.year], from: today).year + let components = Calendar.current.dateComponents([.year, .day], from: today) + let sameYearDate = try XCTUnwrap(DateComponents( calendar: .current, timeZone: .current, - year: year, + year: components.year, month: 1, day: 24, hour: 18, diff --git a/FlowCryptAppTests/Functionality/Services/ComposeMessageServiceTests.swift b/FlowCryptAppTests/Functionality/Services/ComposeMessageServiceTests.swift index 95c86847e..da644e63b 100644 --- a/FlowCryptAppTests/Functionality/Services/ComposeMessageServiceTests.swift +++ b/FlowCryptAppTests/Functionality/Services/ComposeMessageServiceTests.swift @@ -43,8 +43,10 @@ class ComposeMessageServiceTests: XCTestCase { ), encryptedStorage: encryptedStorage, messageGateway: MessageGatewayMock(), + passPhraseService: PassPhraseServiceMock(), draftGateway: DraftGatewayMock(), contactsService: contactsService, + sender: "some@gmail.com", core: core ) @@ -65,7 +67,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: [], subject: nil ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -88,7 +89,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: nil ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -106,7 +106,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: nil ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -121,7 +120,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -136,7 +134,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: " " ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -154,7 +151,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -169,7 +165,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -184,7 +179,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -203,12 +197,11 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") } catch { - XCTAssertEqual(error as? MessageValidationError, MessageValidationError.missedPublicKey) + XCTAssertEqual(error as? MessageValidationError, MessageValidationError.missingPublicKey) } } @@ -227,7 +220,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -255,7 +247,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -283,7 +274,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -327,7 +317,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: subject ), - email: email, signingPrv: nil ) @@ -374,7 +363,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: "Some subject" ), - email: "some@gmail.com", signingPrv: nil ) XCTFail("expected to throw above") @@ -402,7 +390,6 @@ class ComposeMessageServiceTests: XCTestCase { recipients: recipients, subject: subject ), - email: email, signingPrv: nil ) diff --git a/FlowCryptCommon/Extensions/StringExtensions.swift b/FlowCryptCommon/Extensions/StringExtensions.swift index bae4bdd32..d75c20202 100644 --- a/FlowCryptCommon/Extensions/StringExtensions.swift +++ b/FlowCryptCommon/Extensions/StringExtensions.swift @@ -6,7 +6,7 @@ import Foundation public extension String { var hasContent: Bool { - trimmingCharacters(in: .whitespaces).isEmpty == false + !trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } var trimLeadingSlash: String { diff --git a/Gemfile.lock b/Gemfile.lock index fb0bc06aa..e51f6de72 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,7 +18,7 @@ GEM atomos (0.1.3) aws-eventstream (1.2.0) aws-partitions (1.549.0) - aws-sdk-core (3.125.4) + aws-sdk-core (3.125.5) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) @@ -26,7 +26,7 @@ GEM aws-sdk-kms (1.53.0) aws-sdk-core (~> 3, >= 3.125.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.111.1) + aws-sdk-s3 (1.111.3) aws-sdk-core (~> 3, >= 3.125.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) @@ -116,7 +116,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.200.0) + fastlane (2.201.2) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -162,7 +162,7 @@ GEM gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.15.0) google-apis-core (>= 0.4, < 2.a) - google-apis-core (0.4.1) + google-apis-core (0.4.2) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) diff --git a/Podfile.lock b/Podfile.lock index c9ee828b6..4cbc19c1a 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -16,7 +16,7 @@ PODS: - PINCache (~> 3.0.3) - PINRemoteImage/Core - SwiftFormat/CLI (0.49.2) - - SwiftLint (0.45.1) + - SwiftLint (0.46.1) - SwiftyRSA (1.7.0): - SwiftyRSA/ObjC (= 1.7.0) - SwiftyRSA/ObjC (1.7.0) @@ -65,7 +65,7 @@ SPEC CHECKSUMS: PINOperation: 00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20 PINRemoteImage: f1295b29f8c5e640e25335a1b2bd9d805171bd01 SwiftFormat: dca5803d3e2120aed5614f1653d252e62ac33be1 - SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761 + SwiftLint: aaa29a9f649316095a9079595cb60906bd899353 SwiftyRSA: 8c6dd1ea7db1b8dc4fb517a202f88bb1354bc2c6 Texture: 2e8ab2519452515f7f5a520f5a8f7e0a413abfa3 diff --git a/appium/tests/data/index.ts b/appium/tests/data/index.ts index 322ef4edc..7490e429c 100644 --- a/appium/tests/data/index.ts +++ b/appium/tests/data/index.ts @@ -107,10 +107,15 @@ export const CommonData = { }, recipientWithoutPublicKey: { email: 'no.publickey@flowcrypt.com', - password: '123456', - modalMessage: `Set web portal password\nThe recipients will receive a link to read your message on a web portal, where they will need to enter this password.\n\nYou are responsible for sharing this password with recipients (use other medium to share the password - not email)`, + subject: 'Test subject 1*', + weakPassword: '123aaBBc', + password: 'abcABC1*', + modalMessage: `Set web portal password\nThe recipients will receive a link to read your message on a web portal, where they will need to enter this password.\n\nYou are responsible for sharing this password with recipients (use other medium to share the password - not email)\n\nPassword should include: - one uppercase - one lowercase - one number - one special character eg &/#"-'_%-@,;:!*() - min 8 characters length`, emptyPasswordMessage: 'Tap to add password for recipients who don\'t have encryption set up.', addedPasswordMessage: 'Web portal password added', + weakPasswordMessage: 'Error\nPassword didn\'t comply with company policy, which requires at least:\n\n- one uppercase - one lowercase - one number - one special character eg &/#"-\'_%-@,;:!*() - 8 characters length\n\nPlease update the password and re-send.', + passphrasePasswordErrorMessage: 'Error\nPlease do not use your private key pass phrase as a password for this message.\n\nYou should come up with some other unique password that you can share with recipient.', + subjectPasswordErrorMessage: 'Error\nPlease do not include the password in the email subject. Sharing password over email undermines password based encryption.\n\nYou can ask the recipient to also install FlowCrypt, messages between FlowCrypt users don\'t need a password.' }, recipientWithExpiredPublicKey: { email: 'expired@flowcrypt.com' diff --git a/appium/tests/screenobjects/new-message.screen.ts b/appium/tests/screenobjects/new-message.screen.ts index 1d57140a0..175ddde68 100644 --- a/appium/tests/screenobjects/new-message.screen.ts +++ b/appium/tests/screenobjects/new-message.screen.ts @@ -116,8 +116,8 @@ class NewMessageScreen extends BaseScreen { composeEmail = async (recipient: string, subject: string, message: string) => { await this.setAddRecipient(recipient); - await this.setSubject(subject); await this.setComposeSecurityMessage(message); + await this.setSubject(subject); }; setAddRecipientByName = async (name: string, email: string) => { @@ -199,6 +199,11 @@ class NewMessageScreen extends BaseScreen { await ElementHelper.waitAndClick(await this.cancelButton); } + checkSetPasswordButton = async(isEnabled: boolean) => { + const el = await this.setPasswordButton; + expect(await el.isEnabled()).toBe(isEnabled); + } + checkPasswordCell = async (text: string) => { await ElementHelper.waitElementVisible(await this.passwordCell); await ElementHelper.checkStaticText(await this.passwordCell, text); diff --git a/appium/tests/screenobjects/splash.screen.ts b/appium/tests/screenobjects/splash.screen.ts index 0ec5f25d1..09577e756 100644 --- a/appium/tests/screenobjects/splash.screen.ts +++ b/appium/tests/screenobjects/splash.screen.ts @@ -84,7 +84,7 @@ class SplashScreen extends BaseScreen { return $(SELECTORS.SIGN_IN_WITH_GMAIL); } - get useAnotherAcoount() { + get useAnotherAccount() { return $(SELECTORS.USE_ANOTHER_ACCOUNT); } @@ -147,7 +147,7 @@ class SplashScreen extends BaseScreen { await browser.pause(1000); // stability sleep for language change if (await (await $(emailSelector)).isDisplayed()) { await ElementHelper.waitAndClick(await $(emailSelector)); - await (await this.useAnotherAcoount).waitForDisplayed({ timeout: 5000, reverse: true }); + await (await this.useAnotherAccount).waitForDisplayed({ timeout: 5000, reverse: true }); if (await (await this.passwordField).isDisplayed()) { await this.fillPassword(password); await this.clickNextBtn(); diff --git a/appium/tests/specs/live/composeEmail/CheckComposeEmailAfterReopening.spec.ts b/appium/tests/specs/live/composeEmail/CheckComposeEmailAfterReopening.spec.ts index 06e7a4468..5ea5b72bc 100644 --- a/appium/tests/specs/live/composeEmail/CheckComposeEmailAfterReopening.spec.ts +++ b/appium/tests/specs/live/composeEmail/CheckComposeEmailAfterReopening.spec.ts @@ -21,7 +21,7 @@ describe('COMPOSE EMAIL: ', () => { await MailFolderScreen.checkInboxScreen(); await MailFolderScreen.clickCreateEmail(); - await NewMessageScreen.composeEmail('', '', longEmailText); + await NewMessageScreen.setComposeSecurityMessage(longEmailText); await NewMessageScreen.checkRecipientsTextFieldIsInvisible(); await NewMessageScreen.clickBackButton(); diff --git a/appium/tests/specs/live/composeEmail/SendEmailToRecipientWithoutPublicKey.spec.ts b/appium/tests/specs/live/composeEmail/SendEmailToRecipientWithoutPublicKey.spec.ts index 85cd96577..cff6052bb 100644 --- a/appium/tests/specs/live/composeEmail/SendEmailToRecipientWithoutPublicKey.spec.ts +++ b/appium/tests/specs/live/composeEmail/SendEmailToRecipientWithoutPublicKey.spec.ts @@ -13,12 +13,14 @@ describe('COMPOSE EMAIL: ', () => { it('sending message to user without public key produces password modal', async () => { const recipient = CommonData.recipientWithoutPublicKey.email; - const emailSubject = CommonData.simpleEmail.subject; + const emailSubject = CommonData.recipientWithoutPublicKey.subject; const emailText = CommonData.simpleEmail.message; + const emailWeakPassword = CommonData.recipientWithoutPublicKey.weakPassword; const emailPassword = CommonData.recipientWithoutPublicKey.password; const passwordModalMessage = CommonData.recipientWithoutPublicKey.modalMessage; const emptyPasswordMessage = CommonData.recipientWithoutPublicKey.emptyPasswordMessage; + const subjectPasswordErrorMessage = CommonData.recipientWithoutPublicKey.subjectPasswordErrorMessage; const addedPasswordMessage = CommonData.recipientWithoutPublicKey.addedPasswordMessage; await SplashScreen.login(); @@ -42,6 +44,15 @@ describe('COMPOSE EMAIL: ', () => { await NewMessageScreen.checkPasswordCell(emptyPasswordMessage); await NewMessageScreen.clickPasswordCell(); + await NewMessageScreen.setMessagePassword(emailSubject); + await NewMessageScreen.clickSendButton(); + await BaseScreen.checkModalMessage(subjectPasswordErrorMessage); + await BaseScreen.clickOkButtonOnError(); + + await NewMessageScreen.clickPasswordCell(); + await NewMessageScreen.setMessagePassword(emailWeakPassword); + await NewMessageScreen.checkSetPasswordButton(false); + await NewMessageScreen.setMessagePassword(emailPassword); await NewMessageScreen.checkPasswordCell(addedPasswordMessage); });