Fix filter stuff

This commit is contained in:
2026-06-08 23:26:15 +02:00
parent ba9b92d419
commit 14efff8078
6 changed files with 174 additions and 21 deletions
+24
View File
@@ -158,3 +158,27 @@ class FilterBarRenderingTest(TestCase):
# for the double-escape bug the dedup fixed.
self.assertIn(""status"", html)
self.assertNotIn(""", html)
def test_game_filter_bar_preserves_excludes_modifier(self):
"""An enum field with an EXCLUDES modifier renders data-modifier correctly
so the JS roundtrip preserves the modifier (regression: _split_modifier
silently dropped non-presence modifiers when match_modes was None)."""
filter_json = json.dumps(
{
"status": {
"value": [{"id": "f", "label": "Finished"}],
"modifier": "EXCLUDES",
}
}
)
html = str(
FilterBar(
filter_json=filter_json, preset_list_url="/l", preset_save_url="/s"
)
)
# The full modifier is stored on data-modifier when there's no match-mode
# select (enum/choice fields). No data-match attribute is present.
self.assertIn('data-modifier="EXCLUDES"', html)
self.assertNotIn("data-match=", html)
self.assertIn("Finished", html)
self.assertNoEscapedTags(html)
+10 -6
View File
@@ -101,10 +101,12 @@ class TestChoiceCriterion:
c = ChoiceCriterion(value=["f"], excludes=["a"], modifier=Modifier.EXCLUDES)
assert c.to_q("status") == ~Q(status__in=["f"]) & ~Q(status__in=["a"])
def test_includes_all(self):
"""INCLUDES_ALL ANDs an equality per value (shared with MultiCriterion)."""
def test_includes_all_requires_filter_builder(self):
"""INCLUDES_ALL cannot be built by the generic criterion layer — it
requires a filter-level Q builder (see PurchaseFilter._games_to_q)."""
c = ChoiceCriterion(value=["f", "p"], modifier=Modifier.INCLUDES_ALL)
assert c.to_q("status") == Q(status="f") & Q(status="p")
with pytest.raises(AssertionError, match="INCLUDES_ALL requires"):
c.to_q("status")
def test_not_equals(self):
c = ChoiceCriterion(value=["f"], modifier=Modifier.NOT_EQUALS)
@@ -136,10 +138,12 @@ class TestMultiCriterion:
c = MultiCriterion(value=[1], excludes=[2], modifier=Modifier.EXCLUDES)
assert c.to_q("game_id") == ~Q(game_id__in=[1]) & ~Q(game_id__in=[2])
def test_includes_all(self):
"""INCLUDES_ALL requires the row to relate to every value (M2M)."""
def test_includes_all_requires_filter_builder(self):
"""INCLUDES_ALL cannot be built by the generic criterion layer — it
requires a filter-level Q builder (see PurchaseFilter._games_to_q)."""
c = MultiCriterion(value=[1, 2], modifier=Modifier.INCLUDES_ALL)
assert c.to_q("games") == Q(games=1) & Q(games=2)
with pytest.raises(AssertionError, match="INCLUDES_ALL requires"):
c.to_q("games")
def test_is_null(self):
c = MultiCriterion(value=[], modifier=Modifier.IS_NULL)