1- // Integration tests for ScheduleController using SQLite in-memory database.
2- // Covers Student, Alumni, Facstaff, and Advisor schedule access scenarios.
3-
41using Gordon360 . Controllers ;
52using Gordon360 . Models . CCT . Context ;
6- using Gordon360 . Models . ViewModels ;
3+ using Gordon360 . Models . CCT ;
74using Gordon360 . Services ;
85using Microsoft . AspNetCore . Http ;
96using Microsoft . AspNetCore . Mvc ;
107using Microsoft . Data . Sqlite ;
118using Microsoft . EntityFrameworkCore ;
9+ using Microsoft . Extensions . Configuration ;
1210using System ;
1311using System . Collections . Generic ;
14- using System . Linq ;
1512using System . Security . Claims ;
1613using System . Threading . Tasks ;
1714using Xunit ;
18- using Microsoft . Extensions . Configuration ;
1915
2016namespace Gordon360 . Tests . Integration_Test ;
2117
@@ -34,35 +30,25 @@ public class ScheduleControllerIntegrationTest : IDisposable
3430
3531 public ScheduleControllerIntegrationTest ( )
3632 {
37- // Setup SQLite in-memory
3833 _connection = new SqliteConnection ( "DataSource=:memory:" ) ;
3934 _connection . Open ( ) ;
40-
4135 var options = new DbContextOptionsBuilder < CCTContext > ( )
4236 . UseSqlite ( _connection )
4337 . Options ;
44-
4538 _context = new CCTContext ( options ) ;
4639 _context . Database . EnsureCreated ( ) ;
47-
48- // Minimal configuration and webSQLContext for ProfileService
4940 var configBuilder = new ConfigurationBuilder ( ) ;
5041 _configuration = configBuilder . Build ( ) ;
5142 var webSQLOptions = new DbContextOptionsBuilder < Gordon360 . Models . webSQL . Context . webSQLContext > ( )
5243 . UseSqlite ( _connection )
5344 . Options ;
5445 _webSQLContext = new Gordon360 . Models . webSQL . Context . webSQLContext ( webSQLOptions ) ;
55-
56- // Seed minimal data for integration
5746 SeedTestData ( ) ;
58-
59- // Setup real services
6047 _sessionService = new SessionService ( _context ) ;
6148 _academicTermService = new AcademicTermService ( _context ) ;
6249 _scheduleService = new ScheduleService ( _context , _sessionService , _academicTermService ) ;
6350 _accountService = new AccountService ( _context ) ;
6451 _profileService = new ProfileService ( _context , _configuration , _accountService , _webSQLContext ) ;
65-
6652 _controller = new ScheduleController ( _profileService , _scheduleService , _accountService ) ;
6753 }
6854
@@ -83,16 +69,14 @@ private void SetUser(string username, string group)
8369
8470 private void SeedTestData ( )
8571 {
86- // Add a session
87- _context . CM_SESSION_MSTR . Add ( new Gordon360 . Models . CCT . CM_SESSION_MSTR
72+ _context . CM_SESSION_MSTR . Add ( new CM_SESSION_MSTR
8873 {
8974 SESS_CDE = "202401" ,
9075 SESS_DESC = "Spring 2024" ,
9176 SESS_BEGN_DTE = new DateTime ( 2024 , 1 , 10 ) ,
9277 SESS_END_DTE = new DateTime ( 2024 , 5 , 10 )
9378 } ) ;
94- // Add a term
95- _context . YearTermTable . Add ( new Gordon360 . Models . CCT . YearTermTable
79+ _context . YearTermTable . Add ( new YearTermTable
9680 {
9781 YR_CDE = "2024" ,
9882 TRM_CDE = "SP" ,
@@ -105,8 +89,7 @@ private void SeedTestData()
10589 APPROWVERSION = new byte [ ] { 1 } ,
10690 SHOW_ON_WEB = "Y"
10791 } ) ;
108- // Add user courses
109- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
92+ _context . UserCourses . Add ( new UserCourses
11093 {
11194 Username = "jdoe" ,
11295 Role = "Student" ,
@@ -128,297 +111,20 @@ private void SeedTestData()
128111 END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
129112 SUBTERM_DESC = "A"
130113 } ) ;
131- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
132- {
133- Username = "student2" ,
134- Role = "Student" ,
135- YR_CDE = "2024" ,
136- TRM_CDE = "SP" ,
137- CRS_CDE = "CS102" ,
138- CRS_TITLE = "Data Structures" ,
139- BLDG_CDE = "KEN" ,
140- ROOM_CDE = "102" ,
141- MONDAY_CDE = "Y" ,
142- TUESDAY_CDE = "Y" ,
143- WEDNESDAY_CDE = "N" ,
144- THURSDAY_CDE = "N" ,
145- FRIDAY_CDE = "Y" ,
146- SATURDAY_CDE = "N" ,
147- BEGIN_TIME = new TimeSpan ( 10 , 30 , 0 ) ,
148- END_TIME = new TimeSpan ( 11 , 45 , 0 ) ,
149- BEGIN_DATE = new DateTime ( 2024 , 1 , 10 ) ,
150- END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
151- SUBTERM_DESC = "A"
152- } ) ;
153- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
154- {
155- Username = "alum1" ,
156- Role = "Student" ,
157- YR_CDE = "2024" ,
158- TRM_CDE = "SP" ,
159- CRS_CDE = "HIST101" ,
160- CRS_TITLE = "World History" ,
161- BLDG_CDE = "HIS" ,
162- ROOM_CDE = "201" ,
163- MONDAY_CDE = "N" ,
164- TUESDAY_CDE = "Y" ,
165- WEDNESDAY_CDE = "N" ,
166- THURSDAY_CDE = "Y" ,
167- FRIDAY_CDE = "N" ,
168- SATURDAY_CDE = "N" ,
169- BEGIN_TIME = new TimeSpan ( 13 , 0 , 0 ) ,
170- END_TIME = new TimeSpan ( 14 , 15 , 0 ) ,
171- BEGIN_DATE = new DateTime ( 2024 , 1 , 10 ) ,
172- END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
173- SUBTERM_DESC = "A"
174- } ) ;
175- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
176- {
177- Username = "fac1" ,
178- Role = "Student" ,
179- YR_CDE = "2024" ,
180- TRM_CDE = "SP" ,
181- CRS_CDE = "ENG201" ,
182- CRS_TITLE = "English Lit" ,
183- BLDG_CDE = "ENG" ,
184- ROOM_CDE = "301" ,
185- MONDAY_CDE = "N" ,
186- TUESDAY_CDE = "N" ,
187- WEDNESDAY_CDE = "Y" ,
188- THURSDAY_CDE = "Y" ,
189- FRIDAY_CDE = "N" ,
190- SATURDAY_CDE = "N" ,
191- BEGIN_TIME = new TimeSpan ( 14 , 30 , 0 ) ,
192- END_TIME = new TimeSpan ( 15 , 45 , 0 ) ,
193- BEGIN_DATE = new DateTime ( 2024 , 1 , 10 ) ,
194- END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
195- SUBTERM_DESC = "A"
196- } ) ;
197- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
198- {
199- Username = "advisor1" ,
200- Role = "Student" ,
201- YR_CDE = "2024" ,
202- TRM_CDE = "SP" ,
203- CRS_CDE = "ADV101" ,
204- CRS_TITLE = "Advising 101" ,
205- BLDG_CDE = "ADV" ,
206- ROOM_CDE = "401" ,
207- MONDAY_CDE = "Y" ,
208- TUESDAY_CDE = "N" ,
209- WEDNESDAY_CDE = "Y" ,
210- THURSDAY_CDE = "N" ,
211- FRIDAY_CDE = "Y" ,
212- SATURDAY_CDE = "N" ,
213- BEGIN_TIME = new TimeSpan ( 8 , 0 , 0 ) ,
214- END_TIME = new TimeSpan ( 9 , 15 , 0 ) ,
215- BEGIN_DATE = new DateTime ( 2024 , 1 , 10 ) ,
216- END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
217- SUBTERM_DESC = "A"
218- } ) ;
219- _context . UserCourses . Add ( new Gordon360 . Models . CCT . UserCourses
220- {
221- Username = "hybrid1" ,
222- Role = "Instructor" ,
223- YR_CDE = "2024" ,
224- TRM_CDE = "SP" ,
225- CRS_CDE = "MATH301" ,
226- CRS_TITLE = "Advanced Math" ,
227- BLDG_CDE = "MAT" ,
228- ROOM_CDE = "501" ,
229- MONDAY_CDE = "Y" ,
230- TUESDAY_CDE = "Y" ,
231- WEDNESDAY_CDE = "Y" ,
232- THURSDAY_CDE = "Y" ,
233- FRIDAY_CDE = "Y" ,
234- SATURDAY_CDE = "N" ,
235- BEGIN_TIME = new TimeSpan ( 11 , 0 , 0 ) ,
236- END_TIME = new TimeSpan ( 12 , 15 , 0 ) ,
237- BEGIN_DATE = new DateTime ( 2024 , 1 , 10 ) ,
238- END_DATE = new DateTime ( 2024 , 5 , 10 ) ,
239- SUBTERM_DESC = "A"
240- } ) ;
241- // Add students
242- _context . Student . Add ( new Gordon360 . Models . CCT . Student { ID = "S1234567" , FirstName = "John" , LastName = "Doe" , AD_Username = "jdoe" } ) ;
243- _context . Student . Add ( new Gordon360 . Models . CCT . Student { ID = "S7654321" , FirstName = "Jane" , LastName = "Smith" , AD_Username = "student2" } ) ;
244- // Add alumni
245- _context . Alumni . Add ( new Gordon360 . Models . CCT . Alumni { ID = "A1111111" , FirstName = "Alice" , LastName = "Alumni" , AD_Username = "alum1" } ) ;
246- // Add facstaff
247- _context . FacStaff . Add ( new Gordon360 . Models . CCT . FacStaff { ID = "F2222222" , FirstName = "Frank" , LastName = "Faculty" , AD_Username = "fac1" } ) ;
248- _context . FacStaff . Add ( new Gordon360 . Models . CCT . FacStaff { ID = "F3333333" , FirstName = "Adrian" , LastName = "Advisor" , AD_Username = "advisor1" } ) ;
249- _context . FacStaff . Add ( new Gordon360 . Models . CCT . FacStaff { ID = "F4444444" , FirstName = "Hank" , LastName = "Hybrid" , AD_Username = "hybrid1" } ) ;
114+ _context . Student . Add ( new Student { ID = "S1234567" , FirstName = "John" , LastName = "Doe" , AD_Username = "jdoe" } ) ;
250115 _context . SaveChanges ( ) ;
251116 }
252117
253- // ===================== Student Cases =====================
254-
255- /// <summary>Student for self: should return their own course</summary>
256- [ Fact ]
257- public async Task Student_ForSelf_ReturnsCourse ( )
258- {
259- SetUser ( "jdoe" , "360-Student-SG" ) ;
260- var result = await _controller . GetAllCoursesByTerm ( "jdoe" ) ;
261- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
262- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
263- // Expect CS101 (jdoe's course)
264- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "CS101" ) ;
265- }
266-
267- /// <summary>Student for other student: should return empty</summary>
268- [ Fact ]
269- public async Task Student_ForOtherStudent_ReturnsEmpty ( )
270- {
271- SetUser ( "jdoe" , "360-Student-SG" ) ;
272- var result = await _controller . GetAllCoursesByTerm ( "student2" ) ;
273- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
274- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
275- Assert . Empty ( data . SelectMany ( t => t . AllCourses ) ) ;
276- }
277-
278- /// <summary>Student for alumni: should return empty</summary>
279- [ Fact ]
280- public async Task Student_ForAlumni_ReturnsEmpty ( )
281- {
282- SetUser ( "jdoe" , "360-Student-SG" ) ;
283- var result = await _controller . GetAllCoursesByTerm ( "alum1" ) ;
284- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
285- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
286- Assert . Empty ( data . SelectMany ( t => t . AllCourses ) ) ;
287- }
288-
289- /// <summary>Student for facstaff: should return facstaff's course</summary>
290- [ Fact ]
291- public async Task Student_ForFacstaff_ReturnsCourse ( )
292- {
293- SetUser ( "jdoe" , "360-Student-SG" ) ;
294- var result = await _controller . GetAllCoursesByTerm ( "fac1" ) ;
295- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
296- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
297- // Expect ENG201 (fac1's course)
298- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "ENG201" ) ;
299- }
300-
301- /// <summary>Student for (Student,Faculty): should return instructor course</summary>
302118 [ Fact ]
303- public async Task Student_ForHybrid_ReturnsInstructorCourse ( )
119+ public async Task GetAllCoursesByTerm_ReturnsCourses_ForSelf ( )
304120 {
305121 SetUser ( "jdoe" , "360-Student-SG" ) ;
306- var result = await _controller . GetAllCoursesByTerm ( "hybrid1" ) ;
307- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
308- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
309- // Expect MATH301 (hybrid1's instructor course)
310- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "MATH301" && c . Role == "Instructor" ) ;
311- }
312-
313- // ===================== Alumni Cases =====================
314-
315- /// <summary>Alumni for other alumni: should return empty</summary>
316- [ Fact ]
317- public async Task Alumni_ForOtherAlumni_ReturnsEmpty ( )
318- {
319- SetUser ( "alum1" , "360-Alumni-SG" ) ;
320- // Self: expect HIST101
321- var result = await _controller . GetAllCoursesByTerm ( "alum1" ) ;
322- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
323- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
324- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "HIST101" ) ;
325- // Other alumni (not seeded, so should be empty)
326- result = await _controller . GetAllCoursesByTerm ( "alum2" ) ;
327- ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
328- data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
329- Assert . Empty ( data . SelectMany ( t => t . AllCourses ) ) ;
330- }
331-
332- /// <summary>Alumni for facstaff: should return facstaff's course</summary>
333- [ Fact ]
334- public async Task Alumni_ForFacstaff_ReturnsCourse ( )
335- {
336- SetUser ( "alum1" , "360-Alumni-SG" ) ;
337- var result = await _controller . GetAllCoursesByTerm ( "fac1" ) ;
338- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
339- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
340- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "ENG201" ) ;
341- }
342-
343- /// <summary>Alumni for self: should return their own course</summary>
344- [ Fact ]
345- public async Task Alumni_ForSelf_ReturnsCourse ( )
346- {
347- SetUser ( "alum1" , "360-Alumni-SG" ) ;
348- var result = await _controller . GetAllCoursesByTerm ( "alum1" ) ;
349- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
350- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
351- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "HIST101" ) ;
352- }
353-
354- /// <summary>Alumni for (Student,Faculty): should return instructor course</summary>
355- [ Fact ]
356- public async Task Alumni_ForHybrid_ReturnsInstructorCourse ( )
357- {
358- SetUser ( "alum1" , "360-Alumni-SG" ) ;
359- var result = await _controller . GetAllCoursesByTerm ( "hybrid1" ) ;
360- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
361- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
362- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "MATH301" && c . Role == "Instructor" ) ;
363- }
364-
365- // ===================== Facstaff/Advisor Cases =====================
366-
367- /// <summary>Facstaff for student: should return empty</summary>
368- [ Fact ]
369- public async Task Facstaff_ForStudent_ReturnsEmpty ( )
370- {
371- SetUser ( "fac1" , "360-FacStaff-SG" ) ;
372122 var result = await _controller . GetAllCoursesByTerm ( "jdoe" ) ;
373123 var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
374- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
375- Assert . Empty ( data . SelectMany ( t => t . AllCourses ) ) ;
376- }
377-
378- /// <summary>Advisor for student: should return student's course</summary>
379- [ Fact ]
380- public async Task Advisor_ForStudent_ReturnsCourse ( )
381- {
382- SetUser ( "advisor1" , "360-FacStaff-SG,360-Advisor-SG" ) ;
383- var result = await _controller . GetAllCoursesByTerm ( "jdoe" ) ;
384- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
385- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
124+ var data = Assert . IsAssignableFrom < IEnumerable < Gordon360 . Models . ViewModels . CoursesByTermViewModel > > ( ok . Value ) ;
386125 Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "CS101" ) ;
387126 }
388127
389- /// <summary>Facstaff for self: should return their own course</summary>
390- [ Fact ]
391- public async Task Facstaff_ForSelf_ReturnsCourse ( )
392- {
393- SetUser ( "fac1" , "360-FacStaff-SG" ) ;
394- var result = await _controller . GetAllCoursesByTerm ( "fac1" ) ;
395- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
396- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
397- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "ENG201" ) ;
398- }
399-
400- /// <summary>Advisor for self: should return their own course</summary>
401- [ Fact ]
402- public async Task Advisor_ForSelf_ReturnsCourse ( )
403- {
404- SetUser ( "advisor1" , "360-FacStaff-SG,360-Advisor-SG" ) ;
405- var result = await _controller . GetAllCoursesByTerm ( "advisor1" ) ;
406- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
407- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
408- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "ADV101" ) ;
409- }
410-
411- /// <summary>Facstaff for alumni: should return alumni's course</summary>
412- [ Fact ]
413- public async Task Facstaff_ForAlumni_ReturnsCourse ( )
414- {
415- SetUser ( "fac1" , "360-FacStaff-SG" ) ;
416- var result = await _controller . GetAllCoursesByTerm ( "alum1" ) ;
417- var ok = Assert . IsType < OkObjectResult > ( result . Result ) ;
418- var data = Assert . IsAssignableFrom < IEnumerable < CoursesByTermViewModel > > ( ok . Value ) ;
419- Assert . Contains ( data . SelectMany ( t => t . AllCourses ) , c => c . CRS_CDE == "HIST101" ) ;
420- }
421-
422128 public void Dispose ( )
423129 {
424130 _context . Dispose ( ) ;
0 commit comments