@@ -10,10 +10,10 @@ import {
10
10
addQuestion ,
11
11
updateQuestion ,
12
12
deleteQuestion ,
13
+ deleteQuestions ,
13
14
} from '../../src/controllers/questionController' ;
14
15
import { Question } from '../../src/models/questionModel' ;
15
16
import * as seq from '../../src/utils/sequence' ;
16
- import { getNextSequenceValue } from '../../src/utils/sequence' ;
17
17
18
18
chai . use ( sinonChai ) ;
19
19
@@ -810,3 +810,326 @@ describe('addQuestion', () => {
810
810
} ) ;
811
811
} ) ;
812
812
} ) ;
813
+
814
+ // Testing function updateQuestion
815
+ describe ( 'updateQuestion' , ( ) => {
816
+ let req : Partial < Request > ;
817
+ let res : Partial < Response > ;
818
+ let findOneStub : SinonStub ;
819
+ let findOneAndUpdateStub : SinonStub ;
820
+ let collationStub : SinonStub ;
821
+
822
+ beforeEach ( ( ) => {
823
+ req = {
824
+ params : { } ,
825
+ body : { } ,
826
+ } ;
827
+ res = {
828
+ status : sinon . stub ( ) . returnsThis ( ) ,
829
+ json : sinon . stub ( ) ,
830
+ } ;
831
+ findOneStub = sinon . stub ( Question , 'findOne' ) ;
832
+ findOneAndUpdateStub = sinon . stub ( Question , 'findOneAndUpdate' ) ;
833
+ collationStub = sinon . stub ( ) . returnsThis ( ) ;
834
+ findOneStub . returns ( { collation : collationStub } ) ;
835
+ } ) ;
836
+
837
+ afterEach ( ( ) => {
838
+ sinon . restore ( ) ;
839
+ } ) ;
840
+
841
+ it ( 'should update a question successfully' , async ( ) => {
842
+ req . params = { id : '1' } ;
843
+ req . body = {
844
+ title : 'Updated Title' ,
845
+ description : 'Updated Description' ,
846
+ topics : [ 'topic1' ] ,
847
+ difficulty : 'medium' ,
848
+ } ;
849
+
850
+ collationStub . resolves ( null ) ;
851
+ findOneAndUpdateStub . resolves ( {
852
+ id : 1 ,
853
+ title : 'Updated Title' ,
854
+ description : 'Updated Description' ,
855
+ topics : [ 'topic1' ] ,
856
+ difficulty : 'medium' ,
857
+ } ) ;
858
+
859
+ await updateQuestion ( req as Request , res as Response ) ;
860
+
861
+ expect ( findOneStub ) . to . have . been . calledWith ( {
862
+ $and : [ { $or : [ { title : 'Updated Title' } , { description : 'Updated Description' } ] } , { id : { $ne : 1 } } ] ,
863
+ } ) ;
864
+ expect ( findOneAndUpdateStub ) . to . have . been . calledWith (
865
+ { id : 1 } ,
866
+ { title : 'Updated Title' , description : 'Updated Description' , topics : [ 'topic1' ] , difficulty : 'medium' } ,
867
+ { new : true , runValidators : true } ,
868
+ ) ;
869
+ expect ( res . status ) . to . have . been . calledWith ( 200 ) ;
870
+ expect ( res . json ) . to . have . been . calledWith ( {
871
+ status : 'Success' ,
872
+ message : 'Question updated successfully' ,
873
+ data : {
874
+ id : 1 ,
875
+ title : 'Updated Title' ,
876
+ description : 'Updated Description' ,
877
+ topics : [ 'topic1' ] ,
878
+ difficulty : 'medium' ,
879
+ } ,
880
+ } ) ;
881
+ } ) ;
882
+
883
+ it ( 'should return bad request if ID is in updates' , async ( ) => {
884
+ req . params = { id : '1' } ;
885
+ req . body = { id : '2' , title : 'Updated Title' } ;
886
+
887
+ await updateQuestion ( req as Request , res as Response ) ;
888
+
889
+ expect ( res . status ) . to . have . been . calledWith ( 400 ) ;
890
+ expect ( res . json ) . to . have . been . calledWith ( {
891
+ status : 'Error' ,
892
+ message : 'ID cannot be updated' ,
893
+ } ) ;
894
+ } ) ;
895
+
896
+ it ( 'should return bad request if a question with the same title or description exists' , async ( ) => {
897
+ req . params = { id : '1' } ;
898
+ req . body = { title : 'Existing Title' , description : 'Updated Description' } ;
899
+
900
+ collationStub . resolves ( {
901
+ id : 2 ,
902
+ title : 'Existing Title' ,
903
+ description : 'Existing Description' ,
904
+ } ) ;
905
+
906
+ await updateQuestion ( req as Request , res as Response ) ;
907
+
908
+ expect ( findOneStub ) . to . have . been . calledWith ( {
909
+ $and : [ { $or : [ { title : 'Existing Title' } , { description : 'Updated Description' } ] } , { id : { $ne : 1 } } ] ,
910
+ } ) ;
911
+ expect ( res . status ) . to . have . been . calledWith ( 400 ) ;
912
+ expect ( res . json ) . to . have . been . calledWith ( {
913
+ status : 'Error' ,
914
+ message : 'A question with the same title or description already exists.' ,
915
+ } ) ;
916
+ } ) ;
917
+
918
+ it ( 'should return not found if the question does not exist' , async ( ) => {
919
+ req . params = { id : '1' } ;
920
+ req . body = { title : 'Updated Title' , description : 'Updated Description' } ;
921
+
922
+ collationStub . resolves ( null ) ;
923
+ findOneAndUpdateStub . resolves ( null ) ;
924
+
925
+ await updateQuestion ( req as Request , res as Response ) ;
926
+
927
+ expect ( findOneAndUpdateStub ) . to . have . been . calledWith (
928
+ { id : 1 } ,
929
+ { title : 'Updated Title' , description : 'Updated Description' } ,
930
+ { new : true , runValidators : true } ,
931
+ ) ;
932
+ expect ( res . status ) . to . have . been . calledWith ( 404 ) ;
933
+ expect ( res . json ) . to . have . been . calledWith ( {
934
+ status : 'Error' ,
935
+ message : 'Question not found' ,
936
+ } ) ;
937
+ } ) ;
938
+
939
+ it ( 'should handle errors during the update process' , async ( ) => {
940
+ req . params = { id : '1' } ;
941
+ req . body = { title : 'Updated Title' , description : 'Updated Description' } ;
942
+
943
+ const error = new Error ( 'Database error' ) ;
944
+ findOneStub . rejects ( error ) ;
945
+
946
+ await updateQuestion ( req as Request , res as Response ) ;
947
+
948
+ expect ( findOneStub ) . to . have . been . calledWith ( {
949
+ $and : [ { $or : [ { title : 'Updated Title' } , { description : 'Updated Description' } ] } , { id : { $ne : 1 } } ] ,
950
+ } ) ;
951
+ expect ( res . status ) . to . have . been . calledWith ( 500 ) ;
952
+ expect ( res . json ) . to . have . been . calledWith ( {
953
+ status : 'Error' ,
954
+ message : 'Failed to update question' ,
955
+ } ) ;
956
+ } ) ;
957
+ } ) ;
958
+
959
+ // Testing function deleteQuestion
960
+ describe ( 'deleteQuestion' , ( ) => {
961
+ let req : Partial < Request > ;
962
+ let res : Partial < Response > ;
963
+ let findOneAndDeleteStub : SinonStub ;
964
+
965
+ beforeEach ( ( ) => {
966
+ req = {
967
+ params : { } ,
968
+ } ;
969
+ res = {
970
+ status : sinon . stub ( ) . returnsThis ( ) ,
971
+ json : sinon . stub ( ) ,
972
+ } ;
973
+ findOneAndDeleteStub = sinon . stub ( Question , 'findOneAndDelete' ) ;
974
+ } ) ;
975
+
976
+ afterEach ( ( ) => {
977
+ sinon . restore ( ) ;
978
+ } ) ;
979
+
980
+ it ( 'should delete a question successfully' , async ( ) => {
981
+ req . params = { id : '1' } ;
982
+
983
+ findOneAndDeleteStub . resolves ( {
984
+ id : 1 ,
985
+ title : 'Question 1' ,
986
+ description : 'Description 1' ,
987
+ topics : [ 'topic1' ] ,
988
+ difficulty : 'easy' ,
989
+ } ) ;
990
+
991
+ await deleteQuestion ( req as Request , res as Response ) ;
992
+
993
+ expect ( findOneAndDeleteStub ) . to . have . been . calledWith ( { id : 1 } ) ;
994
+ expect ( res . status ) . to . have . been . calledWith ( 200 ) ;
995
+ expect ( res . json ) . to . have . been . calledWith ( {
996
+ status : 'Success' ,
997
+ message : 'Question deleted successfully' ,
998
+ data : {
999
+ id : 1 ,
1000
+ title : 'Question 1' ,
1001
+ description : 'Description 1' ,
1002
+ topics : [ 'topic1' ] ,
1003
+ difficulty : 'easy' ,
1004
+ } ,
1005
+ } ) ;
1006
+ } ) ;
1007
+
1008
+ it ( 'should return not found if the question does not exist' , async ( ) => {
1009
+ req . params = { id : '1' } ;
1010
+
1011
+ findOneAndDeleteStub . resolves ( null ) ;
1012
+
1013
+ await deleteQuestion ( req as Request , res as Response ) ;
1014
+
1015
+ expect ( findOneAndDeleteStub ) . to . have . been . calledWith ( { id : 1 } ) ;
1016
+ expect ( res . status ) . to . have . been . calledWith ( 404 ) ;
1017
+ expect ( res . json ) . to . have . been . calledWith ( {
1018
+ status : 'Error' ,
1019
+ message : 'Question not found' ,
1020
+ } ) ;
1021
+ } ) ;
1022
+
1023
+ it ( 'should handle errors during the deletion process' , async ( ) => {
1024
+ req . params = { id : '1' } ;
1025
+
1026
+ const error = new Error ( 'Database error' ) ;
1027
+ findOneAndDeleteStub . rejects ( error ) ;
1028
+
1029
+ await deleteQuestion ( req as Request , res as Response ) ;
1030
+
1031
+ expect ( findOneAndDeleteStub ) . to . have . been . calledWith ( { id : 1 } ) ;
1032
+ expect ( res . status ) . to . have . been . calledWith ( 500 ) ;
1033
+ expect ( res . json ) . to . have . been . calledWith ( {
1034
+ status : 'Error' ,
1035
+ message : 'Failed to delete question' ,
1036
+ } ) ;
1037
+ } ) ;
1038
+ } ) ;
1039
+
1040
+ // Testing function deleteQuestions
1041
+ describe ( 'deleteQuestions' , ( ) => {
1042
+ let req : Partial < Request > ;
1043
+ let res : Partial < Response > ;
1044
+ let countDocumentsStub : SinonStub ;
1045
+ let deleteManyStub : SinonStub ;
1046
+
1047
+ beforeEach ( ( ) => {
1048
+ req = {
1049
+ body : { } ,
1050
+ } ;
1051
+ res = {
1052
+ status : sinon . stub ( ) . returnsThis ( ) ,
1053
+ json : sinon . stub ( ) ,
1054
+ } ;
1055
+ countDocumentsStub = sinon . stub ( Question , 'countDocuments' ) ;
1056
+ deleteManyStub = sinon . stub ( Question , 'deleteMany' ) ;
1057
+ } ) ;
1058
+
1059
+ afterEach ( ( ) => {
1060
+ sinon . restore ( ) ;
1061
+ } ) ;
1062
+
1063
+ it ( 'should delete multiple questions successfully' , async ( ) => {
1064
+ req . body = { ids : [ '1' , '2' , '3' ] } ;
1065
+
1066
+ countDocumentsStub . resolves ( 3 ) ;
1067
+ deleteManyStub . resolves ( { deletedCount : 3 } ) ;
1068
+
1069
+ await deleteQuestions ( req as Request , res as Response ) ;
1070
+
1071
+ expect ( countDocumentsStub ) . to . have . been . calledWith ( { id : { $in : [ 1 , 2 , 3 ] } } ) ;
1072
+ expect ( deleteManyStub ) . to . have . been . calledWith ( { id : { $in : [ 1 , 2 , 3 ] } } ) ;
1073
+ expect ( res . status ) . to . have . been . calledWith ( 200 ) ;
1074
+ expect ( res . json ) . to . have . been . calledWith ( {
1075
+ status : 'Success' ,
1076
+ message : 'Questions deleted successfully' ,
1077
+ data : null ,
1078
+ } ) ;
1079
+ } ) ;
1080
+
1081
+ it ( 'should return bad request if IDs are missing or not an array' , async ( ) => {
1082
+ req . body = { ids : '1,2,3' } ;
1083
+
1084
+ await deleteQuestions ( req as Request , res as Response ) ;
1085
+
1086
+ expect ( res . status ) . to . have . been . calledWith ( 400 ) ;
1087
+ expect ( res . json ) . to . have . been . calledWith ( {
1088
+ status : 'Error' ,
1089
+ message : 'IDs are missing or not specified as an array' ,
1090
+ } ) ;
1091
+ } ) ;
1092
+
1093
+ it ( 'should return bad request if any ID is invalid' , async ( ) => {
1094
+ req . body = { ids : [ '1' , 'invalid' , '3' ] } ;
1095
+
1096
+ await deleteQuestions ( req as Request , res as Response ) ;
1097
+
1098
+ expect ( res . status ) . to . have . been . calledWith ( 400 ) ;
1099
+ expect ( res . json ) . to . have . been . calledWith ( {
1100
+ status : 'Error' ,
1101
+ message : 'Invalid question ID' ,
1102
+ } ) ;
1103
+ } ) ;
1104
+
1105
+ it ( 'should return not found if some questions do not exist' , async ( ) => {
1106
+ req . body = { ids : [ '1' , '2' , '3' ] } ;
1107
+
1108
+ countDocumentsStub . resolves ( 2 ) ;
1109
+
1110
+ await deleteQuestions ( req as Request , res as Response ) ;
1111
+
1112
+ expect ( countDocumentsStub ) . to . have . been . calledWith ( { id : { $in : [ 1 , 2 , 3 ] } } ) ;
1113
+ expect ( res . status ) . to . have . been . calledWith ( 404 ) ;
1114
+ expect ( res . json ) . to . have . been . calledWith ( {
1115
+ status : 'Error' ,
1116
+ message : 'Question not found' ,
1117
+ } ) ;
1118
+ } ) ;
1119
+
1120
+ it ( 'should handle errors during the deletion process' , async ( ) => {
1121
+ req . body = { ids : [ '1' , '2' , '3' ] } ;
1122
+
1123
+ const error = new Error ( 'Database error' ) ;
1124
+ countDocumentsStub . rejects ( error ) ;
1125
+
1126
+ await deleteQuestions ( req as Request , res as Response ) ;
1127
+
1128
+ expect ( countDocumentsStub ) . to . have . been . calledWith ( { id : { $in : [ 1 , 2 , 3 ] } } ) ;
1129
+ expect ( res . status ) . to . have . been . calledWith ( 500 ) ;
1130
+ expect ( res . json ) . to . have . been . calledWith ( {
1131
+ status : 'Error' ,
1132
+ message : 'Failed to delete questions' ,
1133
+ } ) ;
1134
+ } ) ;
1135
+ } ) ;
0 commit comments