11import { NotFoundException } from '@nestjs/common' ;
22import { DateTime } from 'luxon' ;
33import { AttendanceState } from 'shared/model/Attendance' ;
4- import { IStudent , StudentStatus } from 'shared/model/Student' ;
4+ import { ICreateStudentsDTO , IStudent , IStudentDTO , StudentStatus } from 'shared/model/Student' ;
55import { sortListById } from '../../../test/helpers/test.helpers' ;
66import { TestSuite } from '../../../test/helpers/TestSuite' ;
77import {
@@ -15,6 +15,7 @@ import {
1515 AttendanceDTO ,
1616 CakeCountDTO ,
1717 CreateStudentDTO ,
18+ CreateStudentsDTO ,
1819 PresentationPointsDTO ,
1920} from './student.dto' ;
2021import { StudentModule } from './student.module' ;
@@ -36,6 +37,17 @@ interface AssertStudentDTOParams {
3637 oldStudent ?: IStudent ;
3738}
3839
40+ interface AssertGeneratedStudentsParams {
41+ expected : CreateStudentsDTO ;
42+ actual : IStudent [ ] ;
43+ }
44+
45+ interface AssertGenerateStudentDTOParams {
46+ expected : IStudentDTO ;
47+ expectedTutorial : string ;
48+ actual : IStudent ;
49+ }
50+
3951function assertStudentBasics ( { expected, actual } : AssertStudentParams ) {
4052 expect ( actual . firstname ) . toEqual ( expected . firstname ) ;
4153 expect ( actual . lastname ) . toEqual ( expected . lastname ) ;
@@ -157,6 +169,71 @@ function assertStudentDTO({ expected, actual, oldStudent }: AssertStudentDTOPara
157169 }
158170}
159171
172+ /**
173+ * Checks if the two given lists match.
174+ * Requires that each student has a unique matriculation number to define equivalent students.
175+ *
176+ * Matching is defined as:
177+ * - Both lists have the same length.
178+ * - Each DTO has a corresponding student which got created using it's information.
179+ *
180+ * @param expected List containing the DTO holding the information of the students which should have been created.
181+ * @param actual List of actually generated students.
182+ */
183+ function assertGeneratedStudents ( { expected, actual } : AssertGeneratedStudentsParams ) {
184+ expect ( actual . length ) . toBe ( expected . students . length ) ;
185+
186+ for ( const { ...dto } of expected . students ) {
187+ const idx = actual . findIndex ( ( u ) => u . matriculationNo === dto . matriculationNo ) ;
188+ const user = actual [ idx ] ;
189+
190+ expect ( idx ) . not . toBe ( - 1 ) ;
191+ assertGenerateStudentDTO ( {
192+ expected : dto ,
193+ expectedTutorial : expected . tutorial ,
194+ actual : user ,
195+ } ) ;
196+ }
197+ }
198+
199+ /**
200+ * Compares the given actual student with the expected one.
201+ *
202+ * This function will assert that `gradings` and `attendances` are empty and `cakeCount` is 0.
203+ *
204+ * All other properties are just being compared with the following two exceptions:
205+ * - `id` must only be defined and is not compared to an expected value.
206+ * - For the `tutorial` only the `id` property gets asserted to match the expected tutorial.
207+ * - The `team` is not compared.
208+ *
209+ * @param params Must contain the expected StudentDocument and the actual Student. Can also include the old version of the Student.
210+ */
211+ function assertGenerateStudentDTO ( {
212+ expected,
213+ actual,
214+ expectedTutorial,
215+ } : AssertGenerateStudentDTOParams ) {
216+ const { team, ...restExpected } = expected ;
217+ const {
218+ id,
219+ attendances,
220+ tutorial : actualTutorial ,
221+ presentationPoints,
222+ cakeCount,
223+ team : actualTeam ,
224+ ...restActual
225+ } = actual ;
226+
227+ expect ( id ) . toBeDefined ( ) ;
228+ expect ( restActual ) . toEqual ( restExpected ) ;
229+
230+ expect ( actualTutorial . id ) . toEqual ( expectedTutorial ) ;
231+
232+ expect ( attendances ) . toEqual ( [ ] ) ;
233+ expect ( presentationPoints ) . toEqual ( [ ] ) ;
234+ expect ( cakeCount ) . toBe ( 0 ) ;
235+ }
236+
160237describe ( 'StudentService' , ( ) => {
161238 const suite = new TestSuite ( StudentService , StudentModule ) ;
162239
@@ -504,4 +581,151 @@ describe('StudentService', () => {
504581
505582 expect ( updatedStudent . cakeCount ) . toBe ( cakeCountDTO . cakeCount ) ;
506583 } ) ;
584+
585+ it ( 'create multiple students without team' , async ( ) => {
586+ const expectedTutorial = MOCKED_TUTORIALS [ 0 ] ;
587+ const studentsToCreate : CreateStudentsDTO = {
588+ tutorial : expectedTutorial . id ,
589+ students : [
590+ {
591+ firstname : 'Ginny' ,
592+ lastname : 'Weasley' ,
593+ iliasName : 'GinnyWeasley' ,
594+ status : StudentStatus . ACTIVE ,
595+ courseOfStudies : 'Computer science B. Sc.' ,
596+ email : 'weasley_ginny@hogwarts.com' ,
597+ matriculationNo : '111111' ,
598+ team : undefined ,
599+ } ,
600+ {
601+ firstname : 'Harry' ,
602+ lastname : 'Potter' ,
603+ iliasName : 'HarryPotter' ,
604+ status : StudentStatus . INACTIVE ,
605+ courseOfStudies : 'Data science' ,
606+ email : 'potter_harry@hogwarts.com' ,
607+ matriculationNo : '111112' ,
608+ team : undefined ,
609+ } ,
610+ ] ,
611+ } ;
612+
613+ const created = await suite . service . createMany ( studentsToCreate ) ;
614+
615+ assertGeneratedStudents ( { expected : studentsToCreate , actual : created } ) ;
616+
617+ expect ( created [ 0 ] . team ) . toBe ( undefined ) ;
618+ expect ( created [ 1 ] . team ) . toBe ( undefined ) ;
619+ } ) ;
620+
621+ it ( 'create multiple students in same new team' , async ( ) => {
622+ const expectedTutorial = MOCKED_TUTORIALS [ 0 ] ;
623+ const studentsToCreate : CreateStudentsDTO = {
624+ tutorial : expectedTutorial . id ,
625+ students : [
626+ {
627+ firstname : 'Ginny' ,
628+ lastname : 'Weasley' ,
629+ iliasName : 'GinnyWeasley' ,
630+ status : StudentStatus . ACTIVE ,
631+ courseOfStudies : 'Computer science B. Sc.' ,
632+ email : 'weasley_ginny@hogwarts.com' ,
633+ matriculationNo : '111111' ,
634+ team : 'a' ,
635+ } ,
636+ {
637+ firstname : 'Harry' ,
638+ lastname : 'Potter' ,
639+ iliasName : 'HarryPotter' ,
640+ status : StudentStatus . INACTIVE ,
641+ courseOfStudies : 'Data science' ,
642+ email : 'potter_harry@hogwarts.com' ,
643+ matriculationNo : '111112' ,
644+ team : 'a' ,
645+ } ,
646+ ] ,
647+ } ;
648+
649+ const created = await suite . service . createMany ( studentsToCreate ) ;
650+
651+ assertGeneratedStudents ( { expected : studentsToCreate , actual : created } ) ;
652+
653+ expect ( created [ 0 ] . team ) . toBeDefined ( ) ;
654+ expect ( created [ 0 ] . team ?. teamNo ) . toBe ( MOCKED_TEAMS . length + 1 ) ;
655+ expect ( created [ 0 ] . team ?. id ) . toBe ( created [ 1 ] . team ?. id ) ;
656+ } ) ;
657+
658+ it ( 'create multiple students in same different new teams' , async ( ) => {
659+ const expectedTutorial = MOCKED_TUTORIALS [ 0 ] ;
660+ const studentsToCreate : CreateStudentsDTO = {
661+ tutorial : expectedTutorial . id ,
662+ students : [
663+ {
664+ firstname : 'Ginny' ,
665+ lastname : 'Weasley' ,
666+ iliasName : 'GinnyWeasley' ,
667+ status : StudentStatus . ACTIVE ,
668+ courseOfStudies : 'Computer science B. Sc.' ,
669+ email : 'weasley_ginny@hogwarts.com' ,
670+ matriculationNo : '111111' ,
671+ team : 'a' ,
672+ } ,
673+ {
674+ firstname : 'Harry' ,
675+ lastname : 'Potter' ,
676+ iliasName : 'HarryPotter' ,
677+ status : StudentStatus . INACTIVE ,
678+ courseOfStudies : 'Data science' ,
679+ email : 'potter_harry@hogwarts.com' ,
680+ matriculationNo : '111112' ,
681+ team : 'b' ,
682+ } ,
683+ ] ,
684+ } ;
685+
686+ const created = await suite . service . createMany ( studentsToCreate ) ;
687+
688+ assertGeneratedStudents ( { expected : studentsToCreate , actual : created } ) ;
689+
690+ expect ( created [ 0 ] . team ) . toBeDefined ( ) ;
691+ expect ( created [ 1 ] . team ) . toBeDefined ( ) ;
692+ expect ( created [ 0 ] . team ?. id == created [ 1 ] . team ?. id ) . toBeFalsy ( ) ;
693+ } ) ;
694+
695+ it ( 'create multiple students in same existing team' , async ( ) => {
696+ const expectedTutorial = MOCKED_TUTORIALS [ 0 ] ;
697+ const expectedTeam = MOCKED_TEAMS [ 0 ] ;
698+ const studentsToCreate : CreateStudentsDTO = {
699+ tutorial : expectedTutorial . id ,
700+ students : [
701+ {
702+ firstname : 'Ginny' ,
703+ lastname : 'Weasley' ,
704+ iliasName : 'GinnyWeasley' ,
705+ status : StudentStatus . ACTIVE ,
706+ courseOfStudies : 'Computer science B. Sc.' ,
707+ email : 'weasley_ginny@hogwarts.com' ,
708+ matriculationNo : '111111' ,
709+ team : expectedTeam . teamNo . toString ( ) ,
710+ } ,
711+ {
712+ firstname : 'Harry' ,
713+ lastname : 'Potter' ,
714+ iliasName : 'HarryPotter' ,
715+ status : StudentStatus . INACTIVE ,
716+ courseOfStudies : 'Data science' ,
717+ email : 'potter_harry@hogwarts.com' ,
718+ matriculationNo : '111112' ,
719+ team : expectedTeam . teamNo . toString ( ) ,
720+ } ,
721+ ] ,
722+ } ;
723+
724+ const created = await suite . service . createMany ( studentsToCreate ) ;
725+
726+ assertGeneratedStudents ( { expected : studentsToCreate , actual : created } ) ;
727+
728+ expect ( created [ 0 ] . team ?. id ) . toBe ( expectedTeam . id ) ;
729+ expect ( created [ 1 ] . team ?. id ) . toBe ( expectedTeam . id ) ;
730+ } ) ;
507731} ) ;
0 commit comments