"""End-to-end Playwright test for the RangeSlider JS synchronization, cross-over, and clamping behavior.
"""
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 FilterBar
def _bar_page(filter_json: str = "") -> str:
return f"""
Range Slider E2E
{FilterBar(filter_json=filter_json, preset_list_url="/p/l", preset_save_url="/p/s")}
"""
def empty_bar_view(request):
return HttpResponse(_bar_page())
urlpatterns = [
path("test-range-slider/", empty_bar_view),
]
@pytest.mark.django_db
@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"
@pytest.mark.django_db
@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"
@pytest.mark.django_db
@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
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
assert min_input.input_value() == "0"
@pytest.mark.django_db
@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"]')
# 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