fix: commit verified semantic repair changes

This commit is contained in:
2026-03-21 11:05:20 +03:00
parent 6262347acd
commit cf601a717e
10 changed files with 2504 additions and 901 deletions

View File

@@ -1,4 +1,5 @@
# [DEF:backend.src.plugins.llm_analysis.__tests__.test_screenshot_service:Module]
# [DEF:TestScreenshotService:Module]
# @RELATION: VERIFIES ->[src.plugins.llm_analysis.service.ScreenshotService]
# @COMPLEXITY: 3
# @SEMANTICS: tests, screenshot-service, navigation, timeout-regression
# @PURPOSE: Protect dashboard screenshot navigation from brittle networkidle waits.
@@ -9,6 +10,7 @@ from src.plugins.llm_analysis.service import ScreenshotService
# [DEF:test_iter_login_roots_includes_child_frames:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Login discovery must search embedded auth frames, not only the main page.
# @PRE: Page exposes child frames list.
# @POST: Returned roots include page plus child frames in order.
@@ -21,10 +23,13 @@ def test_iter_login_roots_includes_child_frames():
roots = service._iter_login_roots(fake_page)
assert roots == [fake_page, frame_a, frame_b]
# [/DEF:test_iter_login_roots_includes_child_frames:Function]
# [DEF:test_response_looks_like_login_page_detects_login_markup:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Direct login fallback must reject responses that render the login screen again.
# @PRE: Response body contains stable login-page markers.
# @POST: Helper returns True so caller treats fallback as failed authentication.
@@ -45,10 +50,13 @@ def test_response_looks_like_login_page_detects_login_markup():
)
assert result is True
# [/DEF:test_response_looks_like_login_page_detects_login_markup:Function]
# [DEF:test_find_first_visible_locator_skips_hidden_first_match:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Locator helper must not reject a selector collection just because its first element is hidden.
# @PRE: First matched element is hidden and second matched element is visible.
# @POST: Helper returns the second visible candidate.
@@ -73,18 +81,23 @@ async def test_find_first_visible_locator_skips_hidden_first_match():
return self._elements[index]
service = ScreenshotService(env=type("Env", (), {})())
hidden_then_visible = _FakeLocator([
_FakeElement(False, "hidden"),
_FakeElement(True, "visible"),
])
hidden_then_visible = _FakeLocator(
[
_FakeElement(False, "hidden"),
_FakeElement(True, "visible"),
]
)
result = await service._find_first_visible_locator([hidden_then_visible])
assert result.label == "visible"
# [/DEF:test_find_first_visible_locator_skips_hidden_first_match:Function]
# [DEF:test_submit_login_via_form_post_uses_browser_context_request:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Fallback login must submit hidden fields and credentials through the context request cookie jar.
# @PRE: Login DOM exposes csrf hidden field and request context returns authenticated HTML.
# @POST: Helper returns True and request payload contains csrf_token plus credentials plus request options.
@@ -122,15 +135,25 @@ async def test_submit_login_via_form_post_uses_browser_context_request():
def __init__(self):
self.calls = []
async def post(self, url, form=None, headers=None, timeout=None, fail_on_status_code=None, max_redirects=None):
self.calls.append({
"url": url,
"form": dict(form or {}),
"headers": dict(headers or {}),
"timeout": timeout,
"fail_on_status_code": fail_on_status_code,
"max_redirects": max_redirects,
})
async def post(
self,
url,
form=None,
headers=None,
timeout=None,
fail_on_status_code=None,
max_redirects=None,
):
self.calls.append(
{
"url": url,
"form": dict(form or {}),
"headers": dict(headers or {}),
"timeout": timeout,
"fail_on_status_code": fail_on_status_code,
"max_redirects": max_redirects,
}
)
return _FakeResponse()
class _FakeContext:
@@ -144,39 +167,48 @@ async def test_submit_login_via_form_post_uses_browser_context_request():
def locator(self, selector):
if selector == "input[type='hidden'][name]":
return _FakeLocator([
_FakeInput("csrf_token", "csrf-123"),
_FakeInput("next", "/superset/welcome/"),
])
return _FakeLocator(
[
_FakeInput("csrf_token", "csrf-123"),
_FakeInput("next", "/superset/welcome/"),
]
)
return _FakeLocator([])
env = type("Env", (), {"username": "admin", "password": "secret"})()
service = ScreenshotService(env=env)
page = _FakePage()
result = await service._submit_login_via_form_post(page, "https://example.test/login/")
result = await service._submit_login_via_form_post(
page, "https://example.test/login/"
)
assert result is True
assert page.context.request.calls == [{
"url": "https://example.test/login/",
"form": {
"csrf_token": "csrf-123",
"next": "/superset/welcome/",
"username": "admin",
"password": "secret",
},
"headers": {
"Origin": "https://example.test",
"Referer": "https://example.test/login/",
},
"timeout": 10000,
"fail_on_status_code": False,
"max_redirects": 0,
}]
assert page.context.request.calls == [
{
"url": "https://example.test/login/",
"form": {
"csrf_token": "csrf-123",
"next": "/superset/welcome/",
"username": "admin",
"password": "secret",
},
"headers": {
"Origin": "https://example.test",
"Referer": "https://example.test/login/",
},
"timeout": 10000,
"fail_on_status_code": False,
"max_redirects": 0,
}
]
# [/DEF:test_submit_login_via_form_post_uses_browser_context_request:Function]
# [DEF:test_submit_login_via_form_post_accepts_authenticated_redirect:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Fallback login must treat non-login 302 redirect as success without waiting for redirect target.
# @PRE: Request response is 302 with Location outside login path.
# @POST: Helper returns True.
@@ -212,7 +244,15 @@ async def test_submit_login_via_form_post_accepts_authenticated_redirect():
return ""
class _FakeRequest:
async def post(self, url, form=None, headers=None, timeout=None, fail_on_status_code=None, max_redirects=None):
async def post(
self,
url,
form=None,
headers=None,
timeout=None,
fail_on_status_code=None,
max_redirects=None,
):
return _FakeResponse()
class _FakeContext:
@@ -232,13 +272,18 @@ async def test_submit_login_via_form_post_accepts_authenticated_redirect():
env = type("Env", (), {"username": "admin", "password": "secret"})()
service = ScreenshotService(env=env)
result = await service._submit_login_via_form_post(_FakePage(), "https://example.test/login/")
result = await service._submit_login_via_form_post(
_FakePage(), "https://example.test/login/"
)
assert result is True
# [/DEF:test_submit_login_via_form_post_accepts_authenticated_redirect:Function]
# [DEF:test_submit_login_via_form_post_rejects_login_markup_response:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Fallback login must fail when POST response still contains login form content.
# @PRE: Login DOM exposes csrf hidden field and request response renders login markup.
# @POST: Helper returns False.
@@ -282,7 +327,15 @@ async def test_submit_login_via_form_post_rejects_login_markup_response():
"""
class _FakeRequest:
async def post(self, url, form=None, headers=None, timeout=None, fail_on_status_code=None, max_redirects=None):
async def post(
self,
url,
form=None,
headers=None,
timeout=None,
fail_on_status_code=None,
max_redirects=None,
):
return _FakeResponse()
class _FakeContext:
@@ -302,13 +355,18 @@ async def test_submit_login_via_form_post_rejects_login_markup_response():
env = type("Env", (), {"username": "admin", "password": "secret"})()
service = ScreenshotService(env=env)
result = await service._submit_login_via_form_post(_FakePage(), "https://example.test/login/")
result = await service._submit_login_via_form_post(
_FakePage(), "https://example.test/login/"
)
assert result is False
# [/DEF:test_submit_login_via_form_post_rejects_login_markup_response:Function]
# [DEF:test_goto_resilient_falls_back_from_domcontentloaded_to_load:Function]
# @RELATION: BINDS_TO ->[TestScreenshotService]
# @PURPOSE: Pages with unstable primary wait must retry with fallback wait strategy.
# @PRE: First page.goto call raises; second succeeds.
# @POST: Helper returns second response and attempts both wait modes in order.
@@ -340,5 +398,7 @@ async def test_goto_resilient_falls_back_from_domcontentloaded_to_load():
("https://example.test/dashboard", "domcontentloaded", 1234),
("https://example.test/dashboard", "load", 1234),
]
# [/DEF:test_goto_resilient_falls_back_from_domcontentloaded_to_load:Function]
# [/DEF:backend.src.plugins.llm_analysis.__tests__.test_screenshot_service:Module]
# [/DEF:TestScreenshotService:Module]