mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-07-01 11:14:52 +02:00
184 lines
6.9 KiB
Python
184 lines
6.9 KiB
Python
def test_ui_modules_import_without_creating_root_window() -> None:
|
|
import ccma.app # noqa: F401
|
|
import ccma.ui.asset_tab # noqa: F401
|
|
import ccma.ui.claim_tab # noqa: F401
|
|
import ccma.ui.main_window # noqa: F401
|
|
import ccma.ui.member_tab # noqa: F401
|
|
import ccma.ui.splash # noqa: F401
|
|
|
|
|
|
def test_splash_position_centers_on_pointer_and_stays_on_screen() -> None:
|
|
from ccma.ui.splash import centered_position
|
|
|
|
assert centered_position(
|
|
width=620,
|
|
height=330,
|
|
pointer_x=2500,
|
|
pointer_y=600,
|
|
screen_x=0,
|
|
screen_y=0,
|
|
screen_width=3840,
|
|
screen_height=1080,
|
|
) == (2190, 435)
|
|
assert centered_position(
|
|
width=620,
|
|
height=330,
|
|
pointer_x=10,
|
|
pointer_y=10,
|
|
screen_x=0,
|
|
screen_y=0,
|
|
screen_width=1920,
|
|
screen_height=1080,
|
|
) == (0, 0)
|
|
|
|
|
|
def test_splash_minimum_time_only_waits_for_remaining_duration() -> None:
|
|
from ccma.ui.splash import (
|
|
_member_delay_for_splash,
|
|
_progress_value,
|
|
_remaining_minimum_ms,
|
|
)
|
|
|
|
assert _remaining_minimum_ms(100.0, 5.0, 102.25) == 2750
|
|
assert _remaining_minimum_ms(100.0, 5.0, 106.0) == 0
|
|
assert _remaining_minimum_ms(100.0, 0.0, 100.0) == 0
|
|
assert _progress_value(2.5, 5.0, startup_finished=False) == 47.5
|
|
assert _progress_value(5.0, 5.0, startup_finished=False) == 95.0
|
|
assert _progress_value(2.5, 5.0, startup_finished=True) == 50.0
|
|
assert _progress_value(5.0, 5.0, startup_finished=True) == 100.0
|
|
assert _member_delay_for_splash(5.0, 10) == 0.5
|
|
assert _member_delay_for_splash(5.0, 0) == 0.0
|
|
assert _member_delay_for_splash(0.0, 10) == 0.0
|
|
|
|
|
|
def test_event_labels_hide_board_actor_but_keep_automatic_marker() -> None:
|
|
from ccma.domain.models import Event
|
|
from ccma.ui.member_tab import _event_label
|
|
|
|
user_event = Event("1", "2026-01-01T00:00:00+01:00", "comment", "Kommentar", "user", "Vorstand")
|
|
system_event = Event("2", "2026-01-01T00:00:00+01:00", "automatic", "Automatisch")
|
|
assert _event_label(user_event) == "Kommentar"
|
|
assert _event_label(system_event) == "[AUTO] Automatisch"
|
|
|
|
|
|
def test_housekeeper_details_are_multiline() -> None:
|
|
from datetime import date
|
|
|
|
from ccma.domain.models import HousekeeperFinding
|
|
from ccma.ui.work_tabs import _finding_details
|
|
|
|
finding = HousekeeperFinding(
|
|
severity="error",
|
|
code="invalid_member_record",
|
|
title="Mitgliederakte beschädigt",
|
|
detail="Die JSON-Datei ist leer und wird nicht automatisch überschrieben.",
|
|
member_id="member-1",
|
|
due_date=date(2026, 7, 31),
|
|
)
|
|
|
|
rendered = _finding_details(finding)
|
|
assert rendered.splitlines()[0] == "ERROR · invalid_member_record"
|
|
assert "Mitgliederakte beschädigt\nFällig:" in rendered
|
|
assert rendered.endswith("nicht automatisch überschrieben.")
|
|
|
|
|
|
def test_german_ui_labels_round_trip_to_english_storage_keys() -> None:
|
|
from ccma.domain.models import MEMBERSHIP_STATUS_LABELS
|
|
from ccma.ui.labels import (
|
|
CLAIM_ITEM_TYPE_LABELS,
|
|
THEME_LABELS,
|
|
display_label,
|
|
storage_key,
|
|
)
|
|
|
|
assert display_label(THEME_LABELS, "dark") == "Dunkel"
|
|
assert storage_key(THEME_LABELS, "Hell") == "light"
|
|
assert display_label(CLAIM_ITEM_TYPE_LABELS, "credit") == "Gutschrift"
|
|
assert storage_key(CLAIM_ITEM_TYPE_LABELS, "Dienstleistung") == "service"
|
|
assert display_label(MEMBERSHIP_STATUS_LABELS, "active") == "AKTIV"
|
|
assert storage_key(MEMBERSHIP_STATUS_LABELS, "EHRENMITGLIED") == "honorary"
|
|
|
|
|
|
def test_member_table_filter_only_keeps_selected_status() -> None:
|
|
from ccma.domain.models import Member
|
|
from ccma.ui.work_tabs import _filter_members, _selected_status_filter
|
|
|
|
members = [
|
|
Member("1", "0001", "Ada", "Lovelace", status="active"),
|
|
Member("2", "0002", "Grace", "Hopper", status="application"),
|
|
Member("3", "0003", "Linus", "Example", status="active"),
|
|
]
|
|
|
|
assert _selected_status_filter("Alle") == "all"
|
|
assert _selected_status_filter("AKTIV") == "active"
|
|
assert [member.member_id for member in _filter_members(members, "active")] == ["1", "3"]
|
|
assert [member.member_id for member in _filter_members(members, "all")] == ["1", "2", "3"]
|
|
|
|
|
|
def test_member_table_sort_uses_display_values() -> None:
|
|
from ccma.domain.models import Member
|
|
from ccma.ui.work_tabs import _sort_members
|
|
|
|
members = [
|
|
Member("1", "0002", "Grace", "Hopper", status="application"),
|
|
Member("2", "0001", "Ada", "Lovelace", status="active"),
|
|
Member("3", "0003", "Linus", "Example", status="honorary"),
|
|
]
|
|
|
|
assert [member.member_id for member in _sort_members(members, "number", False)] == ["2", "1", "3"]
|
|
assert [member.member_id for member in _sort_members(members, "first_name", False)] == ["2", "1", "3"]
|
|
assert [member.member_id for member in _sort_members(members, "last_name", False)] == ["3", "1", "2"]
|
|
assert [member.member_id for member in _sort_members(members, "status", False)] == ["2", "1", "3"]
|
|
|
|
|
|
def test_asset_table_filter_and_sort_use_status_and_holder_label() -> None:
|
|
from ccma.domain.models import Asset
|
|
from ccma.ui.work_tabs import _asset_table_value, _filter_assets, _selected_asset_filter
|
|
|
|
assets = [
|
|
Asset("1", "Clubraumschlüssel", status="issued", current_holder_member_id="member-1"),
|
|
Asset("2", "Beamer", status="available"),
|
|
]
|
|
|
|
assert _selected_asset_filter("Alle") == "all"
|
|
assert _selected_asset_filter("AUSGEGEBEN") == "issued"
|
|
assert [asset.asset_id for asset in _filter_assets(assets, "available")] == ["2"]
|
|
assert _asset_table_value(assets[0], "holder", "0001 · Ada") == "0001 · Ada"
|
|
|
|
|
|
def test_claim_table_sort_uses_due_date_by_raw_value() -> None:
|
|
from ccma.domain.models import ContributionData
|
|
from ccma.ui.member_tab import _claim_sort_value
|
|
|
|
data = ContributionData()
|
|
older = {"title": "Alt", "due_date": "2024-01-31", "amount": "75.00"}
|
|
newer = {"title": "Neu", "due_date": "2025-07-31", "amount": "50.00"}
|
|
|
|
assert _claim_sort_value(data, older, "due") < _claim_sort_value(data, newer, "due")
|
|
|
|
|
|
def test_negative_claims_are_labeled_as_credit() -> None:
|
|
from ccma.domain.contributions import claim_status
|
|
from ccma.domain.models import ContributionData
|
|
|
|
data = ContributionData()
|
|
claim = {"claim_id": "claim-1", "title": "Rueckzahlung", "amount": "-25.00"}
|
|
assert claim_status(data, claim) == "credit"
|
|
|
|
|
|
def test_housekeeper_details_include_asset_target() -> None:
|
|
from ccma.domain.models import HousekeeperFinding
|
|
from ccma.ui.work_tabs import _finding_details
|
|
|
|
finding = HousekeeperFinding(
|
|
severity="warning",
|
|
code="json_hash_mismatch",
|
|
title="Assetakte extern geändert",
|
|
detail="asset.json: Hash fehlt oder stimmt nicht.",
|
|
asset_id="asset-1",
|
|
target_type="asset",
|
|
)
|
|
|
|
rendered = _finding_details(finding)
|
|
assert "Asset: asset-1" in rendered
|