diff --git a/src/main/java/roomescape/member/MemberRepository.java b/src/main/java/roomescape/member/MemberRepository.java index 3ccf48945..8cb0108c8 100644 --- a/src/main/java/roomescape/member/MemberRepository.java +++ b/src/main/java/roomescape/member/MemberRepository.java @@ -4,5 +4,13 @@ import org.springframework.data.repository.CrudRepository; public interface MemberRepository extends CrudRepository { + + default Member findByEmailOrThrow(String email) { + return findByEmail(email).orElseThrow( + () -> new IllegalArgumentException(String.format("Member not found: %s", email))); + } + + Optional findByEmail(String email); + Optional findByEmailAndPassword(String email, String password); } diff --git a/src/main/java/roomescape/reservation/MyReservationResponse.java b/src/main/java/roomescape/reservation/MyReservationResponse.java new file mode 100644 index 000000000..8728135ff --- /dev/null +++ b/src/main/java/roomescape/reservation/MyReservationResponse.java @@ -0,0 +1,33 @@ +package roomescape.reservation; + +import roomescape.waiting.Waiting; +import roomescape.waiting.WaitingWithRank; + +public record MyReservationResponse( + Long id, + String theme, + String date, + String time, + String status +) { + public static MyReservationResponse from(Reservation reservation) { + return new MyReservationResponse( + reservation.getId(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getValue(), + "예약"); + } + + public static MyReservationResponse from(WaitingWithRank waitingWithRank) { + Waiting waiting = waitingWithRank.waiting(); + return new MyReservationResponse( + waiting.getId(), + waiting.getTheme().getName(), + waiting.getDate(), + waiting.getTime().getValue(), + waitingWithRank.rank() + "번째 예약대기" + ); + } +} + diff --git a/src/main/java/roomescape/reservation/Reservation.java b/src/main/java/roomescape/reservation/Reservation.java index f6321299a..4dd216c85 100644 --- a/src/main/java/roomescape/reservation/Reservation.java +++ b/src/main/java/roomescape/reservation/Reservation.java @@ -6,6 +6,7 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; +import roomescape.member.Member; import roomescape.theme.Theme; import roomescape.time.Time; @@ -21,24 +22,18 @@ public class Reservation { private Time time; @ManyToOne(fetch = FetchType.LAZY) private Theme theme; + @ManyToOne(fetch = FetchType.LAZY) + private Member member; - public Reservation(Long id, String name, String date, Time time, Theme theme) { - this.id = id; - this.name = name; - this.date = date; - this.time = time; - this.theme = theme; + public Reservation() { } - public Reservation(String name, String date, Time time, Theme theme) { + public Reservation(String name, String date, Time time, Theme theme, Member member) { this.name = name; this.date = date; this.time = time; this.theme = theme; - } - - public Reservation() { - + this.member = member; } public Long getId() { @@ -60,4 +55,8 @@ public Time getTime() { public Theme getTheme() { return theme; } + + public Member getMember() { + return member; + } } diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 42d50e9c6..0444e7179 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -25,12 +25,16 @@ public List list() { return reservationService.findAll(); } + @GetMapping("/reservations-mine") + public ResponseEntity> readAllByMember(LoginMember loginMember) { + List response = reservationService.readAllByMember(loginMember.email()); + return ResponseEntity.ok(response); + } + @PostMapping("/reservations") public ResponseEntity create(@RequestBody ReservationRequest reservationRequest, LoginMember loginMember) { - reservationRequest.checkName(loginMember.name()); - ReservationResponse reservation = reservationService.save(reservationRequest); - - return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); + ReservationResponse reservation = reservationService.create(reservationRequest, loginMember.email()); + return ResponseEntity.created(URI.create("/reservations/" + reservation.id())).body(reservation); } @DeleteMapping("/reservations/{id}") diff --git a/src/main/java/roomescape/reservation/ReservationRepository.java b/src/main/java/roomescape/reservation/ReservationRepository.java index a71c623e3..8959b2964 100644 --- a/src/main/java/roomescape/reservation/ReservationRepository.java +++ b/src/main/java/roomescape/reservation/ReservationRepository.java @@ -1,12 +1,23 @@ package roomescape.reservation; import java.util.List; -import org.springframework.data.jpa.repository.Query; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.repository.CrudRepository; +import roomescape.member.Member; +import roomescape.theme.Theme; +import roomescape.time.Time; public interface ReservationRepository extends CrudRepository { - @Query("SELECT r FROM Reservation r JOIN FETCH r.theme JOIN FETCH r.time") + + @EntityGraph(attributePaths = {"member"}) + Optional findWithMemberByDateAndTimeAndTheme(String date, Time time, Theme theme); + + @EntityGraph(attributePaths = {"time", "theme"}) List findAll(); + @EntityGraph(attributePaths = {"time", "theme"}) + List findByMember(Member member); + List findByDateAndThemeId(String date, Long themeId); } diff --git a/src/main/java/roomescape/reservation/ReservationRequest.java b/src/main/java/roomescape/reservation/ReservationRequest.java index a0b271444..06993507c 100644 --- a/src/main/java/roomescape/reservation/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/ReservationRequest.java @@ -1,43 +1,17 @@ package roomescape.reservation; -public class ReservationRequest { - private String name; - private String date; - private Long theme; - private Long time; - - public ReservationRequest(String name, String date, Long theme, Long time) { +public record ReservationRequest( + String name, + String date, + Long theme, + Long time +) { + public ReservationRequest { validateDate(date); validateTheme(theme); validateTime(time); - this.name = name; - this.date = date; - this.theme = theme; - this.time = time; - } - - public String getName() { - return name; - } - - public String getDate() { - return date; - } - - public Long getTheme() { - return theme; } - - public Long getTime() { - return time; - } - - public void checkName(String name) { - if (this.name == null) { - this.name = name; - } - } - + private void validateDate(String date) { if (date == null) { throw new IllegalArgumentException("Invalid date"); diff --git a/src/main/java/roomescape/reservation/ReservationResponse.java b/src/main/java/roomescape/reservation/ReservationResponse.java index 41360a363..fd96900e8 100644 --- a/src/main/java/roomescape/reservation/ReservationResponse.java +++ b/src/main/java/roomescape/reservation/ReservationResponse.java @@ -1,37 +1,19 @@ package roomescape.reservation; -public class ReservationResponse { - private Long id; - private String name; - private String theme; - private String date; - private String time; - - public ReservationResponse(Long id, String name, String theme, String date, String time) { - this.id = id; - this.name = name; - this.theme = theme; - this.date = date; - this.time = time; - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public String getTheme() { - return theme; - } - - public String getDate() { - return date; - } - - public String getTime() { - return time; +public record ReservationResponse( + Long id, + String name, + String theme, + String date, + String time +) { + public static ReservationResponse from(Reservation reservation) { + return new ReservationResponse( + reservation.getId(), + reservation.getName(), + reservation.getTheme().getName(), + reservation.getDate(), + reservation.getTime().getValue() + ); } } diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index f32fa7fb3..8bc9dcd8f 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -1,36 +1,71 @@ package roomescape.reservation; import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; import org.springframework.stereotype.Service; +import roomescape.member.Member; +import roomescape.member.MemberRepository; import roomescape.theme.Theme; import roomescape.theme.ThemeRepository; import roomescape.time.Time; import roomescape.time.TimeRepository; +import roomescape.waiting.WaitingRepository; @Service public class ReservationService { private final ReservationRepository reservationRepository; private final TimeRepository timeRepository; private final ThemeRepository themeRepository; + private final MemberRepository memberRepository; + private final WaitingRepository waitingRepository; public ReservationService(ReservationRepository reservationRepository, TimeRepository timeRepository, - ThemeRepository themeRepository) { + ThemeRepository themeRepository, MemberRepository memberRepository, + WaitingRepository waitingRepository) { this.reservationRepository = reservationRepository; this.timeRepository = timeRepository; this.themeRepository = themeRepository; + this.memberRepository = memberRepository; + this.waitingRepository = waitingRepository; } - public ReservationResponse save(ReservationRequest reservationRequest) { - Time time = timeRepository.findByIdOrThrow(reservationRequest.getTime()); - Theme theme = themeRepository.findByIdOrThrow(reservationRequest.getTime()); - Reservation reservation = new Reservation(reservationRequest.getName(), reservationRequest.getDate(), time, - theme); + public List readAllByMember(String email) { + Member member = memberRepository.findByEmailOrThrow(email); + List reservations = getMemberReservation(member); + List waitings = getMemberWaiting(member); + return Stream.concat(reservations.stream(), waitings.stream()).toList(); + } + + public List getMemberReservation(Member member) { + return reservationRepository.findByMember(member).stream() + .map(MyReservationResponse::from) + .toList(); + } - Reservation savedReservation = reservationRepository.save(reservation); + public List getMemberWaiting(Member member) { + return waitingRepository.findAllWithRankByMemberId(member.getId()).stream() + .map(MyReservationResponse::from) + .toList(); + } + + public ReservationResponse create(ReservationRequest reservationRequest, String email) { + Member member = memberRepository.findByEmailOrThrow(email); + Time time = timeRepository.findByIdOrThrow(reservationRequest.time()); + Theme theme = themeRepository.findByIdOrThrow(reservationRequest.theme()); + String name = getNonNullName(reservationRequest.name(), member.getName()); + + Reservation reservation = save(name, reservationRequest.date(), time, theme, member); + return ReservationResponse.from(reservation); + } + + public Reservation save(String name, String date, Time time, Theme theme, Member member) { + Reservation reservation = new Reservation(name, date, time, theme, member); + return reservationRepository.save(reservation); + } - return new ReservationResponse(savedReservation.getId(), savedReservation.getName(), - savedReservation.getTheme().getName(), savedReservation.getDate(), - savedReservation.getTime().getValue()); + private String getNonNullName(String value, String other) { + return Optional.ofNullable(value).orElse(other); } public void deleteById(Long id) { @@ -39,8 +74,7 @@ public void deleteById(Long id) { public List findAll() { return reservationRepository.findAll().stream() - .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), - it.getTime().getValue())) + .map(ReservationResponse::from) .toList(); } } diff --git a/src/main/java/roomescape/waiting/Waiting.java b/src/main/java/roomescape/waiting/Waiting.java new file mode 100644 index 000000000..459062fc8 --- /dev/null +++ b/src/main/java/roomescape/waiting/Waiting.java @@ -0,0 +1,57 @@ +package roomescape.waiting; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import roomescape.member.Member; +import roomescape.theme.Theme; +import roomescape.time.Time; + +@Entity +public class Waiting { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String name; + private String date; + @ManyToOne(fetch = FetchType.LAZY) + private Time time; + @ManyToOne(fetch = FetchType.LAZY) + private Theme theme; + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + public Waiting() { + } + + public Waiting(String name, String date, Time time, Theme theme, Member member) { + this.name = name; + this.date = date; + this.time = time; + this.theme = theme; + this.member = member; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDate() { + return date; + } + + public Time getTime() { + return time; + } + + public Theme getTheme() { + return theme; + } +} diff --git a/src/main/java/roomescape/waiting/WaitingController.java b/src/main/java/roomescape/waiting/WaitingController.java new file mode 100644 index 000000000..1cebe7ce2 --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingController.java @@ -0,0 +1,24 @@ +package roomescape.waiting; + +import java.net.URI; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import roomescape.auth.LoginMember; + +@RestController +public class WaitingController { + private final WaitingService waitingService; + + public WaitingController(WaitingService waitingService) { + this.waitingService = waitingService; + } + + @PostMapping("/waitings") + public ResponseEntity create(@RequestBody WaitingRequest waitingRequest, + LoginMember loginMember) { + WaitingResponse waitingResponse = waitingService.create(waitingRequest, loginMember.email()); + return ResponseEntity.created(URI.create("/waitings/" + waitingResponse.id())).body(waitingResponse); + } +} diff --git a/src/main/java/roomescape/waiting/WaitingRepository.java b/src/main/java/roomescape/waiting/WaitingRepository.java new file mode 100644 index 000000000..a85846e7a --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingRepository.java @@ -0,0 +1,26 @@ +package roomescape.waiting; + +import java.util.List; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import roomescape.member.Member; +import roomescape.theme.Theme; +import roomescape.time.Time; + +@Repository +public interface WaitingRepository extends CrudRepository { + @Query("SELECT new roomescape.waiting.WaitingWithRank(" + + " w, " + + " (SELECT COUNT(w2) " + + " FROM Waiting w2 " + + " WHERE w2.theme = w.theme " + + " AND w2.date = w.date " + + " AND w2.time = w.time " + + " AND w2.id <= w.id)) " + + "FROM Waiting w " + + "WHERE w.member.id = :memberId") + List findAllWithRankByMemberId(Long memberId); + + boolean existsByDateAndTimeAndThemeAndMember(String date, Time time, Theme theme, Member member); +} diff --git a/src/main/java/roomescape/waiting/WaitingRequest.java b/src/main/java/roomescape/waiting/WaitingRequest.java new file mode 100644 index 000000000..0352316b3 --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingRequest.java @@ -0,0 +1,32 @@ +package roomescape.waiting; + +public record WaitingRequest( + String name, + String date, + Long timeId, + Long themeId +) { + public WaitingRequest { + validateDate(date); + validateTime(timeId); + validateTheme(themeId); + } + + private void validateDate(String date) { + if (date == null) { + throw new IllegalArgumentException("Invalid date"); + } + } + + private void validateTime(Long time) { + if (time == null) { + throw new IllegalArgumentException("Invalid time"); + } + } + + private void validateTheme(Long theme) { + if (theme == null) { + throw new IllegalArgumentException("Invalid theme"); + } + } +} diff --git a/src/main/java/roomescape/waiting/WaitingResponse.java b/src/main/java/roomescape/waiting/WaitingResponse.java new file mode 100644 index 000000000..b757d101a --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingResponse.java @@ -0,0 +1,14 @@ +package roomescape.waiting; + +public record WaitingResponse( + Long id, + String name, + String date, + String time, + String theme +) { + public static WaitingResponse from(Waiting waiting) { + return new WaitingResponse(waiting.getId(), waiting.getName(), waiting.getDate(), waiting.getTime().getValue(), + waiting.getTheme().getName()); + } +} diff --git a/src/main/java/roomescape/waiting/WaitingService.java b/src/main/java/roomescape/waiting/WaitingService.java new file mode 100644 index 000000000..f1fd85ea2 --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingService.java @@ -0,0 +1,65 @@ +package roomescape.waiting; + +import org.springframework.stereotype.Service; +import roomescape.member.Member; +import roomescape.member.MemberRepository; +import roomescape.reservation.Reservation; +import roomescape.reservation.ReservationRepository; +import roomescape.theme.Theme; +import roomescape.theme.ThemeRepository; +import roomescape.time.Time; +import roomescape.time.TimeRepository; + +@Service +public class WaitingService { + private final WaitingRepository waitingRepository; + private final TimeRepository timeRepository; + private final ThemeRepository themeRepository; + private final MemberRepository memberRepository; + private final ReservationRepository reservationRepository; + + public WaitingService(WaitingRepository waitingRepository, TimeRepository timeRepository, + ThemeRepository themeRepository, MemberRepository memberRepository, + ReservationRepository reservationRepository) { + this.waitingRepository = waitingRepository; + this.timeRepository = timeRepository; + this.themeRepository = themeRepository; + this.memberRepository = memberRepository; + this.reservationRepository = reservationRepository; + } + + public WaitingResponse create(WaitingRequest waitingRequest, String memberEmail) { + Member member = memberRepository.findByEmailOrThrow(memberEmail); + Time time = timeRepository.findByIdOrThrow(waitingRequest.timeId()); + Theme theme = themeRepository.findByIdOrThrow(waitingRequest.themeId()); + + validateReservationExistsAndNotOwnedByMember(waitingRequest.date(), time, theme, member); + validateDuplicateWaiting(waitingRequest.date(), time, theme, member); + + Waiting waiting = new Waiting(waitingRequest.name(), waitingRequest.date(), time, theme, member); + Waiting savedWaiting = waitingRepository.save(waiting); + return WaitingResponse.from(savedWaiting); + } + + private void validateDuplicateWaiting(String date, Time time, Theme theme, Member member) { + if (hasExistingWaiting(date, time, theme, member)) { + throw new IllegalArgumentException( + String.format("Waiting already exist %s, %s, %s", date, time.getValue(), theme.getName())); + } + } + + private void validateReservationExistsAndNotOwnedByMember(String date, Time time, Theme theme, Member member) { + Reservation reservation = reservationRepository.findWithMemberByDateAndTimeAndTheme(date, time, theme) + .orElseThrow(() -> new IllegalArgumentException( + String.format("Reservation is available %s, %s, %s", date, time.getValue(), theme.getName()))); + + if (reservation.getMember().equals(member)) { + throw new IllegalArgumentException( + String.format("Reservation already exist %s, %s, %s", date, time.getValue(), theme.getName())); + } + } + + public boolean hasExistingWaiting(String date, Time time, Theme theme, Member member) { + return waitingRepository.existsByDateAndTimeAndThemeAndMember(date, time, theme, member); + } +} diff --git a/src/main/java/roomescape/waiting/WaitingWithRank.java b/src/main/java/roomescape/waiting/WaitingWithRank.java new file mode 100644 index 000000000..53bb5b328 --- /dev/null +++ b/src/main/java/roomescape/waiting/WaitingWithRank.java @@ -0,0 +1,7 @@ +package roomescape.waiting; + +public record WaitingWithRank( + Waiting waiting, + Long rank +) { +} diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 45d0d21c6..1c7dbab1a 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -15,7 +15,7 @@ VALUES ('10:00'), ('18:00'), ('20:00'); -INSERT INTO reservation (name, date, time_id, theme_id) -VALUES ('어드민', '2024-03-01', 1, 1), - ('어드민', '2024-03-01', 2, 2), - ('어드민', '2024-03-01', 3, 3); +INSERT INTO reservation (name, date, time_id, theme_id, member_id) +VALUES ('어드민', '2024-03-01', 1, 1, 1), + ('어드민', '2024-03-01', 2, 2, 1), + ('어드민', '2024-03-01', 3, 3, 1); diff --git a/src/test/java/roomescape/MissionStepTest.java b/src/test/java/roomescape/MissionStepTest.java index 0813ec3ae..892680713 100644 --- a/src/test/java/roomescape/MissionStepTest.java +++ b/src/test/java/roomescape/MissionStepTest.java @@ -7,11 +7,14 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; +import roomescape.reservation.MyReservationResponse; import roomescape.reservation.ReservationResponse; +import roomescape.waiting.WaitingResponse; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -63,7 +66,7 @@ public class MissionStepTest { .extract(); assertThat(response.statusCode()).isEqualTo(201); - assertThat(response.as(ReservationResponse.class).getName()).isEqualTo("어드민"); + assertThat(response.as(ReservationResponse.class).name()).isEqualTo("어드민"); params.put("name", "브라운"); @@ -76,7 +79,7 @@ public class MissionStepTest { .extract(); assertThat(adminResponse.statusCode()).isEqualTo(201); - assertThat(adminResponse.as(ReservationResponse.class).getName()).isEqualTo("브라운"); + assertThat(adminResponse.as(ReservationResponse.class).name()).isEqualTo("브라운"); } private String createToken(String email, String password) { @@ -113,4 +116,58 @@ private String createToken(String email, String password) { .then().log().all() .statusCode(200); } + + @Test + void 오단계() { + String adminToken = createToken("admin@email.com", "password"); + + List reservations = RestAssured.given().log().all() + .cookie("token", adminToken) + .get("/reservations-mine") + .then().log().all() + .statusCode(200) + .extract().jsonPath().getList(".", MyReservationResponse.class); + + assertThat(reservations).hasSize(3); + } + + @Test + void 육단계() { + String brownToken = createToken("brown@email.com", "password"); + + Map params = new HashMap<>(); + params.put("date", "2024-03-01"); + params.put("timeId", "1"); + params.put("themeId", "1"); + + // 예약 대기 생성 + WaitingResponse waiting = RestAssured.given().log().all() + .body(params) + .cookie("token", brownToken) + .contentType(ContentType.JSON) + .post("/waitings") + .then().log().all() + .statusCode(201) + .extract().as(WaitingResponse.class); + + // 내 예약 목록 조회 + List myReservations = RestAssured.given().log().all() + .body(params) + .cookie("token", brownToken) + .contentType(ContentType.JSON) + .get("/reservations-mine") + .then().log().all() + .statusCode(200) + .extract().jsonPath().getList(".", MyReservationResponse.class); + + // 예약 대기 상태 확인 + String status = myReservations.stream() + .filter(it -> it.id() == waiting.id()) + .filter(it -> !it.status().equals("예약")) + .findFirst() + .map(it -> it.status()) + .orElse(null); + + assertThat(status).isEqualTo("1번째 예약대기"); + } } diff --git a/src/test/java/roomescape/reservation/CreateReservations.java b/src/test/java/roomescape/reservation/CreateReservationTest.java similarity index 96% rename from src/test/java/roomescape/reservation/CreateReservations.java rename to src/test/java/roomescape/reservation/CreateReservationTest.java index c2d6fc311..896583b54 100644 --- a/src/test/java/roomescape/reservation/CreateReservations.java +++ b/src/test/java/roomescape/reservation/CreateReservationTest.java @@ -13,8 +13,8 @@ import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -class CreateReservations { - +class CreateReservationTest { + @Test void 로그인_상태에서_예약자명이_존재하지않는_경우_로그인_정보명으로_예약된다() { //given @@ -26,7 +26,7 @@ class CreateReservations { ReservationResponse.class); //then - assertThat(reservationResponse.getName()).isEqualTo("어드민"); + assertThat(reservationResponse.name()).isEqualTo("어드민"); } @Test @@ -40,7 +40,7 @@ class CreateReservations { ReservationResponse.class); //then - assertThat(reservationResponse.getName()).isEqualTo("브라운"); + assertThat(reservationResponse.name()).isEqualTo("브라운"); } @Test diff --git a/src/test/java/roomescape/reservation/ReservationRepositoryTest.java b/src/test/java/roomescape/reservation/ReservationRepositoryTest.java new file mode 100644 index 000000000..cbfcf416b --- /dev/null +++ b/src/test/java/roomescape/reservation/ReservationRepositoryTest.java @@ -0,0 +1,67 @@ +package roomescape.reservation; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import roomescape.member.Member; +import roomescape.member.MemberRepository; +import roomescape.theme.Theme; +import roomescape.theme.ThemeRepository; +import roomescape.time.Time; +import roomescape.time.TimeRepository; + +@DataJpaTest +class ReservationRepositoryTest { + @Autowired + private ReservationRepository reservationRepository; + @Autowired + private TimeRepository timeRepository; + @Autowired + private ThemeRepository themeRepository; + @Autowired + private MemberRepository memberRepository; + + private String date = "2024-03-01"; + private Time time; + private Theme theme; + private Member member; + + @BeforeEach + void setUp() { + time = new Time("10:00"); + theme = new Theme("테마1", "테마1입니다."); + member = new Member("admin", "admin@email.com", "password", "ADMIN"); + timeRepository.save(time); + themeRepository.save(theme); + memberRepository.save(member); + } + + @Test + void 해당_날짜_시간_테마에_대한_예약이_존재하지_않는_경우_조회_결과가_비어있다() { + // when + Optional savedReservation = reservationRepository.findWithMemberByDateAndTimeAndTheme(date, time, + theme); + + // then + assertThat(savedReservation).isEmpty(); + } + + @Test + void 해당_날짜_시간_테마에_대한_예약이_존재_하는_경우_사용자와_함께_조회된다() { + // given + Reservation reservation = new Reservation(member.getName(), date, time, theme, member); + reservationRepository.save(reservation); + + // when + Optional savedReservation = reservationRepository.findWithMemberByDateAndTimeAndTheme(date, time, + theme); + + // then + assertThat(savedReservation).isNotEmpty(); + assertThat(savedReservation.get().getMember()).isEqualTo(member); + } +} diff --git a/src/test/java/roomescape/reservation/ReservationServiceTest.java b/src/test/java/roomescape/reservation/ReservationServiceTest.java index ad1211d68..cf4a0fd82 100644 --- a/src/test/java/roomescape/reservation/ReservationServiceTest.java +++ b/src/test/java/roomescape/reservation/ReservationServiceTest.java @@ -16,11 +16,20 @@ class ReservationServiceTest { private ReservationService reservationService; @Test - void 추가_쿼리_없이_예약_목록_응답_반환_성공() { + void 추가_쿼리_없이_모든_예약_목록_응답_반환_성공() { // when List reservations = reservationService.findAll(); // then assertThat(reservations.size()).isEqualTo(3); } + + @Test + void 추가_쿼리_없이_내_예약_목록_응답_반환_성공() { + // when + List reservations = reservationService.readAllByMember("admin@email.com"); + + // then + assertThat(reservations.size()).isEqualTo(3); + } } diff --git a/src/test/java/roomescape/waiting/WaitingControllerTest.java b/src/test/java/roomescape/waiting/WaitingControllerTest.java new file mode 100644 index 000000000..aa141732d --- /dev/null +++ b/src/test/java/roomescape/waiting/WaitingControllerTest.java @@ -0,0 +1,110 @@ +package roomescape.waiting; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class WaitingControllerTest { + + @Test + void 예약이_존재하며_본인의_예약_및_예약_대기가_존재하지_않는_경우_예약_대기_생성에_성공한다() { + // given + String brownToken = createToken("brown@email.com", "password"); + Map waitingRequest = createPostWaitingRequest("브라운", "2024-03-01", "1", "1"); + + // when + ExtractableResponse response = sendPostWaitingRequest(brownToken, waitingRequest); + WaitingResponse waitingResponse = response.as(WaitingResponse.class); + + // then + assertThat(response.statusCode()).isEqualTo(201); + assertThat(waitingResponse.name()).isEqualTo("브라운"); + assertThat(waitingResponse.date()).isEqualTo("2024-03-01"); + assertThat(waitingResponse.time()).isEqualTo("10:00"); + assertThat(waitingResponse.theme()).isEqualTo("테마1"); + } + + @Test + void 본인의_예약이_존재하는_경우_예약_대기_생성에_실패한다() { + // given + String adminToken = createToken("admin@email.com", "password"); + Map waitingRequest = createPostWaitingRequest("어드민", "2024-03-01", "1", "1"); + + // when + ExtractableResponse response = sendPostWaitingRequest(adminToken, waitingRequest); + + // then + assertThat(response.statusCode()).isEqualTo(400); + } + + @Test + void 본인의_예약_대기가_존재하는_경우_예약_대기_생성에_실패한다() { + // given + String brownToken = createToken("brown@email.com", "password"); + Map waitingRequest = createPostWaitingRequest("어드민", "2024-03-01", "1", "1"); + sendPostWaitingRequest(brownToken, waitingRequest); + + // when + ExtractableResponse duplicateResponse = sendPostWaitingRequest(brownToken, waitingRequest); + + // then + assertThat(duplicateResponse.statusCode()).isEqualTo(400); + } + + @Test + void 예약이_존재하지_않는_경우_예약_대기_생성에_실패한다() { + // given + String brownToken = createToken("brown@email.com", "password"); + Map waitingRequest = createPostWaitingRequest("브라운", "2024-03-02", "1", "1"); + + // when + ExtractableResponse response = sendPostWaitingRequest(brownToken, waitingRequest); + + // then + assertThat(response.statusCode()).isEqualTo(400); + } + + private Map createPostWaitingRequest(String name, String date, String timeId, String themeId) { + Map request = new HashMap<>(); + request.put("name", name); + request.put("date", date); + request.put("timeId", timeId); + request.put("themeId", themeId); + return request; + } + + private ExtractableResponse sendPostWaitingRequest(String token, Map param) { + return RestAssured.given().log().all() + .cookie("token", token) + .body(param) + .contentType(ContentType.JSON) + .post("/waitings") + .then().log().all().extract(); + } + + private String createToken(String email, String password) { + Map params = new HashMap<>(); + params.put("email", email); + params.put("password", password); + + ExtractableResponse response = RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/login") + .then().log().all() + .statusCode(200) + .extract(); + + return response.headers().get("Set-Cookie").getValue().split(";")[0].split("=")[1]; + } +} diff --git a/src/test/java/roomescape/waiting/WaitingRepositoryTest.java b/src/test/java/roomescape/waiting/WaitingRepositoryTest.java new file mode 100644 index 000000000..8c76c49ed --- /dev/null +++ b/src/test/java/roomescape/waiting/WaitingRepositoryTest.java @@ -0,0 +1,88 @@ +package roomescape.waiting; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import roomescape.member.Member; +import roomescape.member.MemberRepository; +import roomescape.theme.Theme; +import roomescape.theme.ThemeRepository; +import roomescape.time.Time; +import roomescape.time.TimeRepository; + +@DataJpaTest +class WaitingRepositoryTest { + @Autowired + private TimeRepository timeRepository; + @Autowired + private ThemeRepository themeRepository; + @Autowired + private MemberRepository memberRepository; + @Autowired + private WaitingRepository waitingRepository; + + private Member admin; + private Member brown; + private Time time; + private Theme theme; + + @BeforeEach + void setUp() { + admin = new Member("어드민", "admin@email.com", "password", "ADMIN"); + brown = new Member("브라운", "brown@email.com", "password", "USER"); + time = new Time("10:00"); + theme = new Theme("테마1", "테마1입니다."); + + memberRepository.save(admin); + memberRepository.save(brown); + timeRepository.save(time); + themeRepository.save(theme); + } + + @Test + void 순위를_포함한_예약_대기_조회_성공() { + // given + String date = "2024-03-01"; + Waiting adminWaiting = new Waiting(admin.getName(), date, time, theme, admin); + Waiting brownWaiting = new Waiting(brown.getName(), date, time, theme, brown); + waitingRepository.save(adminWaiting); + waitingRepository.save(brownWaiting); + + // when + List adminWaitings = waitingRepository.findAllWithRankByMemberId(admin.getId()); + List brownWaitings = waitingRepository.findAllWithRankByMemberId(brown.getId()); + + // then + assertThat(adminWaitings.size()).isEqualTo(1); + assertThat(adminWaitings.get(0).rank()).isEqualTo(1); + assertThat(brownWaitings.size()).isEqualTo(1); + assertThat(brownWaitings.get(0).rank()).isEqualTo(2); + } + + @Test + void 해당_날짜_시간_테마_사용자에_대한_예약_대기가_존재하지_않는_경우_거짓을_반환한다() { + // when + boolean exists = waitingRepository.existsByDateAndTimeAndThemeAndMember("2024-03-01", time, theme, admin); + + // then + assertThat(exists).isFalse(); + } + + @Test + void 해당_날짜_시간_테마_사용자에_대한_예약_대기가_존재하는_경우_참을_반환한다() { + // given + String date = "2024-03-01"; + Waiting waiting = new Waiting(admin.getName(), date, time, theme, admin); + waitingRepository.save(waiting); + + // when + boolean exists = waitingRepository.existsByDateAndTimeAndThemeAndMember(date, time, theme, admin); + + // then + assertThat(exists).isTrue(); + } +}