diff --git a/src/main/java/com/debatetimer/controller/sharing/SharingController.java b/src/main/java/com/debatetimer/controller/sharing/SharingController.java index edacf8e6..0216a15b 100644 --- a/src/main/java/com/debatetimer/controller/sharing/SharingController.java +++ b/src/main/java/com/debatetimer/controller/sharing/SharingController.java @@ -1,9 +1,10 @@ package com.debatetimer.controller.sharing; -import com.debatetimer.controller.auth.AuthMember; -import com.debatetimer.domain.member.Member; import com.debatetimer.dto.sharing.request.SharingRequest; import com.debatetimer.dto.sharing.response.SharingResponse; +import com.debatetimer.service.sharing.SharingService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.Payload; @@ -11,15 +12,18 @@ import org.springframework.stereotype.Controller; @Controller +@RequiredArgsConstructor public class SharingController { + private final SharingService sharingService; + @MessageMapping("/event/{roomId}") @SendTo("/room/{roomId}") public SharingResponse share( - @AuthMember Member member, @DestinationVariable(value = "roomId") long roomId, - @Payload SharingRequest request + @Valid @Payload SharingRequest request ) { - return new SharingResponse(request.time()); + + return sharingService.share(request); } } diff --git a/src/main/java/com/debatetimer/domain/sharing/TimerEvent.java b/src/main/java/com/debatetimer/domain/sharing/TimerEvent.java new file mode 100644 index 00000000..e32a9a20 --- /dev/null +++ b/src/main/java/com/debatetimer/domain/sharing/TimerEvent.java @@ -0,0 +1,28 @@ +package com.debatetimer.domain.sharing; + +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class TimerEvent { + + @NotNull + private final TimerEventType eventType; + + @Nullable + private final TimerEventData timerEventData; + + public TimerEvent( + TimerEventType eventType, + @Nullable TimerEventData timerEventData + ) { + eventType.validateEventData(timerEventData); + this.eventType = eventType; + this.timerEventData = timerEventData; + } + + public TimerEvent(TimerEventType eventType) { + this(eventType, null); + } +} diff --git a/src/main/java/com/debatetimer/domain/sharing/TimerEventData.java b/src/main/java/com/debatetimer/domain/sharing/TimerEventData.java new file mode 100644 index 00000000..85de556b --- /dev/null +++ b/src/main/java/com/debatetimer/domain/sharing/TimerEventData.java @@ -0,0 +1,46 @@ +package com.debatetimer.domain.sharing; + +import com.debatetimer.domain.customize.CustomizeBoxType; +import com.debatetimer.domain.customize.Stance; +import com.debatetimer.exception.custom.DTClientErrorException; +import com.debatetimer.exception.errorcode.ClientErrorCode; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class TimerEventData { + + @NotNull + private final CustomizeBoxType timerType; + + private final int sequence; + + @Nullable + private final Stance currentTeam; + + private final long remainingTime; + + public TimerEventData( + CustomizeBoxType timerType, + int sequence, + @Nullable Stance currentTeam, + long remainingTime + ) { + validateCurrentTeam(timerType, currentTeam); + this.timerType = timerType; + this.sequence = sequence; + this.currentTeam = currentTeam; + this.remainingTime = remainingTime; + } + + private void validateCurrentTeam(CustomizeBoxType timerType, Stance currentTeam) { + if (timerType.isTimeBased() && currentTeam == null) { + throw new DTClientErrorException(ClientErrorCode.INVALID_TIME_BASED_TIMER_EVENT_DATA); + } + + if (!timerType.isTimeBased() && currentTeam != null) { + throw new DTClientErrorException(ClientErrorCode.INVALID_NORMAL_TIMER_EVENT_DATA); + } + } +} diff --git a/src/main/java/com/debatetimer/domain/sharing/TimerEventType.java b/src/main/java/com/debatetimer/domain/sharing/TimerEventType.java new file mode 100644 index 00000000..ca1a5427 --- /dev/null +++ b/src/main/java/com/debatetimer/domain/sharing/TimerEventType.java @@ -0,0 +1,28 @@ +package com.debatetimer.domain.sharing; + +import com.debatetimer.exception.custom.DTClientErrorException; +import com.debatetimer.exception.errorcode.ClientErrorCode; +import java.util.Objects; +import java.util.function.Predicate; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum TimerEventType { + + NEXT(Objects::nonNull), + BEFORE(Objects::nonNull), + STOP(Objects::nonNull), + PLAY(Objects::nonNull), + RESET(Objects::nonNull), + TEAM_SWITCH(Objects::nonNull), + FINISHED(Objects::isNull), + ; + + private final Predicate eventDataValidator; + + public void validateEventData(Object eventData) { + if (!eventDataValidator.test(eventData)) { + throw new DTClientErrorException(ClientErrorCode.INVALID_TIMER_EVENT); + } + } +} diff --git a/src/main/java/com/debatetimer/dto/sharing/request/SharingRequest.java b/src/main/java/com/debatetimer/dto/sharing/request/SharingRequest.java index b6063711..dab8299a 100644 --- a/src/main/java/com/debatetimer/dto/sharing/request/SharingRequest.java +++ b/src/main/java/com/debatetimer/dto/sharing/request/SharingRequest.java @@ -1,9 +1,25 @@ package com.debatetimer.dto.sharing.request; -import java.time.LocalDateTime; +import com.debatetimer.domain.sharing.TimerEvent; +import com.debatetimer.domain.sharing.TimerEventType; +import jakarta.annotation.Nullable; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.util.Optional; public record SharingRequest( - LocalDateTime time + @NotNull + TimerEventType eventType, + + @Valid + @Nullable + TimerEventInfoRequest data ) { + public TimerEvent toTimerEvent() { + return Optional.ofNullable(data) + .map(TimerEventInfoRequest::toTimerEventInfo) + .map(eventData -> new TimerEvent(eventType, eventData)) + .orElseGet(() -> new TimerEvent(eventType)); + } } diff --git a/src/main/java/com/debatetimer/dto/sharing/request/TimerEventInfoRequest.java b/src/main/java/com/debatetimer/dto/sharing/request/TimerEventInfoRequest.java new file mode 100644 index 00000000..6a4c591e --- /dev/null +++ b/src/main/java/com/debatetimer/dto/sharing/request/TimerEventInfoRequest.java @@ -0,0 +1,28 @@ +package com.debatetimer.dto.sharing.request; + +import com.debatetimer.domain.customize.CustomizeBoxType; +import com.debatetimer.domain.customize.Stance; +import com.debatetimer.domain.sharing.TimerEventData; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +public record TimerEventInfoRequest( + @NotNull + CustomizeBoxType timerType, + + @Nullable + Stance currentTeam, + + int sequence, + long remainingTime +) { + + public TimerEventData toTimerEventInfo() { + return new TimerEventData( + timerType, + sequence, + currentTeam, + remainingTime + ); + } +} diff --git a/src/main/java/com/debatetimer/dto/sharing/response/SharingResponse.java b/src/main/java/com/debatetimer/dto/sharing/response/SharingResponse.java index 704384d1..2973fb94 100644 --- a/src/main/java/com/debatetimer/dto/sharing/response/SharingResponse.java +++ b/src/main/java/com/debatetimer/dto/sharing/response/SharingResponse.java @@ -1,9 +1,16 @@ package com.debatetimer.dto.sharing.response; -import java.time.LocalDateTime; +import com.debatetimer.domain.sharing.TimerEventType; +import jakarta.annotation.Nullable; public record SharingResponse( - LocalDateTime time + TimerEventType eventType, + + @Nullable + TimerEventDataResponse data ) { + public SharingResponse(TimerEventType eventType) { + this(eventType, null); + } } diff --git a/src/main/java/com/debatetimer/dto/sharing/response/TimerEventDataResponse.java b/src/main/java/com/debatetimer/dto/sharing/response/TimerEventDataResponse.java new file mode 100644 index 00000000..5fde093a --- /dev/null +++ b/src/main/java/com/debatetimer/dto/sharing/response/TimerEventDataResponse.java @@ -0,0 +1,29 @@ +package com.debatetimer.dto.sharing.response; + + +import com.debatetimer.domain.customize.CustomizeBoxType; +import com.debatetimer.domain.customize.Stance; +import com.debatetimer.domain.sharing.TimerEventData; +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; + +public record TimerEventDataResponse( + @NotNull + CustomizeBoxType timerType, + + @Nullable + Stance currentTeam, + + int sequence, + long remainingTime +) { + + public TimerEventDataResponse(TimerEventData timerEventInfo) { + this( + timerEventInfo.getTimerType(), + timerEventInfo.getCurrentTeam(), + timerEventInfo.getSequence(), + timerEventInfo.getRemainingTime() + ); + } +} diff --git a/src/main/java/com/debatetimer/exception/errorcode/ClientErrorCode.java b/src/main/java/com/debatetimer/exception/errorcode/ClientErrorCode.java index 5bf7d05b..6079ba2f 100644 --- a/src/main/java/com/debatetimer/exception/errorcode/ClientErrorCode.java +++ b/src/main/java/com/debatetimer/exception/errorcode/ClientErrorCode.java @@ -77,6 +77,10 @@ public enum ClientErrorCode implements ResponseErrorCode { INVALID_BELL_TIME(HttpStatus.BAD_REQUEST, "벨 시간은 0 이상의 정수여야 합니다."), INVALID_BELL_COUNT(HttpStatus.BAD_REQUEST, "벨 카운트는 1 이상 %d 이하의 정수여야 합니다.".formatted(Bell.MAX_BELL_COUNT)), + + INVALID_NORMAL_TIMER_EVENT_DATA(HttpStatus.BAD_REQUEST, "잘못된 일반 타이머 이벤트 데이터입니다"), + INVALID_TIME_BASED_TIMER_EVENT_DATA(HttpStatus.BAD_REQUEST, "잘못된 자유토론 타이머 이벤트 데이터입니다"), + INVALID_TIMER_EVENT(HttpStatus.BAD_REQUEST, "잘못된 타이머 이벤트 데이터입니다"), ; private final HttpStatus status; diff --git a/src/main/java/com/debatetimer/service/sharing/SharingService.java b/src/main/java/com/debatetimer/service/sharing/SharingService.java new file mode 100644 index 00000000..8002052f --- /dev/null +++ b/src/main/java/com/debatetimer/service/sharing/SharingService.java @@ -0,0 +1,22 @@ +package com.debatetimer.service.sharing; + +import com.debatetimer.domain.sharing.TimerEvent; +import com.debatetimer.dto.sharing.request.SharingRequest; +import com.debatetimer.dto.sharing.response.SharingResponse; +import com.debatetimer.dto.sharing.response.TimerEventDataResponse; +import java.util.Optional; +import org.springframework.stereotype.Service; + +@Service +public class SharingService { + + public SharingResponse share(SharingRequest request) { + TimerEvent timerEvent = request.toTimerEvent(); + return Optional.ofNullable(timerEvent.getTimerEventData()) + .map(eventData -> new SharingResponse( + request.eventType(), + new TimerEventDataResponse(eventData) + )) + .orElse(new SharingResponse(request.eventType(), null)); + } +} diff --git a/src/test/java/com/debatetimer/BaseStompTest.java b/src/test/java/com/debatetimer/BaseStompTest.java index 4f0410c0..cf38a6e4 100644 --- a/src/test/java/com/debatetimer/BaseStompTest.java +++ b/src/test/java/com/debatetimer/BaseStompTest.java @@ -10,6 +10,7 @@ import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; @@ -23,6 +24,7 @@ import org.springframework.web.socket.sockjs.client.Transport; import org.springframework.web.socket.sockjs.client.WebSocketTransport; +@ExtendWith(DataBaseCleaner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public abstract class BaseStompTest { diff --git a/src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java b/src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java index e2613aa0..dc565166 100644 --- a/src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java +++ b/src/test/java/com/debatetimer/controller/customize/CustomizeDocumentTest.java @@ -114,7 +114,8 @@ class Save { new CustomizeTimeBoxCreateRequest(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxCreateRequest(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), + new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -129,7 +130,8 @@ class Save { new CustomizeTimeBoxResponse(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxResponse(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), + new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -173,7 +175,8 @@ class Save { new CustomizeTimeBoxCreateRequest(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxCreateRequest(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), + new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -252,7 +255,8 @@ class GetTable { new CustomizeTimeBoxResponse(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxResponse(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), + new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -370,7 +374,8 @@ class UpdateTable { new CustomizeTimeBoxCreateRequest(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxCreateRequest(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), + new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -385,7 +390,8 @@ class UpdateTable { new CustomizeTimeBoxResponse(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxResponse(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), + new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -432,7 +438,8 @@ class UpdateTable { new CustomizeTimeBoxCreateRequest(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxCreateRequest(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellRequest(BellType.AFTER_START, 90, 1), + new BellRequest(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxCreateRequest(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, @@ -514,7 +521,8 @@ class Debate { new CustomizeTimeBoxResponse(Stance.PROS, "입론", CustomizeBoxType.NORMAL, 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1)), null, null, "콜리"), new CustomizeTimeBoxResponse(Stance.CONS, "입론", CustomizeBoxType.NORMAL, - 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), + 120, List.of(new BellResponse(BellType.AFTER_START, 90, 1), + new BellResponse(BellType.AFTER_START, 120, 2)), null, null, "비토"), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "난상 토론", CustomizeBoxType.TIME_BASED, null, null, 360, 120, null), new CustomizeTimeBoxResponse(Stance.NEUTRAL, "존중 토론", CustomizeBoxType.TIME_BASED, diff --git a/src/test/java/com/debatetimer/controller/sharing/SharingControllerTest.java b/src/test/java/com/debatetimer/controller/sharing/SharingControllerTest.java index c1362bc5..d644f907 100644 --- a/src/test/java/com/debatetimer/controller/sharing/SharingControllerTest.java +++ b/src/test/java/com/debatetimer/controller/sharing/SharingControllerTest.java @@ -1,18 +1,24 @@ package com.debatetimer.controller.sharing; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; import com.debatetimer.BaseStompTest; import com.debatetimer.MessageFrameHandler; +import com.debatetimer.domain.customize.CustomizeBoxType; import com.debatetimer.domain.member.Member; +import com.debatetimer.domain.sharing.TimerEventType; import com.debatetimer.dto.sharing.request.SharingRequest; +import com.debatetimer.dto.sharing.request.TimerEventInfoRequest; import com.debatetimer.dto.sharing.response.SharingResponse; -import java.time.LocalDateTime; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; import org.springframework.messaging.simp.stomp.StompHeaders; class SharingControllerTest extends BaseStompTest { @@ -23,17 +29,78 @@ class Share { @Test void 사회자가_발생시킨_이벤트를_청중이_공유받는다() throws ExecutionException, InterruptedException, TimeoutException { long roomId = 1L; - LocalDateTime time = LocalDateTime.now(); MessageFrameHandler handler = new MessageFrameHandler<>(SharingResponse.class); Member member = memberGenerator.generate("example@email.com"); StompHeaders headers = headerGenerator.generateAccessTokenHeader("/app/event/" + roomId, member); + SharingRequest request = new SharingRequest( + TimerEventType.NEXT, + new TimerEventInfoRequest( + CustomizeBoxType.NORMAL, + null, + 2, + 30 + ) + ); stompSession.subscribe("/room/" + roomId, handler); //청중의 구독 - stompSession.send(headers, new SharingRequest(time)); //사회자의 이벤트 발생 + stompSession.send(headers, request); //사회자의 이벤트 발생 SharingResponse response = handler.getCompletableFuture() .get(3L, TimeUnit.SECONDS); - assertThat(response.time()).isEqualTo(time); + + assertAll( + () -> assertThat(response.eventType()).isEqualTo(request.eventType()), + () -> assertThat(response.data()).isNotNull(), + () -> assertThat(response.data().timerType()).isEqualTo(request.data().timerType()), + () -> assertThat(response.data().sequence()).isEqualTo(request.data().sequence()), + () -> assertThat(response.data().currentTeam()).isEqualTo(request.data().currentTeam()), + () -> assertThat(response.data().remainingTime()).isEqualTo(request.data().remainingTime()) + ); + } + + @Test + void 사회자가_발생시킨_토론_종료_이벤트를_청중이_공유받는다() throws ExecutionException, InterruptedException, TimeoutException { + long roomId = 1L; + MessageFrameHandler handler = new MessageFrameHandler<>(SharingResponse.class); + Member member = memberGenerator.generate("example@email.com"); + StompHeaders headers = headerGenerator.generateAccessTokenHeader("/app/event/" + roomId, member); + SharingRequest request = new SharingRequest(TimerEventType.FINISHED, null); + stompSession.subscribe("/room/" + roomId, handler); //청중의 구독 + + stompSession.send(headers, request); //사회자의 이벤트 발생 + + SharingResponse response = handler.getCompletableFuture() + .get(3L, TimeUnit.SECONDS); + + assertAll( + () -> assertThat(response.eventType()).isEqualTo(request.eventType()), + () -> assertThat(response.data()).isNull() + ); + } + + @ParameterizedTest + @NullSource + void 타이머_타입은_빈_값일_수_없다(CustomizeBoxType boxType) { + long roomId = 1L; + MessageFrameHandler handler = new MessageFrameHandler<>(SharingResponse.class); + Member member = memberGenerator.generate("example@email.com"); + StompHeaders headers = headerGenerator.generateAccessTokenHeader("/app/event/" + roomId, member); + SharingRequest request = new SharingRequest( + TimerEventType.NEXT, + new TimerEventInfoRequest( + boxType, + null, + 2, + 30 + ) + ); + stompSession.subscribe("/room/" + roomId, handler); //청중의 구독 + + stompSession.send(headers, request); //사회자의 이벤트 발생 + + assertThatThrownBy(() -> handler.getCompletableFuture() + .get(2L, TimeUnit.SECONDS)) + .isInstanceOf(TimeoutException.class); } } } diff --git a/src/test/java/com/debatetimer/domain/sharing/TimerEventDataTest.java b/src/test/java/com/debatetimer/domain/sharing/TimerEventDataTest.java new file mode 100644 index 00000000..1811b00e --- /dev/null +++ b/src/test/java/com/debatetimer/domain/sharing/TimerEventDataTest.java @@ -0,0 +1,39 @@ +package com.debatetimer.domain.sharing; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.debatetimer.domain.customize.CustomizeBoxType; +import com.debatetimer.domain.customize.Stance; +import com.debatetimer.exception.custom.DTClientErrorException; +import com.debatetimer.exception.errorcode.ClientErrorCode; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class TimerEventDataTest { + + @Nested + class ValidateCurrentTeam { + + @Test + void 일반_타이머의_경우_현재_발언팀이_입력되면_안된다() { + assertThatThrownBy(() -> new TimerEventData( + CustomizeBoxType.NORMAL, + 2, + Stance.CONS, + 30L + )).isInstanceOf(DTClientErrorException.class) + .hasMessage(ClientErrorCode.INVALID_NORMAL_TIMER_EVENT_DATA.getMessage()); + } + + @Test + void 자유토론_타이머의_경우_현재_발언팀이_입력되어야_한다() { + assertThatThrownBy(() -> new TimerEventData( + CustomizeBoxType.TIME_BASED, + 2, + null, + 30L + )).isInstanceOf(DTClientErrorException.class) + .hasMessage(ClientErrorCode.INVALID_TIME_BASED_TIMER_EVENT_DATA.getMessage()); + } + } +} diff --git a/src/test/java/com/debatetimer/domain/sharing/TimerEventTypeTest.java b/src/test/java/com/debatetimer/domain/sharing/TimerEventTypeTest.java new file mode 100644 index 00000000..b080c112 --- /dev/null +++ b/src/test/java/com/debatetimer/domain/sharing/TimerEventTypeTest.java @@ -0,0 +1,50 @@ +package com.debatetimer.domain.sharing; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.debatetimer.domain.customize.CustomizeBoxType; +import com.debatetimer.exception.custom.DTClientErrorException; +import com.debatetimer.exception.errorcode.ClientErrorCode; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +class TimerEventTypeTest { + + @Nested + class ValidateData { + + @EnumSource( + value = TimerEventType.class, + names = { + "NEXT", + "BEFORE", + "STOP", + "PLAY", + "RESET", + "TEAM_SWITCH", + } + ) + @ParameterizedTest + void 타이머_이벤트_데이터가_존재하여야_한다(TimerEventType eventType) { + assertThatThrownBy(() -> eventType.validateEventData(null)) + .isInstanceOf(DTClientErrorException.class) + .hasMessage(ClientErrorCode.INVALID_TIMER_EVENT.getMessage()); + + } + + @EnumSource(value = TimerEventType.class, names = {"FINISHED"}) + @ParameterizedTest + void 타이머_이벤트_데이터가_존재하지_않아야_한다(TimerEventType eventType) { + TimerEventData timerEventData = new TimerEventData( + CustomizeBoxType.NORMAL, + 2, + null, + 30L + ); + assertThatThrownBy(() -> eventType.validateEventData(timerEventData)) + .isInstanceOf(DTClientErrorException.class) + .hasMessage(ClientErrorCode.INVALID_TIMER_EVENT.getMessage()); + } + } +}