diff --git a/umap/static/umap/js/umap.features.js b/umap/static/umap/js/umap.features.js index 275bada8..9e68deeb 100644 --- a/umap/static/umap/js/umap.features.js +++ b/umap/static/umap/js/umap.features.js @@ -496,15 +496,18 @@ U.FeatureMixin = { const selected = this.map.facets.selected for (let [name, { type, min, max, choices }] of Object.entries(selected)) { let value = this.properties[name] + let parser switch (type) { case 'date': case 'datetime': case 'number': - const caster = type === 'number' ? parseFloat : (v) => new Date(v) + if (type === 'number') parser = parseFloat + else if (type == 'datetime') parser = (v) => new Date(v) + else parser = (v) => new Date(new Date(v).toDateString()) // Without time value = value != null ? value : undefined - min = caster(min) - max = caster(max) - value = caster(value) + min = parser(min) + max = parser(max) + value = parser(value) if (!isNaN(min) && !isNaN(value) && min > value) return false if (!isNaN(max) && !isNaN(value) && max < value) return false break diff --git a/umap/tests/integration/test_facets_browser.py b/umap/tests/integration/test_facets_browser.py index 68e64ee3..19faf78d 100644 --- a/umap/tests/integration/test_facets_browser.py +++ b/umap/tests/integration/test_facets_browser.py @@ -1,3 +1,5 @@ +import copy + import pytest from playwright.sync_api import expect @@ -11,12 +13,24 @@ DATALAYER_DATA1 = { "features": [ { "type": "Feature", - "properties": {"mytype": "even", "name": "Point 2"}, + "properties": { + "mytype": "even", + "name": "Point 2", + "mynumber": 10, + # Same day/month value to work around Javascript/browser + # crazyness date format + "mydate": "2024/04/04 12:19:17", + }, "geometry": {"type": "Point", "coordinates": [0.065918, 48.385442]}, }, { "type": "Feature", - "properties": {"mytype": "odd", "name": "Point 1"}, + "properties": { + "mytype": "odd", + "name": "Point 1", + "mynumber": 12, + "mydate": "2024/03/03 12:20:20", + }, "geometry": {"type": "Point", "coordinates": [3.55957, 49.767074]}, }, ], @@ -31,12 +45,22 @@ DATALAYER_DATA2 = { "features": [ { "type": "Feature", - "properties": {"mytype": "even", "name": "Point 4"}, + "properties": { + "mytype": "even", + "name": "Point 4", + "mynumber": 10, + "mydate": "2024/08/08 13:14:15", + }, "geometry": {"type": "Point", "coordinates": [0.856934, 45.290347]}, }, { "type": "Feature", - "properties": {"mytype": "odd", "name": "Point 3"}, + "properties": { + "mytype": "odd", + "name": "Point 3", + "mynumber": 14, + "mydate": "2024/04/04 10:19:17", + }, "geometry": {"type": "Point", "coordinates": [4.372559, 47.945786]}, }, ], @@ -70,23 +94,19 @@ DATALAYER_DATA3 = { } -@pytest.fixture -def bootstrap(map, live_server): +def test_simple_facet_search(live_server, page, map): map.settings["properties"]["onLoadPanel"] = "facet" - map.settings["properties"]["facetKey"] = "mytype|My type" + map.settings["properties"]["facetKey"] = "mytype|My type,mynumber|My Number|number" map.settings["properties"]["showLabel"] = True map.save() DataLayerFactory(map=map, data=DATALAYER_DATA1) DataLayerFactory(map=map, data=DATALAYER_DATA2) DataLayerFactory(map=map, data=DATALAYER_DATA3) - - -def test_simple_facet_search(live_server, page, bootstrap, map): - page.goto(f"{live_server.url}{map.get_absolute_url()}") + page.goto(f"{live_server.url}{map.get_absolute_url()}#6/48.948/1.670") panel = page.locator(".umap-facet-search") # From a non browsable datalayer, should not be impacted paths = page.locator(".leaflet-overlay-pane path") - expect(paths).to_be_visible + expect(paths).to_be_visible() expect(panel).to_be_visible() # Facet name expect(page.get_by_text("My type")).to_be_visible() @@ -95,7 +115,7 @@ def test_simple_facet_search(live_server, page, bootstrap, map): odd = page.get_by_text("odd") expect(oven).to_be_visible() expect(odd).to_be_visible() - expect(paths).to_be_visible + expect(paths).to_be_visible() markers = page.locator(".leaflet-marker-icon") expect(markers).to_have_count(4) # Tooltips @@ -114,4 +134,77 @@ def test_simple_facet_search(live_server, page, bootstrap, map): # Now let's filter odd.click() expect(markers).to_have_count(4) - expect(paths).to_be_visible + expect(paths).to_be_visible() + + # Let's filter using the number facet + expect(page.get_by_text("My Number")).to_be_visible() + expect(page.get_by_label("Min")).to_have_value("10") + expect(page.get_by_label("Max")).to_have_value("14") + page.get_by_label("Min").fill("11") + page.keyboard.press("Tab") # Move out of the input, so the "change" event is sent + expect(markers).to_have_count(2) + expect(paths).to_be_visible() + page.get_by_label("Max").fill("13") + page.keyboard.press("Tab") + expect(markers).to_have_count(1) + + # Now let's combine + page.get_by_label("Min").fill("10") + page.keyboard.press("Tab") + expect(markers).to_have_count(3) + odd.click() + expect(markers).to_have_count(1) + expect(paths).to_be_visible() + + +def test_date_facet_search(live_server, page, map): + map.settings["properties"]["onLoadPanel"] = "facet" + map.settings["properties"]["facetKey"] = "mydate|Date filter|date" + map.save() + DataLayerFactory(map=map, data=DATALAYER_DATA1) + DataLayerFactory(map=map, data=DATALAYER_DATA2) + page.goto(f"{live_server.url}{map.get_absolute_url()}") + markers = page.locator(".leaflet-marker-icon") + expect(markers).to_have_count(4) + expect(page.get_by_text("Date Filter")).to_be_visible() + expect(page.get_by_label("From")).to_have_value("2024-03-03") + expect(page.get_by_label("Until")).to_have_value("2024-08-08") + # Change the month (crazy US date format in Chromium ran by Playwright in my OS) + page.get_by_label("From").press("ArrowUp") + expect(markers).to_have_count(3) + page.get_by_label("Until").press("ArrowDown") + expect(markers).to_have_count(2) + + +def test_choice_with_empty_value(live_server, page, map): + map.settings["properties"]["onLoadPanel"] = "facet" + map.settings["properties"]["facetKey"] = "mytype|My type" + map.save() + data = copy.deepcopy(DATALAYER_DATA1) + data["features"][0]["properties"]["mytype"] = "" + del data["features"][1]["properties"]["mytype"] + DataLayerFactory(map=map, data=data) + DataLayerFactory(map=map, data=DATALAYER_DATA2) + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(page.get_by_text("")).to_be_visible() + markers = page.locator(".leaflet-marker-icon") + expect(markers).to_have_count(4) + page.get_by_text("").click() + expect(markers).to_have_count(2) + + +def test_number_with_zero_value(live_server, page, map): + map.settings["properties"]["onLoadPanel"] = "facet" + map.settings["properties"]["facetKey"] = "mynumber|Filter|number" + map.save() + data = copy.deepcopy(DATALAYER_DATA1) + data["features"][0]["properties"]["mynumber"] = 0 + DataLayerFactory(map=map, data=data) + DataLayerFactory(map=map, data=DATALAYER_DATA2) + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(page.get_by_label("Min")).to_have_value("0") + expect(page.get_by_label("Max")).to_have_value("14") + page.get_by_label("Min").fill("1") + page.keyboard.press("Tab") # Move out of the input, so the "change" event is sent + markers = page.locator(".leaflet-marker-icon") + expect(markers).to_have_count(3)