1+ import tempfile
2+ import os
3+ import sys
4+ import pytest
5+ import pandas as pd
6+ from ruamel .yaml import YAML
7+ from automation_prepare_adhoc_availability import (
8+ get_available_mentor_sort ,
9+ get_unavailable_mentor_sort ,
10+ get_availability_update_dict ,
11+ update_mentor_availability ,
12+ MONTHS_MAP ,
13+ TYPE_LONG_TERM ,
14+ TYPE_AD_HOC ,
15+ TYPE_BOTH
16+ )
17+
18+ yaml = YAML ()
19+
20+
21+ class TestGetAvailableMentorSort :
22+ def test_new_mentor_with_full_availability_returns_500 (self ):
23+ mentor = {'name' : 'Test Mentor' , 'hours' : 2 }
24+ current_availability = [4 , 5 , 6 ]
25+
26+ result = get_available_mentor_sort (mentor , current_availability )
27+
28+ assert result == 500
29+
30+ def test_mentor_with_more_than_3_hours_returns_500 (self ):
31+ mentor = {'name' : 'Test Mentor' , 'hours' : 4 }
32+ current_availability = [4 ]
33+
34+ result = get_available_mentor_sort (mentor , current_availability )
35+
36+ assert result == 500
37+
38+ def test_mentor_with_3_or_less_hours_returns_200 (self ):
39+ mentor = {'name' : 'Test Mentor' , 'hours' : 3 }
40+ current_availability = [4 ]
41+
42+ result = get_available_mentor_sort (mentor , current_availability )
43+
44+ assert result == 200
45+
46+ def test_mentor_with_1_hour_returns_200 (self ):
47+ mentor = {'name' : 'Test Mentor' , 'hours' : 1 }
48+ current_availability = [4 ]
49+
50+ result = get_available_mentor_sort (mentor , current_availability )
51+
52+ assert result == 200
53+
54+
55+ class TestGetUnavailableMentorSort :
56+ def test_disabled_mentor_returns_1 (self ):
57+ mentor = {'name' : 'Test Mentor' , 'disabled' : True , 'type' : TYPE_BOTH }
58+
59+ result = get_unavailable_mentor_sort (mentor )
60+
61+ assert result == 1
62+
63+ def test_long_term_mentor_returns_10 (self ):
64+ mentor = {'name' : 'Test Mentor' , 'disabled' : False , 'type' : TYPE_LONG_TERM }
65+
66+ result = get_unavailable_mentor_sort (mentor )
67+
68+ assert result == 10
69+
70+ def test_ad_hoc_mentor_returns_100 (self ):
71+ mentor = {'name' : 'Test Mentor' , 'disabled' : False , 'type' : TYPE_AD_HOC }
72+
73+ result = get_unavailable_mentor_sort (mentor )
74+
75+ assert result == 100
76+
77+ def test_both_type_mentor_returns_100 (self ):
78+ mentor = {'name' : 'Test Mentor' , 'disabled' : False , 'type' : TYPE_BOTH }
79+
80+ result = get_unavailable_mentor_sort (mentor )
81+
82+ assert result == 100
83+
84+
85+ class TestGetAvailabilityUpdateDict :
86+ def test_returns_dict_with_mentor_hours (self ):
87+ data = {
88+ 'Mentor Name' : ['Alice Smith' , 'Bob Jones' ],
89+ 'Availability (Hours)' : [5 , 3 ]
90+ }
91+ df = pd .DataFrame (data )
92+
93+ result = get_availability_update_dict (df )
94+
95+ assert result ['Alice Smith' ] == 5
96+ assert result ['Bob Jones' ] == 3
97+
98+ def test_empty_hours_returns_none (self ):
99+ data = {
100+ 'Mentor Name' : ['Alice Smith' ],
101+ 'Availability (Hours)' : ['' ]
102+ }
103+ df = pd .DataFrame (data )
104+
105+ result = get_availability_update_dict (df )
106+
107+ assert result ['Alice Smith' ] is None
108+
109+ def test_nan_hours_returns_none (self ):
110+ data = {
111+ 'Mentor Name' : ['Alice Smith' ],
112+ 'Availability (Hours)' : [pd .NA ]
113+ }
114+ df = pd .DataFrame (data )
115+
116+ result = get_availability_update_dict (df )
117+
118+ assert result ['Alice Smith' ] is None
119+
120+ def test_strips_whitespace_from_names (self ):
121+ data = {
122+ 'Mentor Name' : [' Alice Smith ' ],
123+ 'Availability (Hours)' : [4 ]
124+ }
125+ df = pd .DataFrame (data )
126+
127+ result = get_availability_update_dict (df )
128+
129+ assert 'Alice Smith' in result
130+
131+
132+ class TestUpdateMentorAvailability :
133+ def test_updates_mentor_availability_from_xlsx (self , monkeypatch ):
134+
135+ with tempfile .NamedTemporaryFile (suffix = '.xlsx' , delete = False ) as xlsx_file :
136+ xlsx_path = xlsx_file .name
137+
138+ with tempfile .NamedTemporaryFile (suffix = '.yml' , mode = 'w' , delete = False ) as yml_file :
139+ yml_path = yml_file .name
140+
141+ try :
142+ df = pd .DataFrame ({
143+ 'Mentor Name' : ['Alice Smith' ],
144+ 'Availability (Hours)' : [5 ]
145+ })
146+ df .to_excel (xlsx_path , index = False )
147+
148+ mentors = [
149+ {
150+ 'name' : 'Alice Smith' ,
151+ 'hours' : 2 ,
152+ 'availability' : [4 , 5 ],
153+ 'sort' : 200 ,
154+ 'type' : TYPE_AD_HOC ,
155+ 'disabled' : False
156+ },
157+ {
158+ 'name' : 'Bob Jones' ,
159+ 'hours' : 3 ,
160+ 'availability' : [4 ],
161+ 'sort' : 100 ,
162+ 'type' : TYPE_LONG_TERM ,
163+ 'disabled' : False
164+ }
165+ ]
166+
167+ with open (yml_path , 'w' ) as f :
168+ yaml .dump (mentors , f )
169+
170+ update_mentor_availability (4 , xlsx_path , yml_path )
171+
172+ with open (yml_path , 'r' ) as f :
173+ result = yaml .load (f )
174+
175+ alice = next (m for m in result if m ['name' ] == 'Alice Smith' )
176+ assert alice ['hours' ] == 5
177+ assert alice ['availability' ] == [4 ]
178+ assert alice ['sort' ] == 500
179+
180+ bob = next (m for m in result if m ['name' ] == 'Bob Jones' )
181+ assert bob ['availability' ] == []
182+ assert bob ['sort' ] == 10
183+
184+ finally :
185+ os .remove (xlsx_path )
186+ os .remove (yml_path )
187+
188+ def test_mentor_not_in_xlsx_becomes_unavailable (self , monkeypatch ):
189+ with tempfile .NamedTemporaryFile (suffix = '.xlsx' , delete = False ) as xlsx_file :
190+ xlsx_path = xlsx_file .name
191+
192+ with tempfile .NamedTemporaryFile (suffix = '.yml' , mode = 'w' , delete = False ) as yml_file :
193+ yml_path = yml_file .name
194+
195+ try :
196+ df = pd .DataFrame ({
197+ 'Mentor Name' : ['Alice Smith' ],
198+ 'Availability (Hours)' : [5 ]
199+ })
200+ df .to_excel (xlsx_path , index = False )
201+
202+ mentors = [
203+ {'name' : 'Alice Smith' , 'hours' : 2 , 'availability' : [4 ], 'sort' : 200 , 'type' : TYPE_AD_HOC , 'disabled' : False },
204+ {'name' : 'Bob Jones' , 'hours' : 3 , 'availability' : [4 ], 'sort' : 200 , 'type' : TYPE_BOTH , 'disabled' : False }
205+ ]
206+
207+ with open (yml_path , 'w' ) as f :
208+ yaml .dump (mentors , f )
209+
210+ update_mentor_availability (4 , xlsx_path , yml_path )
211+
212+ with open (yml_path , 'r' ) as f :
213+ result = yaml .load (f )
214+
215+ bob = next (m for m in result if m ['name' ] == 'Bob Jones' )
216+ assert bob ['availability' ] == []
217+ assert bob ['sort' ] == 100
218+
219+ finally :
220+ os .remove (xlsx_path )
221+ os .remove (yml_path )
222+
223+ def test_keeps_existing_hours_when_xlsx_hours_empty (self ):
224+ with tempfile .NamedTemporaryFile (suffix = '.xlsx' , delete = False ) as xlsx_file :
225+ xlsx_path = xlsx_file .name
226+
227+ with tempfile .NamedTemporaryFile (suffix = '.yml' , mode = 'w' , delete = False ) as yml_file :
228+ yml_path = yml_file .name
229+
230+ try :
231+ df = pd .DataFrame ({
232+ 'Mentor Name' : ['Alice Smith' ],
233+ 'Availability (Hours)' : ['' ]
234+ })
235+ df .to_excel (xlsx_path , index = False )
236+
237+ mentors = [
238+ {'name' : 'Alice Smith' , 'hours' : 3 , 'availability' : [4 ], 'sort' : 200 , 'type' : TYPE_AD_HOC , 'disabled' : False }
239+ ]
240+
241+ with open (yml_path , 'w' ) as f :
242+ yaml .dump (mentors , f )
243+
244+ update_mentor_availability (4 , xlsx_path , yml_path )
245+
246+ with open (yml_path , 'r' ) as f :
247+ result = yaml .load (f )
248+
249+ alice = result [0 ]
250+ assert alice ['hours' ] == 3
251+
252+ finally :
253+ os .remove (xlsx_path )
254+ os .remove (yml_path )
0 commit comments