Phase 4: Page() collects component media; drop manual scripts= threading
Page() now calls collect_media(content) and emits the ModuleScript / StaticScript tags itself, so views no longer thread scripts= for component-owned JS. The list views (game/session/purchase/device/ platform/playevent) compose with Fragment(filter_bar, content) instead of mark_safe(str(filter_bar) + str(content)) — keeping the node tree intact so the filter bar's media (filter_bar.js + search_select.js + range_slider.js, and date_range_picker.js on purchases) reaches Page(). The stats views drop _STATS_SCRIPTS; YearPicker's datepicker.umd.js is collected from its declared media. The scripts= argument remains for page-specific glue not owned by a component (the add-form helpers add_game.js / add_purchase.js / add_session.js, alongside search_select.js for their form widgets). Adds regression tests asserting the list and stats pages auto-load their widget scripts with no scripts= in the view, and documents the node/ media model in CLAUDE.md. https://claude.ai/code/session_01BKurBhE3Qj25p7Bfsg7EeK
This commit is contained in:
@@ -57,6 +57,22 @@ class RenderedPagesTest(TestCase):
|
||||
marker, html, f"Found double-escaped markup ({marker!r}) in output"
|
||||
)
|
||||
|
||||
# --- scripts auto-collected from component media (Phase 4) ---------------
|
||||
|
||||
def test_list_page_auto_loads_widget_scripts(self):
|
||||
"""The games list view passes no scripts= argument; the filter bar's
|
||||
components declare their JS and Page() collects it."""
|
||||
html = self.get("games:list_games").content.decode()
|
||||
self.assertIn("js/filter_bar.js", html)
|
||||
self.assertIn("js/search_select.js", html)
|
||||
self.assertIn("js/range_slider.js", html)
|
||||
|
||||
def test_stats_page_auto_loads_datepicker(self):
|
||||
"""YearPicker declares the datepicker UMD bundle as media; the stats
|
||||
view no longer hoists it by hand."""
|
||||
html = self.get("games:stats_alltime").content.decode()
|
||||
self.assertIn("js/datepicker.umd.js", html)
|
||||
|
||||
# --- layout wrapper ------------------------------------------------------
|
||||
|
||||
def test_page_layout_wrapper(self):
|
||||
@@ -395,15 +411,12 @@ class PurchaseListDateFilterTest(TestCase):
|
||||
html,
|
||||
)
|
||||
self.assertIn(
|
||||
'name="filter-date-purchased-max" id="filter-date-purchased-max" '
|
||||
'value=""',
|
||||
'name="filter-date-purchased-max" id="filter-date-purchased-max" value=""',
|
||||
html,
|
||||
)
|
||||
|
||||
def test_date_refunded_not_null(self):
|
||||
response = self._get(
|
||||
{"date_refunded": {"value": "", "modifier": "NOT_NULL"}}
|
||||
)
|
||||
response = self._get({"date_refunded": {"value": "", "modifier": "NOT_NULL"}})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
html = response.content.decode()
|
||||
self.assertNotIn("EARLY-MARKER", html)
|
||||
|
||||
Reference in New Issue
Block a user