From a1304e19ad50e870546ee2a0d2474566f63aeaf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Wed, 10 Jun 2026 17:52:35 +0200 Subject: [PATCH] test: implement E2E Playwright tests for string multi-mode filters --- e2e/test_string_filter_e2e.py | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 e2e/test_string_filter_e2e.py diff --git a/e2e/test_string_filter_e2e.py b/e2e/test_string_filter_e2e.py new file mode 100644 index 0000000..b646a86 --- /dev/null +++ b/e2e/test_string_filter_e2e.py @@ -0,0 +1,128 @@ +"""End-to-end Playwright test for String multi-mode filter serialization, null-state toggling, and prefill behaviors.""" + +import json +import urllib.parse + +import pytest +from django.http import HttpResponse +from django.test import override_settings +from django.urls import path + +from common.components import PlatformFilterBar + + +def _bar_page(filter_json: str = "") -> str: + return f""" + + + String filter E2E + + + + + + {PlatformFilterBar(filter_json=filter_json, preset_list_url="/p/l", preset_save_url="/p/s")} + +""" + + +def empty_bar_view(request): + return HttpResponse(_bar_page()) + + +def prefilled_bar_view(request): + filter_json = json.dumps( + { + "name": { + "value": "Switch", + "modifier": "INCLUDES", + }, + "group": { + "modifier": "IS_NULL" + } + } + ) + return HttpResponse(_bar_page(filter_json=filter_json)) + + +urlpatterns = [ + path("test-string-filter-empty/", empty_bar_view), + path("test-string-filter-prefilled/", prefilled_bar_view), +] + + +def _filter_from_url(url: str) -> dict: + query = urllib.parse.urlparse(url).query + params = urllib.parse.parse_qs(query) + raw = params.get("filter", [""])[0] + return json.loads(raw) if raw else {} + + +@pytest.mark.django_db +@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.click() + + with page.expect_navigation(): + page.evaluate( + "document.getElementById('filter-bar-form')" + ".dispatchEvent(new Event('submit', {cancelable: true}))" + ) + parsed = _filter_from_url(page.url) + assert parsed["name"] == {"value": "PlayStation", "modifier": "INCLUDES"} + + +@pytest.mark.django_db +@override_settings(ROOT_URLCONF="e2e.test_string_filter_e2e") +def test_string_filter_null_states(live_server, page): + page.goto(live_server.url + "/test-string-filter-empty/") + + 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')" + ".dispatchEvent(new Event('submit', {cancelable: true}))" + ) + parsed = _filter_from_url(page.url) + assert parsed["name"] == {"modifier": "IS_NULL"} + + +@pytest.mark.django_db +@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() + + # 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()