@@ -35,6 +35,16 @@ jest.mock('@urbackend/common', () => {
3535 Developer . findById = jest . fn ( ) ;
3636 Developer . findByIdAndDelete = jest . fn ( ) ;
3737
38+ // Helper to mock a Mongoose query that is both chainable (select) and thenable
39+ Developer . __mockQuery = ( value ) => {
40+ const query = {
41+ select : jest . fn ( ) . mockReturnThis ( ) ,
42+ then : ( resolve , reject ) => Promise . resolve ( value ) . then ( resolve , reject ) ,
43+ catch : ( reject ) => Promise . resolve ( value ) . catch ( reject ) ,
44+ } ;
45+ return query ;
46+ } ;
47+
3848 const Otp = jest . fn ( ) . mockImplementation ( ( data ) => ( {
3949 ...data ,
4050 save : jest . fn ( ) . mockResolvedValue ( undefined ) ,
@@ -177,7 +187,7 @@ describe('auth.controller', () => {
177187
178188 test ( 'returns 200 with cookie tokens on valid credentials' , async ( ) => {
179189 const user = mockUser ( ) ;
180- Developer . findOne . mockResolvedValue ( user ) ;
190+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( user ) ) ;
181191 bcrypt . compare . mockResolvedValue ( true ) ;
182192 jwt . sign . mockReturnValue ( 'signed_token' ) ;
183193
@@ -196,7 +206,7 @@ describe('auth.controller', () => {
196206 } ) ;
197207
198208 test ( 'returns 400 when user is not found' , async ( ) => {
199- Developer . findOne . mockResolvedValue ( null ) ;
209+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( null ) ) ;
200210
201211 const req = makeReq ( { email : 'noone@example.com' , password : 'pass' } ) ;
202212 const res = makeRes ( ) ;
@@ -208,7 +218,7 @@ describe('auth.controller', () => {
208218 } ) ;
209219
210220 test ( 'returns 400 on invalid password' , async ( ) => {
211- Developer . findOne . mockResolvedValue ( mockUser ( ) ) ;
221+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( mockUser ( ) ) ) ;
212222 bcrypt . compare . mockResolvedValue ( false ) ;
213223
214224 const req = makeReq ( { email : 'test@example.com' , password : 'wrongpass' } ) ;
@@ -245,7 +255,7 @@ describe('auth.controller', () => {
245255 test ( 'returns 200 with new tokens when refresh token is valid' , async ( ) => {
246256 const user = mockUser ( ) ;
247257 jwt . verify . mockReturnValue ( { _id : 'dev_id_1' } ) ;
248- Developer . findById . mockResolvedValue ( user ) ;
258+ Developer . findById . mockReturnValue ( Developer . __mockQuery ( user ) ) ;
249259 jwt . sign . mockReturnValue ( 'new_token' ) ;
250260
251261 const req = makeReq ( { } , null , { refreshToken : 'valid_refresh_token' } ) ;
@@ -280,7 +290,7 @@ describe('auth.controller', () => {
280290
281291 test ( 'returns 403 when stored refresh token does not match' , async ( ) => {
282292 jwt . verify . mockReturnValue ( { _id : 'dev_id_1' } ) ;
283- Developer . findById . mockResolvedValue ( { ...mockUser ( ) , refreshToken : 'different_token' } ) ;
293+ Developer . findById . mockReturnValue ( Developer . __mockQuery ( { ...mockUser ( ) , refreshToken : 'different_token' } ) ) ;
284294
285295 const req = makeReq ( { } , null , { refreshToken : 'valid_refresh_token' } ) ;
286296 const res = makeRes ( ) ;
@@ -370,7 +380,7 @@ describe('auth.controller', () => {
370380 password : 'old_hashed' ,
371381 save : jest . fn ( ) . mockResolvedValue ( undefined ) ,
372382 } ;
373- Developer . findById . mockResolvedValue ( mockUser ) ;
383+ Developer . findById . mockReturnValue ( Developer . __mockQuery ( mockUser ) ) ;
374384 bcrypt . compare . mockResolvedValue ( true ) ;
375385 bcrypt . genSalt . mockResolvedValue ( 'salt' ) ;
376386 bcrypt . hash . mockResolvedValue ( 'new_hashed' ) ;
@@ -391,10 +401,10 @@ describe('auth.controller', () => {
391401 } ) ;
392402
393403 test ( 'returns 400 when current password is incorrect' , async ( ) => {
394- Developer . findById . mockResolvedValue ( {
404+ Developer . findById . mockReturnValue ( Developer . __mockQuery ( {
395405 password : 'old_hashed' ,
396406 save : jest . fn ( ) ,
397- } ) ;
407+ } ) ) ;
398408 bcrypt . compare . mockResolvedValue ( false ) ;
399409
400410 const req = makeReq (
@@ -413,32 +423,32 @@ describe('auth.controller', () => {
413423 // -----------------------------------------------------------------------
414424 describe ( 'sendOtp' , ( ) => {
415425 test ( 'returns 400 when user is not found' , async ( ) => {
416- Developer . findOne . mockResolvedValue ( null ) ;
426+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( null ) ) ;
417427
418428 const req = makeReq ( { email : 'noone@example.com' } ) ;
419429 const res = makeRes ( ) ;
420430
421431 await authController . sendOtp ( req , res ) ;
422432
423433 expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
424- expect ( res . json ) . toHaveBeenCalledWith ( { error : 'User not found' } ) ;
434+ expect ( res . json ) . toHaveBeenCalledWith ( { error : 'User not found. Ensure you are using the correct email. ' } ) ;
425435 } ) ;
426436
427437 test ( 'returns 400 when user is already verified' , async ( ) => {
428- Developer . findOne . mockResolvedValue ( { _id : 'u1' , isVerified : true } ) ;
438+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( { _id : 'u1' , isVerified : true } ) ) ;
429439
430440 const req = makeReq ( { email : 'verified@example.com' } ) ;
431441 const res = makeRes ( ) ;
432442
433443 await authController . sendOtp ( req , res ) ;
434444
435445 expect ( res . status ) . toHaveBeenCalledWith ( 400 ) ;
436- expect ( res . json ) . toHaveBeenCalledWith ( { error : 'User already verified' } ) ;
446+ expect ( res . json ) . toHaveBeenCalledWith ( { error : 'Account is already verified. Please login. ' } ) ;
437447 } ) ;
438448
439449 test ( 'sends OTP and returns success for unverified user' , async ( ) => {
440450 const user = { _id : 'u1' , isVerified : false } ;
441- Developer . findOne . mockResolvedValue ( user ) ;
451+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( user ) ) ;
442452 Otp . deleteOne . mockResolvedValue ( undefined ) ;
443453 bcrypt . genSalt . mockResolvedValue ( 'salt' ) ;
444454 bcrypt . hash . mockResolvedValue ( 'hashed_otp' ) ;
@@ -459,7 +469,7 @@ describe('auth.controller', () => {
459469 // -----------------------------------------------------------------------
460470 describe ( 'forgotPassword' , ( ) => {
461471 test ( 'returns the same message regardless of whether user exists (prevents email enumeration)' , async ( ) => {
462- Developer . findOne . mockResolvedValue ( null ) ;
472+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( null ) ) ;
463473
464474 const req = makeReq ( { email : 'ghost@example.com' } ) ;
465475 const res = makeRes ( ) ;
@@ -490,7 +500,7 @@ describe('auth.controller', () => {
490500 save : jest . fn ( ) . mockResolvedValue ( undefined ) ,
491501 } ;
492502
493- Developer . findOne . mockResolvedValue ( mockUser ) ;
503+ Developer . findOne . mockReturnValue ( Developer . __mockQuery ( mockUser ) ) ;
494504 Otp . findOne . mockResolvedValue ( mockOtpDoc ) ;
495505 bcrypt . compare . mockResolvedValue ( true ) ;
496506 bcrypt . genSalt . mockResolvedValue ( 'salt' ) ;
0 commit comments