Skip to content

Commit 800a558

Browse files
fix(windows): make login resilient to missing protocol dialog
1 parent 83b95c6 commit 800a558

2 files changed

Lines changed: 69 additions & 9 deletions

File tree

sample/Tests/test/test_windows.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ def _perform_login(self):
120120
bring_sample_app_to_foreground()
121121

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

@@ -224,7 +226,7 @@ def test_6_relogin(self):
224226
self.get_altdriver().wait_for_object(By.NAME, "ReloginBtn").tap()
225227

226228
# Wait for authenticated screen
227-
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
229+
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
228230
print("Re-logged in")
229231

230232
# Get access token
@@ -251,7 +253,7 @@ def test_7_reconnect_connect_imx(self):
251253
self.get_altdriver().wait_for_object(By.NAME, "ReconnectBtn").tap()
252254

253255
# Wait for authenticated screen
254-
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
256+
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
255257
print("Reconnected")
256258

257259
# Get access token
@@ -304,7 +306,7 @@ def test_8_connect_imx(self):
304306
bring_sample_app_to_foreground()
305307

306308
# Wait for authenticated screen
307-
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene")
309+
self.get_altdriver().wait_for_current_scene_to_be("AuthenticatedScene", timeout=90)
308310
print("Logged in and connected to IMX")
309311
stop_browser()
310312

sample/Tests/test/test_windows_helpers.py

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,49 @@
3636
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'src'))
3737
from fetch_otp import EMAIL, fetch_code
3838

39+
# Unity authentication success markers we can reliably detect from Player.log.
40+
_UNITY_AUTH_SUCCESS_MARKERS = [
41+
"AuthenticatedScene",
42+
"COMPLETE_LOGIN_PKCE",
43+
"LoginPKCESuccess",
44+
"HandleLoginPkceSuccess",
45+
"authentication successful",
46+
"logged in successfully",
47+
"Passport token received",
48+
]
49+
50+
51+
def wait_for_authentication_success_in_unity_logs(timeout_seconds: int = 60) -> bool:
52+
"""
53+
Best-effort wait for Unity to process the deep-link callback.
54+
55+
This is needed in CI because the browser may auto-handle the external protocol
56+
without showing any permission dialog (especially if protocol association is set),
57+
so Selenium won't have any button to click, but Unity will still authenticate.
58+
"""
59+
import os
60+
61+
product_name = os.getenv("UNITY_APP_NAME", get_product_name())
62+
log_path = os.path.join("C:\\Users\\WindowsBuildsdkServi\\AppData\\LocalLow\\Immutable", product_name, "Player.log")
63+
64+
print(f"Waiting up to {timeout_seconds}s for Unity auth success in Player.log...")
65+
print(f"Monitoring Unity log: {log_path}")
66+
67+
for _ in range(max(1, int(timeout_seconds))):
68+
try:
69+
with open(log_path, 'r', encoding='utf-8', errors='ignore') as f:
70+
content = f.read()
71+
if any(marker in content for marker in _UNITY_AUTH_SUCCESS_MARKERS):
72+
print("Authentication success detected in Unity logs!")
73+
return True
74+
except Exception:
75+
# Log may not exist yet or be temporarily locked; retry.
76+
pass
77+
time.sleep(1)
78+
79+
print("No authentication success detected in Unity logs within timeout.")
80+
return False
81+
3982
# Add chrome.exe to environment variable
4083
# Download chrome driver and add to environment variable
4184

@@ -538,6 +581,8 @@ def login():
538581
time.sleep(3)
539582

540583
try:
584+
current_url_lower = (driver.current_url or "").lower()
585+
541586
# Check what's actually on the page
542587
buttons = driver.find_elements(By.TAG_NAME, "button")
543588
print(f"Found {len(buttons)} buttons on page:")
@@ -548,16 +593,29 @@ def login():
548593
print(f" Button {i}: '{text}'")
549594
except:
550595
pass
551-
552-
# Wait for the deep link dialog to appear and click the button
553-
# Use more specific selector to avoid clicking "Restore" button
596+
597+
# In CI, if protocol association is already configured, Chrome/Brave may auto-handle
598+
# the external protocol WITHOUT showing any permission dialog. In that case there
599+
# may be 0 buttons on /checking, and waiting for a dialog will just time out.
600+
if "auth.immutable.com/checking" in current_url_lower and len(buttons) == 0:
601+
print("No deep link permission dialog present on /checking (0 buttons).")
602+
print("Assuming protocol is already permitted; waiting for Unity to process callback via Player.log...")
603+
wait_for_authentication_success_in_unity_logs(timeout_seconds=75)
604+
return
605+
606+
# Otherwise, try to click the deep link dialog if it appears.
607+
# Use more specific selector to avoid clicking "Restore" button.
554608
product_name = os.getenv("UNITY_APP_NAME", get_product_name())
555-
deep_link_button = wait.until(EC.element_to_be_clickable((By.XPATH, f"//button[text()='Open {product_name}.cmd']")))
609+
dialog_wait = WebDriverWait(driver, 8)
610+
deep_link_button = dialog_wait.until(
611+
EC.element_to_be_clickable((By.XPATH, f"//button[text()='Open {product_name}.cmd']"))
612+
)
556613
deep_link_button.click()
557614
print("Clicked deep link permission dialog - Unity should receive redirect")
558615
except Exception as e:
559616
print(f"Deep link dialog not found or failed to click: {e}")
560-
print("This may cause the test to timeout waiting for scene change")
617+
print("Assuming dialog was suppressed/auto-handled; waiting for Unity to process callback via Player.log...")
618+
wait_for_authentication_success_in_unity_logs(timeout_seconds=75)
561619

562620
# Keep browser alive for Unity deep link redirect
563621
# driver.quit()

0 commit comments

Comments
 (0)