mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-11-15 22:38:12 +00:00
The destination guard from the oceanofpdf/SSRF fix (f837506) trusts only
hosts in
the mirror lists and refuses any other host that resolves to a private
address.
The full e2e profile has failed on every PR since then: its AA mirror
was mock-aa,
but the slow-download links pointed at cf.mock.test (172.30.0.11). The
guard refused
the slow-download page before the internal Chrome bypasser ever started,
so the
download ended with "All download sources failed". Adding cf.mock.test
as a second
AA mirror would not help: AAMirrorSelector.rewrite would then move the
gated link
onto mock-aa, and the test would pass without Chrome solving anything.
The profile
now uses the gate as its only AA mirror. The cloudflare mock takes
CF_GATED_PATHS,
and the full profile challenges only /slow_download/, so search, detail
and the
final file pass through while the download still needs Chrome. The
unused
SLOW_DOWNLOAD_BASE indirection is gone.
The same allowlist missed a supported setup: Primary Mirror
(AA_BASE_URL) may pin a
URL that is not in the mirror list, and network uses it as the active AA
base. With
it on a LAN address, every AA request was refused. The guard now trusts
the pinned
URL too (mirrors.get_pinned_aa_base_url), and
has_aa_mirror_configuration reuses
the same helper.
download_url also ran the guard a second time outside its try block,
which repeated
the DNS lookup and could raise instead of returning None. The duplicate
call is gone.
89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
"""
|
|
Tests for frontend search menu behavior.
|
|
|
|
These tests verify that the search menu dismissal logic works correctly,
|
|
particularly that clicking on the AdvancedFilters panel does not close
|
|
the main search menu (issue #1301).
|
|
"""
|
|
|
|
from pathlib import Path
|
|
|
|
# Path to the frontend source code
|
|
FRONTEND_SRC_DIR = Path(__file__).parent.parent.parent / "src" / "frontend" / "src"
|
|
|
|
|
|
class TestSearchMenuDismiss:
|
|
"""Test that the search menu dismissal behavior is correct."""
|
|
|
|
def test_advanced_filters_prevents_mousedown_bubbling(self):
|
|
"""
|
|
Verify that AdvancedFilters prevents mousedown events from bubbling
|
|
to the document level, which would otherwise close the main search menu.
|
|
|
|
This is the fix for issue #1301: when clicking on dropdown options
|
|
inside AdvancedFilters, the main search menu was collapsing because
|
|
the mousedown event bubbled up to the document and triggered the
|
|
useDismiss hook.
|
|
|
|
The fix adds onMouseDown={(e) => e.stopPropagation()} to the
|
|
AdvancedFilters container div.
|
|
"""
|
|
advanced_filters_path = FRONTEND_SRC_DIR / "components" / "AdvancedFilters.tsx"
|
|
|
|
# Read the component source
|
|
source_code = advanced_filters_path.read_text()
|
|
|
|
# Verify that the onMouseDown stopPropagation handler is present
|
|
# This prevents the mousedown event from bubbling up to the document
|
|
# and triggering the useDismiss hook in SearchBar
|
|
assert "onMouseDown={(e) => e.stopPropagation()}" in source_code, (
|
|
"AdvancedFilters must prevent mousedown events from bubbling up "
|
|
"to the document. Without this, clicking on dropdown options inside "
|
|
"AdvancedFilters will close the main search menu (issue #1301)."
|
|
)
|
|
|
|
def test_advanced_filters_container_has_onmousedown(self):
|
|
"""
|
|
Verify that the settingsForm div in AdvancedFilters has the
|
|
onMouseDown handler to prevent event bubbling.
|
|
"""
|
|
advanced_filters_path = FRONTEND_SRC_DIR / "components" / "AdvancedFilters.tsx"
|
|
source_code = advanced_filters_path.read_text()
|
|
|
|
# The settingsForm div should have onMouseDown handler
|
|
# Check that the div has both className and onMouseDown
|
|
assert "const settingsForm = (" in source_code, (
|
|
"AdvancedFilters should define settingsForm as a JSX element"
|
|
)
|
|
|
|
# Verify the onMouseDown is on the settingsForm div (not nested inside another element)
|
|
# by checking that it appears after the settingsForm declaration
|
|
settings_form_start = source_code.find("const settingsForm = (")
|
|
onmousedown_pos = source_code.find("onMouseDown={(e) => e.stopPropagation()}")
|
|
|
|
assert settings_form_start != -1, "settingsForm declaration not found"
|
|
assert onmousedown_pos != -1, "onMouseDown handler not found"
|
|
assert onmousedown_pos > settings_form_start, (
|
|
"onMouseDown handler should be inside the settingsForm div"
|
|
)
|
|
|
|
def test_searchbar_uses_usedismiss_for_menu_closing(self):
|
|
"""
|
|
Verify that SearchBar uses useDismiss to close the main menu
|
|
when clicking outside the controlled refs.
|
|
"""
|
|
search_bar_path = FRONTEND_SRC_DIR / "components" / "SearchBar.tsx"
|
|
source_code = search_bar_path.read_text()
|
|
|
|
# SearchBar should use useDismiss to handle menu closing
|
|
assert "useDismiss" in source_code, (
|
|
"SearchBar should use useDismiss hook for menu dismissal"
|
|
)
|
|
|
|
# The options menu stays open for clicks inside selectorRef or optionsPanelRef.
|
|
# AdvancedFilters renders beside SearchBar, outside both, which is why it stops
|
|
# mousedown from reaching this listener.
|
|
assert "useDismiss(isOptionsOpen, [selectorRef, optionsPanelRef]" in source_code, (
|
|
"SearchBar should dismiss the options menu only outside selectorRef and optionsPanelRef"
|
|
)
|