Clock_out_Time_Calculator/tests/test_overtime_accrual_guard.py
KINDNICK 5fb8655a47 v2.11.0: UI 전면 다크 리디자인 + 라인 아이콘 + 적립 가드/삭제
- 모던 다크 미니멀 테마(NanumSquare 번들, 단일 accent #4DABF7, 8px radius, flat 버튼, 다크 기본값)
- 라인 아이콘 시스템(ui/icons.py, QtSvg) — 앱 전반 이모지 교체
- 다크 깨짐 수정: 테이블 헤더/코너 흰색, 도움말 탭 흰 라인, 트레이/미니위젯 메뉴
- fix: 자동 적립 OFF가 자동 퇴근 경로에서 무시되던 버그(게이팅)
- feat: 연장근무 적립 기록 삭제(우클릭)
- 테스트 3건 추가

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:21:54 +09:00

73 lines
2.9 KiB
Python

"""연장근무 자동 적립 가드 테스트.
auto_overtime(자동 적립)가 OFF면, 자동 퇴근 경로(근무일 경계 롤오버 등)에서도
은행 적립을 하지 않아야 한다 — clock_out() 대화상자에서 '아니오'를 고른 것과 동일한 의미.
handle_workday_rollover는 위젯 의존이 tail(load_today_data/update_overtime_balance)뿐이라,
__new__로 만든 인스턴스에 필요한 속성만 채워 단위 테스트한다 (QApplication 불필요).
"""
import os
import sys
from datetime import datetime, timedelta, time as dtime
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from core.database import Database
from core.time_calculator import TimeCalculator
from ui.main_window import MainWindow
def _rollover_balance(db, monkeypatch):
"""어제 미퇴근 상태에서 근무일 경계 롤오버를 실행하고 적립 잔액을 반환."""
from PyQt5.QtWidgets import QMessageBox
monkeypatch.setattr(QMessageBox, 'information',
staticmethod(lambda *a, **k: QMessageBox.Ok))
today = datetime.now().date()
y = today - timedelta(days=1)
db.add_work_record(y.isoformat(), '09:00:00', is_manual=True) # 어제: 미퇴근
w = MainWindow.__new__(MainWindow) # __init__ 우회 (위젯/타이머 없음)
w.db = db
w.time_calc = TimeCalculator(work_minutes=480)
w.clock_in_time = datetime.combine(y, dtime(9, 0, 0))
w.is_clocked_in = True
w.midnight_rollover_handled = False
w.is_on_break = False
w.lunch_break_enabled = False
w.dinner_break_enabled = False
w.load_today_data = lambda: None # tail UI refresh stub
w.update_overtime_balance = lambda: None # tail UI refresh stub
w.handle_workday_rollover(datetime.combine(today, dtime(7, 0, 0)))
return db.get_total_overtime_balance()
def test_rollover_does_not_accrue_when_auto_overtime_off(tmp_path, monkeypatch):
db = Database(str(tmp_path / 'off.db'))
db.set_setting('auto_overtime', 'false')
assert _rollover_balance(db, monkeypatch) == 0
def test_rollover_accrues_when_auto_overtime_on(tmp_path, monkeypatch):
db = Database(str(tmp_path / 'on.db'))
db.set_setting('auto_overtime', 'true')
assert _rollover_balance(db, monkeypatch) > 0
def test_delete_overtime_earned_reduces_balance(tmp_path):
"""적립(은행) 기록 삭제 시 잔액이 그만큼 감소한다."""
from datetime import date
db = Database(str(tmp_path / 'del.db'))
today = date.today().isoformat()
db.add_overtime_earned(None, 90, today)
assert db.get_total_overtime_balance() == 90
bank_id = db.get_connection().execute(
'SELECT id FROM overtime_bank').fetchone()[0]
assert db.delete_overtime_earned(bank_id) is True
assert db.get_total_overtime_balance() == 0
# 없는 id 삭제는 False
assert db.delete_overtime_earned(999999) is False