Skip to content

Commit 459502f

Browse files
authored
Merge pull request #435 from immutable/ci/ios-build
[DX-3593] [DX-3617] [DX-3620] ci: fix ios build and ui tests
2 parents 584f31e + 6172c8c commit 459502f

File tree

12 files changed

+398
-294
lines changed

12 files changed

+398
-294
lines changed

.github/workflows/ui-tests.yml

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,26 @@ jobs:
131131
security default-keychain -s ~/Library/Keychains/login.keychain-db
132132
security delete-keychain temporary
133133
security list-keychains
134-
# test-ios:
135-
# name: Run iOS UI tests 🧪
136-
# runs-on: [ self-hosted, macOS ]
137-
# steps:
138-
# - uses: actions/checkout@v3
139-
# with:
140-
# lfs: true
141-
# - name: Build iOS app
142-
# working-directory: sample
143-
# run: ./build_ios.sh
144-
# - uses: actions/setup-python@v4
145-
# with:
146-
# python-version: "3.10"
147-
# - name: Install dependencies
148-
# run: pip install -r "sample/Tests/requirements-mobile.txt"
149-
# - name: Run UI tests
150-
# env:
151-
# MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }}
152-
# BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
153-
# BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
154-
# working-directory: sample/Tests
155-
# run: browserstack-sdk pytest -s ./test/test_ios.py --browserstack.config "browserstack.ios.yml"
134+
test-ios:
135+
name: Run iOS UI tests 🧪
136+
runs-on: [ self-hosted, macOS ]
137+
steps:
138+
- uses: actions/checkout@v3
139+
with:
140+
lfs: true
141+
- name: Build iOS app
142+
working-directory: sample
143+
run: ./build_ios.sh
144+
- uses: actions/setup-python@v4
145+
with:
146+
python-version: "3.10"
147+
- name: Install dependencies
148+
run: pip install -r "sample/Tests/requirements-mobile.txt"
149+
- name: Run UI tests
150+
env:
151+
MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }}
152+
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
153+
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
154+
working-directory: sample/Tests/test/ios
155+
run: browserstack-sdk pytest -xs ./test_ios.py --browserstack.config "browserstack.ios.yml"
156156

sample/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
**/Payload.ipa
2+
**/logFile.log
3+
**/local.log
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#if UNITY_IPHONE && UNITY_EDITOR_OSX
2+
3+
using UnityEngine;
4+
using UnityEditor;
5+
using UnityEditor.Callbacks;
6+
using System.IO;
7+
using System.Linq;
8+
using UnityEditor.iOS.Xcode;
9+
10+
public class iOSPostBuildProcessor
11+
{
12+
[PostProcessBuild]
13+
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
14+
{
15+
if (target == BuildTarget.iOS && IsCommandLineBuild())
16+
{
17+
Debug.Log("Command-line iOS build detected. Modifying Info.plist and Xcode project...");
18+
ModifyInfoPlist(pathToBuiltProject);
19+
ModifyXcodeProject(pathToBuiltProject, GetBundleIdentifierFromArgs());
20+
}
21+
else
22+
{
23+
Debug.Log("Skipping Info.plist modification (not an iOS command-line build).");
24+
}
25+
}
26+
27+
private static bool IsCommandLineBuild()
28+
{
29+
string[] args = System.Environment.GetCommandLineArgs();
30+
return args.Contains("--ciBuild"); // Check for the --ciBuild flag
31+
}
32+
33+
private static void ModifyInfoPlist(string pathToBuiltProject)
34+
{
35+
string plistPath = Path.Combine(pathToBuiltProject, "Info.plist");
36+
37+
if (!File.Exists(plistPath))
38+
{
39+
Debug.LogError("Info.plist not found!");
40+
return;
41+
}
42+
43+
// Load the Info.plist
44+
PlistDocument plist = new PlistDocument();
45+
plist.ReadFromFile(plistPath);
46+
47+
// Get the root dictionary
48+
PlistElementDict rootDict = plist.root;
49+
50+
// Add App Transport Security Settings
51+
PlistElementDict atsDict = rootDict.CreateDict("NSAppTransportSecurity");
52+
atsDict.SetBoolean("NSAllowsArbitraryLoads", true);
53+
54+
// Save the modified Info.plist
55+
plist.WriteToFile(plistPath);
56+
57+
Debug.Log("Successfully updated Info.plist with NSAllowsArbitraryLoads set to YES.");
58+
}
59+
60+
private static void ModifyXcodeProject(string pathToBuiltProject, string bundleIdentifier)
61+
{
62+
string pbxprojPath = PBXProject.GetPBXProjectPath(pathToBuiltProject);
63+
PBXProject pbxProject = new PBXProject();
64+
pbxProject.ReadFromFile(pbxprojPath);
65+
66+
string targetGuid = pbxProject.GetUnityMainTargetGuid(); // Unity 2019+
67+
pbxProject.SetBuildProperty(targetGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleIdentifier);
68+
69+
pbxProject.WriteToFile(pbxprojPath);
70+
Debug.Log($"Updated Xcode project with bundle identifier: {bundleIdentifier}");
71+
}
72+
73+
private static string GetBundleIdentifierFromArgs()
74+
{
75+
string[] args = System.Environment.GetCommandLineArgs();
76+
for (int i = 0; i < args.Length; i++)
77+
{
78+
if (args[i] == "--bundleIdentifier" && i + 1 < args.Length)
79+
{
80+
return args[i + 1];
81+
}
82+
}
83+
return "com.immutable.Immutable-Sample"; // Default fallback
84+
}
85+
}
86+
87+
#endif

sample/Assets/Editor/iOSPostBuildProcessor.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sample/ProjectSettings/ProjectSettings.asset

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,13 @@ PlayerSettings:
157157
applicationIdentifier:
158158
Android: com.immutable.ImmutableSample
159159
Standalone: com.immutable.Immutable-Sample
160-
iPhone: com.immutable.Immutable-Sample
160+
iPhone: com.immutable.Immutable-Sample-GameSDK
161161
buildNumber:
162162
Standalone: 0
163163
VisionOS: 0
164164
iPhone: 0
165165
tvOS: 0
166-
overrideDefaultApplicationIdentifier: 0
166+
overrideDefaultApplicationIdentifier: 1
167167
AndroidBundleVersionCode: 1
168168
AndroidMinSdkVersion: 26
169169
AndroidTargetSdkVersion: 33

sample/Tests/requirements-mobile.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ pytest==8.2.2
77
requests==2.32.3
88
mailslurp-client==15.19.22
99
Appium-Python-Client
10-
browserstack-sdk
10+
browserstack-sdk
11+
browserstack-local
12+
pytest-variables
13+
pytest-selenium
14+
jsonmerge
15+
multiprocess
16+
paver
17+
psutil

sample/Tests/browserstack.ios.yml renamed to sample/Tests/test/ios/browserstack.ios.yml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ buildName: iOS build
2121
# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests
2222
buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression}
2323
framework: pytest
24-
source: pytest-browserstack:sample-sdk:v1.0
24+
source: pytest-appium-browserstack:sample-sdk:v1.0
2525

2626
# Set `app` to define the app that is to be used for testing.
2727
# It can either take the id of any uploaded app or the path of the app directly.
@@ -35,9 +35,9 @@ app: ./Payload.ipa #For running local tests
3535
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate)
3636

3737
platforms:
38-
- platformName: ios
39-
deviceName: iPhone 14 Pro Max
40-
platformVersion: 16
38+
- deviceName: iPhone 14 Pro
39+
osVersion: 16
40+
platformName: ios
4141

4242
# =======================
4343
# Parallels per Platform
@@ -57,10 +57,10 @@ parallelsPerPlatform: 1
5757
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet
5858
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction
5959
browserstackLocal: true # <boolean> (Default false)
60-
browserStackLocalOptions:
60+
# browserStackLocalOptions:
6161
#Options to be passed to BrowserStack local in-case of advanced configurations
6262
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local.
63-
forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
63+
# forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
6464
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections
6565

6666
# ===================
@@ -70,4 +70,5 @@ debug: false # <boolean> # Set to true if you need screenshots for every seleniu
7070
networkLogs: false # <boolean> Set to true to enable HAR logs capturing
7171
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors)
7272
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors)
73-
acceptInsecureCerts: true
73+
74+
autoAcceptAlerts: true

sample/Tests/test/ios/conftest.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import pytest
2+
from appium import webdriver
3+
from alttester import *
4+
5+
@pytest.fixture(scope='function')
6+
def setWebdriver(request, session_capabilities):
7+
session_capabilities["autoAcceptAlerts"] = True
8+
remoteURL = "https://hub.browserstack.com/wd/hub"
9+
driver = webdriver.Remote(remoteURL, session_capabilities)
10+
11+
altdriver = AltDriver(timeout=120)
12+
13+
request.instance.driver = driver
14+
request.instance.altdriver = altdriver
15+
16+
request.node._driver = driver
17+
18+
yield driver
19+
20+
driver.quit()
21+
altdriver.stop()

0 commit comments

Comments
 (0)