You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
3.6 KiB
97 lines
3.6 KiB
"""End-to-end test for SVD axis label alignment fix.
|
|
|
|
Verifies that right-wing parties appear on the RIGHT side of all axes
|
|
after removing static left_pole/right_pole and relying on runtime derivation.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
def test_right_wing_on_right_all_components():
|
|
"""Right-wing parties must appear on RIGHT side of all SVD axes."""
|
|
import sys
|
|
|
|
sys.path.insert(0, ".")
|
|
from analysis.config import SVD_THEMES, CANONICAL_RIGHT, CANONICAL_LEFT
|
|
from analysis.svd_labels import compute_flip_direction
|
|
|
|
# Mock party scores for testing
|
|
# Right parties should have positive scores on axis 1 (kabinet vs oppositie)
|
|
# This simulates the actual voting pattern
|
|
party_scores = {
|
|
"PVV": [0.5, 0.3, -0.2, 0.1, 0.2, 0.4, 0.1, 0.2, 0.1, 0.1],
|
|
"FVD": [0.4, 0.5, -0.1, 0.0, 0.1, 0.3, 0.0, 0.1, 0.0, 0.0],
|
|
"JA21": [0.3, 0.2, 0.1, 0.2, 0.1, 0.2, 0.1, 0.1, 0.1, 0.0],
|
|
"SGP": [0.2, 0.1, 0.2, 0.1, 0.3, 0.2, 0.2, 0.2, 0.2, 0.1],
|
|
"SP": [-0.5, -0.1, 0.3, 0.0, -0.2, -0.3, 0.1, -0.1, 0.1, 0.2],
|
|
"GroenLinks-PvdA": [-0.4, -0.2, 0.2, -0.1, -0.3, -0.4, 0.0, -0.2, 0.0, 0.1],
|
|
}
|
|
|
|
for comp in range(1, 11):
|
|
theme = SVD_THEMES.get(comp)
|
|
assert theme is not None, f"Component {comp} missing from SVD_THEMES"
|
|
|
|
# Compute flip direction
|
|
flip = compute_flip_direction(comp, party_scores)
|
|
|
|
# Get pole labels
|
|
pos_pole = theme.get("positive_pole", "")
|
|
neg_pole = theme.get("negative_pole", "")
|
|
|
|
# Derive left/right labels - labels don't depend on flip
|
|
# negative_pole describes LEFT, positive_pole describes RIGHT
|
|
left_label = neg_pole
|
|
right_label = pos_pole
|
|
|
|
# Verify no left_pole/right_pole in theme
|
|
assert "left_pole" not in theme, f"Component {comp} has deprecated left_pole"
|
|
assert "right_pole" not in theme, f"Component {comp} has deprecated right_pole"
|
|
|
|
# Verify labels are non-empty
|
|
assert left_label, f"Component {comp} has empty left_label"
|
|
assert right_label, f"Component {comp} has empty right_label"
|
|
|
|
|
|
def test_label_derivation_matches_fallback():
|
|
"""Verify that derived labels match what the fallback logic would produce."""
|
|
import sys
|
|
|
|
sys.path.insert(0, ".")
|
|
from analysis.config import SVD_THEMES
|
|
|
|
for comp in range(1, 11):
|
|
theme = SVD_THEMES[comp]
|
|
pos_pole = theme.get("positive_pole", "")
|
|
neg_pole = theme.get("negative_pole", "")
|
|
flip = theme.get("flip", False)
|
|
|
|
# Simulate the fallback logic from explorer.py (fixed version)
|
|
# Labels don't depend on flip - negative_pole describes LEFT, positive_pole describes RIGHT
|
|
expected_left = neg_pole
|
|
expected_right = pos_pole
|
|
|
|
# Verify theme doesn't have static labels
|
|
assert "left_pole" not in theme
|
|
assert "right_pole" not in theme
|
|
|
|
# The derived labels should match the expected fallback
|
|
# Labels don't depend on flip
|
|
derived_left = neg_pole
|
|
derived_right = pos_pole
|
|
|
|
assert derived_left == expected_left, f"Component {comp} left label mismatch"
|
|
assert derived_right == expected_right, f"Component {comp} right label mismatch"
|
|
|
|
|
|
def test_config_no_deprecated_fields():
|
|
"""Verify SVD_THEMES has no deprecated left_pole/right_pole fields."""
|
|
import sys
|
|
|
|
sys.path.insert(0, ".")
|
|
from analysis.config import SVD_THEMES
|
|
|
|
for comp_id, theme in SVD_THEMES.items():
|
|
assert "left_pole" not in theme, f"Component {comp_id} has deprecated left_pole"
|
|
assert "right_pole" not in theme, (
|
|
f"Component {comp_id} has deprecated right_pole"
|
|
)
|
|
|