7adc7c00ab
Enable managed remote browser custom pages with login autofill and add website sync workflows so external admin surfaces can be handled inside SmartUp. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
105 lines
2.8 KiB
Python
105 lines
2.8 KiB
Python
import asyncio
|
|
|
|
from app.services.browser_session_service import BrowserSessionService
|
|
|
|
|
|
class FakeLocator:
|
|
def __init__(self, *, visible=True, count=1):
|
|
self._visible = list(visible) if isinstance(visible, list) else [visible]
|
|
self._count = count
|
|
self.filled = []
|
|
self.clicked = 0
|
|
self.timeouts = []
|
|
|
|
@property
|
|
def first(self):
|
|
return self
|
|
|
|
async def count(self):
|
|
return self._count
|
|
|
|
async def is_visible(self, timeout=0):
|
|
self.timeouts.append(timeout)
|
|
if not self._visible:
|
|
return False
|
|
if len(self._visible) == 1:
|
|
return self._visible[0]
|
|
return self._visible.pop(0)
|
|
|
|
async def fill(self, value, timeout=0):
|
|
self.filled.append((value, timeout))
|
|
|
|
async def click(self, timeout=0):
|
|
self.clicked += 1
|
|
|
|
|
|
class FakePage:
|
|
url = "https://example.test/login"
|
|
|
|
def __init__(self, locators):
|
|
self.locators = locators
|
|
self.queries = []
|
|
|
|
def locator(self, selector):
|
|
self.queries.append(selector)
|
|
return self.locators.get(selector, FakeLocator(visible=False, count=0))
|
|
|
|
|
|
def run(coro):
|
|
return asyncio.run(coro)
|
|
|
|
|
|
def test_autofill_retries_until_delayed_fields_are_visible():
|
|
service = BrowserSessionService()
|
|
username = FakeLocator(visible=[False, True])
|
|
password = FakeLocator(visible=True)
|
|
submit = FakeLocator(visible=True)
|
|
page = FakePage({
|
|
"#user": username,
|
|
"#pass": password,
|
|
"#submit": submit,
|
|
})
|
|
|
|
run(service._autofill_login(
|
|
page,
|
|
{
|
|
"enabled": True,
|
|
"username": "alice",
|
|
"password": "secret",
|
|
"username_selector": "#user",
|
|
"password_selector": "#pass",
|
|
"submit_selector": "#submit",
|
|
},
|
|
max_wait_seconds=1,
|
|
poll_interval_seconds=0,
|
|
))
|
|
|
|
assert page.queries[0] == "#user"
|
|
assert "#pass" in page.queries
|
|
assert "input[type='password']" not in page.queries
|
|
assert username.filled == [("alice", 3000)]
|
|
assert password.filled == [("secret", 3000)]
|
|
assert submit.clicked == 1
|
|
|
|
|
|
def test_autofill_returns_without_selectors_when_disabled_or_missing_credentials():
|
|
service = BrowserSessionService()
|
|
|
|
disabled_page = FakePage({"#user": FakeLocator()})
|
|
run(service._autofill_login(
|
|
disabled_page,
|
|
{"enabled": False, "username": "alice", "password": "secret"},
|
|
max_wait_seconds=1,
|
|
poll_interval_seconds=0,
|
|
))
|
|
assert disabled_page.queries == []
|
|
|
|
missing_password_page = FakePage({"#user": FakeLocator()})
|
|
run(service._autofill_login(
|
|
missing_password_page,
|
|
{"enabled": True, "username": "alice", "password": ""},
|
|
max_wait_seconds=1,
|
|
poll_interval_seconds=0,
|
|
))
|
|
assert missing_password_page.queries == []
|