""" Database 단위 테스트 — 마이그레이션, 동기화, 헬퍼. """ import os import sys import tempfile from datetime import date import pytest sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from core.database import Database @pytest.fixture def fresh_db(tmp_path): """매 테스트마다 빈 DB.""" return Database(str(tmp_path / "test.db")) class TestSettingsHelpers: def test_get_setting_int_valid(self, fresh_db): fresh_db.set_setting('foo', '42') assert fresh_db.get_setting_int('foo') == 42 def test_get_setting_int_invalid_returns_default(self, fresh_db): fresh_db.set_setting('foo', 'abc') assert fresh_db.get_setting_int('foo', 99) == 99 def test_get_setting_int_missing_returns_default(self, fresh_db): assert fresh_db.get_setting_int('missing', 7) == 7 def test_get_setting_bool_truthy(self, fresh_db): fresh_db.set_setting('flag', 'true') assert fresh_db.get_setting_bool('flag') is True def test_get_setting_bool_falsy(self, fresh_db): fresh_db.set_setting('flag', 'no') assert fresh_db.get_setting_bool('flag') is False def test_get_setting_float(self, fresh_db): fresh_db.set_setting('rate', '3.14') assert fresh_db.get_setting_float('rate') == 3.14 class TestSettingsAutoSync: def test_work_minutes_to_work_hours_floor(self, fresh_db): """work_minutes 저장 시 work_hours는 floor 동기화 (450 → 7)""" fresh_db.save_settings({'work_minutes': 450}) assert fresh_db.get_setting('work_hours') == '7' def test_work_hours_to_work_minutes(self, fresh_db): fresh_db.save_settings({'work_hours': 8}) assert fresh_db.get_setting('work_minutes') == '480' def test_annual_leave_bidirectional(self, fresh_db): fresh_db.save_settings({'annual_leave_days': 12}) assert fresh_db.get_setting('annual_leave_total') == '12' class TestWorkMinutes: def test_get_work_minutes_default(self, fresh_db): assert fresh_db.get_work_minutes() == 480 def test_get_work_minutes_after_save(self, fresh_db): fresh_db.save_settings({'work_minutes': 450}) assert fresh_db.get_work_minutes() == 450 class TestLeaveCalculation: def test_leave_minutes_for_short_worker(self, fresh_db): """단축근무자(7h30m) 1일 연차 = 450분""" fresh_db.save_settings({'work_minutes': 450}) today = date.today().isoformat() fresh_db.add_leave_record(today, 'annual', 1.0) assert fresh_db.get_today_leave_minutes() == 450 def test_half_day_leave(self, fresh_db): today = date.today().isoformat() fresh_db.add_leave_record(today, 'half', 0.5) assert fresh_db.get_today_leave_minutes() == 240 # 8h * 0.5 class TestMigrationIdempotency: def test_annual_leave_keys_migrated_sentinel(self, fresh_db): assert fresh_db.get_setting('annual_leave_keys_migrated') == 'true' def test_re_init_does_not_break(self, tmp_path): path = str(tmp_path / "test.db") db1 = Database(path) db1.save_settings({'work_minutes': 450}) # 두 번째 init db2 = Database(path) assert db2.get_work_minutes() == 450 class TestConsecutiveOvertimeDays: def test_no_records(self, fresh_db): assert fresh_db.get_consecutive_overtime_days() == 0 def test_three_consecutive(self, fresh_db): from datetime import date, timedelta today = date.today() for i in range(3): d = (today - timedelta(days=i)).isoformat() fresh_db.add_work_record(d, '09:00:00') fresh_db.update_clock_out(d, '20:00:00', total_hours=11.0, overtime_minutes=120, overtime_earned=120) assert fresh_db.get_consecutive_overtime_days() == 3