@@ -2,12 +2,16 @@ import { expect } from "chai";
22import cleanDb from "../../utils/cleanDb" ;
33import * as impersonationModel from "../../../models/impersonationRequests" ;
44import { impersonationRequestsBodyData } from "../../fixtures/impersonation-requests/impersonationRequests" ;
5- import { REQUEST_STATE , ERROR_WHILE_CREATING_REQUEST } from "../../../constants/requests" ;
5+ import { REQUEST_STATE , ERROR_WHILE_CREATING_REQUEST , ERROR_WHILE_UPDATING_REQUEST } from "../../../constants/requests" ;
66import addUser from "../../utils/addUser" ;
77import userDataFixture from "../../fixtures/user/user" ;
88import sinon from "sinon" ;
9+ import { UpdateImpersonationRequestStatusBody , UpdateImpersonationRequestDataResponse } from "../../../types/impersonationRequest" ;
10+ import { Timestamp } from "firebase-admin/firestore" ;
11+ import firestore from "../../../utils/firestore" ;
912
10-
13+ const userData = userDataFixture ( ) ;
14+ const logger = require ( "../../../utils/logger" ) ;
1115
1216describe ( "models/impersonationRequests" , ( ) => {
1317 let impersonationRequest ;
@@ -26,7 +30,7 @@ describe("models/impersonationRequests", () => {
2630 await cleanDb ( ) ;
2731 } ) ;
2832
29- describe ( "createImpersonationRequest" , ( ) => {
33+ describe ( "createImpersonationRequest" , ( ) => {
3034 it ( "should create a new impersonation request" , async ( ) => {
3135 impersonationRequest = await impersonationModel . createImpersonationRequest ( mockRequestBody ) ;
3236 expect ( impersonationRequest ) . to . have . property ( "id" ) ;
@@ -39,7 +43,7 @@ describe("models/impersonationRequests", () => {
3943 } ) ;
4044
4145 it ( "should throw an error if there is an existing PENDING impersonation request" , async ( ) => {
42- await impersonationModel . createImpersonationRequest ( mockRequestBody ) ;
46+ await impersonationModel . createImpersonationRequest ( mockRequestBody ) ;
4347 try {
4448 await impersonationModel . createImpersonationRequest ( mockRequestBody ) ;
4549 } catch ( error ) {
@@ -48,8 +52,8 @@ describe("models/impersonationRequests", () => {
4852 } ) ;
4953
5054 it ( "should allow different super users to create requests for same user" , async ( ) => {
51- const request1 = await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , createdBy : "user1" } ) ;
52- const request2 = await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , createdBy : "user2" , userId :"122" } ) ;
55+ const request1 = await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , createdBy : "user1" } ) ;
56+ const request2 = await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , createdBy : "user2" , userId : "122" } ) ;
5357 expect ( request1 ) . to . have . property ( "id" ) ;
5458 expect ( request1 . createdBy ) . to . equal ( "user1" ) ;
5559 expect ( request1 . impersonatedUserId ) . to . equal ( impersonationRequestsBodyData [ 0 ] . impersonatedUserId ) ;
@@ -69,16 +73,16 @@ describe("models/impersonationRequests", () => {
6973 }
7074 } ) ;
7175
72- it ( "should throw forbidden error if an APPROVED request with isImpersonationFinished as false is present" , async ( ) => {
76+ it ( "should throw forbidden error if an APPROVED request with isImpersonationFinished as false is present" , async ( ) => {
7377 try {
74- await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , status :REQUEST_STATE . APPROVED } ) ;
78+ await impersonationModel . createImpersonationRequest ( { ...impersonationRequestsBodyData [ 0 ] , status : REQUEST_STATE . APPROVED } ) ;
7579 await impersonationModel . createImpersonationRequest ( impersonationRequestsBodyData [ 0 ] ) ;
7680 } catch ( error ) {
7781 expect ( error . message ) . to . include ( "You are not allowed for this Operation at the moment" ) ;
7882 }
79- } )
83+ } ) ;
8084 } ) ;
81-
85+
8286 describe ( "getImpersonationRequestById" , ( ) => {
8387 it ( "should return the impersonation request by id" , async ( ) => {
8488 const impersonationRequest = await impersonationModel . createImpersonationRequest ( impersonationRequestsBodyData [ 0 ] ) ;
@@ -206,4 +210,79 @@ describe("models/impersonationRequests", () => {
206210 }
207211 } ) ;
208212 } ) ;
213+
214+ describe ( "updateImpersonationRequest" , ( ) => {
215+ beforeEach ( async ( ) => {
216+ impersonationRequest = await impersonationModel . createImpersonationRequest ( impersonationRequestsBodyData [ 0 ] ) ;
217+ } ) ;
218+
219+ it ( "should approve an impersonation request" , async ( ) => {
220+ const updatedRequest = await impersonationModel . updateImpersonationRequest ( {
221+ id : impersonationRequest . id ,
222+ updatePayload : { status : "APPROVED" } ,
223+ lastModifiedBy : impersonationRequest . impersonatedUserId ,
224+ } ) as UpdateImpersonationRequestStatusBody ;
225+ expect ( updatedRequest . status ) . to . equal ( REQUEST_STATE . APPROVED ) ;
226+ } ) ;
227+
228+ it ( "should reject an impersonation request" , async ( ) => {
229+ const updatedRequest = await impersonationModel . updateImpersonationRequest ( {
230+ id : impersonationRequest . id ,
231+ updatePayload : { status : "REJECTED" } ,
232+ lastModifiedBy : impersonationRequest . impersonatedUserId ,
233+ } ) as UpdateImpersonationRequestStatusBody ;
234+ expect ( updatedRequest . status ) . to . equal ( REQUEST_STATE . REJECTED ) ;
235+ } ) ;
236+
237+ it ( "should change the startedAt,endedAt and isImpersonationFinished fields on update" , async ( ) => {
238+ const updatedBody = {
239+ isImpersonationFinished : true ,
240+ startedAt : Timestamp . fromDate ( new Date ( Date . now ( ) ) ) ,
241+ endedAt : Timestamp . fromDate ( new Date ( Date . now ( ) + 15 * 60 * 1000 ) ) ,
242+ } ;
243+ const updatedRequest = await impersonationModel . updateImpersonationRequest ( {
244+ id : impersonationRequest . id ,
245+ updatePayload : updatedBody ,
246+ lastModifiedBy : impersonationRequest . userId ,
247+ } ) as UpdateImpersonationRequestDataResponse ;
248+ expect ( updatedRequest . isImpersonationFinished ) . to . be . true ;
249+ expect ( Number ( updatedRequest . startedAt ) ) . to . be . greaterThan ( 0 ) ;
250+ expect ( Number ( updatedRequest . endedAt ) ) . to . be . greaterThan ( Number ( updatedRequest . startedAt ) ) ;
251+ } ) ;
252+
253+ it ( "should change updatedAt timestamp on update" , async ( ) => {
254+ const before = Number ( impersonationRequest . updatedAt ) ;
255+ const updatedRequest = await impersonationModel . updateImpersonationRequest ( {
256+ id : impersonationRequest . id ,
257+ updatePayload : { status : "APPROVED" } ,
258+ lastModifiedBy : impersonationRequest . impersonatedUserId ,
259+ } ) ;
260+ const result = await impersonationModel . getImpersonationRequestById ( impersonationRequest . id ) ;
261+ expect ( result ) . to . not . be . null ;
262+ expect ( Number ( result . updatedAt ) ) . to . be . greaterThan ( before ) ;
263+ } ) ;
264+
265+ it ( "should log and throw error if Firestore update fails in updateImpersonationRequest" , async ( ) => {
266+ const error = new Error ( ERROR_WHILE_UPDATING_REQUEST ) ;
267+ const loggerStub = sinon . stub ( logger , "error" ) ;
268+
269+ const docUpdateStub = sinon . stub ( ) . rejects ( error ) ;
270+ const docStub = sinon . stub ( ) . returns ( { update : docUpdateStub } ) ;
271+ const collectionStub = sinon . stub ( ) . returns ( { doc : docStub } ) ;
272+ sinon . stub ( firestore , "collection" ) . callsFake ( collectionStub ) ;
273+
274+ try {
275+ await impersonationModel . updateImpersonationRequest ( {
276+ id : "impersonationRequest.id" ,
277+ updatePayload : { status : "APPROVED" } ,
278+ lastModifiedBy : impersonationRequest . impersonatedUserId ,
279+ } ) ;
280+ expect . fail ( "Should throw error" ) ;
281+ } catch ( err ) {
282+ expect ( loggerStub . called ) . to . be . true ;
283+ expect ( loggerStub . firstCall . args [ 0 ] ) . to . include ( ERROR_WHILE_UPDATING_REQUEST ) ;
284+ expect ( loggerStub . firstCall . args [ 1 ] ) . to . equal ( err ) ;
285+ }
286+ } ) ;
287+ } ) ;
209288} ) ;
0 commit comments