Skip to content

Commit 9a5d0e1

Browse files
claudeedmundmiller
authored andcommitted
test: improve highlight tests to validate correctness
Replace superficial "does it exist" tests with proper validation tests that verify the CORRECT intersections are highlighted. Changes: - test_highlight_least: now verifies the highlighted intersection has the actual minimum count - test_highlight_greatest: now verifies the highlighted intersection has the actual maximum count - test_highlight_specific_index: now verifies the correct intersection_id is selected for the given index - test_highlight_multiple_indices: now verifies all requested indices map to the correct intersection_ids These tests would now catch bugs like: - Swapped least/greatest logic - Off-by-one errors in indexing - Wrong intersection being highlighted - Using degree instead of count for min/max
1 parent 46fea4d commit 9a5d0e1

1 file changed

Lines changed: 129 additions & 29 deletions

File tree

tests/test_advanced_features.py

Lines changed: 129 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -216,70 +216,170 @@ def test_highlight_least(sample_data):
216216
"""Test highlighting the intersection with the smallest size."""
217217
chart = au.UpSetAltair(data=sample_data, sets=["A", "B", "C"], highlight="least")
218218

219-
# Get the chart spec and check for selection with value
219+
# Calculate the expected result independently from the processed data
220+
processed_data = chart.data
221+
intersection_counts = (
222+
processed_data.groupby("intersection_id")["count"]
223+
.first()
224+
.reset_index()
225+
)
226+
expected_min_id = intersection_counts.loc[
227+
intersection_counts["count"].idxmin(), "intersection_id"
228+
]
229+
230+
# Extract actual highlighted intersection from chart spec
220231
spec = chart.chart.to_dict()
221232
params = spec.get("params", [])
222-
assert len(params) > 0
223233

224-
# Check that a selection with a value is present (not just mouseover)
225-
has_value_selection = any(
226-
"value" in p and p["value"] is not None for p in params
234+
# Find the color_selection parameter (has intersection_id field)
235+
color_param = next(
236+
(p for p in params
237+
if "select" in p and "fields" in p["select"]
238+
and "intersection_id" in p["select"]["fields"]
239+
and "value" in p),
240+
None
241+
)
242+
243+
assert color_param is not None, "No selection parameter with intersection_id found"
244+
245+
# Verify the correct intersection is highlighted
246+
actual_ids = [v["intersection_id"] for v in color_param["value"]]
247+
assert len(actual_ids) == 1, f"Expected 1 highlighted intersection, got {len(actual_ids)}"
248+
assert actual_ids[0] == expected_min_id, (
249+
f"Expected intersection {expected_min_id} (smallest), but got {actual_ids[0]}"
250+
)
251+
252+
# Verify it's actually the minimum count
253+
min_count = intersection_counts.loc[
254+
intersection_counts["intersection_id"] == expected_min_id, "count"
255+
].values[0]
256+
assert min_count == intersection_counts["count"].min(), (
257+
"Highlighted intersection doesn't have the minimum count"
227258
)
228-
assert has_value_selection, "Expected to find a selection parameter with a value"
229259

230260

231261
def test_highlight_greatest(sample_data):
232262
"""Test highlighting the intersection with the largest size."""
233263
chart = au.UpSetAltair(data=sample_data, sets=["A", "B", "C"], highlight="greatest")
234264

235-
# Get the chart spec and check for selection with value
265+
# Calculate the expected result independently from the processed data
266+
processed_data = chart.data
267+
intersection_counts = (
268+
processed_data.groupby("intersection_id")["count"]
269+
.first()
270+
.reset_index()
271+
)
272+
expected_max_id = intersection_counts.loc[
273+
intersection_counts["count"].idxmax(), "intersection_id"
274+
]
275+
276+
# Extract actual highlighted intersection from chart spec
236277
spec = chart.chart.to_dict()
237278
params = spec.get("params", [])
238-
assert len(params) > 0
239279

240-
# Check that a selection with a value is present
241-
has_value_selection = any(
242-
"value" in p and p["value"] is not None for p in params
280+
# Find the color_selection parameter
281+
color_param = next(
282+
(p for p in params
283+
if "select" in p and "fields" in p["select"]
284+
and "intersection_id" in p["select"]["fields"]
285+
and "value" in p),
286+
None
287+
)
288+
289+
assert color_param is not None, "No selection parameter with intersection_id found"
290+
291+
# Verify the correct intersection is highlighted
292+
actual_ids = [v["intersection_id"] for v in color_param["value"]]
293+
assert len(actual_ids) == 1, f"Expected 1 highlighted intersection, got {len(actual_ids)}"
294+
assert actual_ids[0] == expected_max_id, (
295+
f"Expected intersection {expected_max_id} (largest), but got {actual_ids[0]}"
296+
)
297+
298+
# Verify it's actually the maximum count
299+
max_count = intersection_counts.loc[
300+
intersection_counts["intersection_id"] == expected_max_id, "count"
301+
].values[0]
302+
assert max_count == intersection_counts["count"].max(), (
303+
"Highlighted intersection doesn't have the maximum count"
243304
)
244-
assert has_value_selection, "Expected to find a selection parameter with a value"
245305

246306

247307
def test_highlight_specific_index(sample_data):
248308
"""Test highlighting a specific intersection by index."""
249309
chart = au.UpSetAltair(data=sample_data, sets=["A", "B", "C"], highlight=0)
250310

251-
# Get the chart spec and check for selection with value
311+
# Calculate the expected result - index 0 should be the first intersection
312+
processed_data = chart.data
313+
intersections = (
314+
processed_data.groupby("intersection_id")["count"]
315+
.first()
316+
.reset_index()
317+
.sort_index()
318+
)
319+
expected_id = intersections.iloc[0]["intersection_id"]
320+
321+
# Extract actual highlighted intersection from chart spec
252322
spec = chart.chart.to_dict()
253323
params = spec.get("params", [])
254-
assert len(params) > 0
255324

256-
# Check that a selection with a value is present
257-
has_value_selection = any(
258-
"value" in p and p["value"] is not None for p in params
325+
# Find the color_selection parameter
326+
color_param = next(
327+
(p for p in params
328+
if "select" in p and "fields" in p["select"]
329+
and "intersection_id" in p["select"]["fields"]
330+
and "value" in p),
331+
None
332+
)
333+
334+
assert color_param is not None, "No selection parameter with intersection_id found"
335+
336+
# Verify the correct intersection is highlighted
337+
actual_ids = [v["intersection_id"] for v in color_param["value"]]
338+
assert len(actual_ids) == 1, f"Expected 1 highlighted intersection, got {len(actual_ids)}"
339+
assert actual_ids[0] == expected_id, (
340+
f"Expected intersection {expected_id} at index 0, but got {actual_ids[0]}"
259341
)
260-
assert has_value_selection, "Expected to find a selection parameter with a value"
261342

262343

263344
def test_highlight_multiple_indices(sample_data):
264345
"""Test highlighting multiple intersections by indices."""
265346
chart = au.UpSetAltair(data=sample_data, sets=["A", "B", "C"], highlight=[0, 1, 2])
266347

267-
# Get the chart spec and check for selection with value
348+
# Calculate the expected results - indices 0, 1, 2
349+
processed_data = chart.data
350+
intersections = (
351+
processed_data.groupby("intersection_id")["count"]
352+
.first()
353+
.reset_index()
354+
.sort_index()
355+
)
356+
expected_ids = [
357+
intersections.iloc[0]["intersection_id"],
358+
intersections.iloc[1]["intersection_id"],
359+
intersections.iloc[2]["intersection_id"]
360+
]
361+
362+
# Extract actual highlighted intersections from chart spec
268363
spec = chart.chart.to_dict()
269364
params = spec.get("params", [])
270-
assert len(params) > 0
271365

272-
# Check that a selection with a value is present
273-
has_value_selection = any(
274-
"value" in p and p["value"] is not None for p in params
366+
# Find the color_selection parameter
367+
color_param = next(
368+
(p for p in params
369+
if "select" in p and "fields" in p["select"]
370+
and "intersection_id" in p["select"]["fields"]
371+
and "value" in p),
372+
None
275373
)
276-
assert has_value_selection, "Expected to find a selection parameter with a value"
277374

278-
# Check that the value contains multiple intersection_ids
279-
value_param = next((p for p in params if "value" in p and p["value"] is not None), None)
280-
assert value_param is not None
281-
# Should have multiple values in the list
282-
assert len(value_param["value"]) > 1, "Expected multiple intersection IDs to be highlighted"
375+
assert color_param is not None, "No selection parameter with intersection_id found"
376+
377+
# Verify the correct intersections are highlighted
378+
actual_ids = [v["intersection_id"] for v in color_param["value"]]
379+
assert len(actual_ids) == 3, f"Expected 3 highlighted intersections, got {len(actual_ids)}"
380+
assert set(actual_ids) == set(expected_ids), (
381+
f"Expected intersections {expected_ids}, but got {actual_ids}"
382+
)
283383

284384

285385
def test_highlight_none_default_hover(sample_data):

0 commit comments

Comments
 (0)