diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 7885d6c8..6bda5c22 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -131,26 +131,26 @@ jobs: security default-keychain -s ~/Library/Keychains/login.keychain-db security delete-keychain temporary security list-keychains -# test-ios: -# name: Run iOS UI tests 🧪 -# runs-on: [ self-hosted, macOS ] -# steps: -# - uses: actions/checkout@v3 -# with: -# lfs: true -# - name: Build iOS app -# working-directory: sample -# run: ./build_ios.sh -# - uses: actions/setup-python@v4 -# with: -# python-version: "3.10" -# - name: Install dependencies -# run: pip install -r "sample/Tests/requirements-mobile.txt" -# - name: Run UI tests -# env: -# MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} -# BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} -# BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} -# working-directory: sample/Tests -# run: browserstack-sdk pytest -s ./test/test_ios.py --browserstack.config "browserstack.ios.yml" + test-ios: + name: Run iOS UI tests 🧪 + runs-on: [ self-hosted, macOS ] + steps: + - uses: actions/checkout@v3 + with: + lfs: true + - name: Build iOS app + working-directory: sample + run: ./build_ios.sh + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Install dependencies + run: pip install -r "sample/Tests/requirements-mobile.txt" + - name: Run UI tests + env: + MAILSLURP_API_KEY: ${{ secrets.MAILSLURP_API_KEY }} + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + working-directory: sample/Tests/test/ios + run: browserstack-sdk pytest -xs ./test_ios.py --browserstack.config "browserstack.ios.yml" diff --git a/sample/.gitignore b/sample/.gitignore new file mode 100644 index 00000000..da85648b --- /dev/null +++ b/sample/.gitignore @@ -0,0 +1,3 @@ +**/Payload.ipa +**/logFile.log +**/local.log \ No newline at end of file diff --git a/sample/Assets/Editor/iOSPostBuildProcessor.cs b/sample/Assets/Editor/iOSPostBuildProcessor.cs new file mode 100644 index 00000000..64ebbd75 --- /dev/null +++ b/sample/Assets/Editor/iOSPostBuildProcessor.cs @@ -0,0 +1,87 @@ +#if UNITY_IPHONE && UNITY_EDITOR_OSX + +using UnityEngine; +using UnityEditor; +using UnityEditor.Callbacks; +using System.IO; +using System.Linq; +using UnityEditor.iOS.Xcode; + +public class iOSPostBuildProcessor +{ + [PostProcessBuild] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) + { + if (target == BuildTarget.iOS && IsCommandLineBuild()) + { + Debug.Log("Command-line iOS build detected. Modifying Info.plist and Xcode project..."); + ModifyInfoPlist(pathToBuiltProject); + ModifyXcodeProject(pathToBuiltProject, GetBundleIdentifierFromArgs()); + } + else + { + Debug.Log("Skipping Info.plist modification (not an iOS command-line build)."); + } + } + + private static bool IsCommandLineBuild() + { + string[] args = System.Environment.GetCommandLineArgs(); + return args.Contains("--ciBuild"); // Check for the --ciBuild flag + } + + private static void ModifyInfoPlist(string pathToBuiltProject) + { + string plistPath = Path.Combine(pathToBuiltProject, "Info.plist"); + + if (!File.Exists(plistPath)) + { + Debug.LogError("Info.plist not found!"); + return; + } + + // Load the Info.plist + PlistDocument plist = new PlistDocument(); + plist.ReadFromFile(plistPath); + + // Get the root dictionary + PlistElementDict rootDict = plist.root; + + // Add App Transport Security Settings + PlistElementDict atsDict = rootDict.CreateDict("NSAppTransportSecurity"); + atsDict.SetBoolean("NSAllowsArbitraryLoads", true); + + // Save the modified Info.plist + plist.WriteToFile(plistPath); + + Debug.Log("Successfully updated Info.plist with NSAllowsArbitraryLoads set to YES."); + } + + private static void ModifyXcodeProject(string pathToBuiltProject, string bundleIdentifier) + { + string pbxprojPath = PBXProject.GetPBXProjectPath(pathToBuiltProject); + PBXProject pbxProject = new PBXProject(); + pbxProject.ReadFromFile(pbxprojPath); + + string targetGuid = pbxProject.GetUnityMainTargetGuid(); // Unity 2019+ + pbxProject.SetBuildProperty(targetGuid, "PRODUCT_BUNDLE_IDENTIFIER", bundleIdentifier); + + pbxProject.WriteToFile(pbxprojPath); + Debug.Log($"Updated Xcode project with bundle identifier: {bundleIdentifier}"); + } + + private static string GetBundleIdentifierFromArgs() + { + string[] args = System.Environment.GetCommandLineArgs(); + for (int i = 0; i < args.Length; i++) + { + if (args[i] == "--bundleIdentifier" && i + 1 < args.Length) + { + return args[i + 1]; + } + } + return "com.immutable.Immutable-Sample"; // Default fallback + } +} + +#endif \ No newline at end of file diff --git a/sample/Assets/Editor/iOSPostBuildProcessor.cs.meta b/sample/Assets/Editor/iOSPostBuildProcessor.cs.meta new file mode 100644 index 00000000..39c192bd --- /dev/null +++ b/sample/Assets/Editor/iOSPostBuildProcessor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 500da24b224a4d3b846ba1ccc9094b2b +timeCreated: 1740453437 \ No newline at end of file diff --git a/sample/ProjectSettings/ProjectSettings.asset b/sample/ProjectSettings/ProjectSettings.asset index 0428f12d..a57f5808 100644 --- a/sample/ProjectSettings/ProjectSettings.asset +++ b/sample/ProjectSettings/ProjectSettings.asset @@ -157,13 +157,13 @@ PlayerSettings: applicationIdentifier: Android: com.immutable.ImmutableSample Standalone: com.immutable.Immutable-Sample - iPhone: com.immutable.Immutable-Sample + iPhone: com.immutable.Immutable-Sample-GameSDK buildNumber: Standalone: 0 VisionOS: 0 iPhone: 0 tvOS: 0 - overrideDefaultApplicationIdentifier: 0 + overrideDefaultApplicationIdentifier: 1 AndroidBundleVersionCode: 1 AndroidMinSdkVersion: 26 AndroidTargetSdkVersion: 33 diff --git a/sample/Tests/requirements-mobile.txt b/sample/Tests/requirements-mobile.txt index 3fc2df38..a4eb2323 100644 --- a/sample/Tests/requirements-mobile.txt +++ b/sample/Tests/requirements-mobile.txt @@ -7,4 +7,11 @@ pytest==8.2.2 requests==2.32.3 mailslurp-client==15.19.22 Appium-Python-Client -browserstack-sdk \ No newline at end of file +browserstack-sdk +browserstack-local +pytest-variables +pytest-selenium +jsonmerge +multiprocess +paver +psutil \ No newline at end of file diff --git a/sample/Tests/browserstack.ios.yml b/sample/Tests/test/ios/browserstack.ios.yml similarity index 91% rename from sample/Tests/browserstack.ios.yml rename to sample/Tests/test/ios/browserstack.ios.yml index 4d39ce54..d85ea5de 100644 --- a/sample/Tests/browserstack.ios.yml +++ b/sample/Tests/test/ios/browserstack.ios.yml @@ -21,7 +21,7 @@ buildName: iOS build # Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} framework: pytest -source: pytest-browserstack:sample-sdk:v1.0 +source: pytest-appium-browserstack:sample-sdk:v1.0 # Set `app` to define the app that is to be used for testing. # 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 # Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) platforms: - - platformName: ios - deviceName: iPhone 14 Pro Max - platformVersion: 16 + - deviceName: iPhone 14 Pro + osVersion: 16 + platformName: ios # ======================= # Parallels per Platform @@ -57,10 +57,10 @@ parallelsPerPlatform: 1 # Set browserStackLocal to true if your website under test is not accessible publicly over the internet # Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction browserstackLocal: true # (Default false) -browserStackLocalOptions: +# browserStackLocalOptions: #Options to be passed to BrowserStack local in-case of advanced configurations # localIdentifier: # (Default: null) Needed if you need to run multiple instances of local. - forceLocal: true # (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. + # forceLocal: true # (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. # Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections # =================== @@ -70,4 +70,5 @@ debug: false # # Set to true if you need screenshots for every seleniu networkLogs: false # Set to true to enable HAR logs capturing consoleLogs: errors # Remote browser's console debug levels to be printed (Default: errors) # Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) -acceptInsecureCerts: true + +autoAcceptAlerts: true \ No newline at end of file diff --git a/sample/Tests/test/ios/conftest.py b/sample/Tests/test/ios/conftest.py new file mode 100644 index 00000000..6c343087 --- /dev/null +++ b/sample/Tests/test/ios/conftest.py @@ -0,0 +1,21 @@ +import pytest +from appium import webdriver +from alttester import * + +@pytest.fixture(scope='function') +def setWebdriver(request, session_capabilities): + session_capabilities["autoAcceptAlerts"] = True + remoteURL = "https://hub.browserstack.com/wd/hub" + driver = webdriver.Remote(remoteURL, session_capabilities) + + altdriver = AltDriver(timeout=120) + + request.instance.driver = driver + request.instance.altdriver = altdriver + + request.node._driver = driver + + yield driver + + driver.quit() + altdriver.stop() \ No newline at end of file diff --git a/sample/Tests/test/ios/test_ios.py b/sample/Tests/test/ios/test_ios.py new file mode 100644 index 00000000..afee4b5c --- /dev/null +++ b/sample/Tests/test/ios/test_ios.py @@ -0,0 +1,237 @@ +import os +import sys +import time +from pathlib import Path +import pytest + +from appium.webdriver.common.appiumby import AppiumBy +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.common.by import By + +from alttester import * + +PROJECT_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(PROJECT_ROOT / "test")) +sys.path.insert(0, str(PROJECT_ROOT / "src")) +from test import TestConfig, UnityTest +from fetch_otp import fetch_code + +@pytest.mark.usefixtures('setWebdriver') +class TestIos: + + def login(self): + driver = self.driver + + # Wait for the ASWebAuthenticationSession context to appear + WebDriverWait(driver, 30).until(lambda d: len(d.contexts) > 1) + time.sleep(5) # Refresh contexts by waiting before fetching again + print("Available contexts:", driver.contexts) + contexts = driver.contexts + driver.switch_to.context(driver.contexts[-1]) + print("Current context:", driver.current_context) + + target_context = None + + # Since it's unclear which WebView context contains the email field on iOS, + # we need to iterate through each context to identify the correct one. + for context in contexts: + if context == "NATIVE_APP": + continue + + driver.switch_to.context(context) + + try: + # Attempt to find the email input field + email_field = WebDriverWait(driver, 5).until( + EC.presence_of_element_located((AppiumBy.XPATH, "//input[@name='address']")) + ) + # Found email + target_context = context + + email_field.send_keys(TestConfig.EMAIL) + submit_button = driver.find_element(by=AppiumBy.XPATH, value="//form/div/div/div[2]/button") + submit_button.click() + + time.sleep(10) # Wait for OTP + + code = fetch_code() + assert code, "Failed to fetch OTP from MailSlurp" + print(f"Successfully fetched OTP: {code}") + + # Unlike on Android, each digit must be entered into a separate input field on iOS. + for i, digit in enumerate(code): + otp_field = driver.find_element(by=AppiumBy.XPATH, value=f"//div[@id='passwordless_container']/div[{i + 1}]/input") + otp_field.send_keys(digit) + + break + except: + # If the field is not found, continue to the next context + print(f"Email field not found in context: {context}") + + # If target context was not found, raise an error + if not target_context: + raise Exception("Could not find the email field in any webview context.") + + # @classmethod + # def close_and_open_app(cls): + # driver = cls.driver + + # # Close app + # time.sleep(5) + # print("Closing app...") + # driver.terminate_app(TestConfig.IOS_BUNDLE_ID) + # time.sleep(5) + # print("Closed app") + + # # Reopen app + # print("Opening app...") + # driver.activate_app(TestConfig.IOS_BUNDLE_ID) + # time.sleep(10) + # print("Opened app") + + def test_1_pkce_login(self): + # Select use PKCE auth + self.altdriver.find_object(By.NAME, "PKCE").tap() + + # Wait for unauthenticated screen + self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + + # Login + loginBtn = self.altdriver.wait_for_object(By.NAME, "LoginBtn") + loginBtn.tap() + + self.login() + + # Wait for authenticated screen + self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") + + # def test_2_other_functions(self): + # self.test_0_other_functions() + + # def test_3_passport_functions(self): + # self.test_1_passport_functions() + + # def test_4_imx_functions(self): + # self.test_2_imx_functions() + + # def test_5_zkevm_functions(self): + # self.test_3_zkevm_functions() + + # def test_6_pkce_relogin(self): + # driver = self.appium_driver + + # self.close_and_open_app() + + # # Restart AltTester + # self.altdriver.stop() + # self.altdriver = AltDriver() + # time.sleep(5) + + # # # Select use PKCE auth + # self.altdriver.find_object(By.NAME, "PKCE").tap() + # # Wait for unauthenticated screen + # self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + + # # Relogin + # print("Re-logging in...") + # self.altdriver.wait_for_object(By.NAME, "ReloginBtn").tap() + + # # Wait for authenticated screen + # self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") + # print("Re-logged in") + + # # Get access token + # self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() + # output = self.altdriver.find_object(By.NAME, "Output") + # self.assertTrue(len(output.get_text()) > 50) + + # # Click Connect to IMX button + # self.altdriver.find_object(By.NAME, "ConnectBtn").tap() + # self.assertEqual("Connected to IMX", output.get_text()) + + # self.altdriver.stop() + + # def test_7_pkce_reconnect(self): + # self.close_and_open_app() + + # # Restart AltTester + # self.altdriver.stop() + # self.altdriver = AltDriver() + # time.sleep(5) + + # # Select use PKCE auth + # self.altdriver.find_object(By.NAME, "PKCE").tap() + # # Wait for unauthenticated screen + # self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + + # # Reconnect + # print("Reconnecting...") + # self.altdriver.wait_for_object(By.NAME, "ReconnectBtn").tap() + + # # Wait for authenticated screen + # self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") + # print("Reconnected") + + # # Get access token + # self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() + # output = self.altdriver.find_object(By.NAME, "Output") + # self.assertTrue(len(output.get_text()) > 50) + + # # Get address without having to click Connect to IMX button + # self.altdriver.find_object(By.NAME, "GetAddressBtn").tap() + # self.assertEqual(TestConfig.WALLET_ADDRESS, output.get_text()) + + # # Logout + # print("Logging out...") + # self.altdriver.find_object(By.NAME, "LogoutBtn").tap() + # time.sleep(5) + + # # Wait for authenticated screen + # self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + # time.sleep(5) + # print("Logged out") + + # self.altdriver.stop() + + # def test_8_pkce_connect_imx(self): + # self.close_and_open_app() + + # # Restart AltTester + # self.altdriver.stop() + # self.altdriver = AltDriver() + # time.sleep(5) + + # # Select use PKCE auth + # self.altdriver.find_object(By.NAME, "PKCE").tap() + # # Wait for unauthenticated screen + # self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + + # # Connect IMX + # print("Logging in and connecting to IMX...") + # self.altdriver.wait_for_object(By.NAME, "ConnectBtn").tap() + + # self.login() + + # # Wait for authenticated screen + # self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") + # print("Logged in and connected to IMX") + + # # Get access token + # self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() + # output = self.altdriver.find_object(By.NAME, "Output") + # self.assertTrue(len(output.get_text()) > 50) + + # # Get address without having to click Connect to IMX button + # self.altdriver.find_object(By.NAME, "GetAddressBtn").tap() + # self.assertEqual(TestConfig.WALLET_ADDRESS, output.get_text()) + + # # Logout + # print("Logging out...") + # self.altdriver.find_object(By.NAME, "LogoutBtn").tap() + # time.sleep(5) + + # # Wait for authenticated screen + # self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") + # time.sleep(5) + # print("Logged out") \ No newline at end of file diff --git a/sample/Tests/test/test.py b/sample/Tests/test/test.py index 76db716c..a03a214e 100644 --- a/sample/Tests/test/test.py +++ b/sample/Tests/test/test.py @@ -11,7 +11,7 @@ class TestConfig: PASSPORT_ID="email|67480492219c150aceeb1f37" WALLET_ADDRESS = "0x547044ea95f03651139081241c99ffedbefdc5e8" ANDROID_PACKAGE = "com.immutable.ImmutableSample" - IOS_BUNDLE_ID = "com.immutable.Immutable-Sample" + IOS_BUNDLE_ID = "com.immutable.Immutable-Sample-GameSDK" class UnityTest(unittest.TestCase): diff --git a/sample/Tests/test/test_ios.py b/sample/Tests/test/test_ios.py deleted file mode 100644 index a35f1e9b..00000000 --- a/sample/Tests/test/test_ios.py +++ /dev/null @@ -1,258 +0,0 @@ -import sys -import time -import unittest -from pathlib import Path - -from appium import webdriver -from appium.options.ios import XCUITestOptions -from appium.webdriver.common.appiumby import AppiumBy -from appium.webdriver.webdriver import WebDriver -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC - -from alttester import * - -from test import TestConfig, UnityTest - -sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'src')) -from fetch_otp import fetch_code - -# To run this test on an actual Android device: appium --base-path /wd/hub --allow-insecure chromedriver_autodownload -class TestBase(UnityTest): - altdriver = None - appium_driver = None - - @classmethod - def setUpClass(cls): - # https://appium.github.io/appium-xcuitest-driver/latest/preparation/real-device-config/ - options = XCUITestOptions() - options.show_xcode_log = True - options.auto_accept_alerts = True - - cls.appium_driver = webdriver.Remote('https://hub-cloud.browserstack.com/wd/hub/', options=options) - - time.sleep(10) - cls.altdriver = AltDriver() - - @classmethod - def tearDownClass(cls): - print("\nEnding") - cls.appium_driver.quit() - cls.altdriver.stop() - - @classmethod - def login(cls): - driver = cls.appium_driver - - # Wait for the ASWebAuthenticationSession context to appear - WebDriverWait(driver, 30).until(lambda d: len(d.contexts) > 2) - time.sleep(5) # Refresh contexts by waiting before fetching again - print("Available contexts:", driver.contexts) - contexts = driver.contexts - driver.switch_to.context(driver.contexts[-1]) - print("Current context:", driver.current_context) - - target_context = None - - # Since it's unclear which WebView context contains the email field on iOS, - # we need to iterate through each context to identify the correct one. - for context in contexts: - if context == "NATIVE_APP": - continue - - driver.switch_to.context(context) - - try: - # Attempt to find the email input field - email_field = WebDriverWait(driver, 5).until( - EC.presence_of_element_located((AppiumBy.XPATH, "//input[@name='address']")) - ) - # Found email - target_context = context - - email_field.send_keys(TestConfig.EMAIL) - submit_button = driver.find_element(by=AppiumBy.XPATH, value="//form/div/div/div[2]/button") - submit_button.click() - - time.sleep(10) # Wait for OTP - - code = fetch_code() - assert code, "Failed to fetch OTP from MailSlurp" - print(f"Successfully fetched OTP: {code}") - - # Unlike on Android, each digit must be entered into a separate input field on iOS. - for i, digit in enumerate(code): - otp_field = driver.find_element(by=AppiumBy.XPATH, value=f"//div[@id='passwordless_container']/div[{i + 1}]/input") - otp_field.send_keys(digit) - - break - except: - # If the field is not found, continue to the next context - print(f"Email field not found in context: {context}") - - # If target context was not found, raise an error - if not target_context: - raise Exception("Could not find the email field in any webview context.") - - @classmethod - def close_and_open_app(cls): - driver = cls.appium_driver - - # Close app - time.sleep(5) - print("Closing app...") - driver.terminate_app(TestConfig.IOS_BUNDLE_ID) - time.sleep(5) - print("Closed app") - - # Reopen app - print("Opening app...") - driver.activate_app(TestConfig.IOS_BUNDLE_ID) - time.sleep(10) - print("Opened app") - - def test_1_pkce_login(self): - # Select use PKCE auth - self.altdriver.find_object(By.NAME, "PKCE").tap() - - # Wait for unauthenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - - # Login - loginBtn = self.altdriver.wait_for_object(By.NAME, "LoginBtn") - loginBtn.tap() - - self.login() - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") - - def test_2_other_functions(self): - self.test_0_other_functions() - - def test_3_passport_functions(self): - self.test_1_passport_functions() - - def test_4_imx_functions(self): - self.test_2_imx_functions() - - def test_5_zkevm_functions(self): - self.test_3_zkevm_functions() - - def test_6_pkce_relogin(self): - driver = self.appium_driver - - self.close_and_open_app() - - # Restart AltTester - self.altdriver.stop() - self.altdriver = AltDriver() - time.sleep(5) - - # # Select use PKCE auth - self.altdriver.find_object(By.NAME, "PKCE").tap() - # Wait for unauthenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - - # Relogin - print("Re-logging in...") - self.altdriver.wait_for_object(By.NAME, "ReloginBtn").tap() - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") - print("Re-logged in") - - # Get access token - self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() - output = self.altdriver.find_object(By.NAME, "Output") - self.assertTrue(len(output.get_text()) > 50) - - # Click Connect to IMX button - self.altdriver.find_object(By.NAME, "ConnectBtn").tap() - self.assertEqual("Connected to IMX", output.get_text()) - - self.altdriver.stop() - - def test_7_pkce_reconnect(self): - self.close_and_open_app() - - # Restart AltTester - self.altdriver.stop() - self.altdriver = AltDriver() - time.sleep(5) - - # Select use PKCE auth - self.altdriver.find_object(By.NAME, "PKCE").tap() - # Wait for unauthenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - - # Reconnect - print("Reconnecting...") - self.altdriver.wait_for_object(By.NAME, "ReconnectBtn").tap() - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") - print("Reconnected") - - # Get access token - self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() - output = self.altdriver.find_object(By.NAME, "Output") - self.assertTrue(len(output.get_text()) > 50) - - # Get address without having to click Connect to IMX button - self.altdriver.find_object(By.NAME, "GetAddressBtn").tap() - self.assertEqual(TestConfig.WALLET_ADDRESS, output.get_text()) - - # Logout - print("Logging out...") - self.altdriver.find_object(By.NAME, "LogoutBtn").tap() - time.sleep(5) - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - time.sleep(5) - print("Logged out") - - self.altdriver.stop() - - def test_8_pkce_connect_imx(self): - self.close_and_open_app() - - # Restart AltTester - self.altdriver.stop() - self.altdriver = AltDriver() - time.sleep(5) - - # Select use PKCE auth - self.altdriver.find_object(By.NAME, "PKCE").tap() - # Wait for unauthenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - - # Connect IMX - print("Logging in and connecting to IMX...") - self.altdriver.wait_for_object(By.NAME, "ConnectBtn").tap() - - self.login() - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("AuthenticatedScene") - print("Logged in and connected to IMX") - - # Get access token - self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap() - output = self.altdriver.find_object(By.NAME, "Output") - self.assertTrue(len(output.get_text()) > 50) - - # Get address without having to click Connect to IMX button - self.altdriver.find_object(By.NAME, "GetAddressBtn").tap() - self.assertEqual(TestConfig.WALLET_ADDRESS, output.get_text()) - - # Logout - print("Logging out...") - self.altdriver.find_object(By.NAME, "LogoutBtn").tap() - time.sleep(5) - - # Wait for authenticated screen - self.altdriver.wait_for_current_scene_to_be("UnauthenticatedScene") - time.sleep(5) - print("Logged out") \ No newline at end of file diff --git a/sample/build_ios.sh b/sample/build_ios.sh index 9cdeb517..bba80f62 100755 --- a/sample/build_ios.sh +++ b/sample/build_ios.sh @@ -34,7 +34,10 @@ mkdir -p "$BUILD_IPA_PATH" mkdir -p "$DERIVED_DATA_PATH" # Unity build command -UNITY_COMMAND="$PATH_UNITY -projectPath \"$PATH_TO_UNITY_SDK_SAMPLE_APP\" -executeMethod $BUILD_METHOD -logFile logFile.log -quit -batchmode --buildPath \"$BUILD_XCODE_PATH\" --platform iOS --bundleIdentifier com.immutable.Immutable-Sample-GameSDK" +UNITY_COMMAND="$PATH_UNITY -projectPath \"$PATH_TO_UNITY_SDK_SAMPLE_APP\" -executeMethod $BUILD_METHOD \ +-logFile logFile.log -quit -batchmode --buildPath \"$BUILD_XCODE_PATH\" \ +--platform iOS --bundleIdentifier com.immutable.Immutable-Sample-GameSDK \ +--host \"127.0.0.1\" --ciBuild" echo "Running command: $UNITY_COMMAND" # Execute the Unity build command @@ -47,7 +50,7 @@ if [ $? -ne 0 ]; then fi echo "Building app..." -xcodebuild clean build \ +/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild clean build \ -project "$(pwd)/build/output/iOS/Xcode/Unity-iPhone.xcodeproj" \ -scheme Unity-iPhone \ -destination "generic/platform=iOS" \ @@ -61,4 +64,4 @@ mv "$(pwd)/build/output/iOS/DerivedData/Build/Products/ReleaseForRunning-iphoneo pushd "$(pwd)/build/output/iOS/IPA" && zip -r Payload.zip Payload && popd -mv "$(pwd)/build/output/iOS/IPA/Payload.zip" "$(pwd)/Tests/Payload.ipa" \ No newline at end of file +mv "$(pwd)/build/output/iOS/IPA/Payload.zip" "$(pwd)/Tests/test/ios/Payload.ipa" \ No newline at end of file