@@ -58,6 +58,107 @@ describe('PostRepository', () => {
5858 } ) ;
5959 } ) ;
6060
61+ describe ( 'findPostsByUserIdWithGrowthMetrics' , ( ) => {
62+ it ( '트래픽 성장률 데이터를 포함한 게시글 목록을 반환해야 한다' , async ( ) => {
63+ const mockPosts = [
64+ {
65+ id : 1 ,
66+ post_released_at : '2025-03-01T00:00:00Z' ,
67+ daily_view_count : 30 ,
68+ yesterday_daily_view_count : 10 ,
69+ view_growth : 20 ,
70+ like_growth : 5
71+ } ,
72+ {
73+ id : 2 ,
74+ post_released_at : '2025-03-02T00:00:00Z' ,
75+ daily_view_count : 25 ,
76+ yesterday_daily_view_count : 15 ,
77+ view_growth : 10 ,
78+ like_growth : 3
79+ } ,
80+ ] ;
81+
82+ mockPool . query . mockResolvedValue ( {
83+ rows : mockPosts ,
84+ rowCount : mockPosts . length ,
85+ command : '' ,
86+ oid : 0 ,
87+ fields : [ ] ,
88+ } as QueryResult ) ;
89+
90+ const result = await repo . findPostsByUserIdWithGrowthMetrics ( 1 ) ;
91+
92+ expect ( result . posts ) . toEqual ( mockPosts ) ;
93+ expect ( result ) . toHaveProperty ( 'nextCursor' ) ;
94+ expect ( result . posts [ 0 ] ) . toHaveProperty ( 'view_growth' ) ;
95+ expect ( result . posts [ 0 ] ) . toHaveProperty ( 'like_growth' ) ;
96+ } ) ;
97+
98+ it ( '트래픽 성장률을 기준으로 내림차순 정렬해야 한다' , async ( ) => {
99+ const mockPosts = [
100+ {
101+ id : 1 ,
102+ post_released_at : '2025-03-01T00:00:00Z' ,
103+ daily_view_count : 30 ,
104+ yesterday_daily_view_count : 10 ,
105+ view_growth : 20
106+ } ,
107+ {
108+ id : 2 ,
109+ post_released_at : '2025-03-02T00:00:00Z' ,
110+ daily_view_count : 25 ,
111+ yesterday_daily_view_count : 15 ,
112+ view_growth : 10
113+ } ,
114+ ] ;
115+
116+ mockPool . query . mockResolvedValue ( {
117+ rows : mockPosts ,
118+ rowCount : mockPosts . length ,
119+ command : '' ,
120+ oid : 0 ,
121+ fields : [ ] ,
122+ } as QueryResult ) ;
123+
124+ const result = await repo . findPostsByUserIdWithGrowthMetrics ( 1 , undefined , false ) ;
125+ expect ( result . posts ) . toEqual ( mockPosts ) ;
126+ expect ( result . posts [ 0 ] . view_growth ) . toBeGreaterThan ( result . posts [ 1 ] . view_growth ) ;
127+ } ) ;
128+
129+ it ( '커서 기반 페이지네이션이 트래픽 성장률 기준으로 작동해야 한다' , async ( ) => {
130+ const mockPosts = [
131+ {
132+ id : 3 ,
133+ post_released_at : '2025-03-03T00:00:00Z' ,
134+ daily_view_count : 20 ,
135+ yesterday_daily_view_count : 15 ,
136+ view_growth : 5
137+ } ,
138+ ] ;
139+
140+ mockPool . query . mockResolvedValue ( {
141+ rows : mockPosts ,
142+ rowCount : mockPosts . length ,
143+ command : '' ,
144+ oid : 0 ,
145+ fields : [ ] ,
146+ } as QueryResult ) ;
147+
148+ const result = await repo . findPostsByUserIdWithGrowthMetrics ( 1 , "10,2" , false ) ;
149+ expect ( result . posts ) . toEqual ( mockPosts ) ;
150+ expect ( mockPool . query ) . toHaveBeenCalledWith (
151+ expect . stringContaining ( "(COALESCE(pds.daily_view_count, 0) - COALESCE(yesterday_stats.daily_view_count, 0)) < $2" ) ,
152+ expect . arrayContaining ( [ 1 , "10" , "2" , expect . anything ( ) ] )
153+ ) ;
154+ } ) ;
155+
156+ it ( '에러 발생 시 DBError를 던져야 한다' , async ( ) => {
157+ mockPool . query . mockRejectedValue ( new Error ( 'DB connection failed' ) ) ;
158+ await expect ( repo . findPostsByUserIdWithGrowthMetrics ( 1 ) ) . rejects . toThrow ( DBError ) ;
159+ } ) ;
160+ } ) ;
161+
61162 describe ( 'getTotalPostCounts' , ( ) => {
62163 it ( '사용자의 총 게시글 수를 반환해야 한다' , async ( ) => {
63164 mockPool . query . mockResolvedValue ( {
0 commit comments