summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBug Magnet <marco.nikic@mullvad.net>2024-01-16 12:42:54 +0100
committerBug Magnet <marco.nikic@mullvad.net>2024-01-16 12:42:54 +0100
commitb700b79d16c4980ee2028b4b5fb67caa785fbcfd (patch)
tree8601bb208284433651ae2f63a931c0f8663c6747
parentee9597c4628773fcc6cc93306bab5e01ce2401f1 (diff)
parentd26686cef766ac0248883e79c71ba5ba6481340f (diff)
downloadmullvadvpn-b700b79d16c4980ee2028b4b5fb67caa785fbcfd.tar.xz
mullvadvpn-b700b79d16c4980ee2028b4b5fb67caa785fbcfd.zip
Merge branch 'test-app-login-ios-428'
-rw-r--r--ios/Configurations/UITests.xcconfig.template13
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj178
-rw-r--r--ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNUITests.xcscheme67
-rw-r--r--ios/MullvadVPN/Classes/AccessbilityIdentifier.swift10
-rw-r--r--ios/MullvadVPN/Containers/Root/HeaderBarView.swift1
-rw-r--r--ios/MullvadVPN/View controllers/Alert/AlertViewController.swift3
-rw-r--r--ios/MullvadVPN/View controllers/Login/AccountInputGroupView.swift1
-rw-r--r--ios/MullvadVPN/View controllers/Login/LoginContentView.swift1
-rw-r--r--ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceContentView.swift2
-rw-r--r--ios/MullvadVPNUITests/AccountTests.swift53
-rw-r--r--ios/MullvadVPNUITests/BaseUITestCase.swift19
-rw-r--r--ios/MullvadVPNUITests/Info.plist12
-rw-r--r--ios/MullvadVPNUITests/Pages/Alert.swift25
-rw-r--r--ios/MullvadVPNUITests/Pages/LoginPage.swift48
-rw-r--r--ios/MullvadVPNUITests/Pages/Page.swift34
-rw-r--r--ios/MullvadVPNUITests/Pages/TermsOfServicePage.swift23
-rw-r--r--ios/TestPlans/MullvadVPNUITests.xctestplan28
17 files changed, 517 insertions, 1 deletions
diff --git a/ios/Configurations/UITests.xcconfig.template b/ios/Configurations/UITests.xcconfig.template
new file mode 100644
index 0000000000..c8727dd3e1
--- /dev/null
+++ b/ios/Configurations/UITests.xcconfig.template
@@ -0,0 +1,13 @@
+//
+// MullvadVPNUITests.xcconfig
+// MullvadVPN
+//
+// Created by Niklas Berglund on 2024-01-10.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+// Mullvad accounts used by UI tests
+MULLVAD_NO_TIME_ACCOUNT_NUMBER =
+MULLVAD_HAS_TIME_ACCOUNT_NUMBER =
+MULLVAD_FIVE_WIREGUARD_KEYS_ACCOUNT_NUMBER =
+
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 60a74fa1b5..dde9de3805 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -566,6 +566,13 @@
7AF9BE902A39F26000DBFEDB /* Collection+Sorting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF9BE8F2A39F26000DBFEDB /* Collection+Sorting.swift */; };
7AF9BE952A40461100DBFEDB /* RelayFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF9BE942A40461100DBFEDB /* RelayFilterView.swift */; };
7AF9BE972A41C71F00DBFEDB /* RelayFilterChipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF9BE962A41C71F00DBFEDB /* RelayFilterChipView.swift */; };
+ 850201E12B51389500EF8C96 /* BaseUITestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850201E02B51389500EF8C96 /* BaseUITestCase.swift */; };
+ 852969282B4D9C1F007EAD4C /* AccountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852969272B4D9C1F007EAD4C /* AccountTests.swift */; };
+ 852969332B4E9232007EAD4C /* Page.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852969322B4E9232007EAD4C /* Page.swift */; };
+ 852969352B4E9270007EAD4C /* LoginPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852969342B4E9270007EAD4C /* LoginPage.swift */; };
+ 852969362B4E9724007EAD4C /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
+ 8529693A2B4F0238007EAD4C /* TermsOfServicePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852969392B4F0238007EAD4C /* TermsOfServicePage.swift */; };
+ 8529693C2B4F0257007EAD4C /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8529693B2B4F0257007EAD4C /* Alert.swift */; };
A900E9B82ACC5C2B00C95F67 /* AccountsProxy+Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = A900E9B72ACC5C2B00C95F67 /* AccountsProxy+Stubs.swift */; };
A900E9BA2ACC5D0600C95F67 /* RESTRequestExecutor+Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = A900E9B92ACC5D0600C95F67 /* RESTRequestExecutor+Stubs.swift */; };
A900E9BC2ACC609200C95F67 /* DevicesProxy+Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = A900E9BB2ACC609200C95F67 /* DevicesProxy+Stubs.swift */; };
@@ -1031,6 +1038,13 @@
remoteGlobalIDString = 7A88DCCD2A8FABBE00D2FF0E;
remoteInfo = Routing;
};
+ 8529692B2B4D9C1F007EAD4C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 58CE5E58224146200008646E /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 58CE5E5F224146200008646E;
+ remoteInfo = MullvadVPN;
+ };
A91614D22B108F4D00F416EB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58CE5E58224146200008646E /* Project object */;
@@ -1697,6 +1711,16 @@
7AF9BE8F2A39F26000DBFEDB /* Collection+Sorting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+Sorting.swift"; sourceTree = "<group>"; };
7AF9BE942A40461100DBFEDB /* RelayFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterView.swift; sourceTree = "<group>"; };
7AF9BE962A41C71F00DBFEDB /* RelayFilterChipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterChipView.swift; sourceTree = "<group>"; };
+ 850201E02B51389500EF8C96 /* BaseUITestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseUITestCase.swift; sourceTree = "<group>"; };
+ 852969252B4D9C1F007EAD4C /* MullvadVPNUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MullvadVPNUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 852969272B4D9C1F007EAD4C /* AccountTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTests.swift; sourceTree = "<group>"; };
+ 852969302B4D9E70007EAD4C /* MullvadVPNUITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MullvadVPNUITests.xctestplan; sourceTree = "<group>"; };
+ 852969322B4E9232007EAD4C /* Page.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Page.swift; sourceTree = "<group>"; };
+ 852969342B4E9270007EAD4C /* LoginPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginPage.swift; sourceTree = "<group>"; };
+ 852969372B4ED20E007EAD4C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 852969382B4ED818007EAD4C /* UITests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UITests.xcconfig; sourceTree = "<group>"; };
+ 852969392B4F0238007EAD4C /* TermsOfServicePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServicePage.swift; sourceTree = "<group>"; };
+ 8529693B2B4F0257007EAD4C /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = "<group>"; };
A900E9B72ACC5C2B00C95F67 /* AccountsProxy+Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountsProxy+Stubs.swift"; sourceTree = "<group>"; };
A900E9B92ACC5D0600C95F67 /* RESTRequestExecutor+Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RESTRequestExecutor+Stubs.swift"; sourceTree = "<group>"; };
A900E9BB2ACC609200C95F67 /* DevicesProxy+Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DevicesProxy+Stubs.swift"; sourceTree = "<group>"; };
@@ -1975,6 +1999,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 852969222B4D9C1F007EAD4C /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -2905,6 +2936,7 @@
58C7A4432A863F490060C66F /* PacketTunnelCoreTests */,
7A88DCCF2A8FABBE00D2FF0E /* Routing */,
7A88DCDD2A8FABBE00D2FF0E /* RoutingTests */,
+ 852969262B4D9C1F007EAD4C /* MullvadVPNUITests */,
58CE5E61224146200008646E /* Products */,
584F991F2902CBDD001F858D /* Frameworks */,
);
@@ -2930,6 +2962,7 @@
7A88DCCE2A8FABBE00D2FF0E /* Routing.framework */,
7A88DCD72A8FABBE00D2FF0E /* RoutingTests.xctest */,
58B2FDD32AA71D2A003EB5C6 /* MullvadSettings.framework */,
+ 852969252B4D9C1F007EAD4C /* MullvadVPNUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -3143,6 +3176,7 @@
5808273B284888BC006B77A4 /* App.xcconfig */,
5808273C284888E5006B77A4 /* PacketTunnel.xcconfig */,
58ECD29123F178FD004298B6 /* Screenshots.xcconfig */,
+ 852969382B4ED818007EAD4C /* UITests.xcconfig */,
);
path = Configurations;
sourceTree = "<group>";
@@ -3221,6 +3255,7 @@
7A83C3FC2A55B39500DFB83A /* TestPlans */ = {
isa = PBXGroup;
children = (
+ 852969302B4D9E70007EAD4C /* MullvadVPNUITests.xctestplan */,
7A83C3FE2A55B72E00DFB83A /* MullvadVPNApp.xctestplan */,
7A83C4002A55B81A00DFB83A /* MullvadVPNCI.xctestplan */,
7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */,
@@ -3262,6 +3297,28 @@
path = RelayFilter;
sourceTree = "<group>";
};
+ 852969262B4D9C1F007EAD4C /* MullvadVPNUITests */ = {
+ isa = PBXGroup;
+ children = (
+ 852969372B4ED20E007EAD4C /* Info.plist */,
+ 852969312B4E9220007EAD4C /* Pages */,
+ 852969272B4D9C1F007EAD4C /* AccountTests.swift */,
+ 850201E02B51389500EF8C96 /* BaseUITestCase.swift */,
+ );
+ path = MullvadVPNUITests;
+ sourceTree = "<group>";
+ };
+ 852969312B4E9220007EAD4C /* Pages */ = {
+ isa = PBXGroup;
+ children = (
+ 852969322B4E9232007EAD4C /* Page.swift */,
+ 852969342B4E9270007EAD4C /* LoginPage.swift */,
+ 852969392B4F0238007EAD4C /* TermsOfServicePage.swift */,
+ 8529693B2B4F0257007EAD4C /* Alert.swift */,
+ );
+ path = Pages;
+ sourceTree = "<group>";
+ };
A907639F2B2857D50045ADF0 /* Socks5 */ = {
isa = PBXGroup;
children = (
@@ -3913,6 +3970,24 @@
productReference = 7A88DCD72A8FABBE00D2FF0E /* RoutingTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
+ 852969242B4D9C1F007EAD4C /* MullvadVPNUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8529692F2B4D9C1F007EAD4C /* Build configuration list for PBXNativeTarget "MullvadVPNUITests" */;
+ buildPhases = (
+ 852969212B4D9C1F007EAD4C /* Sources */,
+ 852969222B4D9C1F007EAD4C /* Frameworks */,
+ 852969232B4D9C1F007EAD4C /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 8529692C2B4D9C1F007EAD4C /* PBXTargetDependency */,
+ );
+ name = MullvadVPNUITests;
+ productName = MullvadVPNUITests;
+ productReference = 852969252B4D9C1F007EAD4C /* MullvadVPNUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -3920,7 +3995,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
- LastSwiftUpdateCheck = 1430;
+ LastSwiftUpdateCheck = 1510;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "Mullvad VPN AB";
TargetAttributes = {
@@ -3995,6 +4070,10 @@
7A88DCD62A8FABBE00D2FF0E = {
CreatedOnToolsVersion = 14.3.1;
};
+ 852969242B4D9C1F007EAD4C = {
+ CreatedOnToolsVersion = 15.1;
+ TestTargetID = 58CE5E5F224146200008646E;
+ };
};
};
buildConfigurationList = 58CE5E5B224146200008646E /* Build configuration list for PBXProject "MullvadVPN" */;
@@ -4019,6 +4098,7 @@
58CE5E78224146470008646E /* PacketTunnel */,
58B0A29F238EE67E00BC001D /* MullvadVPNTests */,
58D0C79223F1CE7000FE9BA7 /* MullvadVPNScreenshots */,
+ 852969242B4D9C1F007EAD4C /* MullvadVPNUITests */,
58D223A4294C8A480029F5F8 /* Operations */,
589A455128E094B300565204 /* OperationsTests */,
06799ABB28F98E1D00ACD94E /* MullvadREST */,
@@ -4151,6 +4231,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 852969232B4D9C1F007EAD4C /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -5070,6 +5157,20 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 852969212B4D9C1F007EAD4C /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8529693C2B4F0257007EAD4C /* Alert.swift in Sources */,
+ 852969362B4E9724007EAD4C /* AccessbilityIdentifier.swift in Sources */,
+ 852969352B4E9270007EAD4C /* LoginPage.swift in Sources */,
+ 850201E12B51389500EF8C96 /* BaseUITestCase.swift in Sources */,
+ 852969282B4D9C1F007EAD4C /* AccountTests.swift in Sources */,
+ 8529693A2B4F0238007EAD4C /* TermsOfServicePage.swift in Sources */,
+ 852969332B4E9232007EAD4C /* Page.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@@ -5255,6 +5356,11 @@
target = 7A88DCCD2A8FABBE00D2FF0E /* Routing */;
targetProxy = 7ABCA5B52A9349F20044A708 /* PBXContainerItemProxy */;
};
+ 8529692C2B4D9C1F007EAD4C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 58CE5E5F224146200008646E /* MullvadVPN */;
+ targetProxy = 8529692B2B4D9C1F007EAD4C /* PBXContainerItemProxy */;
+ };
A91614D32B108F4D00F416EB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 58D223D4294C8E5E0029F5F8 /* MullvadTypes */;
@@ -6398,6 +6504,67 @@
};
name = Release;
};
+ 8529692D2B4D9C1F007EAD4C /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 852969382B4ED818007EAD4C /* UITests.xcconfig */;
+ buildSettings = {
+ APPLICATION_IDENTIFIER = net.mullvad.MullvadVPN;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
+ "DEVELOPMENT_TEAM[sdk=macosx*]" = CKG9MXH72F;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = MullvadVPNUITests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).MullvadVPNUITests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MullvadVPN app integration tests";
+ SECURITY_GROUP_IDENTIFIER = group.net.mullvad.MullvadVPN;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = MullvadVPN;
+ };
+ name = Debug;
+ };
+ 8529692E2B4D9C1F007EAD4C /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_IDENTIFIER = net.mullvad.MullvadVPN;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = MullvadVPNUITests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).MullvadVPNUITests";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SECURITY_GROUP_IDENTIFIER = group.net.mullvad.MullvadVPN;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = MullvadVPN;
+ };
+ name = Release;
+ };
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -6572,6 +6739,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 8529692F2B4D9C1F007EAD4C /* Build configuration list for PBXNativeTarget "MullvadVPNUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8529692D2B4D9C1F007EAD4C /* Debug */,
+ 8529692E2B4D9C1F007EAD4C /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
diff --git a/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNUITests.xcscheme b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNUITests.xcscheme
new file mode 100644
index 0000000000..45ec07ec85
--- /dev/null
+++ b/ios/MullvadVPN.xcodeproj/xcshareddata/xcschemes/MullvadVPNUITests.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1510"
+ version = "1.7">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <TestPlans>
+ <TestPlanReference
+ reference = "container:TestPlans/MullvadVPNUITests.xctestplan"
+ default = "YES">
+ </TestPlanReference>
+ </TestPlans>
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "852969242B4D9C1F007EAD4C"
+ BuildableName = "MullvadVPNUITests.xctest"
+ BlueprintName = "MullvadVPNUITests"
+ ReferencedContainer = "container:MullvadVPN.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "58CE5E5F224146200008646E"
+ BuildableName = "MullvadVPN.app"
+ BlueprintName = "MullvadVPN"
+ ReferencedContainer = "container:MullvadVPN.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Release"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
index 340762d787..a69c70c32d 100644
--- a/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
+++ b/ios/MullvadVPN/Classes/AccessbilityIdentifier.swift
@@ -21,6 +21,7 @@ public enum AccessibilityIdentifier: String {
case infoButton
case learnAboutPrivacyButton
case loginBarButton
+ case loginTextFieldButton
case logoutButton
case purchaseButton
case redeemVoucherButton
@@ -37,6 +38,15 @@ public enum AccessibilityIdentifier: String {
case relayFilterOwnershipCell
case relayFilterProviderCell
+ // Labels
+ case headerDeviceNameLabel
+
+ // Views
+ case alertContainerView
+ case alertTitle
+ case loginView
+ case termsOfServiceView
+
// Other UI elements
case loginTextField
diff --git a/ios/MullvadVPN/Containers/Root/HeaderBarView.swift b/ios/MullvadVPN/Containers/Root/HeaderBarView.swift
index 6b551cb276..1f701cbede 100644
--- a/ios/MullvadVPN/Containers/Root/HeaderBarView.swift
+++ b/ios/MullvadVPN/Containers/Root/HeaderBarView.swift
@@ -33,6 +33,7 @@ class HeaderBarView: UIView {
label.font = UIFont.systemFont(ofSize: 14)
label.textColor = UIColor(white: 1.0, alpha: 0.8)
label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+ label.accessibilityIdentifier = .headerDeviceNameLabel
return label
}()
diff --git a/ios/MullvadVPN/View controllers/Alert/AlertViewController.swift b/ios/MullvadVPN/View controllers/Alert/AlertViewController.swift
index 1cc23b2943..3d0e0a29ed 100644
--- a/ios/MullvadVPN/View controllers/Alert/AlertViewController.swift
+++ b/ios/MullvadVPN/View controllers/Alert/AlertViewController.swift
@@ -53,6 +53,8 @@ class AlertViewController: UIViewController {
view.backgroundColor = .secondaryColor
view.layer.cornerRadius = 11
+ view.accessibilityIdentifier = .alertContainerView
+
return view
}()
@@ -198,6 +200,7 @@ class AlertViewController: UIViewController {
header.adjustsFontForContentSizeCategory = true
header.textAlignment = .center
header.numberOfLines = 0
+ header.accessibilityIdentifier = .alertTitle
contentView.addArrangedSubview(header)
contentView.setCustomSpacing(16, after: header)
diff --git a/ios/MullvadVPN/View controllers/Login/AccountInputGroupView.swift b/ios/MullvadVPN/View controllers/Login/AccountInputGroupView.swift
index e5eb0ddb77..c021286c0d 100644
--- a/ios/MullvadVPN/View controllers/Login/AccountInputGroupView.swift
+++ b/ios/MullvadVPN/View controllers/Login/AccountInputGroupView.swift
@@ -24,6 +24,7 @@ final class AccountInputGroupView: UIView {
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(named: "IconArrow"), for: .normal)
button.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
+ button.accessibilityIdentifier = .loginTextFieldButton
button.accessibilityLabel = NSLocalizedString(
"ACCOUNT_INPUT_LOGIN_BUTTON_ACCESSIBILITY_LABEL",
tableName: "AccountInput",
diff --git a/ios/MullvadVPN/View controllers/Login/LoginContentView.swift b/ios/MullvadVPN/View controllers/Login/LoginContentView.swift
index 940317347c..c994286d51 100644
--- a/ios/MullvadVPN/View controllers/Login/LoginContentView.swift
+++ b/ios/MullvadVPN/View controllers/Login/LoginContentView.swift
@@ -102,6 +102,7 @@ class LoginContentView: UIView {
backgroundColor = .primaryColor
directionalLayoutMargins = UIMetrics.contentLayoutMargins
+ accessibilityIdentifier = .loginView
accountInputGroup.textField.accessibilityIdentifier = .loginTextField
diff --git a/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceContentView.swift b/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceContentView.swift
index e4292d2a80..945b2bccc5 100644
--- a/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceContentView.swift
+++ b/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceContentView.swift
@@ -100,6 +100,8 @@ class TermsOfServiceContentView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
+ self.accessibilityIdentifier = .termsOfServiceView
+
addSubviews()
}
diff --git a/ios/MullvadVPNUITests/AccountTests.swift b/ios/MullvadVPNUITests/AccountTests.swift
new file mode 100644
index 0000000000..bb719c91a9
--- /dev/null
+++ b/ios/MullvadVPNUITests/AccountTests.swift
@@ -0,0 +1,53 @@
+//
+// MullvadVPNUITests.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-09.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import XCTest
+
+class AccountTests: BaseUITestCase {
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ override func tearDownWithError() throws {}
+
+ func testLogin() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ TermsOfServicePage(app)
+ .tapAgreeButton()
+
+ Alert(app)
+ .tapOkay()
+
+ LoginPage(app)
+ .tapAccountNumberTextField()
+ .enterText(self.noTimeAccountNumber)
+ .tapAccountNumberSubmitButton()
+ .verifySuccessIconShown()
+ .verifyDeviceLabelShown()
+ }
+
+ func testLoginWithIncorrectAccountNumber() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ TermsOfServicePage(app)
+ .tapAgreeButton()
+
+ Alert(app)
+ .tapOkay()
+
+ LoginPage(app)
+ .tapAccountNumberTextField()
+ .enterText("0000000000000000")
+ .tapAccountNumberSubmitButton()
+ .verifyFailIconShown()
+ .waitForPageToBeShown() // Verify still on login page
+ }
+}
diff --git a/ios/MullvadVPNUITests/BaseUITestCase.swift b/ios/MullvadVPNUITests/BaseUITestCase.swift
new file mode 100644
index 0000000000..7ca4356e03
--- /dev/null
+++ b/ios/MullvadVPNUITests/BaseUITestCase.swift
@@ -0,0 +1,19 @@
+//
+// BaseTestCase.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-12.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class BaseUITestCase: XCTestCase {
+ // swiftlint:disable force_cast
+ let noTimeAccountNumber = Bundle(for: AccountTests.self).infoDictionary?["MullvadNoTimeAccountNumber"] as! String
+ let hasTimeAccountNumber = Bundle(for: AccountTests.self).infoDictionary?["MullvadHasTimeAccountNumber"] as! String
+ let fiveWireGuardKeysAccountNumber = Bundle(for: AccountTests.self)
+ .infoDictionary?["MullvadFiveWireGuardKeysAccountNumber"] as! String
+ // swiftlint:enable force_cast
+}
diff --git a/ios/MullvadVPNUITests/Info.plist b/ios/MullvadVPNUITests/Info.plist
new file mode 100644
index 0000000000..f0e3228b4b
--- /dev/null
+++ b/ios/MullvadVPNUITests/Info.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>MullvadFiveWireGuardKeysAccountNumber</key>
+ <string>$(MULLVAD_FIVE_WIREGUARD_KEYS_ACCOUNT_NUMBER)</string>
+ <key>MullvadHasTimeAccountNumber</key>
+ <string>$(MULLVAD_HAS_TIME_ACCOUNT_NUMBER)</string>
+ <key>MullvadNoTimeAccountNumber</key>
+ <string>$(MULLVAD_NO_TIME_ACCOUNT_NUMBER)</string>
+</dict>
+</plist>
diff --git a/ios/MullvadVPNUITests/Pages/Alert.swift b/ios/MullvadVPNUITests/Pages/Alert.swift
new file mode 100644
index 0000000000..7ecfb59e25
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/Alert.swift
@@ -0,0 +1,25 @@
+//
+// Alert.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-10.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+/// Generic alert "page"
+class Alert: Page {
+ @discardableResult override init(_ app: XCUIApplication) {
+ super.init(app)
+
+ self.pageAccessibilityIdentifier = .alertContainerView
+ waitForPageToBeShown()
+ }
+
+ @discardableResult func tapOkay() -> Self {
+ app.buttons[AccessibilityIdentifier.alertOkButton.rawValue].tap()
+ return self
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/LoginPage.swift b/ios/MullvadVPNUITests/Pages/LoginPage.swift
new file mode 100644
index 0000000000..7d13d88088
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/LoginPage.swift
@@ -0,0 +1,48 @@
+//
+// LoginPage.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-10.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class LoginPage: Page {
+ @discardableResult override init(_ app: XCUIApplication) {
+ super.init(app)
+
+ self.pageAccessibilityIdentifier = .loginView
+ waitForPageToBeShown()
+ }
+
+ @discardableResult public func tapAccountNumberTextField() -> Self {
+ app.textFields[AccessibilityIdentifier.loginTextField.rawValue].tap()
+ return self
+ }
+
+ @discardableResult public func tapAccountNumberSubmitButton() -> Self {
+ app.buttons[AccessibilityIdentifier.loginTextFieldButton.rawValue].tap()
+ return self
+ }
+
+ @discardableResult public func verifyDeviceLabelShown() -> Self {
+ XCTAssertTrue(
+ app.staticTexts[AccessibilityIdentifier.headerDeviceNameLabel.rawValue]
+ .waitForExistence(timeout: defaultTimeout)
+ )
+
+ return self
+ }
+
+ @discardableResult public func verifySuccessIconShown() -> Self {
+ app.images.element(matching: .image, identifier: "IconSuccess")
+ return self
+ }
+
+ @discardableResult public func verifyFailIconShown() -> Self {
+ app.images.element(matching: .image, identifier: "IconFail")
+ return self
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/Page.swift b/ios/MullvadVPNUITests/Pages/Page.swift
new file mode 100644
index 0000000000..775edf0beb
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/Page.swift
@@ -0,0 +1,34 @@
+//
+// Page.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-10.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class Page {
+ let app: XCUIApplication
+ var pageAccessibilityIdentifier: AccessibilityIdentifier?
+ let defaultTimeout = 10.0
+
+ init(_ app: XCUIApplication) {
+ self.app = app
+ }
+
+ public func enterText(_ text: String) -> Self {
+ app.typeText(text)
+ return self
+ }
+
+ public func waitForPageToBeShown() {
+ if let pageAccessibilityIdentifier = self.pageAccessibilityIdentifier {
+ XCTAssert(
+ self.app.otherElements[pageAccessibilityIdentifier.rawValue]
+ .waitForExistence(timeout: defaultTimeout)
+ )
+ }
+ }
+}
diff --git a/ios/MullvadVPNUITests/Pages/TermsOfServicePage.swift b/ios/MullvadVPNUITests/Pages/TermsOfServicePage.swift
new file mode 100644
index 0000000000..fb64b3237d
--- /dev/null
+++ b/ios/MullvadVPNUITests/Pages/TermsOfServicePage.swift
@@ -0,0 +1,23 @@
+//
+// TermsOfServicePage.swift
+// MullvadVPNUITests
+//
+// Created by Niklas Berglund on 2024-01-10.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+import XCTest
+
+class TermsOfServicePage: Page {
+ @discardableResult override init(_ app: XCUIApplication) {
+ super.init(app)
+
+ self.pageAccessibilityIdentifier = .termsOfServiceView
+ }
+
+ @discardableResult func tapAgreeButton() -> Self {
+ app.buttons[AccessibilityIdentifier.agreeButton.rawValue].tap()
+ return self
+ }
+}
diff --git a/ios/TestPlans/MullvadVPNUITests.xctestplan b/ios/TestPlans/MullvadVPNUITests.xctestplan
new file mode 100644
index 0000000000..dd5cb5a09e
--- /dev/null
+++ b/ios/TestPlans/MullvadVPNUITests.xctestplan
@@ -0,0 +1,28 @@
+{
+ "configurations" : [
+ {
+ "id" : "97A9D9C1-040F-4F36-8CFE-B600F97AB953",
+ "name" : "Test Scheme Action",
+ "options" : {
+
+ }
+ }
+ ],
+ "defaultOptions" : {
+ "targetForVariableExpansion" : {
+ "containerPath" : "container:MullvadVPN.xcodeproj",
+ "identifier" : "58CE5E5F224146200008646E",
+ "name" : "MullvadVPN"
+ }
+ },
+ "testTargets" : [
+ {
+ "target" : {
+ "containerPath" : "container:MullvadVPN.xcodeproj",
+ "identifier" : "852969242B4D9C1F007EAD4C",
+ "name" : "MullvadVPNUITests"
+ }
+ }
+ ],
+ "version" : 1
+}