1+ import { BadRequestException , NotFoundException } from '@nestjs/common' ;
12import { ThrottlerGuard } from '@nestjs/throttler' ;
23import {
34 THROTTLER_LIMIT ,
@@ -6,6 +7,34 @@ import {
67import { SocialLinksDto } from './social-links.dto' ;
78import { SocialLinkController } from './social-links.controller' ;
89import { SocialLinksService } from './social-links.service' ;
10+ import { PaginatedResponseDto } from '../common/dto' ;
11+ import { SocialLinksListItem } from './social-links.service' ;
12+
13+ // ─── shared mock ────────────────────────────────────────────────────────────
14+
15+ const mockPaginatedResult : PaginatedResponseDto < SocialLinksListItem > = {
16+ data : [ ] ,
17+ cursor : null ,
18+ limit : 20 ,
19+ nextCursor : null ,
20+ hasMore : false ,
21+ total : 0 ,
22+ page : 1 ,
23+ totalPages : 0 ,
24+ } ;
25+
26+ const mockSocialLinksService = {
27+ extractUpdatePayload : jest
28+ . fn ( )
29+ . mockImplementation ( ( dto : SocialLinksDto ) => dto ) ,
30+ createSocialLinks : jest
31+ . fn ( )
32+ . mockImplementation ( ( dto : SocialLinksDto ) => dto ) ,
33+ updateSocialLinks : jest
34+ . fn ( )
35+ . mockImplementation ( ( _id : string , dto : SocialLinksDto ) => dto ) ,
36+ listSocialLinks : jest . fn ( ) . mockReturnValue ( mockPaginatedResult ) ,
37+ } ;
938
1039describe ( 'SocialLinkController' , ( ) => {
1140 let controller : SocialLinkController ;
@@ -30,12 +59,38 @@ describe('SocialLinkController', () => {
3059 expect ( controller ) . toBeDefined ( ) ;
3160 } ) ;
3261
33- it ( 'applies the throttler guard at the controller level' , ( ) => {
34- const guards = Reflect . getMetadata (
35- '__guards__' ,
36- SocialLinkController ,
37- ) as unknown as Array < new ( ) => unknown > ;
38- expect ( guards ) . toContain ( ThrottlerGuard ) ;
62+ // ─── guard & throttle metadata ────────────────────────────────────────────
63+
64+ describe ( 'guard and throttle metadata' , ( ) => {
65+ it ( 'applies the throttler guard at the controller level' , ( ) => {
66+ const guards = Reflect . getMetadata (
67+ '__guards__' ,
68+ SocialLinkController ,
69+ ) as unknown as Array < new ( ) => unknown > ;
70+ expect ( guards ) . toContain ( ThrottlerGuard ) ;
71+ } ) ;
72+
73+ it ( 'configures create with the expected throttling policy' , ( ) => {
74+ const createHandler = SocialLinkController . prototype . create ;
75+ const limit = Reflect . getMetadata ( THROTTLER_LIMIT + 'default' , createHandler ) ;
76+ const ttl = Reflect . getMetadata ( THROTTLER_TTL + 'default' , createHandler ) ;
77+ expect ( limit ) . toBe ( 5 ) ;
78+ expect ( ttl ) . toBe ( 60000 ) ;
79+ } ) ;
80+
81+ it ( 'configures update with the expected throttling policy' , ( ) => {
82+ const updateHandler = SocialLinkController . prototype . update ;
83+ const limit = Reflect . getMetadata ( THROTTLER_LIMIT + 'default' , updateHandler ) ;
84+ const ttl = Reflect . getMetadata ( THROTTLER_TTL + 'default' , updateHandler ) ;
85+ expect ( limit ) . toBe ( 5 ) ;
86+ expect ( ttl ) . toBe ( 60000 ) ;
87+ } ) ;
88+
89+ it ( 'list (read endpoint) has no @Throttle metadata' , ( ) => {
90+ const listHandler = SocialLinkController . prototype . list ;
91+ const limit = Reflect . getMetadata ( THROTTLER_LIMIT + 'default' , listHandler ) ;
92+ expect ( limit ) . toBeUndefined ( ) ;
93+ } ) ;
3994 } ) ;
4095
4196 it ( 'configures create with the expected throttling policy' , ( ) => {
@@ -44,8 +99,13 @@ describe('SocialLinkController', () => {
4499 const limit : unknown = Reflect . getMetadata ( THROTTLER_LIMIT + 'default' , createHandler ) ;
45100 const ttl : unknown = Reflect . getMetadata ( THROTTLER_TTL + 'default' , createHandler ) ;
46101
47- expect ( limit ) . toBe ( 5 ) ;
48- expect ( ttl ) . toBe ( 60000 ) ;
102+ it ( 'update has @ApiResponse for 404' , ( ) => {
103+ const meta = Reflect . getMetadata (
104+ 'swagger/apiResponse' ,
105+ SocialLinkController . prototype . update ,
106+ ) ;
107+ expect ( meta ?. [ '404' ] ) . toBeDefined ( ) ;
108+ } ) ;
49109 } ) ;
50110
51111 it ( 'configures update with the expected throttling policy' , ( ) => {
@@ -54,8 +114,18 @@ describe('SocialLinkController', () => {
54114 const limit : unknown = Reflect . getMetadata ( THROTTLER_LIMIT + 'default' , updateHandler ) ;
55115 const ttl : unknown = Reflect . getMetadata ( THROTTLER_TTL + 'default' , updateHandler ) ;
56116
57- expect ( limit ) . toBe ( 5 ) ;
58- expect ( ttl ) . toBe ( 60000 ) ;
117+ controller . list ( pagination ) ;
118+
119+ expect ( mockSocialLinksService . listSocialLinks ) . toHaveBeenCalledWith ( pagination ) ;
120+ } ) ;
121+
122+ it ( 'propagates errors thrown by the service' , ( ) => {
123+ mockSocialLinksService . listSocialLinks . mockImplementationOnce ( ( ) => {
124+ throw new BadRequestException ( 'Invalid pagination' ) ;
125+ } ) ;
126+
127+ expect ( ( ) => controller . list ( { page : - 1 , limit : 0 } ) ) . toThrow ( BadRequestException ) ;
128+ } ) ;
59129 } ) ;
60130
61131 describe ( 'create' , ( ) => {
0 commit comments