Skip to content
Open
524 changes: 464 additions & 60 deletions sample/Assets/WebGLTemplates/unity-webview/Passport/index.html

Large diffs are not rendered by default.

64 changes: 56 additions & 8 deletions sample/Tests/test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,33 @@ def stop_altdriver(self):
if self.__class__.altdriver:
self.__class__.altdriver.stop()

def wait_for_output(
self,
output_obj,
predicate,
*,
timeout_seconds: float = 15.0,
poll_seconds: float = 0.25,
) -> str:
"""
Poll the `Output` UI element until `predicate(text)` is True.

UI actions often update `Output` asynchronously (especially in CI),
so reading immediately after `.tap()` can be flaky.
"""
deadline = time.time() + float(timeout_seconds)
last_text = ""
while time.time() < deadline:
try:
last_text = output_obj.get_text()
if predicate(last_text):
return last_text
except Exception:
# App/UI might be mid-transition; retry.
pass
time.sleep(float(poll_seconds))
return last_text

@pytest.mark.skip(reason="Base test should not be executed directly")
def test_0_other_functions(self):
# Show set call timeout scene
Expand All @@ -59,31 +86,52 @@ def test_1_passport_functions(self):
output = self.altdriver.find_object(By.NAME, "Output")

# Get access token
prev = output.get_text()
self.altdriver.find_object(By.NAME, "GetAccessTokenBtn").tap()
text = output.get_text()
self.assertTrue(len(text) > 50)
text = self.wait_for_output(
output,
lambda t: len(t) > 50 and (t != prev or prev == ""),
timeout_seconds=20,
)
self.assertTrue(len(text) > 50, f"Access token output too short. Actual output: '{text}'")

# Get ID token
prev = output.get_text()
self.altdriver.find_object(By.NAME, "GetIdTokenBtn").tap()
text = output.get_text()
self.assertTrue(len(text) > 50)
text = self.wait_for_output(
output,
lambda t: len(t) > 50 and (t != prev or prev == ""),
timeout_seconds=20,
)
self.assertTrue(len(text) > 50, f"ID token output too short. Actual output: '{text}'")

# Get email
self.altdriver.find_object(By.NAME, "GetEmail").tap()
text = output.get_text()
text = self.wait_for_output(
output,
lambda t: t == TestConfig.EMAIL,
timeout_seconds=10,
)
print(f"GetEmail output: {text}")
self.assertEqual(TestConfig.EMAIL, text)

# Get Passport ID
self.altdriver.find_object(By.NAME, "GetPassportId").tap()
text = output.get_text()
text = self.wait_for_output(
output,
lambda t: t == TestConfig.PASSPORT_ID,
timeout_seconds=10,
)
print(f"GetPassportId output: {text}")
self.assertEqual(TestConfig.PASSPORT_ID, text)

# Get linked addresses
self.altdriver.find_object(By.NAME, "GetLinkedAddresses").tap()
time.sleep(1)
text = output.get_text()
text = self.wait_for_output(
output,
lambda t: t == "No linked addresses",
timeout_seconds=10,
)
print(f"GetLinkedAddresses output: {text}")
self.assertEqual("No linked addresses", text)

Expand Down
55 changes: 50 additions & 5 deletions sample/Tests/test/test_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from alttester import *

from test import TestConfig, UnityTest
from test_windows_helpers import login, open_sample_app, launch_browser, bring_sample_app_to_foreground, stop_browser, stop_sample_app, logout_with_controlled_browser
from test_windows_helpers import login, open_sample_app, launch_browser, bring_sample_app_to_foreground, stop_browser, stop_sample_app, logout_with_controlled_browser, get_product_name

class WindowsTest(UnityTest):

Expand Down Expand Up @@ -120,11 +120,56 @@ def _perform_login(self):
bring_sample_app_to_foreground()

# Wait for authenticated screen
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
# Default AltTester timeout for this command is ~20s; CI often needs longer,
# especially when the browser auto-handles the deep-link without a dialog.
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
stop_browser()
print("[SUCCESS] Login successful")

except Exception as err:
# Dump Player.log tail to help diagnose why the deep-link callback
# wasn't processed (or why Unity failed after receiving it).
try:
import os
product_name = os.getenv("UNITY_APP_NAME", get_product_name())
log_path = os.path.join(
"C:\\Users\\WindowsBuildsdkServi\\AppData\\LocalLow\\Immutable",
product_name,
"Player.log",
)
print(f"Attempting to dump Unity Player.log tail: {log_path}")
if os.path.exists(log_path):
with open(log_path, "r", encoding="utf-8", errors="ignore") as f:
lines = f.read().splitlines()
# The tail is often dominated by AltTester noise. Print:
# 1) last lines, and 2) last relevant lines (Passport/Immutable/URLs/errors).
tail = lines[-200:] if len(lines) > 200 else lines
print("----- Player.log (tail) -----")
for line in tail:
print(line)
print("----- end Player.log (tail) -----")

needles = (
"immutable",
"passport",
"launchauthurl",
"passport_auth_url",
"immutablerunner",
"error",
"exception",
"gb:",
)
relevant = [ln for ln in lines if any(n in ln.lower() for n in needles)]
relevant_tail = relevant[-200:] if len(relevant) > 200 else relevant
print("----- Player.log (relevant tail) -----")
for line in relevant_tail:
print(line)
print("----- end Player.log (relevant tail) -----")
else:
print("Player.log not found.")
except Exception as e:
print(f"Failed to dump Player.log: {e}")

stop_browser()
raise SystemExit(f"Login failed: {err}")

Expand Down Expand Up @@ -224,7 +269,7 @@ def test_6_relogin(self):
self.get_altdriver().wait_for_object(By.NAME, "ReloginBtn").tap()

# Wait for authenticated screen
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
print("Re-logged in")

# Get access token
Expand All @@ -251,7 +296,7 @@ def test_7_reconnect_connect_imx(self):
self.get_altdriver().wait_for_object(By.NAME, "ReconnectBtn").tap()

# Wait for authenticated screen
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
print("Reconnected")

# Get access token
Expand Down Expand Up @@ -304,7 +349,7 @@ def test_8_connect_imx(self):
bring_sample_app_to_foreground()

# Wait for authenticated screen
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
print("Logged in and connected to IMX")
stop_browser()

Expand Down
Loading
Loading