Clear pre-existing ruff lint + format debt (make check now green)

This commit is contained in:
2026-06-13 21:27:46 +02:00
parent 1258c529d2
commit c7af814364
11 changed files with 65 additions and 64 deletions
+1 -4
View File
@@ -17,7 +17,6 @@ widget into a ``DateCriterion`` unchanged. All behaviour is wired by
``games/static/js/date_range_picker.js``.
"""
from common.components.core import Element, HTMLAttribute, Media, Node, Safe
from common.components.primitives import Div, Input, Span
from common.time import DatePartSpec, date_parts
@@ -101,9 +100,7 @@ def _iso_part_values(iso_value: str, parts: list[DatePartSpec]) -> dict[str, str
return values
def _segment_input(
*, part: DatePartSpec, side: str, label: str, value: str
) -> Node:
def _segment_input(*, part: DatePartSpec, side: str, label: str, value: str) -> Node:
side_label = "from" if side == "min" else "to"
return Input(
attributes=[
+1 -3
View File
@@ -173,9 +173,7 @@ def _split_modifier(modifier: str, has_m2m: bool = False) -> str:
return ""
def _enum_filter(
field_name: str, options, choice: FilterChoice, *, nullable
) -> Node:
def _enum_filter(field_name: str, options, choice: FilterChoice, *, nullable) -> Node:
"""A FilterSelect over a small, fully pre-rendered option set (enum field).
Enum fields are single-valued, so no M2M modifiers (all/only are
+1
View File
@@ -7,6 +7,7 @@ import pytest
# synchronous operations inside the async context safely.
os.environ.setdefault("DJANGO_ALLOW_ASYNC_UNSAFE", "true")
@pytest.fixture(scope="session")
def browser_type_launch_args(browser_type_launch_args):
# Try to find a system-installed Google Chrome or Chromium to bypass Nix/NixOS shared library issues
+1 -3
View File
@@ -121,9 +121,7 @@ def test_max_only_serializes_as_less_than(live_server, page):
".dispatchEvent(new Event('submit', {cancelable: true}))"
)
parsed = _filter_from_url(page.url)
assert parsed == {
"date_refunded": {"value": "2025-06-30", "modifier": "LESS_THAN"}
}
assert parsed == {"date_refunded": {"value": "2025-06-30", "modifier": "LESS_THAN"}}
@pytest.mark.django_db
+23 -25
View File
@@ -1,8 +1,4 @@
"""End-to-end Playwright test for the RangeSlider JS synchronization, cross-over, and clamping behavior.
"""
import json
import urllib.parse
"""End-to-end Playwright test for the RangeSlider JS synchronization, cross-over, and clamping behavior."""
import pytest
from django.http import HttpResponse
@@ -41,17 +37,17 @@ urlpatterns = [
@override_settings(ROOT_URLCONF="e2e.test_range_slider_e2e")
def test_range_slider_crossover_min_higher_than_max(live_server, page):
page.goto(live_server.url + "/test-range-slider/")
# 1. Start with known state: Min is empty, Max is empty
min_input = page.locator('input[name="filter-session-count-min"]')
max_input = page.locator('input[name="filter-session-count-max"]')
# 2. Type "20" into max input
max_input.fill("20")
# 3. Type "50" into min input (which is higher than 20)
min_input.fill("50")
# 4. Max input should have automatically synchronized/snapped to 50
assert max_input.input_value() == "50"
@@ -60,16 +56,16 @@ def test_range_slider_crossover_min_higher_than_max(live_server, page):
@override_settings(ROOT_URLCONF="e2e.test_range_slider_e2e")
def test_range_slider_crossover_max_less_than_min(live_server, page):
page.goto(live_server.url + "/test-range-slider/")
min_input = page.locator('input[name="filter-session-count-min"]')
max_input = page.locator('input[name="filter-session-count-max"]')
# 1. Type "50" into min input
min_input.fill("50")
# 2. Type "30" into max input (which is less than 50)
max_input.fill("30")
# 3. Min input should have automatically synchronized/snapped to 30
assert min_input.input_value() == "30"
@@ -78,20 +74,20 @@ def test_range_slider_crossover_max_less_than_min(live_server, page):
@override_settings(ROOT_URLCONF="e2e.test_range_slider_e2e")
def test_range_slider_strict_bounds_clamping_on_blur(live_server, page):
page.goto(live_server.url + "/test-range-slider/")
min_input = page.locator('input[name="filter-session-count-min"]')
max_input = page.locator('input[name="filter-session-count-max"]')
# 1. Type value higher than dataMax (100 is max, type "150")
max_input.fill("150")
max_input.blur() # triggers "change" event
max_input.blur() # triggers "change" event
assert max_input.input_value() == "100"
# 2. Type value lower than dataMin (0 is min, type "-20")
min_input.fill("-20")
min_input.blur() # triggers "change" event
min_input.blur() # triggers "change" event
assert min_input.input_value() == "0"
@@ -99,18 +95,20 @@ def test_range_slider_strict_bounds_clamping_on_blur(live_server, page):
@override_settings(ROOT_URLCONF="e2e.test_range_slider_e2e")
def test_range_slider_empty_max_thumb_does_not_jump_to_beginning(live_server, page):
page.goto(live_server.url + "/test-range-slider/")
# Locate handles
max_handle = page.locator('.range-handle-max[data-target="filter-session-count-max"]')
max_handle = page.locator(
'.range-handle-max[data-target="filter-session-count-max"]'
)
# Initially, max_input is empty, so handle should sit at 100% (far right)
style = max_handle.get_attribute("style")
assert "left:100%" in style or "left: 100%" in style
# Set min to 50
min_input = page.locator('input[name="filter-session-count-min"]')
min_input.fill("50")
# Max handle should STILL stay at 100% since max input is still empty (defaults to max_value)
style = max_handle.get_attribute("style")
assert "left:100%" in style or "left: 100%" in style
+21 -17
View File
@@ -38,9 +38,7 @@ def prefilled_bar_view(request):
"value": "Switch",
"modifier": "INCLUDES",
},
"group": {
"modifier": "IS_NULL"
}
"group": {"modifier": "IS_NULL"},
}
)
return HttpResponse(_bar_page(filter_json=filter_json))
@@ -63,19 +61,21 @@ def _filter_from_url(url: str) -> dict:
@override_settings(ROOT_URLCONF="e2e.test_string_filter_e2e")
def test_string_filter_defaults_and_toggles(live_server, page):
page.goto(live_server.url + "/test-string-filter-empty/")
# 1. Verify text inputs are active by default and modifier "is" (EQUALS) is checked
name_input = page.locator('input[name="filter-name"]')
assert name_input.is_enabled()
is_radio = page.locator('input[name="filter-name-modifier"][value="EQUALS"]')
assert is_radio.is_checked()
# 2. Enter values, click "includes" (INCLUDES), and submit
name_input.fill("PlayStation")
includes_radio = page.locator('input[name="filter-name-modifier"][value="INCLUDES"]')
includes_radio = page.locator(
'input[name="filter-name-modifier"][value="INCLUDES"]'
)
includes_radio.click()
with page.expect_navigation():
page.evaluate(
"document.getElementById('filter-bar-form')"
@@ -92,15 +92,15 @@ def test_string_filter_null_states(live_server, page):
name_input = page.locator('input[name="filter-name"]')
name_input.fill("Xbox")
# Click "is null"
is_null_radio = page.locator('input[name="filter-name-modifier"][value="IS_NULL"]')
is_null_radio.click()
# Verification of interactive disabling
assert not name_input.is_enabled()
assert name_input.input_value() == ""
with page.expect_navigation():
page.evaluate(
"document.getElementById('filter-bar-form')"
@@ -114,19 +114,23 @@ def test_string_filter_null_states(live_server, page):
@override_settings(ROOT_URLCONF="e2e.test_string_filter_e2e")
def test_string_filter_prefilled_states(live_server, page):
page.goto(live_server.url + "/test-string-filter-prefilled/")
name_input = page.locator('input[name="filter-name"]')
group_input = page.locator('input[name="filter-group"]')
# Verifies name matches "Switch" and "includes" is checked
assert name_input.input_value() == "Switch"
assert name_input.is_enabled()
assert page.locator('input[name="filter-name-modifier"][value="INCLUDES"]').is_checked()
assert page.locator(
'input[name="filter-name-modifier"][value="INCLUDES"]'
).is_checked()
# Verifies group is empty, disabled, and "is null" is checked
assert group_input.input_value() == ""
assert not group_input.is_enabled()
assert page.locator('input[name="filter-group-modifier"][value="IS_NULL"]').is_checked()
assert page.locator(
'input[name="filter-group-modifier"][value="IS_NULL"]'
).is_checked()
@pytest.mark.django_db
@@ -136,11 +140,11 @@ def test_string_filter_deselect_re_enables(live_server, page):
name_input = page.locator('input[name="filter-name"]')
is_null_radio = page.locator('input[name="filter-name-modifier"][value="IS_NULL"]')
# 1. Click "is null" -> disables input
is_null_radio.click()
assert not name_input.is_enabled()
# 2. Click "is null" again to deselect/uncheck -> should re-enable the text input
is_null_radio.click()
assert name_input.is_enabled()
+3 -1
View File
@@ -412,7 +412,9 @@ class GameFilter(OperatorFilter):
from games.models import PlayEvent
event_q = criterion.to_q("note")
matching_ids = PlayEvent.objects.filter(event_q).values_list("game_id", flat=True)
matching_ids = PlayEvent.objects.filter(event_q).values_list(
"game_id", flat=True
)
return Q(id__in=matching_ids)
@@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('games', '0017_add_filter_preset'),
("games", "0017_add_filter_preset"),
]
operations = [
migrations.AlterField(
model_name='session',
name='timestamp_start',
field=models.DateTimeField(db_index=True, verbose_name='Start'),
model_name="session",
name="timestamp_start",
field=models.DateTimeField(db_index=True, verbose_name="Start"),
),
]
-1
View File
@@ -362,4 +362,3 @@ class FilterBarRenderingTest(TestCase):
self.assertIn('name="filter-refunded"', purchase_html)
self.assertIn('value="true"', purchase_html)
self.assertIn('value="false"', purchase_html)
-1
View File
@@ -85,4 +85,3 @@ class ParseBoolNullableTest(SimpleTestCase):
self.assertTrue(_parse_bool_nullable({"field": {"value": "1"}}, "field"))
self.assertFalse(_parse_bool_nullable({"field": {"value": "false"}}, "field"))
self.assertFalse(_parse_bool_nullable({"field": {"value": "0"}}, "field"))
+10 -4
View File
@@ -560,8 +560,14 @@ class TestFilterBarRendering:
def test_mastered_not_checked_by_default(self):
html = str(FilterBar(filter_json=""))
assert 'name="filter-mastered" value="true" class="rounded-full border-default-medium bg-neutral-secondary-medium text-brand focus:ring-brand" checked="true"' not in html
assert 'name="filter-mastered" value="false" class="rounded-full border-default-medium bg-neutral-secondary-medium text-brand focus:ring-brand" checked="true"' not in html
assert (
'name="filter-mastered" value="true" class="rounded-full border-default-medium bg-neutral-secondary-medium text-brand focus:ring-brand" checked="true"'
not in html
)
assert (
'name="filter-mastered" value="false" class="rounded-full border-default-medium bg-neutral-secondary-medium text-brand focus:ring-brand" checked="true"'
not in html
)
def test_mastered_checked_when_filtered(self):
html = str(
@@ -784,7 +790,7 @@ class TestExpandedFiltersAgainstDB:
from games.filters import SessionFilter
from games.models import Session
data = self._setup_entities()
self._setup_entities()
# Test duration_total_hours equals 4
sf_tot = SessionFilter.from_json(
@@ -808,7 +814,7 @@ class TestExpandedFiltersAgainstDB:
from games.filters import PurchaseFilter
from games.models import Purchase
data = self._setup_entities()
self._setup_entities()
pf = PurchaseFilter.from_json(
{