@@ -13,6 +13,7 @@ import {
1313 ConflictException ,
1414 ForbiddenException ,
1515 NotFoundException ,
16+ UnauthorizedException ,
1617} from '@nestjs/common' ;
1718import { ERROR_MESSAGES } from 'src/constants/swagger-messages' ;
1819import { GetUsersByIdDto } from './dto/get-users-by-id.dto' ;
@@ -29,6 +30,7 @@ import { CursorPaginationDto } from './dto/cursor-pagination-params.dto';
2930import { TweetResponseDTO } from 'src/tweets/dto/tweet-response.dto' ;
3031import { TweetType } from 'src/shared/enums/tweet-types.enum' ;
3132import { UsernameRecommendationsResponseDto } from './dto/username-recommendations-response.dto' ;
33+ import { UserRelationsResponseDto } from './dto/user-relations-response.dto' ;
3234
3335describe ( 'UserController' , ( ) => {
3436 let controller : UserController ;
@@ -65,6 +67,7 @@ describe('UserController', () => {
6567 assignInterests : jest . fn ( ) ,
6668 changeLanguage : jest . fn ( ) ,
6769 getUsernameRecommendations : jest . fn ( ) ,
70+ getUserRelationsCounts : jest . fn ( ) ,
6871 } ;
6972
7073 const module : TestingModule = await Test . createTestingModule ( {
@@ -679,6 +682,144 @@ describe('UserController', () => {
679682 } ) ;
680683 } ) ;
681684
685+ describe ( 'getFollowings' , ( ) => {
686+ it ( 'should call user_service.getFollowing with the current user id, target user id and getFollowingDto without following filter' , async ( ) => {
687+ const mock_response : UserListResponseDto = {
688+ data : [
689+ {
690+ user_id : '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ,
691+ name : 'Alyaa Ali' ,
692+ username : 'Alyaali242' ,
693+ bio : 'hi there!' ,
694+ avatar_url : 'https://cdn.app.com/profiles/u877.jpg' ,
695+ is_following : false ,
696+ is_follower : false ,
697+ is_muted : false ,
698+ is_blocked : true ,
699+ verified : false ,
700+ followers : 0 ,
701+ following : 0 ,
702+ } ,
703+ {
704+ user_id : '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ,
705+ name : 'Amira Khalid' ,
706+ username : 'amira2342' ,
707+ bio : 'hi there!' ,
708+ avatar_url : 'https://cdn.app.com/profiles/u877.jpg' ,
709+ is_following : true ,
710+ is_follower : false ,
711+ is_muted : true ,
712+ is_blocked : true ,
713+ verified : false ,
714+ followers : 0 ,
715+ following : 0 ,
716+ } ,
717+ ] ,
718+ pagination : {
719+ next_cursor : '2025-10-31T12:00:00.000Z_550e8400-e29b-41d4-a716-446655440000' ,
720+ has_more : false ,
721+ } ,
722+ } ;
723+
724+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
725+ const target_user_id = 'b2d59899-f706-4c8f-97d7-ba2e9fc22d90' ;
726+ const query_dto : GetFollowersDto = {
727+ cursor : '2025-10-31T12:00:00.000Z_550e8400-e29b-41d4-a716-446655440000' ,
728+ limit : 20 ,
729+ } ;
730+
731+ const get_followers_spy = jest
732+ . spyOn ( user_service , 'getFollowing' )
733+ . mockResolvedValueOnce ( mock_response ) ;
734+
735+ const result = await controller . getFollowing (
736+ current_user_id ,
737+ target_user_id ,
738+ query_dto
739+ ) ;
740+
741+ expect ( get_followers_spy ) . toHaveBeenCalledWith (
742+ current_user_id ,
743+ target_user_id ,
744+ query_dto
745+ ) ;
746+ expect ( get_followers_spy ) . toHaveBeenCalledTimes ( 1 ) ;
747+ expect ( result ) . toEqual ( mock_response ) ;
748+ } ) ;
749+ it ( 'should call user_service.getFollowing with the current user id, target user id and getFollowingDto with following filter' , async ( ) => {
750+ const mock_response : UserListResponseDto = {
751+ data : [
752+ {
753+ user_id : '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ,
754+ name : 'Alyaa Ali' ,
755+ username : 'Alyaali242' ,
756+ bio : 'hi there!' ,
757+ avatar_url : 'https://cdn.app.com/profiles/u877.jpg' ,
758+ is_following : false ,
759+ is_follower : false ,
760+ is_muted : false ,
761+ is_blocked : true ,
762+ verified : false ,
763+ followers : 0 ,
764+ following : 0 ,
765+ } ,
766+ ] ,
767+ pagination : {
768+ next_cursor : '2025-10-31T12:00:00.000Z_550e8400-e29b-41d4-a716-446655440000' ,
769+ has_more : false ,
770+ } ,
771+ } ;
772+
773+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
774+ const target_user_id = 'b2d59899-f706-4c8f-97d7-ba2e9fc22d90' ;
775+ const query_dto : GetFollowersDto = {
776+ cursor : '2025-10-31T12:00:00.000Z_550e8400-e29b-41d4-a716-446655440000' ,
777+ limit : 20 ,
778+ } ;
779+
780+ const get_followers_spy = jest
781+ . spyOn ( user_service , 'getFollowing' )
782+ . mockResolvedValueOnce ( mock_response ) ;
783+
784+ const result = await controller . getFollowing (
785+ current_user_id ,
786+ target_user_id ,
787+ query_dto
788+ ) ;
789+
790+ expect ( get_followers_spy ) . toHaveBeenCalledWith (
791+ current_user_id ,
792+ target_user_id ,
793+ query_dto
794+ ) ;
795+ expect ( get_followers_spy ) . toHaveBeenCalledTimes ( 1 ) ;
796+ expect ( result ) . toEqual ( mock_response ) ;
797+ } ) ;
798+
799+ it ( 'should throw if service throws user not found' , async ( ) => {
800+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
801+ const target_user_id = 'b2d59899-f706-4c8f-97d7-ba2e9fc22d90' ;
802+
803+ const query_dto : GetFollowersDto = {
804+ cursor : '2025-10-31T12:00:00.000Z_550e8400-e29b-41d4-a716-446655440000' ,
805+ limit : 20 ,
806+ } ;
807+
808+ const error = new NotFoundException ( ERROR_MESSAGES . USER_NOT_FOUND ) ;
809+
810+ const get_followers = jest
811+ . spyOn ( user_service , 'getFollowing' )
812+ . mockRejectedValueOnce ( error ) ;
813+
814+ await expect (
815+ controller . getFollowing ( current_user_id , target_user_id , query_dto )
816+ ) . rejects . toThrow ( ERROR_MESSAGES . USER_NOT_FOUND ) ;
817+
818+ expect ( get_followers ) . toHaveBeenCalledWith ( current_user_id , target_user_id , query_dto ) ;
819+ expect ( get_followers ) . toHaveBeenCalledTimes ( 1 ) ;
820+ } ) ;
821+ } ) ;
822+
682823 describe ( 'getMutedList' , ( ) => {
683824 it ( 'should call user_service.getMutedList with the current user id, target user id and queryDto' , async ( ) => {
684825 const mock_response : UserListResponseDto = {
@@ -2134,4 +2275,118 @@ describe('UserController', () => {
21342275 expect ( get_username_recommendations_spy ) . toHaveBeenCalledTimes ( 1 ) ;
21352276 } ) ;
21362277 } ) ;
2278+
2279+ describe ( 'getRelationsCount' , ( ) => {
2280+ it ( 'should return user relations count' , async ( ) => {
2281+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2282+ const mock_relations : UserRelationsResponseDto = {
2283+ blocked_count : 5 ,
2284+ muted_count : 10 ,
2285+ } ;
2286+
2287+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( mock_relations ) ;
2288+
2289+ const result = await controller . getRelationsCount ( current_user_id ) ;
2290+
2291+ expect ( result ) . toEqual ( mock_relations ) ;
2292+ expect ( result . blocked_count ) . toBe ( 5 ) ;
2293+ expect ( result . muted_count ) . toBe ( 10 ) ;
2294+ expect ( user_service . getUserRelationsCounts ) . toHaveBeenCalledWith ( current_user_id ) ;
2295+ expect ( user_service . getUserRelationsCounts ) . toHaveBeenCalledTimes ( 1 ) ;
2296+ } ) ;
2297+
2298+ it ( 'should handle zero counts' , async ( ) => {
2299+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2300+ const mock_relations : UserRelationsResponseDto = {
2301+ blocked_count : 0 ,
2302+ muted_count : 0 ,
2303+ } ;
2304+
2305+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( mock_relations ) ;
2306+
2307+ const result = await controller . getRelationsCount ( current_user_id ) ;
2308+
2309+ expect ( result ) . toEqual ( mock_relations ) ;
2310+ expect ( result . blocked_count ) . toBe ( 0 ) ;
2311+ expect ( result . muted_count ) . toBe ( 0 ) ;
2312+ } ) ;
2313+
2314+ it ( 'should throw error when service fails' , async ( ) => {
2315+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2316+
2317+ user_service . getUserRelationsCounts . mockRejectedValueOnce ( new Error ( 'Database error' ) ) ;
2318+
2319+ await expect ( controller . getRelationsCount ( current_user_id ) ) . rejects . toThrow (
2320+ 'Database error'
2321+ ) ;
2322+ expect ( user_service . getUserRelationsCounts ) . toHaveBeenCalledWith ( current_user_id ) ;
2323+ } ) ;
2324+
2325+ it ( 'should handle service returning null' , async ( ) => {
2326+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2327+
2328+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( null as any ) ;
2329+
2330+ const result = await controller . getRelationsCount ( current_user_id ) ;
2331+
2332+ expect ( result ) . toBeNull ( ) ;
2333+ } ) ;
2334+
2335+ it ( 'should handle large blocked and muted counts' , async ( ) => {
2336+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2337+ const mock_relations : UserRelationsResponseDto = {
2338+ blocked_count : 1000 ,
2339+ muted_count : 500 ,
2340+ } ;
2341+
2342+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( mock_relations ) ;
2343+
2344+ const result = await controller . getRelationsCount ( current_user_id ) ;
2345+
2346+ expect ( result . blocked_count ) . toBe ( 1000 ) ;
2347+ expect ( result . muted_count ) . toBe ( 500 ) ;
2348+ } ) ;
2349+
2350+ it ( 'should handle only blocked count with no muted' , async ( ) => {
2351+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2352+ const mock_relations : UserRelationsResponseDto = {
2353+ blocked_count : 25 ,
2354+ muted_count : 0 ,
2355+ } ;
2356+
2357+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( mock_relations ) ;
2358+
2359+ const result = await controller . getRelationsCount ( current_user_id ) ;
2360+
2361+ expect ( result . blocked_count ) . toBe ( 25 ) ;
2362+ expect ( result . muted_count ) . toBe ( 0 ) ;
2363+ } ) ;
2364+
2365+ it ( 'should handle only muted count with no blocked' , async ( ) => {
2366+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2367+ const mock_relations : UserRelationsResponseDto = {
2368+ blocked_count : 0 ,
2369+ muted_count : 15 ,
2370+ } ;
2371+
2372+ user_service . getUserRelationsCounts . mockResolvedValueOnce ( mock_relations ) ;
2373+
2374+ const result = await controller . getRelationsCount ( current_user_id ) ;
2375+
2376+ expect ( result . blocked_count ) . toBe ( 0 ) ;
2377+ expect ( result . muted_count ) . toBe ( 15 ) ;
2378+ } ) ;
2379+
2380+ it ( 'should handle unauthorized error' , async ( ) => {
2381+ const current_user_id = '0c059899-f706-4c8f-97d7-ba2e9fc22d6d' ;
2382+
2383+ user_service . getUserRelationsCounts . mockRejectedValueOnce (
2384+ new UnauthorizedException ( ERROR_MESSAGES . INVALID_OR_EXPIRED_TOKEN )
2385+ ) ;
2386+
2387+ await expect ( controller . getRelationsCount ( current_user_id ) ) . rejects . toThrow (
2388+ UnauthorizedException
2389+ ) ;
2390+ } ) ;
2391+ } ) ;
21372392} ) ;
0 commit comments