From 00aea59d8c9e3ae5ee247bc1e10ad5fafeaf098e Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Wed, 15 Nov 2023 21:34:17 -0800 Subject: [PATCH] Improve unit tests. --- DuckDuckGo.xcodeproj/project.pbxproj | 7 +- ...tworkProtectionAccessControllerTests.swift | 159 ++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 DuckDuckGoTests/NetworkProtectionAccessControllerTests.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index bfff45d66d..a718592dc9 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -307,6 +307,7 @@ 4BCD14672B05B682000B1E4C /* NetworkProtectionTermsAndConditionsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCD14662B05B682000B1E4C /* NetworkProtectionTermsAndConditionsStore.swift */; }; 4BCD14692B05BDD5000B1E4C /* AppDelegate+Waitlists.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCD14682B05BDD5000B1E4C /* AppDelegate+Waitlists.swift */; }; 4BCD146B2B05C4B5000B1E4C /* VPNWaitlistTermsAndConditionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCD146A2B05C4B5000B1E4C /* VPNWaitlistTermsAndConditionsViewController.swift */; }; + 4BCD146D2B05DB09000B1E4C /* NetworkProtectionAccessControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCD146C2B05DB09000B1E4C /* NetworkProtectionAccessControllerTests.swift */; }; 4BE2756827304F57006B20B0 /* URLRequestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE27566272F878F006B20B0 /* URLRequestExtension.swift */; }; 4BEF65692989C2FC00B650CB /* AdapterSocketEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021D307A2989C0C400918636 /* AdapterSocketEvent.swift */; }; 4BEF656A2989C2FC00B650CB /* ProxyServerEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021D307C2989C0C600918636 /* ProxyServerEvent.swift */; }; @@ -1333,6 +1334,7 @@ 4BCD14662B05B682000B1E4C /* NetworkProtectionTermsAndConditionsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionTermsAndConditionsStore.swift; sourceTree = ""; }; 4BCD14682B05BDD5000B1E4C /* AppDelegate+Waitlists.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Waitlists.swift"; sourceTree = ""; }; 4BCD146A2B05C4B5000B1E4C /* VPNWaitlistTermsAndConditionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNWaitlistTermsAndConditionsViewController.swift; sourceTree = ""; }; + 4BCD146C2B05DB09000B1E4C /* NetworkProtectionAccessControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionAccessControllerTests.swift; sourceTree = ""; }; 4BE27566272F878F006B20B0 /* URLRequestExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = URLRequestExtension.swift; path = ../DuckDuckGo/URLRequestExtension.swift; sourceTree = ""; }; 4BFB911A29B7D9530014D4B7 /* AppTrackingProtectionStoringModelPerformanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTrackingProtectionStoringModelPerformanceTests.swift; sourceTree = ""; }; 56244C1C2A137B1900EDF259 /* WaitlistViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistViews.swift; sourceTree = ""; }; @@ -4527,6 +4529,7 @@ EEFE9C722A603CE9005B0A26 /* NetworkProtectionStatusViewModelTests.swift */, EE0153EA2A6FF970002A8B26 /* NetworkProtectionRootViewModelTests.swift */, EE41BD182A729E9C00546C57 /* NetworkProtectionInviteViewModelTests.swift */, + 4BCD146C2B05DB09000B1E4C /* NetworkProtectionAccessControllerTests.swift */, ); name = NetworkProtection; sourceTree = ""; @@ -6124,7 +6127,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Conditionally embeds PacketTunnelProvider extension for Debug and Alpha builds.\n\n# Conditionally embeds the PacketTunnelProvider extension for debug builds.\\n# To be moved to the Embed App Extensions phase on release.\n\nif [ \"${CONFIGURATION}\" = \"Debug\" ] || [ \"${CONFIGURATION}\" = \"Alpha\" ]; then\n# Copy the extension \n rsync -r --copy-links \"${CONFIGURATION_BUILD_DIR}/PacketTunnelProvider.appex\" \"${CONFIGURATION_BUILD_DIR}/${PLUGINS_FOLDER_PATH}\"\nfi\n"; + shellScript = "# Conditionally embeds PacketTunnelProvider extension for Debug and Alpha builds.\n\n# Conditionally embeds the PacketTunnelProvider extension for debug builds.\\n# To be moved to the Embed App Extensions phase on release.\n\nif [ \"${CONFIGURATION}\" = \"Debug\" ] || [ \"${CONFIGURATION}\" = \"Release\" ] || [ \"${CONFIGURATION}\" = \"Alpha\" ]; then\n# Copy the extension \n rsync -r --copy-links \"${CONFIGURATION_BUILD_DIR}/PacketTunnelProvider.appex\" \"${CONFIGURATION_BUILD_DIR}/${PLUGINS_FOLDER_PATH}\"\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -6706,6 +6709,7 @@ F1D477C91F2139410031ED49 /* SmallOmniBarStateTests.swift in Sources */, 987130C9294AAB9F00AB05E0 /* BookmarkUtilsTests.swift in Sources */, C1BF0BA929B63E2200482B73 /* AutofillLoginPromptViewModelTests.swift in Sources */, + 4BCD146D2B05DB09000B1E4C /* NetworkProtectionAccessControllerTests.swift in Sources */, EE3B226B29DE0F110082298A /* MockInternalUserStoring.swift in Sources */, 987130C8294AAB9F00AB05E0 /* BookmarksTestHelpers.swift in Sources */, F198D7981E3A45D90088DA8A /* WKWebViewConfigurationExtensionTests.swift in Sources */, @@ -8120,6 +8124,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = NETWORK_PROTECTION; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/DuckDuckGoTests/NetworkProtectionAccessControllerTests.swift b/DuckDuckGoTests/NetworkProtectionAccessControllerTests.swift new file mode 100644 index 0000000000..cdc354de28 --- /dev/null +++ b/DuckDuckGoTests/NetworkProtectionAccessControllerTests.swift @@ -0,0 +1,159 @@ +// +// NetworkProtectionAccessControllerTests.swift +// DuckDuckGo +// +// Copyright © 2023 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if NETWORK_PROTECTION + +import XCTest +import BrowserServicesKit +import NetworkProtection +import NetworkExtension +import NetworkProtectionTestUtils +import WaitlistMocks +@testable import DuckDuckGo + +final class NetworkProtectionAccessControllerTests: XCTestCase { + + func testWhenFeatureFlagsAreDisabled_AndTheUserHasNotBeenDirectlyInvited_ThenNetworkProtectionIsNotAccessible() { + let controller = createMockAccessController( + featureActivated: false, + termsAccepted: false, + featureFlagsEnabled: false, + hasJoinedWaitlist: false, + hasBeenInvited: false + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .none) + } + + func testWhenFeatureFlagsAreDisabled_AndTheUserHasBeenDirectlyInvited_ThenNetworkProtectionIsNotAccessible() { + let controller = createMockAccessController( + featureActivated: true, + termsAccepted: false, + featureFlagsEnabled: false, + hasJoinedWaitlist: false, + hasBeenInvited: false + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .inviteCodeInvited) + } + + func testWhenFeatureFlagsAreEnabled_AndTheUserHasNotSignedUp_ThenNetworkProtectionIsAccessible() { + let controller = createMockAccessController( + featureActivated: false, + termsAccepted: false, + featureFlagsEnabled: true, + hasJoinedWaitlist: false, + hasBeenInvited: false + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .waitlistAvailable) + } + + func testWhenFeatureFlagsAreEnabled_AndTheUserHasSignedUp_ThenNetworkProtectionIsAccessible() { + let controller = createMockAccessController( + featureActivated: false, + termsAccepted: false, + featureFlagsEnabled: true, + hasJoinedWaitlist: true, + hasBeenInvited: false + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .waitlistJoined) + } + + func testWhenFeatureFlagsAreEnabled_AndTheUserHasBeenInvited_ThenNetworkProtectionIsAccessible() { + let controller = createMockAccessController( + featureActivated: true, + termsAccepted: false, + featureFlagsEnabled: true, + hasJoinedWaitlist: true, + hasBeenInvited: true + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .waitlistInvitedPendingTermsAcceptance) + } + + func testWhenFeatureFlagsAreEnabled_AndTheUserHasAcceptedTerms_ThenNetworkProtectionIsAccessible() { + let controller = createMockAccessController( + featureActivated: true, + termsAccepted: true, + featureFlagsEnabled: true, + hasJoinedWaitlist: true, + hasBeenInvited: true + ) + + XCTAssertEqual(controller.networkProtectionAccessType(), .waitlistInvited) + } + + private func createMockAccessController( + featureActivated: Bool, + termsAccepted: Bool, + featureFlagsEnabled: Bool, + hasJoinedWaitlist: Bool, + hasBeenInvited: Bool + ) -> NetworkProtectionAccessController { + let mockActivation = MockNetworkProtectionFeatureActivation() + mockActivation.isFeatureActivated = featureActivated + + let mockWaitlistStorage = MockWaitlistStorage() + + if hasJoinedWaitlist { + mockWaitlistStorage.store(waitlistTimestamp: 1) + mockWaitlistStorage.store(waitlistToken: "token") + + if hasBeenInvited { + mockWaitlistStorage.store(inviteCode: "INVITECODE") + } + } + + let mockTermsAndConditionsStore = MockNetworkProtectionTermsAndConditionsStore() + mockTermsAndConditionsStore.networkProtectionWaitlistTermsAndConditionsAccepted = termsAccepted + + let mockManager = mockConfigurationManager(subfeatureEnabled: featureFlagsEnabled) + + return NetworkProtectionAccessController( + networkProtectionActivation: mockActivation, + networkProtectionWaitlistStorage: mockWaitlistStorage, + networkProtectionTermsAndConditionsStore: mockTermsAndConditionsStore, + privacyConfigurationManager: mockManager + ) + } + + private func mockConfigurationManager(subfeatureEnabled: Bool) -> PrivacyConfigurationManaging { + let mockPrivacyConfiguration = MockPrivacyConfiguration() + + mockPrivacyConfiguration.isSubfeatureKeyEnabled = { _, _ in + return subfeatureEnabled + } + + let mockManager = MockPrivacyConfigurationManager() + mockManager.privacyConfig = mockPrivacyConfiguration + + return mockManager + } + +} + +private class MockNetworkProtectionTermsAndConditionsStore: NetworkProtectionTermsAndConditionsStore { + + var networkProtectionWaitlistTermsAndConditionsAccepted: Bool = false + +} + +#endif