From 2a0379857ce7773c6c4a45b8e385607c8b68454a Mon Sep 17 00:00:00 2001 From: pilyang Date: Thu, 27 Jul 2023 20:22:42 +0900 Subject: [PATCH 1/8] =?UTF-8?q?test:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=94=BD=EC=8A=A4=EC=B3=90=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teambyteam/fixtures/ScheduleFixtures.java | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 backend/src/test/java/team/teamby/teambyteam/fixtures/ScheduleFixtures.java diff --git a/backend/src/test/java/team/teamby/teambyteam/fixtures/ScheduleFixtures.java b/backend/src/test/java/team/teamby/teambyteam/fixtures/ScheduleFixtures.java deleted file mode 100644 index 7e457454a..000000000 --- a/backend/src/test/java/team/teamby/teambyteam/fixtures/ScheduleFixtures.java +++ /dev/null @@ -1,34 +0,0 @@ -package team.teamby.teambyteam.fixtures; - -import team.teamby.teambyteam.schedule.application.dto.ScheduleRegisterRequest; -import team.teamby.teambyteam.schedule.application.dto.ScheduleUpdateRequest; -import team.teamby.teambyteam.schedule.domain.Schedule; -import team.teamby.teambyteam.schedule.domain.vo.Span; -import team.teamby.teambyteam.schedule.domain.vo.Title; - -import java.time.LocalDateTime; - -public class ScheduleFixtures { - - public static class Schedule1_N_Hour { - - public static final Long ID = 1L; - public static final String TITLE = "1번 팀플 N시간 일정"; - public static final String UPDATE_TITLE = "업데이트 1번 팀플 N시간 일정"; - public static final Long TEAM_PLACE_ID = 1L; - public static final LocalDateTime START_DATE_TIME = LocalDateTime.of(2023, 7, 12, 10, 0, 0); - public static final LocalDateTime END_DATE_TIME = LocalDateTime.of(2023, 7, 12, 18, 0, 0); - public static final LocalDateTime UPDATE_END_DATE_TIME = LocalDateTime.of(2023, 7, 13, 15, 0, 0); - - public static final ScheduleRegisterRequest REQUEST = new ScheduleRegisterRequest(TITLE, START_DATE_TIME, END_DATE_TIME); - public static final ScheduleUpdateRequest UPDATE_REQUEST = new ScheduleUpdateRequest(UPDATE_TITLE, START_DATE_TIME, UPDATE_END_DATE_TIME); - - public static Schedule ENTITY() { - return new Schedule(TEAM_PLACE_ID, new Title(TITLE), new Span(START_DATE_TIME, END_DATE_TIME)); - } - - public static Schedule UPDATE_ENTITY() { - return new Schedule(TEAM_PLACE_ID, new Title(UPDATE_TITLE), new Span(START_DATE_TIME, UPDATE_END_DATE_TIME)); - } - } -} From 0abfbe516f5ba748272e1557719007d7d2a1fff9 Mon Sep 17 00:00:00 2001 From: pilyang Date: Thu, 27 Jul 2023 20:30:35 +0900 Subject: [PATCH 2/8] =?UTF-8?q?test:=20Feed=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=84=B8=ED=8C=85=20=EB=B0=8F=20=ED=94=BD?= =?UTF-8?q?=EC=8A=A4=EC=B3=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/builder/BuilderSupporter.java | 8 +++++++ .../common/builder/TestFixtureBuilder.java | 9 ++++++++ .../common/fixtures/FeedThreadFixtures.java | 22 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java diff --git a/backend/src/test/java/team/teamby/teambyteam/common/builder/BuilderSupporter.java b/backend/src/test/java/team/teamby/teambyteam/common/builder/BuilderSupporter.java index 6205bf31b..d82403ea2 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/builder/BuilderSupporter.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/builder/BuilderSupporter.java @@ -2,6 +2,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import team.teamby.teambyteam.feed.domain.FeedRepository; import team.teamby.teambyteam.member.domain.MemberRepository; import team.teamby.teambyteam.member.domain.MemberTeamPlaceRepository; import team.teamby.teambyteam.schedule.domain.ScheduleRepository; @@ -22,6 +23,9 @@ public class BuilderSupporter { @Autowired private TeamPlaceRepository teamPlaceRepository; + @Autowired + private FeedRepository feedRepository; + public ScheduleRepository scheduleRepository() { return scheduleRepository; } @@ -37,4 +41,8 @@ public MemberTeamPlaceRepository memberTeamPlaceRepository() { public TeamPlaceRepository teamPlaceRepository() { return teamPlaceRepository; } + + public FeedRepository feedRepository() { + return feedRepository; + } } diff --git a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java index 8c9358758..2fbae0b53 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java @@ -2,6 +2,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import team.teamby.teambyteam.feed.domain.Feed; import team.teamby.teambyteam.member.domain.Member; import team.teamby.teambyteam.member.domain.MemberTeamPlace; import team.teamby.teambyteam.schedule.domain.Schedule; @@ -46,4 +47,12 @@ public List buildMemberTeamPlaces(final List m public List buildTeamPlaces(final List teamPlaces) { return bs.teamPlaceRepository().saveAll(teamPlaces); } + + public Feed buildFeed(final Feed feed) { + return bs.feedRepository().save(feed); + } + + public List buildFeeds(final List feeds) { + return bs.feedRepository().saveAll(feeds); + } } diff --git a/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java new file mode 100644 index 000000000..0c4818603 --- /dev/null +++ b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java @@ -0,0 +1,22 @@ +package team.teamby.teambyteam.common.fixtures; + +import team.teamby.teambyteam.feed.domain.FeedThread; +import team.teamby.teambyteam.feed.domain.vo.Content; + +public class FeedThreadFixtures { + + /** + * CONTENT + */ + public static final String HELLO_CONTENT = "Hello"; + public static final String HI_CONTENT = "Hi"; + + + public static FeedThread HELLO_THREAD(final Long teamPlaceId, final Long authorId) { + return new FeedThread(teamPlaceId, new Content(HELLO_CONTENT), authorId); + } + + public static FeedThread HI_THREAD(final Long teamPlaceId, final Long authorId) { + return new FeedThread(teamPlaceId, new Content(HI_CONTENT), authorId); + } +} From 10fefbfa1bdea4376da15132b16de48f834c0ef6 Mon Sep 17 00:00:00 2001 From: pilyang Date: Thu, 27 Jul 2023 20:53:57 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=ED=94=BC=EB=93=9C=EC=97=90=20?= =?UTF-8?q?=EC=8A=A4=EB=A0=88=EB=93=9C=20=EC=9E=91=EC=84=B1=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/application/FeedThreadService.java | 40 +++++++++++++ .../dto/FeedThreadWritingRequest.java | 9 +++ .../teambyteam/feed/domain/vo/Content.java | 2 +- .../teambyteam/member/domain/IdOnly.java | 4 ++ .../member/domain/MemberRepository.java | 2 + .../common/fixtures/FeedThreadFixtures.java | 10 ++++ .../application/FeedThreadServiceTest.java | 60 +++++++++++++++++++ 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/team/teamby/teambyteam/feed/application/FeedThreadService.java create mode 100644 backend/src/main/java/team/teamby/teambyteam/feed/application/dto/FeedThreadWritingRequest.java create mode 100644 backend/src/main/java/team/teamby/teambyteam/member/domain/IdOnly.java create mode 100644 backend/src/test/java/team/teamby/teambyteam/feed/application/FeedThreadServiceTest.java diff --git a/backend/src/main/java/team/teamby/teambyteam/feed/application/FeedThreadService.java b/backend/src/main/java/team/teamby/teambyteam/feed/application/FeedThreadService.java new file mode 100644 index 000000000..5e4feb81c --- /dev/null +++ b/backend/src/main/java/team/teamby/teambyteam/feed/application/FeedThreadService.java @@ -0,0 +1,40 @@ +package team.teamby.teambyteam.feed.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.feed.domain.Feed; +import team.teamby.teambyteam.feed.domain.FeedRepository; +import team.teamby.teambyteam.feed.domain.FeedThread; +import team.teamby.teambyteam.feed.domain.vo.Content; +import team.teamby.teambyteam.member.configuration.dto.MemberEmailDto; +import team.teamby.teambyteam.member.domain.IdOnly; +import team.teamby.teambyteam.member.domain.MemberRepository; +import team.teamby.teambyteam.member.domain.vo.Email; +import team.teamby.teambyteam.member.exception.MemberException; + +@Service +@Transactional +@RequiredArgsConstructor +public class FeedThreadService { + + private final FeedRepository feedRepository; + private final MemberRepository memberRepository; + + public Long write( + final FeedThreadWritingRequest feedThreadWritingRequest, + final MemberEmailDto memberEmailDto, + final Long teamPlaceId + ) { + + final Content content = new Content(feedThreadWritingRequest.content()); + final IdOnly memberId = memberRepository.findIdByEmail(new Email(memberEmailDto.email())) + .orElseThrow(MemberException.MemberNotFoundException::new); + + final Feed feed = new FeedThread(teamPlaceId, content, memberId.id()); + + final Feed savedFeed = feedRepository.save(feed); + return savedFeed.getId(); + } +} diff --git a/backend/src/main/java/team/teamby/teambyteam/feed/application/dto/FeedThreadWritingRequest.java b/backend/src/main/java/team/teamby/teambyteam/feed/application/dto/FeedThreadWritingRequest.java new file mode 100644 index 000000000..d086c5ee0 --- /dev/null +++ b/backend/src/main/java/team/teamby/teambyteam/feed/application/dto/FeedThreadWritingRequest.java @@ -0,0 +1,9 @@ +package team.teamby.teambyteam.feed.application.dto; + +import jakarta.validation.constraints.NotBlank; + +public record FeedThreadWritingRequest( + @NotBlank(message = "스레드 내용이 있어야 합니다.") + String content +) { +} diff --git a/backend/src/main/java/team/teamby/teambyteam/feed/domain/vo/Content.java b/backend/src/main/java/team/teamby/teambyteam/feed/domain/vo/Content.java index acfe2c47d..88f11620d 100644 --- a/backend/src/main/java/team/teamby/teambyteam/feed/domain/vo/Content.java +++ b/backend/src/main/java/team/teamby/teambyteam/feed/domain/vo/Content.java @@ -22,7 +22,7 @@ public class Content { @Lob private String value; - public Content(String value) { + public Content(final String value) { validate(value); this.value = value; } diff --git a/backend/src/main/java/team/teamby/teambyteam/member/domain/IdOnly.java b/backend/src/main/java/team/teamby/teambyteam/member/domain/IdOnly.java new file mode 100644 index 000000000..d87dee95f --- /dev/null +++ b/backend/src/main/java/team/teamby/teambyteam/member/domain/IdOnly.java @@ -0,0 +1,4 @@ +package team.teamby.teambyteam.member.domain; + +public record IdOnly(Long id) { +} diff --git a/backend/src/main/java/team/teamby/teambyteam/member/domain/MemberRepository.java b/backend/src/main/java/team/teamby/teambyteam/member/domain/MemberRepository.java index 6c97745c3..46074e675 100644 --- a/backend/src/main/java/team/teamby/teambyteam/member/domain/MemberRepository.java +++ b/backend/src/main/java/team/teamby/teambyteam/member/domain/MemberRepository.java @@ -10,4 +10,6 @@ public interface MemberRepository extends JpaRepository { boolean existsByEmail(Email email); Optional findByEmail(Email email); + + Optional findIdByEmail(Email email); } diff --git a/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java index 0c4818603..f3ab3c483 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/FeedThreadFixtures.java @@ -1,17 +1,27 @@ package team.teamby.teambyteam.common.fixtures; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; import team.teamby.teambyteam.feed.domain.FeedThread; import team.teamby.teambyteam.feed.domain.vo.Content; public class FeedThreadFixtures { + /** * CONTENT */ public static final String HELLO_CONTENT = "Hello"; public static final String HI_CONTENT = "Hi"; + /** + * REQUEST + */ + public static final FeedThreadWritingRequest HELLO_WRITING_REQUEST = new FeedThreadWritingRequest(HELLO_CONTENT); + public static final FeedThreadWritingRequest HI_WRITING_REQUEST = new FeedThreadWritingRequest(HI_CONTENT); + /** + * ENTITY + */ public static FeedThread HELLO_THREAD(final Long teamPlaceId, final Long authorId) { return new FeedThread(teamPlaceId, new Content(HELLO_CONTENT), authorId); } diff --git a/backend/src/test/java/team/teamby/teambyteam/feed/application/FeedThreadServiceTest.java b/backend/src/test/java/team/teamby/teambyteam/feed/application/FeedThreadServiceTest.java new file mode 100644 index 000000000..5178beda6 --- /dev/null +++ b/backend/src/test/java/team/teamby/teambyteam/feed/application/FeedThreadServiceTest.java @@ -0,0 +1,60 @@ +package team.teamby.teambyteam.feed.application; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import team.teamby.teambyteam.common.ServiceTest; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.member.configuration.dto.MemberEmailDto; +import team.teamby.teambyteam.member.domain.Member; +import team.teamby.teambyteam.member.exception.MemberException; +import team.teamby.teambyteam.teamplace.domain.TeamPlace; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static team.teamby.teambyteam.common.fixtures.FeedThreadFixtures.HELLO_WRITING_REQUEST; +import static team.teamby.teambyteam.common.fixtures.MemberFixtures.PHILIP; +import static team.teamby.teambyteam.common.fixtures.TeamPlaceFixtures.ENGLISH_TEAM_PLACE; + +class FeedThreadServiceTest extends ServiceTest { + + @Autowired + private FeedThreadService feedThreadService; + + @Nested + @DisplayName("피드에 스레드 작성시") + class WriteThread { + + @Test + @DisplayName("피드에 스레드를 작성한다.") + void writeThreadSuccess() { + // given + final TeamPlace teamPlace = testFixtureBuilder.buildTeamPlace(ENGLISH_TEAM_PLACE()); + final Member author = testFixtureBuilder.buildMember(PHILIP()); + final FeedThreadWritingRequest request = HELLO_WRITING_REQUEST; + + // when + final Long feedId = feedThreadService.write(request, new MemberEmailDto(author.getEmail().getValue()), teamPlace.getId()); + + //then + assertThat(feedId).isNotNull(); + } + + @Test + @DisplayName("존재하지 않는 멤버로 요청을 보내게 되면 예외가 발생한다.") + void failUnAuthorized() { + // given + final TeamPlace teamPlace = testFixtureBuilder.buildTeamPlace(ENGLISH_TEAM_PLACE()); + final Member author = testFixtureBuilder.buildMember(PHILIP()); + final FeedThreadWritingRequest request = HELLO_WRITING_REQUEST; + + // when & then + assertThatThrownBy(() -> feedThreadService.write(request, new MemberEmailDto(author.getEmail().getValue() + "x"), teamPlace.getId())) + .isInstanceOf(MemberException.MemberNotFoundException.class) + .hasMessage("조회한 멤버가 존재하지 않습니다."); + } + + } + +} From f0d1e0b70cdde3e790162ea3f3d8bf9a8822fda7 Mon Sep 17 00:00:00 2001 From: pilyang Date: Fri, 28 Jul 2023 13:56:24 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/FeedThreadController.java | 36 ++++++ .../common/builder/TestFixtureBuilder.java | 23 ++++ .../FeedThreadAcceptanceFixtures.java | 29 +++++ .../acceptance/FeedThreadAcceptanceTest.java | 107 ++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 backend/src/main/java/team/teamby/teambyteam/feed/presentation/FeedThreadController.java create mode 100644 backend/src/test/java/team/teamby/teambyteam/common/fixtures/acceptance/FeedThreadAcceptanceFixtures.java create mode 100644 backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java diff --git a/backend/src/main/java/team/teamby/teambyteam/feed/presentation/FeedThreadController.java b/backend/src/main/java/team/teamby/teambyteam/feed/presentation/FeedThreadController.java new file mode 100644 index 000000000..cfe94c650 --- /dev/null +++ b/backend/src/main/java/team/teamby/teambyteam/feed/presentation/FeedThreadController.java @@ -0,0 +1,36 @@ +package team.teamby.teambyteam.feed.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import team.teamby.teambyteam.feed.application.FeedThreadService; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.member.configuration.AuthPrincipal; +import team.teamby.teambyteam.member.configuration.dto.MemberEmailDto; + +import java.net.URI; + +@RestController +@RequestMapping("/api/team-place") +@RequiredArgsConstructor +public class FeedThreadController { + + private final FeedThreadService feedThreadService; + + @PostMapping("/{teamPlaceId}/feed/threads") + public ResponseEntity write( + @RequestBody @Valid final FeedThreadWritingRequest request, + @AuthPrincipal final MemberEmailDto memberEmailDto, + @PathVariable final Long teamPlaceId + ) { + final Long threadId = feedThreadService.write(request, memberEmailDto, teamPlaceId); + final URI location = URI.create("/api/team-place/" + teamPlaceId + "/feed/threads/" + threadId); + + return ResponseEntity.created(location).build(); + } +} diff --git a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java index 2fbae0b53..973056304 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java @@ -9,6 +9,7 @@ import team.teamby.teambyteam.teamplace.domain.TeamPlace; import java.util.List; +import java.util.Objects; @Component public class TestFixtureBuilder { @@ -48,6 +49,28 @@ public List buildTeamPlaces(final List teamPlaces) { return bs.teamPlaceRepository().saveAll(teamPlaces); } + public MemberTeamPlace buildMemberAndTeamPlace(final Member member, final TeamPlace teamPlace) { + final Member savedMember = getSavedMember(member); + final TeamPlace savedTeamPlace = getSavedTeamPlace(teamPlace); + final MemberTeamPlace memberTeamPlace = new MemberTeamPlace(); + memberTeamPlace.setMemberAndTeamPlace(savedMember, savedTeamPlace); + return buildMemberTeamPlace(memberTeamPlace); + } + + private Member getSavedMember(final Member member) { + if (bs.memberRepository().existsByEmail(member.getEmail())) { + return member; + } + return buildMember(member); + } + + private TeamPlace getSavedTeamPlace(final TeamPlace teamPlace) { + if (Objects.nonNull(teamPlace.getId()) && bs.teamPlaceRepository().existsById(teamPlace.getId())) { + return teamPlace; + } + return buildTeamPlace(teamPlace); + } + public Feed buildFeed(final Feed feed) { return bs.feedRepository().save(feed); } diff --git a/backend/src/test/java/team/teamby/teambyteam/common/fixtures/acceptance/FeedThreadAcceptanceFixtures.java b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/acceptance/FeedThreadAcceptanceFixtures.java new file mode 100644 index 000000000..eb94c86c2 --- /dev/null +++ b/backend/src/test/java/team/teamby/teambyteam/common/fixtures/acceptance/FeedThreadAcceptanceFixtures.java @@ -0,0 +1,29 @@ +package team.teamby.teambyteam.common.fixtures.acceptance; + +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.teamplace.domain.TeamPlace; + +public class FeedThreadAcceptanceFixtures { + + private static final String JWT_PREFIX = "Bearer "; + + public static ExtractableResponse POST_FEED_THREAD_REQUEST( + final String authToken, + final TeamPlace teamPlace, + final FeedThreadWritingRequest request + ) { + return RestAssured.given().log().all() + .header(HttpHeaders.AUTHORIZATION, JWT_PREFIX + authToken) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .post("/api/team-place/{teamPlaceId}/feed/threads", teamPlace.getId()) + .then().log().all() + .extract(); + + } +} diff --git a/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java b/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java new file mode 100644 index 000000000..7615371df --- /dev/null +++ b/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java @@ -0,0 +1,107 @@ +package team.teamby.teambyteam.feed.acceptance; + +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import team.teamby.teambyteam.common.AcceptanceTest; +import team.teamby.teambyteam.common.fixtures.FeedThreadFixtures; +import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.member.domain.MemberTeamPlace; +import team.teamby.teambyteam.teamplace.domain.TeamPlace; + +import static team.teamby.teambyteam.common.fixtures.MemberFixtures.PHILIP; +import static team.teamby.teambyteam.common.fixtures.MemberFixtures.ROY; +import static team.teamby.teambyteam.common.fixtures.TeamPlaceFixtures.ENGLISH_TEAM_PLACE; +import static team.teamby.teambyteam.common.fixtures.TeamPlaceFixtures.JAPANESE_TEAM_PLACE; +import static team.teamby.teambyteam.common.fixtures.acceptance.FeedThreadAcceptanceFixtures.POST_FEED_THREAD_REQUEST; + +public class FeedThreadAcceptanceTest extends AcceptanceTest { + + @Nested + @DisplayName("피드에 스레드 등록 시") + class PostThread { + + @Test + @DisplayName("스레드 등록에 성공한다.") + void success() { + // given + final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); + final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; + final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); + + // when + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + + //then + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + softly.assertThat(response.header(HttpHeaders.LOCATION)).contains("/api/team-place/" + PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace().getId() + "/feed/threads"); + }); + } + + @ParameterizedTest + @ValueSource(strings = {"", " ", " "}) + @DisplayName("스레드 내용으로 빈 내용의 요청이 오면 등록이 실패한다.") + void failWithBlankContent(final String content) { + // given + final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); + final FeedThreadWritingRequest request = new FeedThreadWritingRequest(content); + final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); + + // when + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + + //then + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(response.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + softly.assertThat(response.body().asString()).contains("스레드 내용이 있어야 합니다."); + }); + } + + @Test + @DisplayName("사용자가 소속되지 않은 팀플레이스 아이디로 요청시 등록이 실패한다.") + void failWithForbiddenTeamPlace() { + // given + final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); + final TeamPlace UN_PARTICIPATED_TEAM_PLACE = testFixtureBuilder.buildTeamPlace(JAPANESE_TEAM_PLACE()); + final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; + final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); + + // when + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, UN_PARTICIPATED_TEAM_PLACE, request); + + //then + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(response.statusCode()).isEqualTo(HttpStatus.FORBIDDEN.value()); + softly.assertThat(response.body().asString()).contains("접근할 수 없는 팀플레이스입니다."); + }); + } + + @Test + @DisplayName("인증되지 않은 사용자로 요청시 등록이 실패한다.") + void failWithUnauthorizedMember() { + // given + final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); + final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; + final String unauthorizedToken = jwtTokenProvider.generateToken(ROY().getEmail().getValue()); + + // when + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(unauthorizedToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + + //then + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(response.statusCode()).isEqualTo(HttpStatus.NOT_FOUND.value()); + softly.assertThat(response.body().asString()).contains("조회한 멤버가 존재하지 않습니다."); + }); + } + + } + +} From 435759b914aa0ec2b87039d844b1d4de62508058 Mon Sep 17 00:00:00 2001 From: pilyang Date: Fri, 28 Jul 2023 14:12:14 +0900 Subject: [PATCH 5/8] =?UTF-8?q?chore:=20local=EC=9A=A9=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=8B=9C=ED=81=AC=EB=A6=BF=ED=82=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index ebad244d2..7ff36e7d3 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -17,3 +17,7 @@ spring: dialect: org.hibernate.dialect.MySQL57Dialect format_sql: true # for test show-sql: true # for test + +jwt: + secret: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + expiration: 10800000 From 90749e2817657726bc59e6c0200f8dd11e96cb42 Mon Sep 17 00:00:00 2001 From: pilyang Date: Fri, 28 Jul 2023 15:49:15 +0900 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B9=8C=EB=8D=94=EC=97=90=EC=84=9C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamby/teambyteam/common/builder/TestFixtureBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java index 973056304..61aa579f2 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java @@ -59,7 +59,7 @@ public MemberTeamPlace buildMemberAndTeamPlace(final Member member, final TeamPl private Member getSavedMember(final Member member) { if (bs.memberRepository().existsByEmail(member.getEmail())) { - return member; + return bs.memberRepository().findByEmail(member.getEmail()).get(); } return buildMember(member); } From d5f19e99db1709c11df1f8eb87a34cdac0fd78fa Mon Sep 17 00:00:00 2001 From: pilyang Date: Fri, 28 Jul 2023 15:51:40 +0900 Subject: [PATCH 7/8] =?UTF-8?q?test:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=8B=9C=20truncate=20sql=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/team/teamby/teambyteam/common/ServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/test/java/team/teamby/teambyteam/common/ServiceTest.java b/backend/src/test/java/team/teamby/teambyteam/common/ServiceTest.java index 5413f4c50..831728167 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/ServiceTest.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/ServiceTest.java @@ -2,11 +2,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; import org.springframework.transaction.annotation.Transactional; import team.teamby.teambyteam.common.builder.TestFixtureBuilder; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @Transactional +@Sql({"/h2-truncate.sql"}) public abstract class ServiceTest { @Autowired From c3c22575fa2bc5e4106cd6dd551204aec1aa8553 Mon Sep 17 00:00:00 2001 From: pilyang Date: Fri, 28 Jul 2023 16:09:11 +0900 Subject: [PATCH 8/8] =?UTF-8?q?test:=20Acceptance=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EB=AA=BB=ED=95=98=EB=8A=94=20=EB=B9=8C=EB=8D=94=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - buildMemberAndMemberTeamPlace제거 - 중복코드 beforeEach로 중복 제거 --- .../common/builder/TestFixtureBuilder.java | 29 ++++------------- .../acceptance/FeedThreadAcceptanceTest.java | 32 ++++++++++++------- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java index 61aa579f2..3583dfe60 100644 --- a/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java +++ b/backend/src/test/java/team/teamby/teambyteam/common/builder/TestFixtureBuilder.java @@ -9,7 +9,6 @@ import team.teamby.teambyteam.teamplace.domain.TeamPlace; import java.util.List; -import java.util.Objects; @Component public class TestFixtureBuilder { @@ -41,6 +40,12 @@ public List buildMembers(final List members) { return bs.memberRepository().saveAll(members); } + public MemberTeamPlace buildMemberTeamPlace(final Member member, final TeamPlace teamPlace) { + final MemberTeamPlace memberTeamPlace = new MemberTeamPlace(); + memberTeamPlace.setMemberAndTeamPlace(member, teamPlace); + return bs.memberTeamPlaceRepository().save(memberTeamPlace); + } + public List buildMemberTeamPlaces(final List memberTeamPlaces) { return bs.memberTeamPlaceRepository().saveAll(memberTeamPlaces); } @@ -49,28 +54,6 @@ public List buildTeamPlaces(final List teamPlaces) { return bs.teamPlaceRepository().saveAll(teamPlaces); } - public MemberTeamPlace buildMemberAndTeamPlace(final Member member, final TeamPlace teamPlace) { - final Member savedMember = getSavedMember(member); - final TeamPlace savedTeamPlace = getSavedTeamPlace(teamPlace); - final MemberTeamPlace memberTeamPlace = new MemberTeamPlace(); - memberTeamPlace.setMemberAndTeamPlace(savedMember, savedTeamPlace); - return buildMemberTeamPlace(memberTeamPlace); - } - - private Member getSavedMember(final Member member) { - if (bs.memberRepository().existsByEmail(member.getEmail())) { - return bs.memberRepository().findByEmail(member.getEmail()).get(); - } - return buildMember(member); - } - - private TeamPlace getSavedTeamPlace(final TeamPlace teamPlace) { - if (Objects.nonNull(teamPlace.getId()) && bs.teamPlaceRepository().existsById(teamPlace.getId())) { - return teamPlace; - } - return buildTeamPlace(teamPlace); - } - public Feed buildFeed(final Feed feed) { return bs.feedRepository().save(feed); } diff --git a/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java b/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java index 7615371df..b3a7eecef 100644 --- a/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java +++ b/backend/src/test/java/team/teamby/teambyteam/feed/acceptance/FeedThreadAcceptanceTest.java @@ -3,6 +3,7 @@ import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -13,6 +14,7 @@ import team.teamby.teambyteam.common.AcceptanceTest; import team.teamby.teambyteam.common.fixtures.FeedThreadFixtures; import team.teamby.teambyteam.feed.application.dto.FeedThreadWritingRequest; +import team.teamby.teambyteam.member.domain.Member; import team.teamby.teambyteam.member.domain.MemberTeamPlace; import team.teamby.teambyteam.teamplace.domain.TeamPlace; @@ -28,21 +30,33 @@ public class FeedThreadAcceptanceTest extends AcceptanceTest { @DisplayName("피드에 스레드 등록 시") class PostThread { + private Member authedMember; + private TeamPlace participatedTeamPlace; + private MemberTeamPlace participatedMemberTeamPlace; + private String authToken; + + @BeforeEach + void setup() { + authedMember = testFixtureBuilder.buildMember(PHILIP()); + participatedTeamPlace = testFixtureBuilder.buildTeamPlace(ENGLISH_TEAM_PLACE()); + participatedMemberTeamPlace = testFixtureBuilder.buildMemberTeamPlace(authedMember, participatedTeamPlace); + authToken = jwtTokenProvider.generateToken(authedMember.getEmail().getValue()); + + } + @Test @DisplayName("스레드 등록에 성공한다.") void success() { // given - final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; - final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); // when - final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, participatedTeamPlace, request); //then SoftAssertions.assertSoftly(softly -> { softly.assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); - softly.assertThat(response.header(HttpHeaders.LOCATION)).contains("/api/team-place/" + PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace().getId() + "/feed/threads"); + softly.assertThat(response.header(HttpHeaders.LOCATION)).contains("/api/team-place/" + participatedMemberTeamPlace.getTeamPlace().getId() + "/feed/threads"); }); } @@ -51,12 +65,10 @@ void success() { @DisplayName("스레드 내용으로 빈 내용의 요청이 오면 등록이 실패한다.") void failWithBlankContent(final String content) { // given - final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); final FeedThreadWritingRequest request = new FeedThreadWritingRequest(content); - final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); // when - final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, participatedTeamPlace, request); //then SoftAssertions.assertSoftly(softly -> { @@ -69,10 +81,9 @@ void failWithBlankContent(final String content) { @DisplayName("사용자가 소속되지 않은 팀플레이스 아이디로 요청시 등록이 실패한다.") void failWithForbiddenTeamPlace() { // given - final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); final TeamPlace UN_PARTICIPATED_TEAM_PLACE = testFixtureBuilder.buildTeamPlace(JAPANESE_TEAM_PLACE()); + final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; - final String authToken = jwtTokenProvider.generateToken(PHILIP_ENGLISH_TEAM_PLACE.getMember().getEmail().getValue()); // when final ExtractableResponse response = POST_FEED_THREAD_REQUEST(authToken, UN_PARTICIPATED_TEAM_PLACE, request); @@ -88,12 +99,11 @@ void failWithForbiddenTeamPlace() { @DisplayName("인증되지 않은 사용자로 요청시 등록이 실패한다.") void failWithUnauthorizedMember() { // given - final MemberTeamPlace PHILIP_ENGLISH_TEAM_PLACE = testFixtureBuilder.buildMemberAndTeamPlace(PHILIP(), ENGLISH_TEAM_PLACE()); final FeedThreadWritingRequest request = FeedThreadFixtures.HELLO_WRITING_REQUEST; final String unauthorizedToken = jwtTokenProvider.generateToken(ROY().getEmail().getValue()); // when - final ExtractableResponse response = POST_FEED_THREAD_REQUEST(unauthorizedToken, PHILIP_ENGLISH_TEAM_PLACE.getTeamPlace(), request); + final ExtractableResponse response = POST_FEED_THREAD_REQUEST(unauthorizedToken, participatedTeamPlace, request); //then SoftAssertions.assertSoftly(softly -> {