diff --git a/src/docs/asciidoc/api/room.adoc b/src/docs/asciidoc/api/room.adoc index 9248ebd..a951d25 100644 --- a/src/docs/asciidoc/api/room.adoc +++ b/src/docs/asciidoc/api/room.adoc @@ -43,3 +43,17 @@ include::{snippets}/create-room-fail-single-room-participant-violation/request-f include::{snippets}/create-room-fail-single-room-participant-violation/http-response.adoc[] include::{snippets}/create-room-fail-single-room-participant-violation/response-fields.adoc[] + +{nbsp} + +[[fetch-room-list-success]] +=== 방 목록 조회 성공 + +==== HTTP Request + +include::{snippets}/fetch-room-list-success/http-request.adoc[] + +==== HTTP Response + +include::{snippets}/fetch-room-list-success/http-response.adoc[] +include::{snippets}/fetch-room-list-success/response-fields.adoc[] diff --git a/src/main/java/site/youtogether/room/application/RoomService.java b/src/main/java/site/youtogether/room/application/RoomService.java index fa0333d..a9b252f 100644 --- a/src/main/java/site/youtogether/room/application/RoomService.java +++ b/src/main/java/site/youtogether/room/application/RoomService.java @@ -1,10 +1,12 @@ package site.youtogether.room.application; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import site.youtogether.room.Room; import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomList; import site.youtogether.room.dto.RoomSettings; import site.youtogether.room.infrastructure.RoomStorage; import site.youtogether.user.Role; @@ -40,4 +42,8 @@ public RoomCode create(String sessionCode, String address, RoomSettings roomSett return new RoomCode(room); } + public RoomList fetchAll(Pageable pageable, String search) { + return null; + } + } diff --git a/src/main/java/site/youtogether/room/dto/RoomDetail.java b/src/main/java/site/youtogether/room/dto/RoomDetail.java new file mode 100644 index 0000000..568485a --- /dev/null +++ b/src/main/java/site/youtogether/room/dto/RoomDetail.java @@ -0,0 +1,26 @@ +package site.youtogether.room.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class RoomDetail { + + private String roomCode; + private String roomTitle; + private String videoTitle; + private String videoThumbnail; + private int capacity; + private int currentParticipant; + + @Builder + public RoomDetail(String roomCode, String roomTitle, String videoTitle, String videoThumbnail, int capacity, int currentParticipant) { + this.roomCode = roomCode; + this.roomTitle = roomTitle; + this.videoTitle = videoTitle; + this.videoThumbnail = videoThumbnail; + this.capacity = capacity; + this.currentParticipant = currentParticipant; + } + +} diff --git a/src/main/java/site/youtogether/room/dto/RoomList.java b/src/main/java/site/youtogether/room/dto/RoomList.java new file mode 100644 index 0000000..42b090d --- /dev/null +++ b/src/main/java/site/youtogether/room/dto/RoomList.java @@ -0,0 +1,31 @@ +package site.youtogether.room.dto; + +import java.util.List; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class RoomList { + + private int pageNumber; + private int pageSize; + private int totalData; + private int totalPage; + private boolean hasPrevious; + private boolean hasNext; + + private List rooms; + + @Builder + public RoomList(int pageNumber, int pageSize, int totalData, int totalPage, boolean hasPrevious, boolean hasNext, List rooms) { + this.pageNumber = pageNumber; + this.pageSize = pageSize; + this.totalData = totalData; + this.totalPage = totalPage; + this.hasPrevious = hasPrevious; + this.hasNext = hasNext; + this.rooms = rooms; + } + +} diff --git a/src/main/java/site/youtogether/room/presentation/RoomController.java b/src/main/java/site/youtogether/room/presentation/RoomController.java index 8e2ba32..f564a63 100644 --- a/src/main/java/site/youtogether/room/presentation/RoomController.java +++ b/src/main/java/site/youtogether/room/presentation/RoomController.java @@ -2,13 +2,17 @@ import static site.youtogether.util.AppConstants.*; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import jakarta.servlet.http.Cookie; @@ -20,6 +24,7 @@ import site.youtogether.resolver.Address; import site.youtogether.room.application.RoomService; import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomList; import site.youtogether.room.dto.RoomSettings; import site.youtogether.util.RandomUtil; import site.youtogether.util.api.ApiResponse; @@ -61,4 +66,12 @@ public ResponseEntity> createRoom(@CookieValue(value = SES .body(ApiResponse.created(ResponseResult.ROOM_CREATION_SUCCESS, roomCode)); } + @GetMapping("/rooms") + public ResponseEntity> fetchRoomList(@PageableDefault Pageable pageable, @RequestParam(required = false) String search) { + RoomList roomList = roomService.fetchAll(pageable, search); + + return ResponseEntity.ok() + .body(ApiResponse.ok(ResponseResult.ROOM_LIST_FETCH_SUCCESS, roomList)); + } + } diff --git a/src/main/java/site/youtogether/util/api/ResponseResult.java b/src/main/java/site/youtogether/util/api/ResponseResult.java index c615ec1..3323025 100644 --- a/src/main/java/site/youtogether/util/api/ResponseResult.java +++ b/src/main/java/site/youtogether/util/api/ResponseResult.java @@ -9,7 +9,8 @@ public enum ResponseResult { EXCEPTION_OCCURRED("예외가 발생했습니다"), // Room - ROOM_CREATION_SUCCESS("방 생성에 성공했습니다"); + ROOM_CREATION_SUCCESS("방 생성에 성공했습니다"), + ROOM_LIST_FETCH_SUCCESS("방 목록 조회에 성공했습니다"); private final String description; diff --git a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java index e1bf9f2..b8c5301 100644 --- a/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java +++ b/src/test/java/site/youtogether/room/presentation/RoomControllerTest.java @@ -9,8 +9,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static site.youtogether.exception.ErrorType.*; +import java.util.List; +import java.util.stream.IntStream; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.restdocs.payload.JsonFieldType; @@ -19,6 +23,8 @@ import site.youtogether.RestDocsSupport; import site.youtogether.exception.room.SingleRoomParticipationViolationException; import site.youtogether.room.dto.RoomCode; +import site.youtogether.room.dto.RoomDetail; +import site.youtogether.room.dto.RoomList; import site.youtogether.room.dto.RoomSettings; import site.youtogether.util.api.ResponseResult; @@ -164,4 +170,83 @@ void createRoomFail_SingleRoomParticipantViolation() throws Exception { )); } + @Test + @DisplayName("방 목록 조회 성공") + void fetchRoomListSuccess() throws Exception { + // given + // Setting up response data for the fetched room list + RoomList roomList = RoomList.builder() + .pageNumber(0) + .pageSize(10) + .totalData(3) + .totalPage(1) + .hasPrevious(false) + .hasNext(false) + .rooms(generateRoomDetails(3)) + .build(); + given(roomService.fetchAll(any(Pageable.class), anyString())) + .willReturn(roomList); + + // when / then + mockMvc.perform(get("/rooms") + .param("page", "0") + .param("size", "10") + .param("search", "침착")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(HttpStatus.OK.value())) + .andExpect(jsonPath("$.status").value(HttpStatus.OK.getReasonPhrase())) + .andExpect(jsonPath("$.result").value(ResponseResult.ROOM_LIST_FETCH_SUCCESS.getDescription())) + .andExpect(jsonPath("$.result").value(ResponseResult.ROOM_LIST_FETCH_SUCCESS.getDescription())) + .andExpect(jsonPath("$.data.pageNumber").value(roomList.getPageNumber())) + .andExpect(jsonPath("$.data.pageSize").value(roomList.getPageSize())) + .andExpect(jsonPath("$.data.totalData").value(roomList.getTotalData())) + .andExpect(jsonPath("$.data.totalPage").value(roomList.getTotalPage())) + .andExpect(jsonPath("$.data.hasPrevious").value(roomList.isHasPrevious())) + .andExpect(jsonPath("$.data.hasNext").value(roomList.isHasNext())) + .andExpect(jsonPath("$.data.rooms[0].roomCode").value(roomList.getRooms().get(0).getRoomCode())) + .andExpect(jsonPath("$.data.rooms[0].roomTitle").value(roomList.getRooms().get(0).getRoomTitle())) + .andExpect(jsonPath("$.data.rooms[0].videoTitle").value(roomList.getRooms().get(0).getVideoTitle())) + .andExpect(jsonPath("$.data.rooms[0].videoThumbnail").value(roomList.getRooms().get(0).getVideoThumbnail())) + .andExpect(jsonPath("$.data.rooms[0].capacity").value(roomList.getRooms().get(0).getCapacity())) + .andExpect(jsonPath("$.data.rooms[0].currentParticipant").value(roomList.getRooms().get(0).getCurrentParticipant())) + .andDo(document("fetch-room-list-success", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + responseFields( + fieldWithPath("code").type(JsonFieldType.NUMBER).description("코드"), + fieldWithPath("status").type(JsonFieldType.STRING).description("상태"), + fieldWithPath("result").type(JsonFieldType.STRING).description("결과"), + fieldWithPath("data").type(JsonFieldType.OBJECT).description("응답 데이터"), + fieldWithPath("data.pageNumber").type(JsonFieldType.NUMBER).description("현재 페이지"), + fieldWithPath("data.pageSize").type(JsonFieldType.NUMBER).description("페이지 크기"), + fieldWithPath("data.totalData").type(JsonFieldType.NUMBER).description("총 데이터 수"), + fieldWithPath("data.totalPage").type(JsonFieldType.NUMBER).description("총 페이지 수"), + fieldWithPath("data.hasPrevious").type(JsonFieldType.BOOLEAN).description("이전 페이지 존재 여부"), + fieldWithPath("data.hasNext").type(JsonFieldType.BOOLEAN).description("다음 페이지 존재 여부"), + fieldWithPath("data.rooms").type(JsonFieldType.ARRAY).description("방 목록 조회 결과"), + fieldWithPath("data.rooms[].roomCode").type(JsonFieldType.STRING).description("방 식별 코드"), + fieldWithPath("data.rooms[].roomTitle").type(JsonFieldType.STRING).description("방 제목"), + fieldWithPath("data.rooms[].videoTitle").type(JsonFieldType.STRING).description("영상 제목"), + fieldWithPath("data.rooms[].videoThumbnail").type(JsonFieldType.STRING).description("영상 썸네일 URL"), + fieldWithPath("data.rooms[].capacity").type(JsonFieldType.NUMBER).description("정원"), + fieldWithPath("data.rooms[].currentParticipant").type(JsonFieldType.NUMBER).description("현재 참여자 수") + ) + )); + } + + private List generateRoomDetails(int count) { + return IntStream.rangeClosed(1, count) + .mapToObj(number -> RoomDetail.builder() + .roomCode("1e7050f7d" + number) + .roomTitle("2023년 침착맨 정주행 " + number) + .videoTitle("궤도 '연애의 과학' 특강 " + number) + .videoThumbnail( + "https://i.ytimg.com/vi/sl7ih5rLfYM/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDbjCXvhBJSBKs9bX_XMy_EfUtvSw") + .capacity(10) + .currentParticipant(6) + .build()) + .toList(); + } + }