@@ -2,11 +2,9 @@ import 'reflect-metadata';
2
2
import { Request , Response } from 'express' ;
3
3
import { WebhookController } from '@/controllers/webhook.controller' ;
4
4
import { sendSlackMessage } from '@/modules/slack/slack.notifier' ;
5
- import { verifySignature } from '@/utils/verify.util' ;
6
5
7
6
// Mock dependencies
8
7
jest . mock ( '@/modules/slack/slack.notifier' ) ;
9
- jest . mock ( '@/utils/verify.util' ) ;
10
8
11
9
// logger 모킹
12
10
jest . mock ( '@/configs/logger.config' , ( ) => ( {
@@ -20,7 +18,6 @@ describe('WebhookController', () => {
20
18
let mockResponse : Partial < Response > ;
21
19
let nextFunction : jest . Mock ;
22
20
let mockSendSlackMessage : jest . MockedFunction < typeof sendSlackMessage > ;
23
- let mockVerifySignature : jest . MockedFunction < typeof verifySignature > ;
24
21
25
22
beforeEach ( ( ) => {
26
23
// WebhookController 인스턴스 생성
@@ -39,10 +36,6 @@ describe('WebhookController', () => {
39
36
40
37
nextFunction = jest . fn ( ) ;
41
38
mockSendSlackMessage = sendSlackMessage as jest . MockedFunction < typeof sendSlackMessage > ;
42
- mockVerifySignature = verifySignature as jest . MockedFunction < typeof verifySignature > ;
43
-
44
- // 기본적으로 시그니처 검증이 성공하도록 설정
45
- mockVerifySignature . mockReturnValue ( true ) ;
46
39
} ) ;
47
40
48
41
afterEach ( ( ) => {
@@ -315,108 +308,4 @@ describe('WebhookController', () => {
315
308
expect ( mockSendSlackMessage ) . toHaveBeenCalledWith ( expectedMessage ) ;
316
309
} ) ;
317
310
} ) ;
318
-
319
- describe ( 'Signature Verification' , ( ) => {
320
- const mockSentryData = {
321
- action : 'created' ,
322
- data : {
323
- issue : {
324
- id : 'test-issue-123' ,
325
- title : '시그니처 테스트 오류' ,
326
- culprit : 'TestFile.js:10' ,
327
- status : 'unresolved' ,
328
- count : "1" ,
329
- userCount : 1 ,
330
- firstSeen : '2024-01-01T12:00:00.000Z' ,
331
- permalink : 'https://velog-dashboardv2.sentry.io/issues/test-issue-123/' ,
332
- project : {
333
- id : 'project-123' ,
334
- name : 'Velog Dashboard' ,
335
- slug : 'velog-dashboard'
336
- }
337
- }
338
- }
339
- } ;
340
-
341
- it ( '유효한 시그니처로 웹훅 처리에 성공해야 한다' , async ( ) => {
342
- mockRequest . body = mockSentryData ;
343
- mockRequest . headers = {
344
- 'sentry-hook-signature' : 'valid-signature'
345
- } ;
346
- mockVerifySignature . mockReturnValue ( true ) ;
347
- mockSendSlackMessage . mockResolvedValue ( ) ;
348
-
349
- await webhookController . handleSentryWebhook (
350
- mockRequest as Request ,
351
- mockResponse as Response ,
352
- nextFunction
353
- ) ;
354
-
355
- expect ( mockVerifySignature ) . toHaveBeenCalledWith ( mockRequest ) ;
356
- expect ( mockSendSlackMessage ) . toHaveBeenCalled ( ) ;
357
- expect ( mockResponse . status ) . toHaveBeenCalledWith ( 200 ) ;
358
- } ) ;
359
-
360
- it ( '잘못된 시그니처로 400 에러를 반환해야 한다' , async ( ) => {
361
- mockRequest . body = mockSentryData ;
362
- mockRequest . headers = {
363
- 'sentry-hook-signature' : 'invalid-signature'
364
- } ;
365
- mockVerifySignature . mockReturnValue ( false ) ;
366
-
367
- await webhookController . handleSentryWebhook (
368
- mockRequest as Request ,
369
- mockResponse as Response ,
370
- nextFunction
371
- ) ;
372
-
373
- expect ( mockVerifySignature ) . toHaveBeenCalledWith ( mockRequest ) ;
374
- expect ( mockSendSlackMessage ) . not . toHaveBeenCalled ( ) ;
375
- expect ( mockResponse . status ) . toHaveBeenCalledWith ( 400 ) ;
376
- expect ( mockResponse . json ) . toHaveBeenCalledWith ( {
377
- success : true ,
378
- message : 'Sentry 웹훅 처리에 실패했습니다' ,
379
- data : { } ,
380
- error : null
381
- } ) ;
382
- } ) ;
383
-
384
- it ( '시그니처 헤더가 누락된 경우 400 에러를 반환해야 한다' , async ( ) => {
385
- mockRequest . body = mockSentryData ;
386
- mockRequest . headers = { } ; // 시그니처 헤더 누락
387
- mockVerifySignature . mockReturnValue ( false ) ;
388
-
389
- await webhookController . handleSentryWebhook (
390
- mockRequest as Request ,
391
- mockResponse as Response ,
392
- nextFunction
393
- ) ;
394
-
395
- expect ( mockVerifySignature ) . toHaveBeenCalledWith ( mockRequest ) ;
396
- expect ( mockSendSlackMessage ) . not . toHaveBeenCalled ( ) ;
397
- expect ( mockResponse . status ) . toHaveBeenCalledWith ( 400 ) ;
398
- } ) ;
399
-
400
- it ( '시그니처 검증 중 예외 발생 시 에러를 전달해야 한다' , async ( ) => {
401
- mockRequest . body = mockSentryData ;
402
- mockRequest . headers = {
403
- 'sentry-hook-signature' : 'some-signature'
404
- } ;
405
- const verificationError = new Error ( 'SENTRY_CLIENT_SECRET is not defined' ) ;
406
- mockVerifySignature . mockImplementation ( ( ) => {
407
- throw verificationError ;
408
- } ) ;
409
-
410
- await webhookController . handleSentryWebhook (
411
- mockRequest as Request ,
412
- mockResponse as Response ,
413
- nextFunction
414
- ) ;
415
-
416
- expect ( mockVerifySignature ) . toHaveBeenCalledWith ( mockRequest ) ;
417
- expect ( nextFunction ) . toHaveBeenCalledWith ( verificationError ) ;
418
- expect ( mockSendSlackMessage ) . not . toHaveBeenCalled ( ) ;
419
- expect ( mockResponse . json ) . not . toHaveBeenCalled ( ) ;
420
- } ) ;
421
- } ) ;
422
311
} ) ;
0 commit comments