From 5aef0fb84d9b67c9f1c088c88a4790e52ccb1ba3 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Tue, 31 Aug 2021 21:45:27 +0300 Subject: [PATCH] Add FlowCryptUITests to swiftformat --- FlowCryptUI/Cell Nodes/ButtonCellNode.swift | 6 +- FlowCryptUI/Cell Nodes/TextCellNode.swift | 2 +- FlowCryptUI/Nodes/AttachmentNode.swift | 21 ++- FlowCryptUI/Nodes/TableNode.swift | 2 +- FlowCryptUI/Nodes/TextFieldNode.swift | 2 +- .../Views/NavigationBarItemsView.swift | 2 +- FlowCryptUITests/AppTestHelper.swift | 12 +- .../Resources/UserCredentials.swift | 6 +- FlowCryptUITests/SignInGoogleTest.swift | 34 ++--- FlowCryptUITests/SignInImapTest.swift | 138 +++++++++--------- FlowCryptUITests/TestCredentials.swift | 2 +- Scripts/format.sh | 2 +- 12 files changed, 113 insertions(+), 116 deletions(-) diff --git a/FlowCryptUI/Cell Nodes/ButtonCellNode.swift b/FlowCryptUI/Cell Nodes/ButtonCellNode.swift index 346bceba1..beafd7a64 100644 --- a/FlowCryptUI/Cell Nodes/ButtonCellNode.swift +++ b/FlowCryptUI/Cell Nodes/ButtonCellNode.swift @@ -13,7 +13,7 @@ public final class ButtonCellNode: CellNode { let title: NSAttributedString let insets: UIEdgeInsets let color: UIColor? - + public init( title: NSAttributedString, insets: UIEdgeInsets, @@ -24,7 +24,7 @@ public final class ButtonCellNode: CellNode { self.color = color } } - + private var onTap: (() -> Void)? public lazy var button = ButtonNode { [weak self] in self?.onTap?() @@ -41,7 +41,7 @@ public final class ButtonCellNode: CellNode { .withAlphaComponent(alpha) } } - + public init(input: Input, action: (() -> Void)?) { onTap = action self.insets = input.insets diff --git a/FlowCryptUI/Cell Nodes/TextCellNode.swift b/FlowCryptUI/Cell Nodes/TextCellNode.swift index 40c752611..e8574c6fc 100644 --- a/FlowCryptUI/Cell Nodes/TextCellNode.swift +++ b/FlowCryptUI/Cell Nodes/TextCellNode.swift @@ -56,7 +56,7 @@ public final class TextCellNode: CellNode { ? [textNode, spinner] : [textNode] ) - + return spec } } diff --git a/FlowCryptUI/Nodes/AttachmentNode.swift b/FlowCryptUI/Nodes/AttachmentNode.swift index 2b99d4cc8..4492019c6 100644 --- a/FlowCryptUI/Nodes/AttachmentNode.swift +++ b/FlowCryptUI/Nodes/AttachmentNode.swift @@ -15,15 +15,15 @@ public final class AttachmentNode: CellNode { self.size = size } } - + private let titleNode = ASTextNode() private let subtitleNode = ASTextNode2() private let imageNode = ASImageNode() private let buttonNode = ASButtonNode() private let borderNode = ASDisplayNode() - + private var onDownloadTap: (() -> Void)? - + public init( input: Input, onDownloadTap: (() -> Void)? @@ -38,20 +38,19 @@ public final class AttachmentNode: CellNode { imageNode.tintColor = .gray buttonNode.tintColor = .gray - + imageNode.image = UIImage(named: "paperclip")?.tinted(.gray) buttonNode.setImage(UIImage(named: "download")?.tinted(.gray), for: .normal) titleNode.attributedText = input.name subtitleNode.attributedText = input.size - + buttonNode.addTarget(self, action: #selector(onDownloadButtonTap), forControlEvents: .touchUpInside) - } - + @objc private func onDownloadButtonTap() { onDownloadTap?() } - + public override func layoutSpecThatFits(_: ASSizeRange) -> ASLayoutSpec { let verticalStack = ASStackLayoutSpec.vertical() verticalStack.spacing = 3 @@ -59,7 +58,7 @@ public final class AttachmentNode: CellNode { verticalStack.style.flexGrow = 1.0 verticalStack.children = [titleNode, subtitleNode] - + let finalSpec = ASStackLayoutSpec( direction: .horizontal, spacing: 10, @@ -69,7 +68,7 @@ public final class AttachmentNode: CellNode { ) let borderInset = UIEdgeInsets.side(8) - + let resultSpec = ASInsetLayoutSpec( insets: UIEdgeInsets( top: 8 + borderInset.top, @@ -79,7 +78,7 @@ public final class AttachmentNode: CellNode { ), child: finalSpec ) - + return ASOverlayLayoutSpec( child: resultSpec, overlay: ASInsetLayoutSpec( diff --git a/FlowCryptUI/Nodes/TableNode.swift b/FlowCryptUI/Nodes/TableNode.swift index 9c46f56c9..51ec6894d 100644 --- a/FlowCryptUI/Nodes/TableNode.swift +++ b/FlowCryptUI/Nodes/TableNode.swift @@ -57,7 +57,7 @@ public extension UIViewController { width: tableNode.frame.size.width, height: max(height, 0) ) - + return size } } diff --git a/FlowCryptUI/Nodes/TextFieldNode.swift b/FlowCryptUI/Nodes/TextFieldNode.swift index c678e2896..2d1b99a71 100644 --- a/FlowCryptUI/Nodes/TextFieldNode.swift +++ b/FlowCryptUI/Nodes/TextFieldNode.swift @@ -121,7 +121,7 @@ public final class TextFieldNode: ASDisplayNode { private var textFiledAction: TextFieldAction? private var onToolbarDoneAction: (() -> Void)? - + public init(preferredHeight: CGFloat?, action: TextFieldAction? = nil, accessibilityIdentifier: String?) { super.init() addSubnode(node) diff --git a/FlowCryptUI/Views/NavigationBarItemsView.swift b/FlowCryptUI/Views/NavigationBarItemsView.swift index 6e50300c4..d2bf89a77 100644 --- a/FlowCryptUI/Views/NavigationBarItemsView.swift +++ b/FlowCryptUI/Views/NavigationBarItemsView.swift @@ -56,7 +56,7 @@ public final class NavigationBarItemsView: UIBarButtonItem { required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - + public override var isEnabled: Bool { didSet { customView?.alpha = isEnabled ? 1 : 0.5 diff --git a/FlowCryptUITests/AppTestHelper.swift b/FlowCryptUITests/AppTestHelper.swift index 33f74b4f5..e5d749e4d 100644 --- a/FlowCryptUITests/AppTestHelper.swift +++ b/FlowCryptUITests/AppTestHelper.swift @@ -6,8 +6,8 @@ // Copyright © 2020 FlowCrypt Limited. All rights reserved. // -import XCTest import FlowCryptCommon +import XCTest protocol AppTest { var app: XCUIApplication! { get set } @@ -44,11 +44,11 @@ extension AppTest { var passPhraseTextField: XCUIElement { app.tables.secureTextFields["Enter your pass phrase"] } - + var navigationBackButton: XCUIElement { app.navigationBars.buttons["arrow left c"] } - + var setupUseAnotherAccount: XCUIElement { app.tables.buttons["Use Another Account"] } @@ -100,17 +100,17 @@ extension AppTest { _ = app.keys["\n"] } } - + func logOutIfNeeded() { logger.logInfo("Log out if needed") - + if menuButton.exists { logger.logInfo("User is logged in. Try to log out") menuButton.tap() tapOnMenu(folder: "Log out") } else { logger.logInfo("No menu button") - + let otherAccountButton = app.tables.buttons["Use Another Account"] if otherAccountButton.exists { logger.logInfo("Try to use another account") diff --git a/FlowCryptUITests/Resources/UserCredentials.swift b/FlowCryptUITests/Resources/UserCredentials.swift index c2b18f1f4..1ca2985ce 100644 --- a/FlowCryptUITests/Resources/UserCredentials.swift +++ b/FlowCryptUITests/Resources/UserCredentials.swift @@ -20,15 +20,15 @@ struct UserCredentials: Codable, Equatable { /// ci.tests.gmail@flowcrypt.dev /// default Gmail account static var gmailDev: UserCredentials = .user(with: "ci.tests.gmail@flowcrypt.dev") - + /// default@flowcrypt.test /// default IMAP/SMTP account static let imapDev = UserCredentials.user(with: "default@flowcrypt.test") - + /// den@flowcrypt.test /// user without messages static let imapDen = UserCredentials.user(with: "den@flowcrypt.test") - + /// has_msgs_no_backups@flowcrypt.test /// user with messages but without any backups static let imapHasMessagesNoBackups = UserCredentials.user(with: "has_msgs_no_backups@flowcrypt.test") diff --git a/FlowCryptUITests/SignInGoogleTest.swift b/FlowCryptUITests/SignInGoogleTest.swift index 8887eb4ee..f99cbecf0 100644 --- a/FlowCryptUITests/SignInGoogleTest.swift +++ b/FlowCryptUITests/SignInGoogleTest.swift @@ -6,8 +6,8 @@ // Copyright © 2020 FlowCrypt Limited. All rights reserved. // -import XCTest import FlowCryptCommon +import XCTest class SignInGoogleTest: XCTestCase, AppTest { var app: XCUIApplication! @@ -19,7 +19,7 @@ class SignInGoogleTest: XCTestCase, AppTest { .setupRegion() .build() .launched() - + logger.logInfo("Wait for launch") wait(10) } @@ -27,47 +27,47 @@ class SignInGoogleTest: XCTestCase, AppTest { private var gmailAlert: XCUIElement { Springboard.springboard.alerts.element } - + private var gmailLoginButton: XCUIElement { app.tables.buttons["Continue with Gmail"] } - + private var findTextFieldForGmailWebView: XCUIElement? { logger.logInfo("Try to find text field for gmail web view") return app.webViews.textFields.firstMatch } - + func test_1_successful_login() { logOutIfNeeded() wait(2) startGmailLoginFlow() wait(5) - + let user = UserCredentials.gmailDev - + enterUserCredentials(for: user) wait(5) enterUserDevCredentials(for: user) wait(5) } - + private func startGmailLoginFlow() { // Tap on Gmail login gmailLoginButton.tap() wait(5) - + // Wait for user alert and continue guard gmailAlert.exists else { assertionFailure("Gmail alert is missing") return } - + logger.logInfo("Gmail alert is on the screen") - + gmailAlert.buttons["Continue"].tap() wait(3) } - + private func enterUserCredentials(for user: UserCredentials) { // Try to find first text field in gmail web view logger.logInfo("Try to find text field for gmail web view") @@ -78,21 +78,21 @@ class SignInGoogleTest: XCTestCase, AppTest { } textField.tap() wait(0.2) - + textField.typeText(user.email) goKeyboardButton.tap() } - + private func enterUserDevCredentials(for user: UserCredentials) { let mainWebView = app.webViews.otherElements["main"] - + let userNameTextField = mainWebView.children(matching: .textField).element userNameTextField.tap() userNameTextField.typeText(user.email) - + app.toolbars.matching(identifier: "Toolbar").buttons["Next"].tap() app.typeText(user.password) - + wait(2) goKeyboardButton.tap() wait(3) diff --git a/FlowCryptUITests/SignInImapTest.swift b/FlowCryptUITests/SignInImapTest.swift index 5fd7a49b9..2e5cf6b35 100644 --- a/FlowCryptUITests/SignInImapTest.swift +++ b/FlowCryptUITests/SignInImapTest.swift @@ -6,93 +6,92 @@ // Copyright © 2019 FlowCrypt Limited. All rights reserved. // -import XCTest import FlowCryptCommon +import XCTest /// make ui_tests_imap class SignInImapTest: XCTestCase, AppTest { var app: XCUIApplication! - + override func setUp() { continueAfterFailure = false - + logger.logInfo("Start App") - + app = XCUIApplicationBuilder() .setupRegion() .build() .addSnapshot() .launched() - + logger.logInfo("Wait for launch") wait(10) } - + // login -> approve -> backups found -> enter pass phrase -> main flow func test_1_successful_login_imap() { let user = UserCredentials.imapDev loginWithImap(user) - + passPhraseTextField.tap() passPhraseTextField.typeText(user.pass) goKeyboardButton.tap() - + wait(4) XCTAssert(app.buttons["+"].exists) } - + // restart app -> loads inbox func test_2_restart_app_load_inbox() { let application = XCUIApplication() wait(2) application.buttons["+"].tap() - + wait(0.3) - + application.typeText("test@test.com") application.tables.textFields["Subject"].tap() wait(3) application.tables.textFields["Subject"].tap() - + application.typeText("ios") - + snapshot("compose") navigationBackButton.tap() wait(1) - + tapOnCell() snapshot("message") navigationBackButton.tap() - + wait(1) - + menuButton.tap() snapshot("menu") - + tapOnMenu(folder: "Settings") snapshot("settings") } - + // restart app -> loads inbox -> verify messages func test_3_restart_app_contains_emails() { let app = XCUIApplication() - + let tablesQuery = app.tables let cellsQuery = tablesQuery.cells - + // open first message cellsQuery.otherElements.containing(.staticText, identifier:"Jun 07").staticTexts["denbond7@flowcrypt.test"].tap() navigationBackButton.tap() - + // message > 5mb cellsQuery.otherElements.containing(.staticText, identifier:"...").staticTexts["denbond7@flowcrypt.test"].tap() wait(0.5) - - + cellsQuery.otherElements.containing(.staticText, identifier:"encrypted message with missing key error").staticTexts["denbond7@flowcrypt.test"].tap() tablesQuery.textViews.textViews["Could not decrypt:"].tap() navigationBackButton.tap() - + // open 3d message cellsQuery.otherElements.containing(.staticText, identifier:"Simple encrypted message").staticTexts["denbond7@flowcrypt.test"].tap() let textView = tablesQuery.children(matching: .cell) @@ -105,39 +104,39 @@ class SignInImapTest: XCTestCase, AppTest { .element textView.children(matching: .textView)["Simple encrypted text"].tap() navigationBackButton.tap() - + // open 4th message cellsQuery.otherElements.containing(.staticText, identifier:"Simple encrypted message + pub key").staticTexts["denbond7@flowcrypt.test"].tap() textView.children(matching: .textView)["It's an encrypted message with my pub key"].tap() navigationBackButton.tap() - + // open message with attachment cellsQuery.otherElements.containing(.staticText, identifier:"Simple encrypted message + attachment").staticTexts["denbond7@flowcrypt.test"].tap() tablesQuery.staticTexts["android.png.pgp"].tap() wait(1) cellsQuery.otherElements.containing(.staticText, identifier:"denbond7@flowcrypt.test").children(matching: .button).element.tap() navigationBackButton.tap() - + tablesQuery.staticTexts["Simple encrypted message + attachment"].tap() textView.children(matching: .textView)["It's an encrypted message with one encrypted attachment."].tap() } - + // restart app -> search functionality func test_4_restart_search() { // search let inboxNavigationBar = app.navigationBars["Inbox"] let searchButton = inboxNavigationBar.buttons["search icn"] let tablesQuery = app.tables - + searchButton.tap() - + let searchNavigationBar = app.navigationBars["Search"] let searchTextField = searchNavigationBar.searchFields["Search"] - + searchTextField.tap() wait(1) searchTextField.typeText("search") - + // Verify result with "search" let denBondMessage = tablesQuery.staticTexts["denbond7@flowcrypt.test"] denBondMessage.tap() @@ -151,28 +150,28 @@ class SignInImapTest: XCTestCase, AppTest { // go back to search controller navigationBackButton.tap() searchTextField.tap() - + // clear previous result let clearTextButton = searchTextField.buttons["Clear text"] clearTextButton.tap() - + // ESPRESSO searchTextField.tap() searchTextField.typeText("espresso") - + let espresso = tablesQuery.staticTexts["'espresso' in a subject"] espresso.tap() espresso.tap() textView.children(matching: .textView)["Some text"].tap() navigationBackButton.tap() - + let cellsQuery = tablesQuery.cells cellsQuery.otherElements.containing(.staticText, identifier:"Message").staticTexts["denbond7@flowcrypt.test"].tap() tablesQuery.staticTexts["Message"].tap() textView.children(matching: .textView)["The message with 'espresso' in a body"].tap() navigationBackButton.tap() clearTextButton.tap() - + // ANDROID searchTextField.tap() searchTextField.typeText("android") @@ -189,7 +188,7 @@ class SignInImapTest: XCTestCase, AppTest { app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element(boundBy: 0).children(matching: .other).element.children(matching: .table).element.tap() navigationBackButton.tap() } - + // login -> cancel func test_5_login_cancel() { let user = UserCredentials.imapDev @@ -198,7 +197,7 @@ class SignInImapTest: XCTestCase, AppTest { passPhraseTextField.swipeUp() tapUseAnotherAccountAndVerify() } - + // login with user without key backups and emails // login -> no messages func test_6_login_no_messages() { @@ -208,19 +207,19 @@ class SignInImapTest: XCTestCase, AppTest { func test_7_has_msgs_no_backups() { verifyFlowWithNoBackups(for: .imapHasMessagesNoBackups) } - + // login with wrong pass phrase func test_8_login_bad_pass_phrase() { let user = UserCredentials.imapDev loginWithImap(user) - + let tablesQuery = app.tables XCTAssert(tablesQuery.staticTexts["Remember pass phrase temporarily"].exists) - + passPhraseTextField.typeText(user.pass + "wrong") tapOnGoButton() wait(2) - + let errorAlert = app.alerts["Error"] XCTAssert(errorAlert.exists, "Error alert is missing after entering wrong pass phrase") XCTAssert(errorAlert.scrollViews.otherElements.staticTexts["Wrong pass phrase, please try again"].exists) @@ -235,94 +234,94 @@ extension SignInImapTest { private var toolbarDoneButton: XCUIElement { app.toolbars["Toolbar"].buttons["Done"] } - + private func loginWithImap(_ user: UserCredentials) { logger.logInfo("Login with \(user.email)") - + // other account logOutIfNeeded() wait(0.3) - + logger.logInfo("Use other email provider") let otherEmailButton = app.tables.buttons["Other email provider"] otherEmailButton.tap() - + logger.logInfo("Fill all user credentials") - + // email let emailTextField = app.tables.textFields["Email"] emailTextField.tap() emailTextField.typeText(user.email) wait(1) - + // move focus to username goKeyboardButton.tap() wait(1) - + // move focus to password goKeyboardButton.tap() app.typeText(user.password) - + // move focus to imap server (filled) goKeyboardButton.tap() - + // move focus to imap port goKeyboardButton.tap() - + // move focus to imap security type. Set none toolbarDoneButton.tap() app.pickerWheels["none"].tap() toolbarDoneButton.tap() - + // move to smtp type let smtpType = app.tables.textFields["SMTP type"] smtpType.tap() app.pickerWheels["none"].tap() toolbarDoneButton.tap() - + app.tables.buttons["Connect"].tap() - + logger.logInfo("Try to connect") wait(10) } - + private func verifyFlowWithNoBackups(for user: UserCredentials) { loginWithImap(user) - + let tablesQuery = app.tables - + let noBackupsLabel = tablesQuery.staticTexts["No backups found on account: \n\(user.email)"] let importMyKeyButton = tablesQuery.buttons["Import my key"] let createNewKeyButton = tablesQuery.buttons["Create a new key"] - + XCTAssert(noBackupsLabel.exists) XCTAssert(importMyKeyButton.exists) XCTAssert(createNewKeyButton.exists) XCTAssert(setupUseAnotherAccount.exists) - + importMyKeyButton.tap() navigationBackButton.tap() - + createNewKeyButton.tap() navigationBackButton.tap() - + importMyKeyButton.tap() - + let loadFromFileButton = tablesQuery.buttons["Load From File"] XCTAssert(loadFromFileButton.exists) - + let loadFromClipboard = tablesQuery.buttons["Load From Clipboard"] XCTAssert(loadFromClipboard.exists) navigationBackButton.tap() - + XCTAssert(noBackupsLabel.exists) - + tapUseAnotherAccountAndVerify() } - + private func tapUseAnotherAccountAndVerify() { setupUseAnotherAccount.tap() - + wait(1) XCTAssert(app.tables.buttons["Other email provider"].exists) } @@ -397,7 +396,6 @@ extension SignInImapTest { // } // } // - // // // send new msg -> inbox -> switch to sent -> open sent msg and verify content, recipient, subject diff --git a/FlowCryptUITests/TestCredentials.swift b/FlowCryptUITests/TestCredentials.swift index 9a716b012..ed340114c 100644 --- a/FlowCryptUITests/TestCredentials.swift +++ b/FlowCryptUITests/TestCredentials.swift @@ -6,8 +6,8 @@ // Copyright © 2020 FlowCrypt Limited. All rights reserved. // -import XCTest import FlowCryptCommon +import XCTest public let logger = Logger.nested("UI Tests") diff --git a/Scripts/format.sh b/Scripts/format.sh index 6c64824c0..70d38b478 100755 --- a/Scripts/format.sh +++ b/Scripts/format.sh @@ -13,7 +13,7 @@ fi if which swiftformat >/dev/null; then echo "Start formatting" # swiftlint autocorrect --path . - swiftformat "FlowCrypt" \ + swiftformat "FlowCrypt", "FlowCryptUITests" \ --rules trailingSpace \ --rules blankLinesAtEndOfScope \ --rules consecutiveBlankLines \