From cd3b7f4c67c7e33b317d8567e59b32520c31449c Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Fri, 10 Sep 2021 20:16:47 +0300 Subject: [PATCH 01/10] Start working on EKM unit tests --- FlowCrypt.xcodeproj/project.pbxproj | 4 + .../Functionality/Services/AppStartup.swift | 4 +- .../ClientConfigurationService.swift | 3 +- .../ClientConfigurationServiceResults.swift | 2 +- FlowCrypt/Models/ClientConfiguration.swift | 16 ++++ FlowCrypt/Models/OrganisationalRule.swift | 7 +- .../ClientConfigurationServiceTest.swift | 81 +++++++++++++++++++ 7 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 FlowCryptAppTests/ClientConfigurationServiceTest.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 4be1ef061..5b7108104 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 9F0C3C2623194E0A00299985 /* FolderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0C3C2523194E0A00299985 /* FolderViewModel.swift */; }; 9F17976D2368EEBD002BF770 /* SetupViewDecorator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F17976C2368EEBD002BF770 /* SetupViewDecorator.swift */; }; 9F1B4A342624E49300420472 /* KeyAlgoObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E26F6924F25AB800612AF1 /* KeyAlgoObject.swift */; }; + 9F1F6D4F26EBBE2B009BC98A /* ClientConfigurationServiceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */; }; 9F228BA623C673AD005D2CB6 /* Springboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F228BA523C673AD005D2CB6 /* Springboard.swift */; }; 9F228BA923C67587005D2CB6 /* UserCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F228BA823C67587005D2CB6 /* UserCredentials.swift */; }; 9F228BAA23C67729005D2CB6 /* DataExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCAEFF16F5D91A35791730 /* DataExtensions.swift */; }; @@ -478,6 +479,7 @@ 9F1797692368EE90002BF770 /* ButtonCellNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonCellNode.swift; sourceTree = ""; }; 9F17976C2368EEBD002BF770 /* SetupViewDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupViewDecorator.swift; sourceTree = ""; }; 9F1797702368EEE8002BF770 /* ButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = ""; }; + 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationServiceTest.swift; sourceTree = ""; }; 9F228BA523C673AD005D2CB6 /* Springboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Springboard.swift; sourceTree = ""; }; 9F228BA823C67587005D2CB6 /* UserCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCredentials.swift; sourceTree = ""; }; 9F23EA4D237216FA0017DFED /* TextViewCellNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewCellNode.swift; sourceTree = ""; }; @@ -1103,6 +1105,7 @@ 9F6F3C6326ADFBDB005BD9C6 /* Mocks */, 9F2F206726AEEAA60044E144 /* CombineTestExtension.swift */, 9FC411892681191D004C0A69 /* PromiseTestExtension.swift */, + 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, ); path = FlowCryptAppTests; sourceTree = ""; @@ -2454,6 +2457,7 @@ 9F6F3C3526ADFA27005BD9C6 /* ComposeMessageServiceTests.swift in Sources */, 9FC41090268100B6004C0A69 /* CoreTypesTest.swift in Sources */, 9F976584267E194F0058419D /* TestData.swift in Sources */, + 9F1F6D4F26EBBE2B009BC98A /* ClientConfigurationServiceTest.swift in Sources */, 9F6F3C6A26ADFBEB005BD9C6 /* MessageGatewayMock.swift in Sources */, 9F7E903926A1AD7A0021C07F /* KeyDetailsTests.swift in Sources */, 9FC41183268118B1004C0A69 /* EmailProviderMock.swift in Sources */, diff --git a/FlowCrypt/Functionality/Services/AppStartup.swift b/FlowCrypt/Functionality/Services/AppStartup.swift index f0c74ff66..54dda78bd 100644 --- a/FlowCrypt/Functionality/Services/AppStartup.swift +++ b/FlowCrypt/Functionality/Services/AppStartup.swift @@ -114,10 +114,10 @@ struct AppStartup { switch session { case let .google(email, name, _): guard currentUser.email != email else { - Logger.logInfo("UserId = current user id") + logger.logInfo("UserId = current user id") return userId } - Logger.logInfo("UserId = google user id") + logger.logInfo("UserId = google user id") userId = UserId(email: email, name: name) case let .session(userObject): guard userObject.email != currentUser.email else { diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift index 68808cef6..7b6130813 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift @@ -6,6 +6,7 @@ // Copyright © 2021 FlowCrypt Limited. All rights reserved. // +// swiftlint:disable line_length protocol ClientConfigurationServiceType { func checkShouldUseEKM() -> ClientConfigurationService.CheckForUsingEKMResult } @@ -26,7 +27,7 @@ class ClientConfigurationService: ClientConfigurationServiceType { * 3) EKM is not in use because organisationalRules.isUsingKeyManager == false (result: normal login flow) */ func checkShouldUseEKM() -> CheckForUsingEKMResult { - let organisationalRules = self.organisationalRulesService.getSavedOrganisationalRulesForCurrentUser() + let organisationalRules = organisationalRulesService.getSavedOrganisationalRulesForCurrentUser() if !organisationalRules.isUsingKeyManager { return .doesNotUseEKM } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift index c6db0461b..4d1e71eb6 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift @@ -9,7 +9,7 @@ import Foundation extension ClientConfigurationService { - enum CheckForUsingEKMResult { + enum CheckForUsingEKMResult: Equatable { case usesEKM case inconsistentClientConfiguration(message: String) case doesNotUseEKM diff --git a/FlowCrypt/Models/ClientConfiguration.swift b/FlowCrypt/Models/ClientConfiguration.swift index 83bacf2a6..663161c34 100644 --- a/FlowCrypt/Models/ClientConfiguration.swift +++ b/FlowCrypt/Models/ClientConfiguration.swift @@ -37,6 +37,22 @@ struct ClientConfiguration: Codable, Equatable { let disallowAttesterSearchForDomains: [String]? let enforceKeygenAlgo: String? let enforceKeygenExpireMonths: Int? + + init( + flags: [ClientConfigurationFlag]? = nil, + customKeyserverUrl: String? = nil, + keyManagerUrl: String? = nil, + disallowAttesterSearchForDomains: [String]? = nil, + enforceKeygenAlgo: String? = nil, + enforceKeygenExpireMonths: Int? = nil + ) { + self.flags = flags + self.customKeyserverUrl = customKeyserverUrl + self.keyManagerUrl = keyManagerUrl + self.disallowAttesterSearchForDomains = disallowAttesterSearchForDomains + self.enforceKeygenAlgo = enforceKeygenAlgo + self.enforceKeygenExpireMonths = enforceKeygenExpireMonths + } } // MARK: - Empty model diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index f67d01eae..0f1c04e01 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -40,7 +40,12 @@ class OrganisationalRules { /// use when finding out if EKM is in use, to change functionality without actually neededing the EKM var isUsingKeyManager: Bool { - clientConfiguration.keyManagerUrl != nil + // check for empty string + guard let urlString = clientConfiguration.keyManagerUrl, urlString.isNotEmpty else { + return false + } + // check is url can be configured + return URL(string: urlString) != nil } /// Enforce a key algo for keygen, eg rsa2048,rsa4096,curve25519 diff --git a/FlowCryptAppTests/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/ClientConfigurationServiceTest.swift new file mode 100644 index 000000000..b2ea3a73f --- /dev/null +++ b/FlowCryptAppTests/ClientConfigurationServiceTest.swift @@ -0,0 +1,81 @@ +// +// ClientConfigurationServiceTest.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 10.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest +import Promises +@testable import FlowCrypt + +class OrganisationalRulesServiceMock: OrganisationalRulesServiceType { + + var fetchOrganisationalRulesForCurrentUserResult: Result = .failure(MockError.some) + func fetchOrganisationalRulesForCurrentUser() -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForCurrentUserResult) + } + + var fetchOrganisationalRulesForEmail: (String) -> (Result) = { email in + return .failure(MockError.some) + } + func fetchOrganisationalRules(for email: String) -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForEmail(email)) + } + + var clientConfiguration: ClientConfiguration! + + var getSavedOrganisationalRulesForCurrentUserResult: OrganisationalRules { + OrganisationalRules(clientConfiguration: clientConfiguration) + } + func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules { + getSavedOrganisationalRulesForCurrentUserResult + } +} + + +// check if Email Key Manager should be used test and other client configuration is consistent +class ClientConfigurationServiceTest: XCTestCase { + + var sut: ClientConfigurationService! + var organisationalRulesService = OrganisationalRulesServiceMock() + + override func setUp() { + super.setUp() + + sut = ClientConfigurationService(organisationalRulesService: organisationalRulesService) + } + + func testCheckDoesNotUseEKM() { + // EKM should not be used if keyManagerUrl is nil + organisationalRulesService.clientConfiguration = ClientConfiguration(keyManagerUrl: nil) + XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) + } + + func testShouldUseEKM() { + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [.privateKeyAutoimportOrAutogen], + keyManagerUrl: "https://test.ekm.flowcrypt.com" + ) + + } +} + +class OrganisationalRulesTests: XCTestCase { + var sut: OrganisationalRules! { + .init(clientConfiguration: clientConfiguration) + } + var clientConfiguration: ClientConfiguration! + + func testIsUsingKeyManager() { + clientConfiguration = ClientConfiguration(keyManagerUrl: "https://test.ekm.flowcrypt.com") + XCTAssertTrue(sut.isUsingKeyManager) + + clientConfiguration = ClientConfiguration(keyManagerUrl: "") + XCTAssertTrue(!sut.isUsingKeyManager) + + clientConfiguration = ClientConfiguration(keyManagerUrl: "not a url string") + XCTAssertTrue(!sut.isUsingKeyManager) + } +} From 74484b32e1b09a9c5a3bc1c42ff938882ccde04d Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Fri, 17 Sep 2021 18:42:44 +0300 Subject: [PATCH 02/10] Add OrganisationalRules tests which covers checkShouldUseEKM functionality --- FlowCrypt.xcodeproj/project.pbxproj | 6 +- .../ClientConfigurationService.swift | 6 +- FlowCrypt/Models/OrganisationalRule.swift | 11 +- .../Resources/en.lproj/Localizable.strings | 1 + .../ClientConfigurationServiceTest.swift | 78 ++++++------- .../OrganisationalRulesTests.swift | 109 ++++++++++++++++++ 6 files changed, 164 insertions(+), 47 deletions(-) rename FlowCryptAppTests/{ => Functionallity}/ClientConfigurationServiceTest.swift (74%) create mode 100644 FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 5b7108104..20a0f3015 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -137,6 +137,7 @@ 9F9362062573D0C80009912F /* Gmail+MessagesList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F9362052573D0C80009912F /* Gmail+MessagesList.swift */; }; 9F9362192573D10E0009912F /* Imap+Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F9362182573D10E0009912F /* Imap+Message.swift */; }; 9F93623F2573D16F0009912F /* Gmail+Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F93623E2573D16F0009912F /* Gmail+Message.swift */; }; + 9F9500AF26F4BAE300E8C78B /* OrganisationalRulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */; }; 9F953E09238310D500AEB98B /* KeyMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F953E08238310D500AEB98B /* KeyMethods.swift */; }; 9F976490267E11880058419D /* ImapHelperTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F3EF32923B15C9500FA0CEF /* ImapHelperTest.swift */; }; 9F9764C5267E14AB0058419D /* GeneralConstantsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A9CA44242622F800E1D898 /* GeneralConstantsTest.swift */; }; @@ -566,6 +567,7 @@ 9F9362052573D0C80009912F /* Gmail+MessagesList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Gmail+MessagesList.swift"; sourceTree = ""; }; 9F9362182573D10E0009912F /* Imap+Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Imap+Message.swift"; sourceTree = ""; }; 9F93623E2573D16F0009912F /* Gmail+Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Gmail+Message.swift"; sourceTree = ""; }; + 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesTests.swift; sourceTree = ""; }; 9F953E08238310D500AEB98B /* KeyMethods.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyMethods.swift; sourceTree = ""; }; 9F95A3F42360778E00C80B64 /* LinkButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkButtonNode.swift; sourceTree = ""; }; 9F95A3F623607C0900C80B64 /* SigninButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SigninButtonNode.swift; sourceTree = ""; }; @@ -875,6 +877,8 @@ 9F4164162665757700106194 /* PGP */, 21F836A72652A1CD00B2448C /* WKDURLs */, 9F4163F3266574CF00106194 /* Services */, + 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */, + 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, ); path = Functionallity; sourceTree = ""; @@ -1105,7 +1109,6 @@ 9F6F3C6326ADFBDB005BD9C6 /* Mocks */, 9F2F206726AEEAA60044E144 /* CombineTestExtension.swift */, 9FC411892681191D004C0A69 /* PromiseTestExtension.swift */, - 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, ); path = FlowCryptAppTests; sourceTree = ""; @@ -2476,6 +2479,7 @@ 9F97653D267E17C90058419D /* LocalStorageTests.swift in Sources */, 9F9764F4267E15CC0058419D /* ExtensionTests.swift in Sources */, 9F2F206826AEEAA60044E144 /* CombineTestExtension.swift in Sources */, + 9F9500AF26F4BAE300E8C78B /* OrganisationalRulesTests.swift in Sources */, 9FC413442683C912004C0A69 /* GmailServiceTest.swift in Sources */, 9F976556267E186D0058419D /* ClientConfigurationTests.swift in Sources */, 9F7E8EC6269877E70021C07F /* KeyInfoTests.swift in Sources */, diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift index 7b6130813..f94f79009 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift @@ -28,9 +28,13 @@ class ClientConfigurationService: ClientConfigurationServiceType { */ func checkShouldUseEKM() -> CheckForUsingEKMResult { let organisationalRules = organisationalRulesService.getSavedOrganisationalRulesForCurrentUser() - if !organisationalRules.isUsingKeyManager { + + guard organisationalRules.isUsingKeyManager else { return .doesNotUseEKM } + guard organisationalRules.isKeyManagerUrlValid else { + return .inconsistentClientConfiguration(message: "organisational_rules_url_not_valid".localized) + } if !organisationalRules.mustAutoImportOrAutogenPrvWithKeyManager { return .inconsistentClientConfiguration(message: "organisational_rules_autoimport_or_autogen_with_private_key_manager_error".localized) } diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index 0f1c04e01..7f24eefe0 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -40,6 +40,11 @@ class OrganisationalRules { /// use when finding out if EKM is in use, to change functionality without actually neededing the EKM var isUsingKeyManager: Bool { + clientConfiguration.keyManagerUrl != nil + } + + /// Check if key manager url set properly + var isKeyManagerUrlValid: Bool { // check for empty string guard let urlString = clientConfiguration.keyManagerUrl, urlString.isNotEmpty else { return false @@ -86,7 +91,11 @@ class OrganisationalRules { /// If a key can be found on FEKM, it will be auto imported /// If not, it will be autogenerated and stored there var mustAutoImportOrAutogenPrvWithKeyManager: Bool { - if !(clientConfiguration.flags ?? []).contains(.privateKeyAutoimportOrAutogen) { + guard let flags = clientConfiguration.flags else { + return false + } + + guard flags.contains(.privateKeyAutoimportOrAutogen) else { return false } diff --git a/FlowCrypt/Resources/en.lproj/Localizable.strings b/FlowCrypt/Resources/en.lproj/Localizable.strings index 83736f1b3..2b54453af 100644 --- a/FlowCrypt/Resources/en.lproj/Localizable.strings +++ b/FlowCrypt/Resources/en.lproj/Localizable.strings @@ -204,6 +204,7 @@ "organisational_rules_parse_error_description" = "Couldn't parse data while getting organisational rules"; "organisational_rules_email_format_error_description" = "Wrong user email format"; +"organisational_rules_url_not_valid" = "Please check if key manager url set correctly"; "organisational_rules_autoimport_or_autogen_with_private_key_manager_error" = "Combination of rules (key_manager_url set but PRV_AUTOIMPORT_OR_AUTOGEN is missing) is not supported on this platform"; "organisational_rules_autogen_passphrase_quitely_error" = "Combination of rules (PRV_AUTOIMPORT_OR_AUTOGEN + PASS_PHRASE_QUIET_AUTOGEN) is not supported on this platform"; "organisational_rules_forbid_storing_passphrase_error" = "Combination of rules (PRV_AUTOIMPORT_OR_AUTOGEN + missing FORBID_STORING_PASS_PHRASE) is not supported on this platform"; diff --git a/FlowCryptAppTests/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift similarity index 74% rename from FlowCryptAppTests/ClientConfigurationServiceTest.swift rename to FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift index b2ea3a73f..8df7a003b 100644 --- a/FlowCryptAppTests/ClientConfigurationServiceTest.swift +++ b/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift @@ -10,72 +10,62 @@ import XCTest import Promises @testable import FlowCrypt -class OrganisationalRulesServiceMock: OrganisationalRulesServiceType { - - var fetchOrganisationalRulesForCurrentUserResult: Result = .failure(MockError.some) - func fetchOrganisationalRulesForCurrentUser() -> Promise { - .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForCurrentUserResult) - } - - var fetchOrganisationalRulesForEmail: (String) -> (Result) = { email in - return .failure(MockError.some) - } - func fetchOrganisationalRules(for email: String) -> Promise { - .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForEmail(email)) - } - - var clientConfiguration: ClientConfiguration! - - var getSavedOrganisationalRulesForCurrentUserResult: OrganisationalRules { - OrganisationalRules(clientConfiguration: clientConfiguration) - } - func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules { - getSavedOrganisationalRulesForCurrentUserResult - } -} - - // check if Email Key Manager should be used test and other client configuration is consistent class ClientConfigurationServiceTest: XCTestCase { var sut: ClientConfigurationService! var organisationalRulesService = OrganisationalRulesServiceMock() - + override func setUp() { super.setUp() - + sut = ClientConfigurationService(organisationalRulesService: organisationalRulesService) } - + func testCheckDoesNotUseEKM() { // EKM should not be used if keyManagerUrl is nil organisationalRulesService.clientConfiguration = ClientConfiguration(keyManagerUrl: nil) XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) } - + func testShouldUseEKM() { organisationalRulesService.clientConfiguration = ClientConfiguration( - flags: [.privateKeyAutoimportOrAutogen], + flags: [ + .privateKeyAutoimportOrAutogen, + .forbidStoringPassphrase + ], keyManagerUrl: "https://test.ekm.flowcrypt.com" ) - + + XCTAssert(sut.checkShouldUseEKM() == .usesEKM) + } + + func testCheckShouldUseEKMShouldFailWithWrongConfiguration() { + } } -class OrganisationalRulesTests: XCTestCase { - var sut: OrganisationalRules! { - .init(clientConfiguration: clientConfiguration) + +class OrganisationalRulesServiceMock: OrganisationalRulesServiceType { + + var fetchOrganisationalRulesForCurrentUserResult: Result = .failure(MockError.some) + func fetchOrganisationalRulesForCurrentUser() -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForCurrentUserResult) + } + + var fetchOrganisationalRulesForEmail: (String) -> (Result) = { email in + return .failure(MockError.some) + } + func fetchOrganisationalRules(for email: String) -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForEmail(email)) } + var clientConfiguration: ClientConfiguration! - - func testIsUsingKeyManager() { - clientConfiguration = ClientConfiguration(keyManagerUrl: "https://test.ekm.flowcrypt.com") - XCTAssertTrue(sut.isUsingKeyManager) - - clientConfiguration = ClientConfiguration(keyManagerUrl: "") - XCTAssertTrue(!sut.isUsingKeyManager) - - clientConfiguration = ClientConfiguration(keyManagerUrl: "not a url string") - XCTAssertTrue(!sut.isUsingKeyManager) + + var getSavedOrganisationalRulesForCurrentUserResult: OrganisationalRules { + OrganisationalRules(clientConfiguration: clientConfiguration) + } + func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules { + getSavedOrganisationalRulesForCurrentUserResult } } diff --git a/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift b/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift new file mode 100644 index 000000000..aeb655aff --- /dev/null +++ b/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift @@ -0,0 +1,109 @@ +// +// OrganisationalRulesTests.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 17.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import XCTest +@testable import FlowCrypt + +class OrganisationalRulesTests: XCTestCase { + var sut: OrganisationalRules! { + .init(clientConfiguration: clientConfiguration) + } + var clientConfiguration: ClientConfiguration! + + func testIsUsingKeyManagerURL() { + clientConfiguration = ClientConfiguration(keyManagerUrl: "https://test.ekm.flowcrypt.com") + XCTAssertTrue(sut.isUsingKeyManager) + + clientConfiguration = ClientConfiguration(keyManagerUrl: nil) + XCTAssertFalse(sut.isKeyManagerUrlValid) + } + + func testIsUsingValidKeyManagerURL() { + // valid url check in + clientConfiguration = ClientConfiguration(keyManagerUrl: "") + XCTAssertFalse(sut.isKeyManagerUrlValid) + + clientConfiguration = ClientConfiguration(keyManagerUrl: "not a url string") + XCTAssertFalse(sut.isKeyManagerUrlValid) + } + + func testMustAutoImportOrAutogenPrvWithKeyManager() { + clientConfiguration = ClientConfiguration( + flags: [.privateKeyAutoimportOrAutogen], + keyManagerUrl: "https://test.ekm.flowcrypt.com" + ) + XCTAssertTrue(sut.mustAutoImportOrAutogenPrvWithKeyManager) + + clientConfiguration = ClientConfiguration( + flags: [], + keyManagerUrl: "https://test.ekm.flowcrypt.com" + ) + XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) + + clientConfiguration = ClientConfiguration( + flags: nil, + keyManagerUrl: "https://test.ekm.flowcrypt.com" + ) + XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) + + clientConfiguration = ClientConfiguration( + flags: [.defaultRememberPassphrase, .hideArmorMeta, .enforceAttesterSubmit], + keyManagerUrl: "https://test.ekm.flowcrypt.com" + ) + XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) + } + + func testMustAutogenPassPhraseQuietly() { + clientConfiguration = ClientConfiguration( + flags: [.passphraseQuietAutogen] + ) + XCTAssertTrue(sut.mustAutogenPassPhraseQuietly) + + clientConfiguration = ClientConfiguration(flags: []) + XCTAssertFalse(sut.mustAutogenPassPhraseQuietly) + + clientConfiguration = ClientConfiguration(flags: [.privateKeyAutoimportOrAutogen]) + XCTAssertFalse(sut.mustAutogenPassPhraseQuietly) + + clientConfiguration = ClientConfiguration(flags: nil) + XCTAssertFalse(sut.mustAutogenPassPhraseQuietly) + } + + func testForbidStoringPassPhrase() { + clientConfiguration = ClientConfiguration( + flags: [.forbidStoringPassphrase] + ) + XCTAssertTrue(sut.forbidStoringPassPhrase) + + clientConfiguration = ClientConfiguration(flags: []) + XCTAssertFalse(sut.forbidStoringPassPhrase) + + clientConfiguration = ClientConfiguration(flags: [.hideArmorMeta]) + XCTAssertFalse(sut.forbidStoringPassPhrase) + + clientConfiguration = ClientConfiguration(flags: nil) + XCTAssertFalse(sut.forbidStoringPassPhrase) + } + + func testMustSubmitAttester() { + clientConfiguration = ClientConfiguration( + flags: [.enforceAttesterSubmit] + ) + XCTAssertTrue(sut.mustSubmitAttester) + + clientConfiguration = ClientConfiguration(flags: []) + XCTAssertFalse(sut.mustSubmitAttester) + + clientConfiguration = ClientConfiguration(flags: [.hideArmorMeta]) + XCTAssertFalse(sut.mustSubmitAttester) + + clientConfiguration = ClientConfiguration(flags: nil) + XCTAssertFalse(sut.mustSubmitAttester) + } +} From f84f1522dad0a07d1ec324fbcd164d457efed70a Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Fri, 17 Sep 2021 22:30:53 +0300 Subject: [PATCH 03/10] Rename test url --- .../ClientConfigurationServiceTest.swift | 2 +- .../Functionallity/OrganisationalRulesTests.swift | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift index 8df7a003b..17ec8ed15 100644 --- a/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift +++ b/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift @@ -34,7 +34,7 @@ class ClientConfigurationServiceTest: XCTestCase { .privateKeyAutoimportOrAutogen, .forbidStoringPassphrase ], - keyManagerUrl: "https://test.ekm.flowcrypt.com" + keyManagerUrl: "https://ekm.example.com" ) XCTAssert(sut.checkShouldUseEKM() == .usesEKM) diff --git a/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift b/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift index aeb655aff..f1b60f89d 100644 --- a/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift +++ b/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift @@ -17,7 +17,7 @@ class OrganisationalRulesTests: XCTestCase { var clientConfiguration: ClientConfiguration! func testIsUsingKeyManagerURL() { - clientConfiguration = ClientConfiguration(keyManagerUrl: "https://test.ekm.flowcrypt.com") + clientConfiguration = ClientConfiguration(keyManagerUrl: "https://ekm.example.com") XCTAssertTrue(sut.isUsingKeyManager) clientConfiguration = ClientConfiguration(keyManagerUrl: nil) @@ -36,25 +36,25 @@ class OrganisationalRulesTests: XCTestCase { func testMustAutoImportOrAutogenPrvWithKeyManager() { clientConfiguration = ClientConfiguration( flags: [.privateKeyAutoimportOrAutogen], - keyManagerUrl: "https://test.ekm.flowcrypt.com" + keyManagerUrl: "https://ekm.example.com" ) XCTAssertTrue(sut.mustAutoImportOrAutogenPrvWithKeyManager) clientConfiguration = ClientConfiguration( flags: [], - keyManagerUrl: "https://test.ekm.flowcrypt.com" + keyManagerUrl: "https://ekm.example.com" ) XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) clientConfiguration = ClientConfiguration( flags: nil, - keyManagerUrl: "https://test.ekm.flowcrypt.com" + keyManagerUrl: "https://ekm.example.com" ) XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) clientConfiguration = ClientConfiguration( flags: [.defaultRememberPassphrase, .hideArmorMeta, .enforceAttesterSubmit], - keyManagerUrl: "https://test.ekm.flowcrypt.com" + keyManagerUrl: "https://ekm.example.com" ) XCTAssertFalse(sut.mustAutoImportOrAutogenPrvWithKeyManager) } From c93394f8ebe4ceb4b2f61bd4005ebd17b273d8c6 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Mon, 20 Sep 2021 21:33:29 +0300 Subject: [PATCH 04/10] Add tests for ClientConfigurationService --- FlowCrypt.xcodeproj/project.pbxproj | 16 +- .../Setup/SetupInitialViewController.swift | 4 +- .../ClientConfigurationService.swift | 10 +- .../ClientConfigurationServiceResults.swift | 25 ++- .../ClientConfigurationServiceTest.swift | 71 -------- .../ClientConfigurationServiceTest.swift | 167 ++++++++++++++++++ .../OrganisationalRulesServiceMock.swift | 35 ++++ .../OrganisationalRulesTests.swift | 0 8 files changed, 247 insertions(+), 81 deletions(-) delete mode 100644 FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift rename FlowCryptAppTests/Functionallity/{ => Services/Organisational Rules Service}/OrganisationalRulesTests.swift (100%) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 20a0f3015..1ad591a7f 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -111,6 +111,7 @@ 9F5C2A8B257E6C4900DE9B4B /* ImapError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A8A257E6C4900DE9B4B /* ImapError.swift */; }; 9F5C2A92257E94DF00DE9B4B /* Imap+MessageOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A91257E94DF00DE9B4B /* Imap+MessageOperations.swift */; }; 9F5C2A99257E94E900DE9B4B /* Gmail+MessageOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */; }; + 9F5F501D26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */; }; 9F6EE1552597399D0059BA51 /* BackupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE1542597399D0059BA51 /* BackupProvider.swift */; }; 9F6EE17B2598F9FA0059BA51 /* Gmail+Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE17A2598F9FA0059BA51 /* Gmail+Backup.swift */; }; 9F6F3BEE26ADF5DE005BD9C6 /* ComposeMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6F3BEC26ADF5DE005BD9C6 /* ComposeMessageService.swift */; }; @@ -528,6 +529,7 @@ 9F5C2A8A257E6C4900DE9B4B /* ImapError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImapError.swift; sourceTree = ""; }; 9F5C2A91257E94DF00DE9B4B /* Imap+MessageOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Imap+MessageOperations.swift"; sourceTree = ""; }; 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Gmail+MessageOperations.swift"; sourceTree = ""; }; + 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceMock.swift; sourceTree = ""; }; 9F696292236091DD003712E1 /* SignInImageNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInImageNode.swift; sourceTree = ""; }; 9F696294236091F4003712E1 /* SignInDescriptionNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInDescriptionNode.swift; sourceTree = ""; }; 9F6EE1542597399D0059BA51 /* BackupProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupProvider.swift; sourceTree = ""; }; @@ -877,8 +879,6 @@ 9F4164162665757700106194 /* PGP */, 21F836A72652A1CD00B2448C /* WKDURLs */, 9F4163F3266574CF00106194 /* Services */, - 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */, - 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, ); path = Functionallity; sourceTree = ""; @@ -1141,6 +1141,7 @@ 9F4163F3266574CF00106194 /* Services */ = { isa = PBXGroup; children = ( + 9F5F500C26F90AC800294FA2 /* Organisational Rules Service */, 9FC7EBB6266EBDF000F3BF5D /* PassPhraseStorageTests */, 9F6F3C3426ADFA27005BD9C6 /* ComposeMessageServiceTests.swift */, ); @@ -1239,6 +1240,16 @@ path = "MessageOperations Provider"; sourceTree = ""; }; + 9F5F500C26F90AC800294FA2 /* Organisational Rules Service */ = { + isa = PBXGroup; + children = ( + 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */, + 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, + 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */, + ); + path = "Organisational Rules Service"; + sourceTree = ""; + }; 9F6EE156259739A40059BA51 /* Backup Provider */ = { isa = PBXGroup; children = ( @@ -2465,6 +2476,7 @@ 9F7E903926A1AD7A0021C07F /* KeyDetailsTests.swift in Sources */, 9FC41183268118B1004C0A69 /* EmailProviderMock.swift in Sources */, 9F976490267E11880058419D /* ImapHelperTest.swift in Sources */, + 9F5F501D26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift in Sources */, 9FC4116526811861004C0A69 /* BackupServiceMock.swift in Sources */, 9FC413182683C492004C0A69 /* InMemoryPassPhraseStorageTest.swift in Sources */, 9F9764C5267E14AB0058419D /* GeneralConstantsTest.swift in Sources */, diff --git a/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift b/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift index beb337c44..6fd8bd00f 100644 --- a/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift @@ -149,8 +149,8 @@ extension SetupInitialViewController { state = .fetchingKeysFromEKM case .doesNotUseEKM: state = .searchingKeyBackupsInInbox - case .inconsistentClientConfiguration(let message): - showAlert(message: message) { [weak self] in + case .inconsistentClientConfiguration(let error): + showAlert(message: error.description) { [weak self] in self?.router.signOut() } } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift index f94f79009..02c582459 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationService.swift @@ -33,19 +33,19 @@ class ClientConfigurationService: ClientConfigurationServiceType { return .doesNotUseEKM } guard organisationalRules.isKeyManagerUrlValid else { - return .inconsistentClientConfiguration(message: "organisational_rules_url_not_valid".localized) + return .inconsistentClientConfiguration(checkError: .urlNotValid) } if !organisationalRules.mustAutoImportOrAutogenPrvWithKeyManager { - return .inconsistentClientConfiguration(message: "organisational_rules_autoimport_or_autogen_with_private_key_manager_error".localized) + return .inconsistentClientConfiguration(checkError: .autoImportOrAutogenPrvWithKeyManager) } if organisationalRules.mustAutogenPassPhraseQuietly { - return .inconsistentClientConfiguration(message: "organisational_rules_autogen_passphrase_quitely_error".localized) + return .inconsistentClientConfiguration(checkError: .autogenPassPhraseQuietly) } if !organisationalRules.forbidStoringPassPhrase { - return .inconsistentClientConfiguration(message: "organisational_rules_forbid_storing_passphrase_error".localized) + return .inconsistentClientConfiguration(checkError: .forbidStoringPassPhrase) } if organisationalRules.mustSubmitAttester { - return .inconsistentClientConfiguration(message: "organisational_rules_must_submit_attester_error".localized) + return .inconsistentClientConfiguration(checkError: .mustSubmitAttester) } return .usesEKM } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift index 4d1e71eb6..b6e6b8d9b 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationServiceResults.swift @@ -8,10 +8,33 @@ import Foundation +enum CheckEKMError: Error, CustomStringConvertible, Equatable { + case urlNotValid + case autoImportOrAutogenPrvWithKeyManager + case autogenPassPhraseQuietly + case forbidStoringPassPhrase + case mustSubmitAttester + + var description: String { + switch self { + case .urlNotValid: + return "organisational_rules_url_not_valid".localized + case .autoImportOrAutogenPrvWithKeyManager: + return "organisational_rules_autoimport_or_autogen_with_private_key_manager_error".localized + case .autogenPassPhraseQuietly: + return "organisational_rules_autogen_passphrase_quitely_error".localized + case .forbidStoringPassPhrase: + return "organisational_rules_forbid_storing_passphrase_error".localized + case .mustSubmitAttester: + return "organisational_rules_must_submit_attester_error".localized + } + } +} + extension ClientConfigurationService { enum CheckForUsingEKMResult: Equatable { case usesEKM - case inconsistentClientConfiguration(message: String) + case inconsistentClientConfiguration(checkError: CheckEKMError) case doesNotUseEKM } } diff --git a/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift deleted file mode 100644 index 17ec8ed15..000000000 --- a/FlowCryptAppTests/Functionallity/ClientConfigurationServiceTest.swift +++ /dev/null @@ -1,71 +0,0 @@ -// -// ClientConfigurationServiceTest.swift -// FlowCryptAppTests -// -// Created by Anton Kharchevskyi on 10.09.2021. -// Copyright © 2021 FlowCrypt Limited. All rights reserved. -// - -import XCTest -import Promises -@testable import FlowCrypt - -// check if Email Key Manager should be used test and other client configuration is consistent -class ClientConfigurationServiceTest: XCTestCase { - - var sut: ClientConfigurationService! - var organisationalRulesService = OrganisationalRulesServiceMock() - - override func setUp() { - super.setUp() - - sut = ClientConfigurationService(organisationalRulesService: organisationalRulesService) - } - - func testCheckDoesNotUseEKM() { - // EKM should not be used if keyManagerUrl is nil - organisationalRulesService.clientConfiguration = ClientConfiguration(keyManagerUrl: nil) - XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) - } - - func testShouldUseEKM() { - organisationalRulesService.clientConfiguration = ClientConfiguration( - flags: [ - .privateKeyAutoimportOrAutogen, - .forbidStoringPassphrase - ], - keyManagerUrl: "https://ekm.example.com" - ) - - XCTAssert(sut.checkShouldUseEKM() == .usesEKM) - } - - func testCheckShouldUseEKMShouldFailWithWrongConfiguration() { - - } -} - - -class OrganisationalRulesServiceMock: OrganisationalRulesServiceType { - - var fetchOrganisationalRulesForCurrentUserResult: Result = .failure(MockError.some) - func fetchOrganisationalRulesForCurrentUser() -> Promise { - .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForCurrentUserResult) - } - - var fetchOrganisationalRulesForEmail: (String) -> (Result) = { email in - return .failure(MockError.some) - } - func fetchOrganisationalRules(for email: String) -> Promise { - .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForEmail(email)) - } - - var clientConfiguration: ClientConfiguration! - - var getSavedOrganisationalRulesForCurrentUserResult: OrganisationalRules { - OrganisationalRules(clientConfiguration: clientConfiguration) - } - func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules { - getSavedOrganisationalRulesForCurrentUserResult - } -} diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift new file mode 100644 index 000000000..73526ac91 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift @@ -0,0 +1,167 @@ +// +// ClientConfigurationServiceTest.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 10.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest +@testable import FlowCrypt + +// check if Email Key Manager should be used test and other client configuration is consistent +class ClientConfigurationServiceTest: XCTestCase { + + var sut: ClientConfigurationService! + var organisationalRulesService = OrganisationalRulesServiceMock() + + override func setUp() { + super.setUp() + + sut = ClientConfigurationService(organisationalRulesService: organisationalRulesService) + } + + func testCheckDoesNotUseEKM() { + // EKM should not be used if keyManagerUrl is nil + organisationalRulesService.clientConfiguration = ClientConfiguration(keyManagerUrl: nil) + XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) + + // EKM should not be used if keyManagerUrl is nil + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [], + keyManagerUrl: nil + ) + + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [.forbidStoringPassphrase], + keyManagerUrl: nil + ) + XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) + } + + func testShouldUseEKM() { + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .privateKeyAutoimportOrAutogen, + .forbidStoringPassphrase + ], + keyManagerUrl: "https://ekm.example.com" + ) + + XCTAssert(sut.checkShouldUseEKM() == .usesEKM) + } + + func testCheckShouldUseEKMShouldFailWithoutValidURL() { + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .privateKeyAutoimportOrAutogen, + .forbidStoringPassphrase + ], + keyManagerUrl: "" + ) + + let result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let error) = result else { + return XCTFail() + } + + XCTAssert(error == .urlNotValid) + } + + func testCheckShouldUseEKMFailForAutogen() { + // No flags + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: nil, + keyManagerUrl: "https://ekm.example.com" + ) + + var result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let error) = result else { + return XCTFail() + } + + XCTAssert(error == .autoImportOrAutogenPrvWithKeyManager) + + // Empty flags + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [], + keyManagerUrl: "https://ekm.example.com" + ) + + result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let emptyFlagsError) = result else { + return XCTFail() + } + + XCTAssert(emptyFlagsError == .autoImportOrAutogenPrvWithKeyManager) + } + + func testCheckShouldUseEKMFailForAutoImportOrAutogen() { + // Wrong flags (without privateKeyAutoimportOrAutogen flag) + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .noAttesterSubmit + ], + keyManagerUrl: "https://ekm.example.com" + ) + + let result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let wrongFlagError) = result else { + return XCTFail() + } + + XCTAssert(wrongFlagError == .autoImportOrAutogenPrvWithKeyManager) + } + + func testCheckShouldUseEKMFailForAutogenPassPhraseQuietly() { + // sut pass mustAutoImportOrAutogenPrvWithKeyManager check + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .privateKeyAutoimportOrAutogen, + .passphraseQuietAutogen + ], + keyManagerUrl: "https://ekm.example.com" + ) + + let result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let error) = result else { + return XCTFail() + } + + XCTAssert(error == .autogenPassPhraseQuietly) + } + + func testCheckShouldUseEKMFailForForbidStoringPassPhrase() { + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .privateKeyAutoimportOrAutogen + ], + keyManagerUrl: "https://ekm.example.com" + ) + + let result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let error) = result else { + return XCTFail() + } + + XCTAssert(error == .forbidStoringPassPhrase) + } + + func testCheckShouldUseEKMFailForMustSubmitAttester() { + organisationalRulesService.clientConfiguration = ClientConfiguration( + flags: [ + .privateKeyAutoimportOrAutogen, + .forbidStoringPassphrase, + .enforceAttesterSubmit + ], + keyManagerUrl: "https://ekm.example.com" + ) + + let result = sut.checkShouldUseEKM() + guard case .inconsistentClientConfiguration(let error) = result else { + return XCTFail() + } + + XCTAssert(error == .mustSubmitAttester) + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift new file mode 100644 index 000000000..5edf84094 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift @@ -0,0 +1,35 @@ +// +// OrganisationalRulesServiceMock.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 20.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import Promises +@testable import FlowCrypt + +class OrganisationalRulesServiceMock: OrganisationalRulesServiceType { + + var fetchOrganisationalRulesForCurrentUserResult: Result = .failure(MockError.some) + func fetchOrganisationalRulesForCurrentUser() -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForCurrentUserResult) + } + + var fetchOrganisationalRulesForEmail: (String) -> (Result) = { email in + return .failure(MockError.some) + } + func fetchOrganisationalRules(for email: String) -> Promise { + .resolveAfter(timeout: 1, with: fetchOrganisationalRulesForEmail(email)) + } + + var clientConfiguration: ClientConfiguration! + + var getSavedOrganisationalRulesForCurrentUserResult: OrganisationalRules { + OrganisationalRules(clientConfiguration: clientConfiguration) + } + func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules { + getSavedOrganisationalRulesForCurrentUserResult + } +} diff --git a/FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesTests.swift similarity index 100% rename from FlowCryptAppTests/Functionallity/OrganisationalRulesTests.swift rename to FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesTests.swift From fd15b8a317f9b8c06f224dc96e8862f600d4b77c Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Mon, 20 Sep 2021 22:15:00 +0300 Subject: [PATCH 05/10] Start working on OrganisationalRulesServiceTests --- FlowCrypt.xcodeproj/project.pbxproj | 6 +- .../ClientConfigurationProvider.swift | 2 +- .../OrganisationalRulesService.swift | 13 +- FlowCrypt/Models/OrganisationalRule.swift | 2 +- .../OrganisationalRulesServiceTests.swift | 130 ++++++++++++++++++ 5 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index ca0d495b8..d6b1303c4 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -113,6 +113,7 @@ 9F5C2A92257E94DF00DE9B4B /* Imap+MessageOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A91257E94DF00DE9B4B /* Imap+MessageOperations.swift */; }; 9F5C2A99257E94E900DE9B4B /* Gmail+MessageOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */; }; 9F5F501D26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */; }; + 9F5F503526F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */; }; 9F6EE1552597399D0059BA51 /* BackupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE1542597399D0059BA51 /* BackupProvider.swift */; }; 9F6EE17B2598F9FA0059BA51 /* Gmail+Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE17A2598F9FA0059BA51 /* Gmail+Backup.swift */; }; 9F6F3BEE26ADF5DE005BD9C6 /* ComposeMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6F3BEC26ADF5DE005BD9C6 /* ComposeMessageService.swift */; }; @@ -485,8 +486,8 @@ 9F1797692368EE90002BF770 /* ButtonCellNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonCellNode.swift; sourceTree = ""; }; 9F17976C2368EEBD002BF770 /* SetupViewDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupViewDecorator.swift; sourceTree = ""; }; 9F1797702368EEE8002BF770 /* ButtonNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonNode.swift; sourceTree = ""; }; - 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationServiceTest.swift; sourceTree = ""; }; 9F1C90ED26F236BE0046E7D7 /* FlowCryptEnterprise.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FlowCryptEnterprise.entitlements; sourceTree = ""; }; + 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationServiceTest.swift; sourceTree = ""; }; 9F228BA523C673AD005D2CB6 /* Springboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Springboard.swift; sourceTree = ""; }; 9F228BA823C67587005D2CB6 /* UserCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCredentials.swift; sourceTree = ""; }; 9F23EA4D237216FA0017DFED /* TextViewCellNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewCellNode.swift; sourceTree = ""; }; @@ -535,6 +536,7 @@ 9F5C2A91257E94DF00DE9B4B /* Imap+MessageOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Imap+MessageOperations.swift"; sourceTree = ""; }; 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Gmail+MessageOperations.swift"; sourceTree = ""; }; 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceMock.swift; sourceTree = ""; }; + 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceTests.swift; sourceTree = ""; }; 9F696292236091DD003712E1 /* SignInImageNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInImageNode.swift; sourceTree = ""; }; 9F696294236091F4003712E1 /* SignInDescriptionNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInDescriptionNode.swift; sourceTree = ""; }; 9F6EE1542597399D0059BA51 /* BackupProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupProvider.swift; sourceTree = ""; }; @@ -1259,6 +1261,7 @@ 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */, 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */, + 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */, ); path = "Organisational Rules Service"; sourceTree = ""; @@ -2505,6 +2508,7 @@ 9FC4116B2681186D004C0A69 /* KeyMethodsTest.swift in Sources */, 9F97653D267E17C90058419D /* LocalStorageTests.swift in Sources */, 9F9764F4267E15CC0058419D /* ExtensionTests.swift in Sources */, + 9F5F503526F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift in Sources */, 9F2F206826AEEAA60044E144 /* CombineTestExtension.swift in Sources */, 9F9500AF26F4BAE300E8C78B /* OrganisationalRulesTests.swift in Sources */, 9FC413442683C912004C0A69 /* GmailServiceTest.swift in Sources */, diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift index 9f55d6942..a1fc75a86 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift @@ -20,7 +20,7 @@ struct ClientConfigurationProvider: CacheServiceType { let storage: CacheStorage let clientConfigurationCache: CacheService - init(storage: @escaping @autoclosure CacheStorage) { + init(storage: @escaping @autoclosure CacheStorage = DataService.shared.storage) { self.storage = storage self.clientConfigurationCache = CacheService(storage: storage()) } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift index 361bf226d..0d53d4c83 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift @@ -21,13 +21,16 @@ final class OrganisationalRulesService { private let enterpriseServerApi: EnterpriseServerApiType private let clientConfigurationProvider: ClientConfigurationProviderType + private let isCurrentUserExist: () -> (String?) init( - storage: @escaping @autoclosure CacheStorage = DataService.shared.storage, - enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi() + enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi(), + clientConfigurationProvider: ClientConfigurationProviderType = ClientConfigurationProvider(), + isCurrentUserExist: @autoclosure @escaping () -> (String?) = DataService.shared.currentUser?.email ) { self.enterpriseServerApi = enterpriseServerApi - self.clientConfigurationProvider = ClientConfigurationProvider(storage: storage()) + self.clientConfigurationProvider = clientConfigurationProvider + self.isCurrentUserExist = isCurrentUserExist } } @@ -35,12 +38,12 @@ final class OrganisationalRulesService { extension OrganisationalRulesService: OrganisationalRulesServiceType { func fetchOrganisationalRulesForCurrentUser() -> Promise { - guard let currentUser = DataService.shared.currentUser else { + guard let currentUserEmail = isCurrentUserExist() else { return Promise { _, reject in reject(OrganisationalRulesServiceError.noCurrentUser) } } - return fetchOrganisationalRules(for: currentUser.email) + return fetchOrganisationalRules(for: currentUserEmail) } func fetchOrganisationalRules(for email: String) -> Promise { diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index 7f24eefe0..d3d3d752d 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -13,7 +13,7 @@ import Foundation /// These either enforce, alter or forbid various behavior to fit customer needs class OrganisationalRules { - private let clientConfiguration: ClientConfiguration + let clientConfiguration: ClientConfiguration init(clientConfiguration: ClientConfiguration) { self.clientConfiguration = clientConfiguration diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift new file mode 100644 index 000000000..6bb1c1ca4 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift @@ -0,0 +1,130 @@ +// +// OrganisationalRulesServiceTests.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 20.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest +import Promises +@testable import FlowCrypt + +class OrganisationalRulesServiceTests: XCTestCase { + + var sut: OrganisationalRulesService! + var enterpriseServerApi: EnterpriseServerApiMock! + var clientConfigurationProvider: ClientConfigurationProviderMock! + var isCurrentUserExistMock: CurrentUserEmailMock! + + override func setUp() { + super.setUp() + enterpriseServerApi = EnterpriseServerApiMock() + clientConfigurationProvider = ClientConfigurationProviderMock() + isCurrentUserExistMock = CurrentUserEmailMock() + + sut = OrganisationalRulesService( + enterpriseServerApi: enterpriseServerApi, + clientConfigurationProvider: clientConfigurationProvider, + isCurrentUserExist: self.isCurrentUserExistMock.currentUserEmail() + ) + } + + func testGetSavedOrganisationalRulesForCurrentUser() { + let expectedConfiguration = ClientConfiguration(keyManagerUrl: "https://ekm.example.com") + clientConfigurationProvider.fetchCall = { + expectedConfiguration + } + + let organisationalRules = sut.getSavedOrganisationalRulesForCurrentUser() + XCTAssert(clientConfigurationProvider.fetchCount == 1) + XCTAssert(clientConfigurationProvider.fetchInvoked == true) + XCTAssert(organisationalRules.clientConfiguration == expectedConfiguration) + } +} + +class CurrentUserEmailMock { + var currentUserEmailCall: () -> (String?) = { + nil + } + func currentUserEmail() -> String? { + currentUserEmailCall() + } +} + +class EnterpriseServerApiMock: EnterpriseServerApiType { + var getActiveFesUrlInvoked = false + var getActiveFesUrlInvokedCount = 0 + var getActiveFesUrlCall: (String) -> (Result) = { email in + .failure(MockError.some) + } + func getActiveFesUrl(for email: String) -> Promise { + getActiveFesUrlInvoked = true + getActiveFesUrlInvokedCount += 1 + return Promise.resolveAfter(with: getActiveFesUrlCall(email)) + } + + var getActiveFesUrlForCurrentUserInvoked = false + var getActiveFesUrlForCurrentUserCount = 0 + var getActiveFesUrlForCurrentUserCall: () -> (Result) = { + .failure(MockError.some) + } + func getActiveFesUrlForCurrentUser() -> Promise { + getActiveFesUrlForCurrentUserInvoked = true + getActiveFesUrlForCurrentUserCount += 1 + return Promise.resolveAfter(with: getActiveFesUrlForCurrentUserCall()) + } + + var getClientConfigurationInvoked = false + var getClientConfigurationCount = 0 + var getClientConfigurationCall: (String) -> (Result) = { email in + .failure(MockError.some) + } + func getClientConfiguration(for email: String) -> Promise { + getClientConfigurationInvoked = true + getClientConfigurationCount += 1 + return Promise.resolveAfter(with: getClientConfigurationCall(email)) + } + + var getClientConfigurationForCurrentUserInvoked = false + var getClientConfigurationForCurrentUserCount = 0 + var getClientConfigurationForCurrentUserCall: () -> (Result) = { + .failure(MockError.some) + } + func getClientConfigurationForCurrentUser() -> Promise { + getClientConfigurationForCurrentUserInvoked = true + getClientConfigurationForCurrentUserCount += 1 + return Promise.resolveAfter(with: getClientConfigurationForCurrentUserCall()) + } +} + +class ClientConfigurationProviderMock: ClientConfigurationProviderType { + var fetchInvoked = false + var fetchCount = 0 + var fetchCall: () -> (ClientConfiguration?) = { + nil + } + func fetch() -> ClientConfiguration? { + fetchInvoked = true + fetchCount += 1 + return fetchCall() + } + + var removeClientConfigurationInvoked = false + var removeClientConfigurationCount = 0 + func removeClientConfiguration() { + removeClientConfigurationInvoked = true + removeClientConfigurationCount += 1 + } + + var saveInvoked = false + var saveCount = 0 + var saveCall: (ClientConfiguration) -> (Void) = { clientConfiguration in + + } + func save(clientConfiguration: ClientConfiguration) { + saveInvoked = true + saveCount += 1 + saveCall(clientConfiguration) + } +} From d2a2ea0cab8ad8773ec3b9173bba59ee5770b5e0 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Mon, 20 Sep 2021 22:46:25 +0300 Subject: [PATCH 06/10] Add tests for testFetchOrganisationalRulesForCurrentUser. Minor fixes --- .../OrganisationalRulesService.swift | 4 +- .../OrganisationalRulesServiceTests.swift | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift index 0d53d4c83..b435c967e 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift @@ -12,8 +12,6 @@ import Promises protocol OrganisationalRulesServiceType { func fetchOrganisationalRulesForCurrentUser() -> Promise - func fetchOrganisationalRules(for email: String) -> Promise - func getSavedOrganisationalRulesForCurrentUser() -> OrganisationalRules } @@ -46,7 +44,7 @@ extension OrganisationalRulesService: OrganisationalRulesServiceType { return fetchOrganisationalRules(for: currentUserEmail) } - func fetchOrganisationalRules(for email: String) -> Promise { + private func fetchOrganisationalRules(for email: String) -> Promise { Promise { [weak self] resolve, _ in guard let self = self else { throw AppErr.nilSelf } diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift index 6bb1c1ca4..7c190db67 100644 --- a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift @@ -41,6 +41,103 @@ class OrganisationalRulesServiceTests: XCTestCase { XCTAssert(clientConfigurationProvider.fetchInvoked == true) XCTAssert(organisationalRules.clientConfiguration == expectedConfiguration) } + + func testFetchOrganisationalRulesForCurrentUserNil() { + let expectation = XCTestExpectation(description: "Promise should resolve with error if current user = nil") + isCurrentUserExistMock.currentUserEmailCall = { + nil + } + sut.fetchOrganisationalRulesForCurrentUser() + .then(on: .main) { _ -> Promise in + XCTFail() + let result: Result = .failure(.some) + return Promise.resolveAfter(with: result) + } + .catch(on: .main) { error in + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + } + + func testFetchOrganisationalRulesForCurrentUser() { + let expectation = XCTestExpectation( + description: "fetchOrganisationalRules for test email should be called" + ) + let getClientConfigurationInvokedExpectation = XCTestExpectation( + description: "getClientConfiguration should be called" + ) + let getClientConfigurationCountExpectation = XCTestExpectation( + description: "getClientConfiguration should be called" + ) + let getClientConfigurationCallExpectation = XCTestExpectation( + description: "getClientConfiguration should be called for test email" + ) + let clientConfigurationProviderSaveCall = XCTestExpectation( + description: "clientConfigurationProvider save method should be called for config" + ) + + let expectations: [XCTestExpectation] = [ + expectation, + getClientConfigurationInvokedExpectation, + getClientConfigurationCountExpectation, + getClientConfigurationCallExpectation, + clientConfigurationProviderSaveCall + ] + + let expectedClientConfiguration = ClientConfiguration(keyManagerUrl: "https://ekm.example.com") + + // (String) -> (Result) + self.enterpriseServerApi.getClientConfigurationCall = { email in + if email == "example@flowcrypt.test" { + getClientConfigurationCallExpectation.fulfill() + } + // TODO: - ANTON - test for error + return Result.success(expectedClientConfiguration) + } + + // (ClientConfiguration) -> (Void) + self.clientConfigurationProvider.saveCall = { clientConfiguration in + // TODO: - ANTON - test in case wrong config fetched + if clientConfiguration.keyManagerUrl == expectedClientConfiguration.keyManagerUrl { + clientConfigurationProviderSaveCall.fulfill() + } + } + + isCurrentUserExistMock.currentUserEmailCall = { + "example@flowcrypt.test" + } + sut.fetchOrganisationalRulesForCurrentUser() + .then(on: .main) { _ -> Promise in + expectation.fulfill() + + // test calls for enterpriseServerApi + if self.enterpriseServerApi.getClientConfigurationInvoked { + getClientConfigurationInvokedExpectation.fulfill() + } + if self.enterpriseServerApi.getClientConfigurationCount == 1 { + getClientConfigurationCountExpectation.fulfill() + } + + + // test calls for clientConfigurationProvider + if self.clientConfigurationProvider.saveInvoked { + + } + if self.clientConfigurationProvider.saveCount == 1 { + + } + + + let result: Result = .failure(.some) + return Promise.resolveAfter(with: result) + } + .catch(on: .main) { error in + XCTFail() + } + + wait(for: expectations, timeout: 1) + } } class CurrentUserEmailMock { From 270566bd366c0d892701a9862ffebea6fdfec406 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Tue, 21 Sep 2021 21:47:37 +0300 Subject: [PATCH 07/10] Add DispatchQueue.promises = .global() to unit tests --- .../OrganisationalRulesServiceTests.swift | 4 +++- FlowCryptAppTests/PromiseTestExtension.swift | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift index 7c190db67..99a43cc2d 100644 --- a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift @@ -28,6 +28,8 @@ class OrganisationalRulesServiceTests: XCTestCase { clientConfigurationProvider: clientConfigurationProvider, isCurrentUserExist: self.isCurrentUserExistMock.currentUserEmail() ) + + DispatchQueue.promises = .global() } func testGetSavedOrganisationalRulesForCurrentUser() { @@ -107,6 +109,7 @@ class OrganisationalRulesServiceTests: XCTestCase { isCurrentUserExistMock.currentUserEmailCall = { "example@flowcrypt.test" } + sut.fetchOrganisationalRulesForCurrentUser() .then(on: .main) { _ -> Promise in expectation.fulfill() @@ -119,7 +122,6 @@ class OrganisationalRulesServiceTests: XCTestCase { getClientConfigurationCountExpectation.fulfill() } - // test calls for clientConfigurationProvider if self.clientConfigurationProvider.saveInvoked { diff --git a/FlowCryptAppTests/PromiseTestExtension.swift b/FlowCryptAppTests/PromiseTestExtension.swift index f4a7dce81..976e7cb75 100644 --- a/FlowCryptAppTests/PromiseTestExtension.swift +++ b/FlowCryptAppTests/PromiseTestExtension.swift @@ -10,7 +10,7 @@ import Foundation import Promises extension Promise { - static func resolveAfter(timeout: TimeInterval = 5, with result: Result) -> Promise { + static func resolveAfter(timeout: TimeInterval = 0.2, with result: Result) -> Promise { Promise { resolve, reject in DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { switch result { From 6ede10afac802a1b8832244ea4e9a871ed07a2b2 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Tue, 21 Sep 2021 22:35:51 +0300 Subject: [PATCH 08/10] Add tests for OrganisationalRulesService --- .../OrganisationalRulesServiceTests.swift | 77 ++++++++++++++----- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift index 99a43cc2d..24b5b5a00 100644 --- a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift @@ -63,7 +63,7 @@ class OrganisationalRulesServiceTests: XCTestCase { } func testFetchOrganisationalRulesForCurrentUser() { - let expectation = XCTestExpectation( + let fetchOrganisationalRulesExpectation = XCTestExpectation( description: "fetchOrganisationalRules for test email should be called" ) let getClientConfigurationInvokedExpectation = XCTestExpectation( @@ -78,13 +78,17 @@ class OrganisationalRulesServiceTests: XCTestCase { let clientConfigurationProviderSaveCall = XCTestExpectation( description: "clientConfigurationProvider save method should be called for config" ) + let clientConfigurationProviderSaveCountCall = XCTestExpectation( + description: "clientConfigurationProvider save method should be called for config" + ) let expectations: [XCTestExpectation] = [ - expectation, + fetchOrganisationalRulesExpectation, getClientConfigurationInvokedExpectation, getClientConfigurationCountExpectation, getClientConfigurationCallExpectation, - clientConfigurationProviderSaveCall + clientConfigurationProviderSaveCall, + clientConfigurationProviderSaveCountCall ] let expectedClientConfiguration = ClientConfiguration(keyManagerUrl: "https://ekm.example.com") @@ -94,13 +98,11 @@ class OrganisationalRulesServiceTests: XCTestCase { if email == "example@flowcrypt.test" { getClientConfigurationCallExpectation.fulfill() } - // TODO: - ANTON - test for error return Result.success(expectedClientConfiguration) } // (ClientConfiguration) -> (Void) self.clientConfigurationProvider.saveCall = { clientConfiguration in - // TODO: - ANTON - test in case wrong config fetched if clientConfiguration.keyManagerUrl == expectedClientConfiguration.keyManagerUrl { clientConfigurationProviderSaveCall.fulfill() } @@ -111,8 +113,8 @@ class OrganisationalRulesServiceTests: XCTestCase { } sut.fetchOrganisationalRulesForCurrentUser() - .then(on: .main) { _ -> Promise in - expectation.fulfill() + .then(on: .main) { orgRules -> Promise in + fetchOrganisationalRulesExpectation.fulfill() // test calls for enterpriseServerApi if self.enterpriseServerApi.getClientConfigurationInvoked { @@ -121,17 +123,11 @@ class OrganisationalRulesServiceTests: XCTestCase { if self.enterpriseServerApi.getClientConfigurationCount == 1 { getClientConfigurationCountExpectation.fulfill() } - - // test calls for clientConfigurationProvider - if self.clientConfigurationProvider.saveInvoked { - - } if self.clientConfigurationProvider.saveCount == 1 { - + clientConfigurationProviderSaveCountCall.fulfill() } - - let result: Result = .failure(.some) + let result: Result = .success(orgRules) return Promise.resolveAfter(with: result) } .catch(on: .main) { error in @@ -140,6 +136,49 @@ class OrganisationalRulesServiceTests: XCTestCase { wait(for: expectations, timeout: 1) } + + func testInCaseGetClientConfigurationReturnsError() { + let fetchOrganisationalRulesForCurrentUserExpectation = XCTestExpectation() + + let expectations = [ + fetchOrganisationalRulesForCurrentUserExpectation + ] + + let expectedClientConfiguration = ClientConfiguration(keyManagerUrl: "https://ekm.example.com") + + self.enterpriseServerApi.getClientConfigurationCall = { email in + .failure(MockError.some) + } + + isCurrentUserExistMock.currentUserEmailCall = { + "example@flowcrypt.test" + } + + clientConfigurationProvider.fetchCall = { + expectedClientConfiguration + } + + sut.fetchOrganisationalRulesForCurrentUser() + .then(on: .main) { organisationalRules -> Promise in + if organisationalRules.clientConfiguration == expectedClientConfiguration { + fetchOrganisationalRulesForCurrentUserExpectation.fulfill() + } + let result: Result = .success(organisationalRules) + return Promise.resolveAfter(with: result) + } + .recover { error -> Promise in + let result: Result = .success(OrganisationalRules(clientConfiguration: expectedClientConfiguration)) + return Promise.resolveAfter(with: result) + } + wait(for: expectations, timeout: 1) + } +} + +enum OrganisationalRulesServiceError: Error { + case getActiveFesUrlCall + case getActiveFesUrlForCurrentUserCall + case getClientConfigurationCall + case getClientConfigurationForCurrentUserCall } class CurrentUserEmailMock { @@ -155,7 +194,7 @@ class EnterpriseServerApiMock: EnterpriseServerApiType { var getActiveFesUrlInvoked = false var getActiveFesUrlInvokedCount = 0 var getActiveFesUrlCall: (String) -> (Result) = { email in - .failure(MockError.some) + .failure(OrganisationalRulesServiceError.getActiveFesUrlCall) } func getActiveFesUrl(for email: String) -> Promise { getActiveFesUrlInvoked = true @@ -166,7 +205,7 @@ class EnterpriseServerApiMock: EnterpriseServerApiType { var getActiveFesUrlForCurrentUserInvoked = false var getActiveFesUrlForCurrentUserCount = 0 var getActiveFesUrlForCurrentUserCall: () -> (Result) = { - .failure(MockError.some) + .failure(OrganisationalRulesServiceError.getActiveFesUrlForCurrentUserCall) } func getActiveFesUrlForCurrentUser() -> Promise { getActiveFesUrlForCurrentUserInvoked = true @@ -177,7 +216,7 @@ class EnterpriseServerApiMock: EnterpriseServerApiType { var getClientConfigurationInvoked = false var getClientConfigurationCount = 0 var getClientConfigurationCall: (String) -> (Result) = { email in - .failure(MockError.some) + .failure(OrganisationalRulesServiceError.getClientConfigurationCall) } func getClientConfiguration(for email: String) -> Promise { getClientConfigurationInvoked = true @@ -188,7 +227,7 @@ class EnterpriseServerApiMock: EnterpriseServerApiType { var getClientConfigurationForCurrentUserInvoked = false var getClientConfigurationForCurrentUserCount = 0 var getClientConfigurationForCurrentUserCall: () -> (Result) = { - .failure(MockError.some) + .failure(OrganisationalRulesServiceError.getClientConfigurationForCurrentUserCall) } func getClientConfigurationForCurrentUser() -> Promise { getClientConfigurationForCurrentUserInvoked = true From a27e5c532e2a13a72ae74f5346ff8e7d1fc9d9b1 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Tue, 21 Sep 2021 22:46:02 +0300 Subject: [PATCH 09/10] Organise code for Organisational Rules Service tests --- FlowCrypt.xcodeproj/project.pbxproj | 22 ++++- .../ClientConfigurationProviderMock.swift | 41 +++++++++ .../Mocks/CurrentUserEmailMock.swift | 18 ++++ .../Mocks/EnterpriseServerApiMock.swift | 57 ++++++++++++ .../OrganisationalRulesServiceMock.swift | 0 .../OrganisationalRulesServiceTests.swift | 90 +------------------ 6 files changed, 139 insertions(+), 89 deletions(-) create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/ClientConfigurationProviderMock.swift create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/CurrentUserEmailMock.swift create mode 100644 FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/EnterpriseServerApiMock.swift rename FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/{ => Mocks}/OrganisationalRulesServiceMock.swift (100%) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index d6b1303c4..fa58e08d1 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -114,6 +114,9 @@ 9F5C2A99257E94E900DE9B4B /* Gmail+MessageOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */; }; 9F5F501D26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */; }; 9F5F503526F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */; }; + 9F5F503C26FA6C5E00294FA2 /* CurrentUserEmailMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F503B26FA6C5E00294FA2 /* CurrentUserEmailMock.swift */; }; + 9F5F504326FA6C7500294FA2 /* EnterpriseServerApiMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F504226FA6C7500294FA2 /* EnterpriseServerApiMock.swift */; }; + 9F5F504A26FA6C8F00294FA2 /* ClientConfigurationProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F504926FA6C8F00294FA2 /* ClientConfigurationProviderMock.swift */; }; 9F6EE1552597399D0059BA51 /* BackupProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE1542597399D0059BA51 /* BackupProvider.swift */; }; 9F6EE17B2598F9FA0059BA51 /* Gmail+Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE17A2598F9FA0059BA51 /* Gmail+Backup.swift */; }; 9F6F3BEE26ADF5DE005BD9C6 /* ComposeMessageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6F3BEC26ADF5DE005BD9C6 /* ComposeMessageService.swift */; }; @@ -537,6 +540,9 @@ 9F5C2A98257E94E900DE9B4B /* Gmail+MessageOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Gmail+MessageOperations.swift"; sourceTree = ""; }; 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceMock.swift; sourceTree = ""; }; 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceTests.swift; sourceTree = ""; }; + 9F5F503B26FA6C5E00294FA2 /* CurrentUserEmailMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentUserEmailMock.swift; sourceTree = ""; }; + 9F5F504226FA6C7500294FA2 /* EnterpriseServerApiMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterpriseServerApiMock.swift; sourceTree = ""; }; + 9F5F504926FA6C8F00294FA2 /* ClientConfigurationProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationProviderMock.swift; sourceTree = ""; }; 9F696292236091DD003712E1 /* SignInImageNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInImageNode.swift; sourceTree = ""; }; 9F696294236091F4003712E1 /* SignInDescriptionNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInDescriptionNode.swift; sourceTree = ""; }; 9F6EE1542597399D0059BA51 /* BackupProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupProvider.swift; sourceTree = ""; }; @@ -1260,12 +1266,23 @@ children = ( 9F9500AE26F4BAE300E8C78B /* OrganisationalRulesTests.swift */, 9F1F6D4E26EBBE2A009BC98A /* ClientConfigurationServiceTest.swift */, - 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */, 9F5F503426F90E5F00294FA2 /* OrganisationalRulesServiceTests.swift */, + 9F5F505026FA6DD700294FA2 /* Mocks */, ); path = "Organisational Rules Service"; sourceTree = ""; }; + 9F5F505026FA6DD700294FA2 /* Mocks */ = { + isa = PBXGroup; + children = ( + 9F5F504926FA6C8F00294FA2 /* ClientConfigurationProviderMock.swift */, + 9F5F504226FA6C7500294FA2 /* EnterpriseServerApiMock.swift */, + 9F5F503B26FA6C5E00294FA2 /* CurrentUserEmailMock.swift */, + 9F5F501C26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift */, + ); + path = Mocks; + sourceTree = ""; + }; 9F6EE156259739A40059BA51 /* Backup Provider */ = { isa = PBXGroup; children = ( @@ -2495,10 +2512,12 @@ 9FC41183268118B1004C0A69 /* EmailProviderMock.swift in Sources */, 9F976490267E11880058419D /* ImapHelperTest.swift in Sources */, 9F5F501D26F90AE100294FA2 /* OrganisationalRulesServiceMock.swift in Sources */, + 9F5F503C26FA6C5E00294FA2 /* CurrentUserEmailMock.swift in Sources */, 9FC4116526811861004C0A69 /* BackupServiceMock.swift in Sources */, 9FC413182683C492004C0A69 /* InMemoryPassPhraseStorageTest.swift in Sources */, 9F9764C5267E14AB0058419D /* GeneralConstantsTest.swift in Sources */, 9F976507267E165D0058419D /* ZBase32EncodingTests.swift in Sources */, + 9F5F504A26FA6C8F00294FA2 /* ClientConfigurationProviderMock.swift in Sources */, 9F2F207326AEECFB0044E144 /* PromiseTestExtension.swift in Sources */, 9FC4117D268118AE004C0A69 /* PassPhraseStorageMock.swift in Sources */, 9F97650E267E16620058419D /* WKDURLsConstructorTests.swift in Sources */, @@ -2514,6 +2533,7 @@ 9FC413442683C912004C0A69 /* GmailServiceTest.swift in Sources */, 9F976556267E186D0058419D /* ClientConfigurationTests.swift in Sources */, 9F7E8EC6269877E70021C07F /* KeyInfoTests.swift in Sources */, + 9F5F504326FA6C7500294FA2 /* EnterpriseServerApiMock.swift in Sources */, 9F976556267E186D0058419D /* ClientConfigurationTests.swift in Sources */, 9FC41171268118A7004C0A69 /* PassPhraseStorageTests.swift in Sources */, 9F6F3C7626ADFC37005BD9C6 /* KeyStorageMock.swift in Sources */, diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/ClientConfigurationProviderMock.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/ClientConfigurationProviderMock.swift new file mode 100644 index 000000000..9ac9c1ba3 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/ClientConfigurationProviderMock.swift @@ -0,0 +1,41 @@ +// +// ClientConfigurationProviderMock.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 21.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +@testable import FlowCrypt + +class ClientConfigurationProviderMock: ClientConfigurationProviderType { + var fetchInvoked = false + var fetchCount = 0 + var fetchCall: () -> (ClientConfiguration?) = { + nil + } + func fetch() -> ClientConfiguration? { + fetchInvoked = true + fetchCount += 1 + return fetchCall() + } + + var removeClientConfigurationInvoked = false + var removeClientConfigurationCount = 0 + func removeClientConfiguration() { + removeClientConfigurationInvoked = true + removeClientConfigurationCount += 1 + } + + var saveInvoked = false + var saveCount = 0 + var saveCall: (ClientConfiguration) -> (Void) = { clientConfiguration in + + } + func save(clientConfiguration: ClientConfiguration) { + saveInvoked = true + saveCount += 1 + saveCall(clientConfiguration) + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/CurrentUserEmailMock.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/CurrentUserEmailMock.swift new file mode 100644 index 000000000..52b2309c2 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/CurrentUserEmailMock.swift @@ -0,0 +1,18 @@ +// +// CurrentUserEmailMock.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 21.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +class CurrentUserEmailMock { + var currentUserEmailCall: () -> (String?) = { + nil + } + func currentUserEmail() -> String? { + currentUserEmailCall() + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/EnterpriseServerApiMock.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/EnterpriseServerApiMock.swift new file mode 100644 index 000000000..a2f89689a --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/EnterpriseServerApiMock.swift @@ -0,0 +1,57 @@ +// +// EnterpriseServerApiMock.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 21.09.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import Promises +@testable import FlowCrypt + +class EnterpriseServerApiMock: EnterpriseServerApiType { + var getActiveFesUrlInvoked = false + var getActiveFesUrlInvokedCount = 0 + var getActiveFesUrlCall: (String) -> (Result) = { email in + .failure(OrganisationalRulesServiceError.getActiveFesUrlCall) + } + func getActiveFesUrl(for email: String) -> Promise { + getActiveFesUrlInvoked = true + getActiveFesUrlInvokedCount += 1 + return Promise.resolveAfter(with: getActiveFesUrlCall(email)) + } + + var getActiveFesUrlForCurrentUserInvoked = false + var getActiveFesUrlForCurrentUserCount = 0 + var getActiveFesUrlForCurrentUserCall: () -> (Result) = { + .failure(OrganisationalRulesServiceError.getActiveFesUrlForCurrentUserCall) + } + func getActiveFesUrlForCurrentUser() -> Promise { + getActiveFesUrlForCurrentUserInvoked = true + getActiveFesUrlForCurrentUserCount += 1 + return Promise.resolveAfter(with: getActiveFesUrlForCurrentUserCall()) + } + + var getClientConfigurationInvoked = false + var getClientConfigurationCount = 0 + var getClientConfigurationCall: (String) -> (Result) = { email in + .failure(OrganisationalRulesServiceError.getClientConfigurationCall) + } + func getClientConfiguration(for email: String) -> Promise { + getClientConfigurationInvoked = true + getClientConfigurationCount += 1 + return Promise.resolveAfter(with: getClientConfigurationCall(email)) + } + + var getClientConfigurationForCurrentUserInvoked = false + var getClientConfigurationForCurrentUserCount = 0 + var getClientConfigurationForCurrentUserCall: () -> (Result) = { + .failure(OrganisationalRulesServiceError.getClientConfigurationForCurrentUserCall) + } + func getClientConfigurationForCurrentUser() -> Promise { + getClientConfigurationForCurrentUserInvoked = true + getClientConfigurationForCurrentUserCount += 1 + return Promise.resolveAfter(with: getClientConfigurationForCurrentUserCall()) + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/OrganisationalRulesServiceMock.swift similarity index 100% rename from FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceMock.swift rename to FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/Mocks/OrganisationalRulesServiceMock.swift diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift index 24b5b5a00..2e970adcb 100644 --- a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/OrganisationalRulesServiceTests.swift @@ -148,7 +148,7 @@ class OrganisationalRulesServiceTests: XCTestCase { self.enterpriseServerApi.getClientConfigurationCall = { email in .failure(MockError.some) - } + } isCurrentUserExistMock.currentUserEmailCall = { "example@flowcrypt.test" @@ -179,90 +179,4 @@ enum OrganisationalRulesServiceError: Error { case getActiveFesUrlForCurrentUserCall case getClientConfigurationCall case getClientConfigurationForCurrentUserCall -} - -class CurrentUserEmailMock { - var currentUserEmailCall: () -> (String?) = { - nil - } - func currentUserEmail() -> String? { - currentUserEmailCall() - } -} - -class EnterpriseServerApiMock: EnterpriseServerApiType { - var getActiveFesUrlInvoked = false - var getActiveFesUrlInvokedCount = 0 - var getActiveFesUrlCall: (String) -> (Result) = { email in - .failure(OrganisationalRulesServiceError.getActiveFesUrlCall) - } - func getActiveFesUrl(for email: String) -> Promise { - getActiveFesUrlInvoked = true - getActiveFesUrlInvokedCount += 1 - return Promise.resolveAfter(with: getActiveFesUrlCall(email)) - } - - var getActiveFesUrlForCurrentUserInvoked = false - var getActiveFesUrlForCurrentUserCount = 0 - var getActiveFesUrlForCurrentUserCall: () -> (Result) = { - .failure(OrganisationalRulesServiceError.getActiveFesUrlForCurrentUserCall) - } - func getActiveFesUrlForCurrentUser() -> Promise { - getActiveFesUrlForCurrentUserInvoked = true - getActiveFesUrlForCurrentUserCount += 1 - return Promise.resolveAfter(with: getActiveFesUrlForCurrentUserCall()) - } - - var getClientConfigurationInvoked = false - var getClientConfigurationCount = 0 - var getClientConfigurationCall: (String) -> (Result) = { email in - .failure(OrganisationalRulesServiceError.getClientConfigurationCall) - } - func getClientConfiguration(for email: String) -> Promise { - getClientConfigurationInvoked = true - getClientConfigurationCount += 1 - return Promise.resolveAfter(with: getClientConfigurationCall(email)) - } - - var getClientConfigurationForCurrentUserInvoked = false - var getClientConfigurationForCurrentUserCount = 0 - var getClientConfigurationForCurrentUserCall: () -> (Result) = { - .failure(OrganisationalRulesServiceError.getClientConfigurationForCurrentUserCall) - } - func getClientConfigurationForCurrentUser() -> Promise { - getClientConfigurationForCurrentUserInvoked = true - getClientConfigurationForCurrentUserCount += 1 - return Promise.resolveAfter(with: getClientConfigurationForCurrentUserCall()) - } -} - -class ClientConfigurationProviderMock: ClientConfigurationProviderType { - var fetchInvoked = false - var fetchCount = 0 - var fetchCall: () -> (ClientConfiguration?) = { - nil - } - func fetch() -> ClientConfiguration? { - fetchInvoked = true - fetchCount += 1 - return fetchCall() - } - - var removeClientConfigurationInvoked = false - var removeClientConfigurationCount = 0 - func removeClientConfiguration() { - removeClientConfigurationInvoked = true - removeClientConfigurationCount += 1 - } - - var saveInvoked = false - var saveCount = 0 - var saveCall: (ClientConfiguration) -> (Void) = { clientConfiguration in - - } - func save(clientConfiguration: ClientConfiguration) { - saveInvoked = true - saveCount += 1 - saveCall(clientConfiguration) - } -} +} From 3626fd6ed66a0febbba48dcba86224b907a5bbd6 Mon Sep 17 00:00:00 2001 From: Anton Kharchevskyi Date: Fri, 24 Sep 2021 20:00:45 +0300 Subject: [PATCH 10/10] Fix missing check. Merge master --- .../ClientConfigurationServiceTest.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift index 73526ac91..4e9b5c628 100644 --- a/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift +++ b/FlowCryptAppTests/Functionallity/Services/Organisational Rules Service/ClientConfigurationServiceTest.swift @@ -31,6 +31,7 @@ class ClientConfigurationServiceTest: XCTestCase { flags: [], keyManagerUrl: nil ) + XCTAssert(sut.checkShouldUseEKM() == .doesNotUseEKM) organisationalRulesService.clientConfiguration = ClientConfiguration( flags: [.forbidStoringPassphrase],