Skip to content

Commit 047a8d5

Browse files
fix(windows): click external protocol prompt via UIAutomation
1 parent 800a558 commit 047a8d5

1 file changed

Lines changed: 81 additions & 7 deletions

File tree

sample/Tests/test/test_windows_helpers.py

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,70 @@ def wait_for_authentication_success_in_unity_logs(timeout_seconds: int = 60) ->
7979
print("No authentication success detected in Unity logs within timeout.")
8080
return False
8181

82+
83+
def try_click_protocol_permission_dialog(timeout_seconds: int = 15) -> bool:
84+
"""
85+
Try to click the browser-level external protocol permission prompt.
86+
87+
Important: this dialog is NOT part of the web page DOM, so Selenium cannot click it.
88+
We use Windows UIAutomation to locate and invoke an "Open/Allow/Yes" button.
89+
"""
90+
product_name = os.getenv("UNITY_APP_NAME", get_product_name())
91+
print("Attempting to click external protocol permission dialog via UIAutomation...")
92+
93+
ps_script = f'''
94+
$deadline = (Get-Date).AddSeconds({int(timeout_seconds)})
95+
Add-Type -AssemblyName UIAutomationClient
96+
97+
function Find-And-Click($titlePart) {{
98+
$procs = Get-Process -ErrorAction SilentlyContinue | Where-Object {{ $_.MainWindowHandle -ne 0 -and $_.MainWindowTitle -like "*$titlePart*" }}
99+
foreach ($p in $procs) {{
100+
try {{
101+
$el = [Windows.Automation.AutomationElement]::FromHandle($p.MainWindowHandle)
102+
if ($null -eq $el) {{ continue }}
103+
$buttons = $el.FindAll([Windows.Automation.TreeScope]::Descendants,
104+
[Windows.Automation.Condition]::new([Windows.Automation.AutomationElement]::ControlTypeProperty, [Windows.Automation.ControlType]::Button))
105+
106+
foreach ($b in $buttons) {{
107+
$name = $b.Current.Name
108+
if ($name -like "*Open*" -or $name -like "*Allow*" -or $name -like "*Yes*" -or $name -like "*{product_name}*") {{
109+
$b.GetCurrentPattern([Windows.Automation.InvokePattern]::Pattern).Invoke()
110+
Write-Host "Clicked protocol dialog button: $name"
111+
return $true
112+
}}
113+
}}
114+
}} catch {{}}
115+
}}
116+
return $false
117+
}}
118+
119+
while ((Get-Date) -lt $deadline) {{
120+
if (Find-And-Click "auth.immutable.com") {{ exit 0 }}
121+
if (Find-And-Click "Immutable Passport") {{ exit 0 }}
122+
if (Find-And-Click "Open") {{ exit 0 }}
123+
Start-Sleep -Milliseconds 500
124+
}}
125+
Write-Host "No protocol dialog found"
126+
exit 1
127+
'''
128+
129+
try:
130+
result = subprocess.run(
131+
["powershell", "-Command", ps_script],
132+
capture_output=True,
133+
text=True,
134+
timeout=max(5, int(timeout_seconds) + 5),
135+
)
136+
if "Clicked protocol dialog button" in (result.stdout or ""):
137+
print(result.stdout.strip())
138+
print("Successfully clicked protocol dialog via UIAutomation.")
139+
return True
140+
print((result.stdout or "").strip() or "UIAutomation did not find/click any dialog button.")
141+
return False
142+
except Exception as e:
143+
print(f"UIAutomation dialog click failed: {e}")
144+
return False
145+
82146
# Add chrome.exe to environment variable
83147
# Download chrome driver and add to environment variable
84148

@@ -594,13 +658,23 @@ def login():
594658
except:
595659
pass
596660

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)
661+
# The "open external protocol" prompt is typically browser UI (not DOM),
662+
# so 0 buttons on /checking is expected. Try:
663+
# - wait briefly for Unity success (maybe protocol already fired)
664+
# - click the browser-level prompt via UIAutomation
665+
# - wait again for Unity success
666+
if "auth.immutable.com/checking" in current_url_lower:
667+
if wait_for_authentication_success_in_unity_logs(timeout_seconds=10):
668+
return
669+
670+
clicked = try_click_protocol_permission_dialog(timeout_seconds=20)
671+
if clicked:
672+
# Give Unity a moment to receive and process the callback
673+
wait_for_authentication_success_in_unity_logs(timeout_seconds=75)
674+
return
675+
676+
print("No protocol dialog clicked; Unity may never receive the callback.")
677+
wait_for_authentication_success_in_unity_logs(timeout_seconds=30)
604678
return
605679

606680
# Otherwise, try to click the deep link dialog if it appears.

0 commit comments

Comments
 (0)