backend.tests.unit.components.reports.test_report_service

  1import pytest
  2from datetime import datetime, timedelta
  3from backend.database.models import Entry, Worker
  4from backend.components.reports.reportService import log_worker_entry, get_report_data
  5
  6
  7# --------------------------------------------------------------------------
  8# Testy funkcji log_worker_entry
  9# --------------------------------------------------------------------------
 10
 11def test_log_worker_entry_success_removes_image(db_session, created_worker):
 12    """
 13    Checks whether, on successful entry (code=0), the image is deleted (set to None),
 14    even if it was passed to the function.
 15    """
 16    fake_image = b'some_image_bytes'
 17
 18    entry = log_worker_entry(
 19        code=0,
 20        message="Access Granted",
 21        worker=created_worker,
 22        image=fake_image
 23    )
 24
 25    # Sprawdzamy czy obiekt został zwrócony i ma ID (czyli jest w sesji/bazie)
 26    assert entry.id is not None
 27    assert entry.worker_id == created_worker.id
 28    assert entry.code == 0
 29    # Kluczowy test logiki biznesowej: code 0 -> image musi być None
 30    assert entry.face_image is None
 31
 32
 33def test_log_worker_entry_failure_keeps_image(db_session, created_worker):
 34    """
 35    Checks whether the photo is saved in the database on an unsuccessful entry (code!=0).
 36    """
 37    fake_image = b'evidence_image_bytes'
 38
 39    entry = log_worker_entry(
 40        code=1,  # Błąd/Odmowa
 41        message="Face mismatch",
 42        worker=created_worker,
 43        image=fake_image
 44    )
 45
 46    assert entry.id is not None
 47    assert entry.code == 1
 48    # Przy błędzie zdjęcie powinno zostać zachowane
 49    assert entry.face_image == fake_image
 50
 51
 52def test_log_worker_entry_unknown_person(db_session):
 53    """
 54    Checks login entry for an unrecognized person (worker=None).
 55    """
 56    entry = log_worker_entry(
 57        code=2,
 58        message="Unknown person",
 59        worker=None,
 60        image=b'intruder_face'
 61    )
 62
 63    assert entry.id is not None
 64    assert entry.worker_id is None
 65    assert entry.message == "Unknown person"
 66
 67
 68# --------------------------------------------------------------------------
 69# Testy funkcji get_report_data
 70# --------------------------------------------------------------------------
 71
 72@pytest.fixture
 73def report_data_setup(db_session, created_worker):
 74    """
 75    A support fixture that creates a test data set for reporting.
 76
 77    Creates 4 entries with different dates and statuses.
 78    """
 79    base_time = datetime(2023, 1, 1, 12, 0, 0)
 80
 81    # Drugi pracownik do testów filtrowania
 82    worker2 = Worker(name="Adam Nowak", face_embedding=b'123', expiration_date=datetime.now(), secret="sec")
 83    db_session.session.add(worker2)
 84    db_session.session.commit()
 85
 86    entries = [
 87        # 1. Wpis poprawny, Worker 1, Data: base_time (najstarszy)
 88        Entry(worker_id=created_worker.id, code=0, message="OK", date=base_time),
 89
 90        # 2. Wpis błędny, Worker 1, Data: base_time + 1 dzień
 91        Entry(worker_id=created_worker.id, code=1, message="Error", date=base_time + timedelta(days=1)),
 92
 93        # 3. Wpis poprawny, Worker 2, Data: base_time + 2 dni
 94        Entry(worker_id=worker2.id, code=0, message="OK", date=base_time + timedelta(days=2)),
 95
 96        # 4. Wpis błędny, Brak Workera, Data: base_time + 3 dni (najnowszy)
 97        Entry(worker_id=None, code=2, message="Unknown", date=base_time + timedelta(days=3))
 98    ]
 99
100    db_session.session.add_all(entries)
101    db_session.session.commit()
102
103    return {
104        "base_time": base_time,
105        "worker1": created_worker,
106        "worker2": worker2
107    }
108
109
110def test_get_report_data_all(db_session, report_data_setup):
111    """Test downloading all data (no filters)."""
112    results = get_report_data()
113
114    assert len(results) == 4
115    # Sprawdzenie sortowania (domyślnie malejąco po dacie - najnowsze pierwsze)
116    assert results[0][0].message == "Unknown"  # Najnowszy (+3 dni)
117    assert results[-1][0].message == "OK"  # Najstarszy (+0 dni)
118
119    # Sprawdzenie czy zwraca krotki (Entry, Worker)
120    first_entry, first_worker = results[0]
121    assert isinstance(first_entry, Entry)
122    assert first_worker is None  # Ten wpis nie miał workera
123
124
125def test_get_report_data_filter_by_worker(db_session, report_data_setup):
126    """Test filtering by employee ID."""
127    worker1 = report_data_setup["worker1"]
128
129    results = get_report_data(worker_id=worker1.id)
130
131    # Worker 1 ma 2 wpisy
132    assert len(results) == 2
133    for entry, worker in results:
134        assert entry.worker_id == worker1.id
135        assert worker.id == worker1.id
136
137
138def test_get_report_data_filter_by_date(db_session, report_data_setup):
139    """Test filtering by date range."""
140    base_time = report_data_setup["base_time"]
141
142    # Filtrujemy od dnia +1 do dnia +2 (powinny być 2 wpisy)
143    date_from = base_time + timedelta(days=1)
144    date_to = base_time + timedelta(days=2)
145
146    results = get_report_data(date_from=date_from, date_to=date_to)
147
148    assert len(results) == 2
149    messages = [r[0].message for r in results]
150    assert "Error" in messages  # +1 dzień
151    assert "OK" in messages  # +2 dni
152
153
154def test_get_report_data_filter_valid_invalid(db_session, report_data_setup):
155    """Test filtering by status (valid/invalid)."""
156
157    # 1. Tylko poprawne (code == 0) -> Powinny być 2 (jeden workera1, jeden workera2)
158    valid_results = get_report_data(show_valid=True, show_invalid=False)
159    assert len(valid_results) == 2
160    for r in valid_results:
161        assert r[0].code == 0
162
163    # 2. Tylko błędne (code != 0) -> Powinny być 2
164    invalid_results = get_report_data(show_valid=False, show_invalid=True)
165    assert len(invalid_results) == 2
166    for r in invalid_results:
167        assert r[0].code != 0
168
169    # 3. Oba zaznaczone -> Wszystkie 4
170    all_results = get_report_data(show_valid=True, show_invalid=True)
171    assert len(all_results) == 4
172
173    # 4. Żaden niezaznaczony -> Domyślnie wszystkie 4 (zgodnie z logiką funkcji)
174    none_results = get_report_data(show_valid=False, show_invalid=False)
175    assert len(none_results) == 4
def test_log_worker_entry_success_removes_image(db_session, created_worker):
12def test_log_worker_entry_success_removes_image(db_session, created_worker):
13    """
14    Checks whether, on successful entry (code=0), the image is deleted (set to None),
15    even if it was passed to the function.
16    """
17    fake_image = b'some_image_bytes'
18
19    entry = log_worker_entry(
20        code=0,
21        message="Access Granted",
22        worker=created_worker,
23        image=fake_image
24    )
25
26    # Sprawdzamy czy obiekt został zwrócony i ma ID (czyli jest w sesji/bazie)
27    assert entry.id is not None
28    assert entry.worker_id == created_worker.id
29    assert entry.code == 0
30    # Kluczowy test logiki biznesowej: code 0 -> image musi być None
31    assert entry.face_image is None

Checks whether, on successful entry (code=0), the image is deleted (set to None), even if it was passed to the function.

def test_log_worker_entry_failure_keeps_image(db_session, created_worker):
34def test_log_worker_entry_failure_keeps_image(db_session, created_worker):
35    """
36    Checks whether the photo is saved in the database on an unsuccessful entry (code!=0).
37    """
38    fake_image = b'evidence_image_bytes'
39
40    entry = log_worker_entry(
41        code=1,  # Błąd/Odmowa
42        message="Face mismatch",
43        worker=created_worker,
44        image=fake_image
45    )
46
47    assert entry.id is not None
48    assert entry.code == 1
49    # Przy błędzie zdjęcie powinno zostać zachowane
50    assert entry.face_image == fake_image

Checks whether the photo is saved in the database on an unsuccessful entry (code!=0).

def test_log_worker_entry_unknown_person(db_session):
53def test_log_worker_entry_unknown_person(db_session):
54    """
55    Checks login entry for an unrecognized person (worker=None).
56    """
57    entry = log_worker_entry(
58        code=2,
59        message="Unknown person",
60        worker=None,
61        image=b'intruder_face'
62    )
63
64    assert entry.id is not None
65    assert entry.worker_id is None
66    assert entry.message == "Unknown person"

Checks login entry for an unrecognized person (worker=None).

@pytest.fixture
def report_data_setup(db_session, created_worker):
 73@pytest.fixture
 74def report_data_setup(db_session, created_worker):
 75    """
 76    A support fixture that creates a test data set for reporting.
 77
 78    Creates 4 entries with different dates and statuses.
 79    """
 80    base_time = datetime(2023, 1, 1, 12, 0, 0)
 81
 82    # Drugi pracownik do testów filtrowania
 83    worker2 = Worker(name="Adam Nowak", face_embedding=b'123', expiration_date=datetime.now(), secret="sec")
 84    db_session.session.add(worker2)
 85    db_session.session.commit()
 86
 87    entries = [
 88        # 1. Wpis poprawny, Worker 1, Data: base_time (najstarszy)
 89        Entry(worker_id=created_worker.id, code=0, message="OK", date=base_time),
 90
 91        # 2. Wpis błędny, Worker 1, Data: base_time + 1 dzień
 92        Entry(worker_id=created_worker.id, code=1, message="Error", date=base_time + timedelta(days=1)),
 93
 94        # 3. Wpis poprawny, Worker 2, Data: base_time + 2 dni
 95        Entry(worker_id=worker2.id, code=0, message="OK", date=base_time + timedelta(days=2)),
 96
 97        # 4. Wpis błędny, Brak Workera, Data: base_time + 3 dni (najnowszy)
 98        Entry(worker_id=None, code=2, message="Unknown", date=base_time + timedelta(days=3))
 99    ]
100
101    db_session.session.add_all(entries)
102    db_session.session.commit()
103
104    return {
105        "base_time": base_time,
106        "worker1": created_worker,
107        "worker2": worker2
108    }

A support fixture that creates a test data set for reporting.

Creates 4 entries with different dates and statuses.

def test_get_report_data_all(db_session, report_data_setup):
111def test_get_report_data_all(db_session, report_data_setup):
112    """Test downloading all data (no filters)."""
113    results = get_report_data()
114
115    assert len(results) == 4
116    # Sprawdzenie sortowania (domyślnie malejąco po dacie - najnowsze pierwsze)
117    assert results[0][0].message == "Unknown"  # Najnowszy (+3 dni)
118    assert results[-1][0].message == "OK"  # Najstarszy (+0 dni)
119
120    # Sprawdzenie czy zwraca krotki (Entry, Worker)
121    first_entry, first_worker = results[0]
122    assert isinstance(first_entry, Entry)
123    assert first_worker is None  # Ten wpis nie miał workera

Test downloading all data (no filters).

def test_get_report_data_filter_by_worker(db_session, report_data_setup):
126def test_get_report_data_filter_by_worker(db_session, report_data_setup):
127    """Test filtering by employee ID."""
128    worker1 = report_data_setup["worker1"]
129
130    results = get_report_data(worker_id=worker1.id)
131
132    # Worker 1 ma 2 wpisy
133    assert len(results) == 2
134    for entry, worker in results:
135        assert entry.worker_id == worker1.id
136        assert worker.id == worker1.id

Test filtering by employee ID.

def test_get_report_data_filter_by_date(db_session, report_data_setup):
139def test_get_report_data_filter_by_date(db_session, report_data_setup):
140    """Test filtering by date range."""
141    base_time = report_data_setup["base_time"]
142
143    # Filtrujemy od dnia +1 do dnia +2 (powinny być 2 wpisy)
144    date_from = base_time + timedelta(days=1)
145    date_to = base_time + timedelta(days=2)
146
147    results = get_report_data(date_from=date_from, date_to=date_to)
148
149    assert len(results) == 2
150    messages = [r[0].message for r in results]
151    assert "Error" in messages  # +1 dzień
152    assert "OK" in messages  # +2 dni

Test filtering by date range.

def test_get_report_data_filter_valid_invalid(db_session, report_data_setup):
155def test_get_report_data_filter_valid_invalid(db_session, report_data_setup):
156    """Test filtering by status (valid/invalid)."""
157
158    # 1. Tylko poprawne (code == 0) -> Powinny być 2 (jeden workera1, jeden workera2)
159    valid_results = get_report_data(show_valid=True, show_invalid=False)
160    assert len(valid_results) == 2
161    for r in valid_results:
162        assert r[0].code == 0
163
164    # 2. Tylko błędne (code != 0) -> Powinny być 2
165    invalid_results = get_report_data(show_valid=False, show_invalid=True)
166    assert len(invalid_results) == 2
167    for r in invalid_results:
168        assert r[0].code != 0
169
170    # 3. Oba zaznaczone -> Wszystkie 4
171    all_results = get_report_data(show_valid=True, show_invalid=True)
172    assert len(all_results) == 4
173
174    # 4. Żaden niezaznaczony -> Domyślnie wszystkie 4 (zgodnie z logiką funkcji)
175    none_results = get_report_data(show_valid=False, show_invalid=False)
176    assert len(none_results) == 4

Test filtering by status (valid/invalid).