Skip to content

Commit

Permalink
로그인한 서포터의 러너 게시글 조회 API 구현 (#342)
Browse files Browse the repository at this point in the history
* test: RestAssured 및 Restdocs 테스트 컨벤션 적용

* feat: review status 상태 하나 추가

* feat: response dto 구현

* test: 인수 테스트 작성

* feat: 서포터와 리뷰 상태로 러너 게시글 최신순으로 조회하는 기능 구현

* feat: 서포터와 리뷰 상태로 러너 게시글 최신순으로 조회하는 서비스 구현

* feat: controller 작성 및 주석 처리

* refactor: 충돌 해결

* refactor: 페이지네이션 적용

* test: NOT_STARTED 인 테스트 진행

* test: restdocs 작성

* refactor: 서브 모듈 업데이트

* refactor: 개행 제거

* refactor: 코드 리뷰 반영

* refactor: 코드 리뷰 반영

* test: restdocs 테스트에 path parameter 추가

* test: 코드리뷰 반영

* test: 코드리뷰 반영

* refactor: 충돌 해결
  • Loading branch information
shb03323 authored Aug 14, 2023
1 parent f5f8614 commit 97a39a5
Show file tree
Hide file tree
Showing 39 changed files with 932 additions and 267 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package touch.baton.domain.runnerpost.controller;

import jakarta.validation.Valid;
import jakarta.websocket.server.PathParam;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -176,6 +177,29 @@ public ResponseEntity<PageResponse<RunnerPostResponse.ReferencedBySupporter>> re
return ResponseEntity.ok(PageResponse.from(pageResponse));
}

@GetMapping("/me/supporter")
public ResponseEntity<PageResponse<RunnerPostResponse.ReferencedBySupporter>> readRunnerPostsByLoginedSupporterAndReviewStatus(
@PageableDefault(size = 10, page = 1, sort = "createdAt", direction = DESC) final Pageable pageable,
@AuthSupporterPrincipal final Supporter supporter,
@PathParam("reviewStatus") final ReviewStatus reviewStatus
) {
final Page<RunnerPost> pageRunnerPosts = runnerPostService.readRunnerPostsBySupporterIdAndReviewStatus(pageable, supporter.getId(), reviewStatus);
final List<RunnerPost> foundRunnerPosts = pageRunnerPosts.getContent();
final List<Long> applicantCounts = collectApplicantCounts(pageRunnerPosts);
final List<RunnerPostResponse.ReferencedBySupporter> responses = IntStream.range(0, foundRunnerPosts.size())
.mapToObj(index -> {
final RunnerPost foundRunnerPost = foundRunnerPosts.get(index);
final Long applicantCount = applicantCounts.get(index);

return RunnerPostResponse.ReferencedBySupporter.of(foundRunnerPost, applicantCount);
}).toList();

final Page<RunnerPostResponse.ReferencedBySupporter> pageResponse
= new PageImpl<>(responses, pageable, pageRunnerPosts.getTotalPages());

return ResponseEntity.ok(PageResponse.from(pageResponse));
}

private List<Long> collectApplicantCounts(final Page<RunnerPost> pageRunnerPosts) {
final List<Long> runnerPostIds = pageRunnerPosts.stream()
.map(RunnerPost::getId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ public static NoFiltering from(final List<RunnerPostResponse.Simple> data) {
return new NoFiltering(data);
}
}

public record LoginedSupporter(List<RunnerPostResponse.LoginedSupporter> data) {

public static LoginedSupporter from(final List<RunnerPostResponse.LoginedSupporter> data) {
return new LoginedSupporter(data);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public record DetailVersionTest(Long runnerPostId,
boolean isOwner,
List<String> tags
) {

public static DetailVersionTest ofVersionTest(final RunnerPost runnerPost, final boolean isOwner) {
return new DetailVersionTest(
runnerPost.getId(),
Expand Down Expand Up @@ -91,13 +92,34 @@ public static Simple from(final RunnerPost runnerPost) {
}
}

public record LoginedSupporter(Long runnerPostId,
String title,
LocalDateTime deadline,
List<String> tags,
int watchedCount,
int applicantCount

) {

public static LoginedSupporter from(final RunnerPost runnerPost, final int applicantCount) {
return new LoginedSupporter(
runnerPost.getId(),
runnerPost.getTitle().getValue(),
runnerPost.getDeadline().getValue(),
convertToTags(runnerPost),
runnerPost.getWatchedCount().getValue(),
applicantCount
);
}
}

public record Mine(Long runnerPostId,
String title,
LocalDateTime deadline,
List<String> tags,
String reviewStatus

) {

public static Mine from(final RunnerPost runnerPost) {
return new Mine(
runnerPost.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import touch.baton.domain.common.vo.Title;
import touch.baton.domain.runnerpost.RunnerPost;
import touch.baton.domain.runnerpost.vo.ReviewStatus;

Expand Down Expand Up @@ -37,7 +36,14 @@ Page<RunnerPost> findBySupporterIdAndReviewStatus(final Pageable pageable,
@Param("supporterId") final Long supporterId,
@Param("reviewStatus") final ReviewStatus reviewStatus);

List<RunnerPost> readBySupporterId(Long supporterId);

Optional<RunnerPost> readByTitle(Title title);
@Query("""
select rp
from RunnerPost rp
join fetch SupporterRunnerPost srp on srp.runnerPost.id = rp.id
where srp.supporter.id = :supporterId
and rp.reviewStatus = :reviewStatus
""")
Page<RunnerPost> joinSupporterRunnerPostBySupporterIdAndReviewStatus(final Pageable pageable,
@Param("supporterId") final Long supporterId,
@Param("reviewStatus") final ReviewStatus reviewStatus);
}
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ public Page<RunnerPost> readRunnerPostsBySupporterIdAndReviewStatus(final Pageab
final Long supporterId,
final ReviewStatus reviewStatus
) {
if (reviewStatus.isSameAsNotStarted()) {
return runnerPostRepository.joinSupporterRunnerPostBySupporterIdAndReviewStatus(pageable, supporterId, reviewStatus);
}
return runnerPostRepository.findBySupporterIdAndReviewStatus(pageable, supporterId, reviewStatus);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public boolean isSame(final ReviewStatus reviewStatus) {
return this == reviewStatus;
}

public boolean isSameAsNotStarted() {
return this == NOT_STARTED;
}

public boolean isNotSameAsNotStarted() {
return this != NOT_STARTED;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,10 @@ public static ExtractableResponse<Response> post(final String uri,
.extract();
}

public static ExtractableResponse<Response> get(final String uri,
final String pathParamName,
final Long id,
final String accessToken
) {
public static ExtractableResponse<Response> get(final String uri, final String accessToken) {
return RestAssured
.given().log().ifValidationFails()
.auth().preemptive().oauth2(accessToken)
.pathParam(pathParamName, id)
.when().log().ifValidationFails()
.get(uri)
.then().log().ifError()
Expand All @@ -75,10 +70,15 @@ public static ExtractableResponse<Response> get(final String uri, final String p
.extract();
}

public static ExtractableResponse<Response> get(final String uri, final String accessToken) {
public static ExtractableResponse<Response> get(final String uri,
final String pathParamName,
final Long id,
final String accessToken
) {
return RestAssured
.given().log().ifValidationFails()
.auth().preemptive().oauth2(accessToken)
.pathParam(pathParamName, id)
.when().log().ifValidationFails()
.get(uri)
.then().log().ifError()
Expand All @@ -97,14 +97,14 @@ public static ExtractableResponse<Response> get(final String uri, final Map<Stri
.extract();
}

public static ExtractableResponse<Response> patch(final String uri, final String accessToken, final Object params) {
public static ExtractableResponse<Response> get(final String uri, final String accessToken, final Map<String, Object> queryParams) {
return RestAssured
.given().log().ifValidationFails()
.auth().preemptive().oauth2(accessToken)
.contentType(APPLICATION_JSON_VALUE)
.body(params)
.queryParams(queryParams)
.when().log().ifValidationFails()
.patch(uri)
.get(uri)
.then().log().ifError()
.extract();
}
Expand All @@ -127,6 +127,19 @@ public static ExtractableResponse<Response> patch(final String uri,
.extract();
}


public static ExtractableResponse<Response> patch(final String uri, final String accessToken, final Object requestBody) {
return RestAssured
.given().log().ifValidationFails()
.auth().preemptive().oauth2(accessToken)
.contentType(APPLICATION_JSON_VALUE)
.body(requestBody)
.when().log().ifValidationFails()
.patch(uri)
.then().log().ifError()
.extract();
}

public static ExtractableResponse<Response> patch(final String uri, final String pathParamName, final Long id, final String accessToken) {
return RestAssured
.given().log().ifValidationFails()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import static org.assertj.core.api.SoftAssertions.assertSoftly;

@SuppressWarnings("NonAsciiCharacters")
public class SupporterFeedbackAssuredSupport {

private SupporterFeedbackAssuredSupport() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import static touch.baton.fixture.vo.ReviewCountFixture.reviewCount;

@SuppressWarnings("NonAsciiCharacters")
class SupporterFeedbackAssuredCreateTest extends AssuredTestConfig {
class SupporterFeedbackCreateAssuredTest extends AssuredTestConfig {

// TODO: 2023/08/03 로그인 기능 테스트 추가
@Disabled
Expand All @@ -41,7 +41,10 @@ class SupporterFeedbackAssuredCreateTest extends AssuredTestConfig {

// when, then
SupporterFeedbackAssuredSupport
.클라이언트_요청().서포터_피드백을_등록한다(request)
.서버_응답().서포터_피드백_등록_성공을_검증한다(new HttpStatusAndLocationHeader(CREATED, "/api/v1/feedback/supporter"));
.클라이언트_요청()
.서포터_피드백을_등록한다(request)

.서버_응답()
.서포터_피드백_등록_성공을_검증한다(new HttpStatusAndLocationHeader(CREATED, "/api/v1/feedback/supporter"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import static org.assertj.core.api.SoftAssertions.assertSoftly;

@SuppressWarnings("NonAsciiCharacters")
public class MemberProfileAssuredSupport {
public class MemberAssuredSupport {

private MemberProfileAssuredSupport() {
private MemberAssuredSupport() {
}

public static MemberClientRequestBuilder 클라이언트_요청() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
import touch.baton.domain.member.Member;
import touch.baton.fixture.domain.MemberFixture;

import static touch.baton.assure.member.MemberProfileAssuredSupport.로그인한_사용자_프로필_응답;
import static touch.baton.assure.member.MemberAssuredSupport.로그인한_사용자_프로필_응답;

@SuppressWarnings("NonAsciiCharacters")
public class MemberProfileAssuredReadTest extends AssuredTestConfig {
public class MemberReadWithLoginedMemberAssuredTest extends AssuredTestConfig {

@Test
void 로그인__맴버_프로필을_조회한다() {
final String 디투_소셜_id = "ditooSocialId";
final Member 사용자_디투 = memberRepository.save(MemberFixture.createWithSocialId(디투_소셜_id));
final String 디투_액세스_토큰 = login(디투_소셜_id);

MemberProfileAssuredSupport
MemberAssuredSupport
.클라이언트_요청()
.로그인_한다(디투_액세스_토큰)
.사용자_본인_프로필을_가지고_있는_토큰으로_조회한다()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,61 @@

import static org.assertj.core.api.SoftAssertions.assertSoftly;

public class RunnerProfileAssuredSupport {
@SuppressWarnings("NonAsciiCharacters")
public class RunnerAssuredSupport {

private RunnerProfileAssuredSupport() {
private RunnerAssuredSupport() {
}

public static RunnerProfileClientRequestBuilder 클라이언트_요청() {
return new RunnerProfileClientRequestBuilder();
public static RunnerClientRequestBuilder 클라이언트_요청() {
return new RunnerClientRequestBuilder();
}

public static RunnerResponse.MyProfile 러너_본인_프로필_응답(final Runner 러너) {
return RunnerResponse.MyProfile.from(러너);
}

public static class RunnerProfileClientRequestBuilder {
public static class RunnerClientRequestBuilder {

private ExtractableResponse<Response> response;

private String accessToken;

public RunnerProfileClientRequestBuilder 토큰으로_로그인한다(final String 토큰) {
public RunnerClientRequestBuilder 토큰으로_로그인한다(final String 토큰) {
this.accessToken = 토큰;
return this;
}

public RunnerProfileClientRequestBuilder 러너_본인_프로필을_가지고_있는_토큰으로_조회한다() {
public RunnerClientRequestBuilder 러너_본인_프로필을_가지고_있는_토큰으로_조회한다() {
response = AssuredSupport.get("/api/v1/profile/runner/me", accessToken);
return this;
}

public RunnerProfileClientRequestBuilder 러너_피드백을_상세_조회한다(final Long 러너_식별자) {
public RunnerClientRequestBuilder 러너_프로필을_상세_조회한다(final Long 러너_식별자) {
response = AssuredSupport.get("/api/v1/profile/runner/{runnerId}", "runnerId", 러너_식별자);
return this;
}

public RunnerProfileServerResponseBuilder 서버_응답() {
return new RunnerProfileServerResponseBuilder(response);
public RunnerServerResponseBuilder 서버_응답() {
return new RunnerServerResponseBuilder(response);
}

public RunnerProfileClientRequestBuilder 러너_본인_프로필을_수정한다(final RunnerUpdateRequest 러너_업데이트_요청) {
public RunnerClientRequestBuilder 러너_본인_프로필을_수정한다(final RunnerUpdateRequest 러너_업데이트_요청) {
response = AssuredSupport.patch("/api/v1/profile/runner/me", accessToken, 러너_업데이트_요청);
return this;
}
}

public static class RunnerProfileServerResponseBuilder {
public static class RunnerServerResponseBuilder {

private final ExtractableResponse<Response> response;

public RunnerProfileServerResponseBuilder(final ExtractableResponse<Response> response) {
public RunnerServerResponseBuilder(final ExtractableResponse<Response> response) {
this.response = response;
}

public static RunnerProfileClientRequestBuilder 클라이언트_요청() {
return new RunnerProfileClientRequestBuilder();
public static RunnerClientRequestBuilder 클라이언트_요청() {
return new RunnerClientRequestBuilder();
}

public void 러너_본인_프로필_조회_성공을_검증한다(final RunnerResponse.MyProfile 러너_본인_프로필_응답) {
Expand Down
Loading

0 comments on commit 97a39a5

Please sign in to comment.