Coverage for tests/test_services.py: 100%

56 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-11-13 19:28 +0000

1"""Tests for domain services.""" 

2 

3from copy import deepcopy 

4from datetime import datetime 

5 

6import pytest 

7 

8from data_api.data.manager import nthudata 

9from data_api.domain.dining import services 

10from data_api.domain.dining.enums import DiningScheduleKeyword 

11from data_api.domain.dining.services import is_restaurant_open 

12 

13 

14class TestDiningService: 

15 """Tests for dining service functions.""" 

16 

17 async def test_is_restaurant_open_no_note(self): 

18 """Test restaurant with no note is open.""" 

19 restaurant = {"name": "Test", "note": ""} 

20 assert is_restaurant_open(restaurant, "weekday") is True 

21 

22 async def test_is_restaurant_open_break_on_saturday(self): 

23 """Test restaurant with break on Saturday is closed.""" 

24 restaurant = {"name": "Test", "note": "週六休息"} 

25 assert is_restaurant_open(restaurant, "saturday") is False 

26 

27 async def test_is_restaurant_open_break_different_day(self): 

28 """Test restaurant with break on different day is open.""" 

29 restaurant = {"name": "Test", "note": "週日休息"} 

30 assert is_restaurant_open(restaurant, "saturday") is True 

31 

32 async def test_is_restaurant_open_weekend(self): 

33 """Test restaurant on weekend.""" 

34 restaurant = {"name": "Test", "note": ""} 

35 assert is_restaurant_open(restaurant, "saturday") is True 

36 assert is_restaurant_open(restaurant, "sunday") is True 

37 

38 async def test_is_restaurant_open_weekday(self): 

39 """Test restaurant on weekday.""" 

40 restaurant = {"name": "Test", "note": ""} 

41 assert is_restaurant_open(restaurant, "weekday") is True 

42 

43 

44class TestDiningScheduleKeyword: 

45 """Tests for DiningScheduleKeyword enum.""" 

46 

47 async def test_break_keywords_exist(self): 

48 """Test break keywords are defined.""" 

49 assert len(DiningScheduleKeyword.BREAK_KEYWORDS) > 0 

50 

51 async def test_day_mapping_exists(self): 

52 """Test day mapping is defined.""" 

53 assert "weekday" in DiningScheduleKeyword.DAY_EN_TO_ZH 

54 assert "saturday" in DiningScheduleKeyword.DAY_EN_TO_ZH 

55 assert "sunday" in DiningScheduleKeyword.DAY_EN_TO_ZH 

56 

57 

58@pytest.mark.parametrize( 

59 "instant,closed_day", 

60 [ 

61 ("2026-09-25T15:59:59+00:00", "weekday"), 

62 ("2026-09-25T16:00:00+00:00", "saturday"), 

63 ("2026-09-26T15:59:59+00:00", "saturday"), 

64 ("2026-09-26T16:00:00+00:00", "sunday"), 

65 ("2026-09-27T15:59:59+00:00", "sunday"), 

66 ("2026-09-27T16:00:00+00:00", "weekday"), 

67 ], 

68) 

69@pytest.mark.parametrize( 

70 "method", ["get_dining_data", "fuzzy_search_dining_data", "get_open_restaurants"] 

71) 

72async def test_today_uses_taiwan_date(monkeypatch, instant, closed_day, method): 

73 restaurants = [ 

74 {"name": "weekday", "note": "平日休息"}, 

75 {"name": "saturday", "note": "週六休息"}, 

76 {"name": "sunday", "note": "週日休息"}, 

77 ] 

78 data = [{"building": "Test", "metadata": "preserved", "restaurants": restaurants}] 

79 original = deepcopy(data) 

80 calls = [] 

81 now = datetime.fromisoformat(instant) 

82 

83 class FrozenDatetime(datetime): 

84 @classmethod 

85 def now(cls, tz=None): 

86 assert str(tz) == "Asia/Taipei" 

87 return now.astimezone(tz) 

88 

89 async def fake_get(endpoint): 

90 calls.append(endpoint) 

91 return "hash", data 

92 

93 monkeypatch.setattr(services, "datetime", FrozenDatetime) 

94 monkeypatch.setattr(nthudata, "get", fake_get) 

95 version, result = await getattr(services.dining_service, method)(schedule="today") 

96 excluded = { 

97 "weekday": {"weekday"}, 

98 "saturday": {"saturday"}, 

99 # The legacy note heuristic also treats "平日休息" as a Sunday closure. 

100 "sunday": {"weekday", "sunday"}, 

101 }[closed_day] 

102 expected = [r for r in restaurants if r["name"] not in excluded] 

103 assert result == ( 

104 expected if method == "get_open_restaurants" else [{**data[0], "restaurants": expected}] 

105 ) 

106 assert version == "hash" 

107 assert calls == ["dining.json"] 

108 assert data == original