From 3e04f3467bd3be2378dc52fe4df4afc7f4326019 Mon Sep 17 00:00:00 2001 From: habin Date: Sat, 4 May 2024 22:24:28 +0900 Subject: [PATCH 1/5] feat(vote-paper) detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: VotePaperController.getVotePaper 메소드 추가 --- .../input/rest/VotePaperController.java | 9 +++++++++ .../input/usecase/GetVotePaperUseCase.java | 8 ++++++++ .../service/GetVotePaperService.java | 20 +++++++++++++++++++ .../v1/vote/domain/value/FullVotePaper.java | 4 ++++ 4 files changed, 41 insertions(+) create mode 100644 src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java create mode 100644 src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java create mode 100644 src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java b/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java index adfc8e87..9ff9b1fa 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java @@ -29,6 +29,8 @@ public class VotePaperController { private final ScrollVotePaperUseCase scrollVotePaperUseCase; + private final GetVotePaperUseCase getVotePaperUseCase; + private final RegisterVotePaperUseCase registerVotePaperUseCase; private final RegisterVoteChoiceUseCase registerVoteChoiceUseCase; @@ -45,6 +47,13 @@ public ResponseEntity> getVotePapers(@RequestP return responseMapper.ok(MessageCode.SUCCESS, new ScrollVotePaperResponse(scrollableVotePapers)); } + @GetMapping(value = Uris.VOTE_PAPER_ROOT + "/{votePaperId}") + public ResponseEntity> getVotePaper(@PathVariable("votePaperId") @NotNull(message = "{vote.paper.id.not_null}") final Long votePaperId, + @CurrentUser final User user) { + getVotePaperUseCase.getVotePaper(votePaperId); + return responseMapper.ok(MessageCode.SUCCESS); + } + // TODO : Follower 로직 구현 후 테스트 재진행 예정 @PreAuthorize("hasRole('ARTIST')") @PostMapping(value = Uris.VOTE_PAPER_ROOT) diff --git a/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java b/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java new file mode 100644 index 00000000..a1a69101 --- /dev/null +++ b/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java @@ -0,0 +1,8 @@ +package com.tune_fun.v1.vote.application.port.input.usecase; + +@FunctionalInterface +public interface GetVotePaperUseCase { + + void getVotePaper(final Long votePaperId); + +} diff --git a/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java b/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java new file mode 100644 index 00000000..a1ef9964 --- /dev/null +++ b/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java @@ -0,0 +1,20 @@ +package com.tune_fun.v1.vote.application.service; + +import com.tune_fun.v1.common.hexagon.UseCase; +import com.tune_fun.v1.vote.application.port.input.usecase.GetVotePaperUseCase; +import com.tune_fun.v1.vote.application.port.output.LoadVotePaperPort; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@UseCase +@RequiredArgsConstructor +public class GetVotePaperService implements GetVotePaperUseCase { + + private final LoadVotePaperPort loadVotePaperPort; + + @Override + public void getVotePaper(final Long votePaperId) { + + } +} diff --git a/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java new file mode 100644 index 00000000..0ad996f8 --- /dev/null +++ b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java @@ -0,0 +1,4 @@ +package com.tune_fun.v1.vote.domain.value; + +public record FullVotePaper() { +} From 12cca49530847155959ab81ea4b1fb99df50e193 Mon Sep 17 00:00:00 2001 From: habin Date: Sun, 5 May 2024 02:08:35 +0900 Subject: [PATCH 2/5] feat(vote-choice) register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: getVotePaper 메소드 추가 --- .../output/persistence/VotePaperMapper.java | 8 +++++++ .../persistence/VotePaperRepository.java | 1 + .../persistence/VotePersistenceAdapter.java | 11 ++++++---- .../port/output/LoadVotePaperPort.java | 3 +++ .../tune_fun/v1/vote/domain/value/Choice.java | 8 +++++++ .../v1/vote/domain/value/FullVotePaper.java | 21 ++++++++++++++++++- 6 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/tune_fun/v1/vote/domain/value/Choice.java diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java index 2ffebe4c..a1758293 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java @@ -4,6 +4,7 @@ import com.tune_fun.v1.common.config.BaseMapperConfig; import com.tune_fun.v1.common.util.StringUtil; import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; import com.tune_fun.v1.vote.domain.value.VotePaperOption; @@ -51,4 +52,11 @@ public Long remainDays(final VotePaperJpaEntity votePaperJpaEntity) { @Mapping(target = "videoUrl", source = "videoUrl") public abstract VotePaperJpaEntity.VotePaperJpaEntityBuilder updateVideoUrl(final String videoUrl, @MappingTarget VotePaperJpaEntity.VotePaperJpaEntityBuilder builder); + + @Mapping(target = "authorUsername", source = "author.username") + @Mapping(target = "authorNickname", source = "author.nickname") + @Mapping(target = "remainDays", source = ".", qualifiedByName = "remainDays") + @Mapping(target = "totalVoteCount", constant = "0") + @Mapping(target = "totalLikeCount", constant = "0") + public abstract FullVotePaper fullVotePaper(VotePaperJpaEntity votePaperJpaEntity); } diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java index 06b9af71..ab4556f2 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java @@ -14,6 +14,7 @@ public interface VotePaperRepository extends JpaRepository findByVoteEndAtAfterAndAuthorUsernameAndEnabledTrue(LocalDateTime voteEndAt, String author); + @EntityGraph(attributePaths = {"author", "choices"}) Optional findByVoteEndAtAfterAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id); Optional findByVoteEndAtBeforeAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id); diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java index 8ab131ef..15df7f28 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java @@ -8,10 +8,7 @@ import com.tune_fun.v1.vote.application.port.output.*; import com.tune_fun.v1.vote.domain.behavior.SaveVoteChoice; import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper; -import com.tune_fun.v1.vote.domain.value.RegisteredVote; -import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice; -import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; -import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; +import com.tune_fun.v1.vote.domain.value.*; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.KeysetScrollPosition; import org.springframework.data.domain.Sort; @@ -91,6 +88,12 @@ public Window scrollVotePaper(final Integer lastId, final S return votePaperRepository.findFirst10ByEnabledTrue(position, sort).map(votePaperMapper::scrollableVotePaper); } + @Override + public Optional loadFullVotePaper(final Long votePaperId) { + return votePaperRepository.findByVoteEndAtAfterAndIdAndEnabledTrue(now(), votePaperId) + .map(votePaperMapper::fullVotePaper); + } + @Override public Optional loadRegisteredVotePaper(final String username) { return findProgressingVotePaperByAuthor(username).map(votePaperMapper::registeredVotePaper); diff --git a/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java b/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java index ffddc956..f97ee474 100644 --- a/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java +++ b/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java @@ -1,5 +1,6 @@ package com.tune_fun.v1.vote.application.port.output; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; import org.springframework.data.domain.Window; @@ -10,6 +11,8 @@ public interface LoadVotePaperPort { Window scrollVotePaper(final Integer lastId, final String sortType); + Optional loadFullVotePaper(final Long votePaperId); + Optional loadRegisteredVotePaper(final String username); Optional loadRegisteredVotePaper(final Long votePaperId); diff --git a/src/main/java/com/tune_fun/v1/vote/domain/value/Choice.java b/src/main/java/com/tune_fun/v1/vote/domain/value/Choice.java new file mode 100644 index 00000000..18c2f751 --- /dev/null +++ b/src/main/java/com/tune_fun/v1/vote/domain/value/Choice.java @@ -0,0 +1,8 @@ +package com.tune_fun.v1.vote.domain.value; + +public record Choice( + Long id, + String music, + String artistName +) { +} diff --git a/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java index 0ad996f8..6f382aa3 100644 --- a/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java +++ b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java @@ -1,4 +1,23 @@ package com.tune_fun.v1.vote.domain.value; -public record FullVotePaper() { +import java.time.LocalDateTime; +import java.util.Set; + +public record FullVotePaper( + Long id, + String uuid, + String authorUsername, + String authorNickname, + String title, + String content, + VotePaperOption option, + String videoUrl, + LocalDateTime voteStartAt, + LocalDateTime voteEndAt, + LocalDateTime deliveryAt, + Long remainDays, + String totalVoteCount, + String totalLikeCount, + Set choices +) { } From 2b43cd215557c550a36843469c692f7f97cd6a80 Mon Sep 17 00:00:00 2001 From: habin Date: Sun, 5 May 2024 11:32:44 +0900 Subject: [PATCH 3/5] configuration(entity) identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor: JPA Entity Identifier Generation 방식 TSID로 수정 --- .../adapter/output/persistence/AccountJpaEntity.java | 5 +++-- .../adapter/output/persistence/device/DeviceJpaEntity.java | 7 ++++--- .../output/persistence/oauth2/OAuth2AccountJpaEntity.java | 5 +++-- src/main/java/com/tune_fun/v1/common/util/StringUtil.java | 5 +++++ .../java/com/tune_fun/v1/external/aws/s3/S3Template.java | 4 ++-- .../adapter/output/persistence/VoteChoiceJpaEntity.java | 5 +++-- .../v1/vote/adapter/output/persistence/VoteJpaEntity.java | 5 +++-- .../adapter/output/persistence/VotePaperJpaEntity.java | 1 + src/test/java/com/tune_fun/v1/dummy/DummyService.java | 2 ++ .../v1/vote/adapter/input/rest/VotePaperControllerIT.java | 2 +- 10 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/AccountJpaEntity.java b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/AccountJpaEntity.java index 34fbdf71..8127d428 100644 --- a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/AccountJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/AccountJpaEntity.java @@ -3,6 +3,7 @@ import com.tune_fun.v1.account.adapter.output.persistence.device.DeviceJpaEntity; import com.tune_fun.v1.account.adapter.output.persistence.oauth2.OAuth2AccountJpaEntity; import com.tune_fun.v1.common.entity.BaseEntity; +import io.hypersistence.utils.hibernate.id.Tsid; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -28,9 +29,9 @@ public class AccountJpaEntity extends BaseEntity implements UserDetails { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @Tsid @Column(name = "id", nullable = false, updatable = false) - @Comment("Sequence") + @Comment("TSID") private Long id; @Size(max = 255) diff --git a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/device/DeviceJpaEntity.java b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/device/DeviceJpaEntity.java index 51123bcb..db509e4d 100644 --- a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/device/DeviceJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/device/DeviceJpaEntity.java @@ -2,6 +2,7 @@ import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity; import com.tune_fun.v1.common.entity.BaseEntity; +import io.hypersistence.utils.hibernate.id.Tsid; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -23,9 +24,9 @@ public class DeviceJpaEntity extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @Tsid @Column(name = "id", nullable = false, updatable = false) - @Comment("Sequence") + @Comment("TSID") private Long id; @Size(max = 255) @@ -65,5 +66,5 @@ public final boolean equals(Object object) { public final int hashCode() { return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode(); } - + } diff --git a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/oauth2/OAuth2AccountJpaEntity.java b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/oauth2/OAuth2AccountJpaEntity.java index ea656743..d127bfd5 100644 --- a/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/oauth2/OAuth2AccountJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/account/adapter/output/persistence/oauth2/OAuth2AccountJpaEntity.java @@ -2,6 +2,7 @@ import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity; import com.tune_fun.v1.common.entity.BaseEntity; +import io.hypersistence.utils.hibernate.id.Tsid; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -24,9 +25,9 @@ public class OAuth2AccountJpaEntity extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @Tsid @Column(name = "id", nullable = false, updatable = false) - @Comment("Sequence") + @Comment("TSID") private Long id; @Size(max = 255) diff --git a/src/main/java/com/tune_fun/v1/common/util/StringUtil.java b/src/main/java/com/tune_fun/v1/common/util/StringUtil.java index 12a9366b..87d1ea2f 100644 --- a/src/main/java/com/tune_fun/v1/common/util/StringUtil.java +++ b/src/main/java/com/tune_fun/v1/common/util/StringUtil.java @@ -1,5 +1,6 @@ package com.tune_fun.v1.common.util; +import com.github.f4b6a3.ulid.UlidCreator; import com.tune_fun.v1.common.constant.Constants; import lombok.experimental.UtilityClass; import org.apache.commons.lang3.RandomStringUtils; @@ -78,6 +79,10 @@ public static String uuid() { return UUID.randomUUID().toString(); } + public static String ulid() { + return UlidCreator.getMonotonicUlid().toString(); + } + public boolean hasText(String text) { return StringUtils.hasText(text); } diff --git a/src/main/java/com/tune_fun/v1/external/aws/s3/S3Template.java b/src/main/java/com/tune_fun/v1/external/aws/s3/S3Template.java index d89aa604..2f3e7596 100644 --- a/src/main/java/com/tune_fun/v1/external/aws/s3/S3Template.java +++ b/src/main/java/com/tune_fun/v1/external/aws/s3/S3Template.java @@ -74,8 +74,8 @@ public ResponseBytes getObject(String s3BucketName, String ke } @NotNull - public String getKey(String rootPath, MultipartFile multipartFile) throws NoSuchAlgorithmException { - String generatedFileName = StringUtil.randomAlphanumeric(40); + public String getKey(String rootPath, MultipartFile multipartFile) { + String generatedFileName = StringUtil.ulid(); log.info("generated file name is {}", generatedFileName); String extractedExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteChoiceJpaEntity.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteChoiceJpaEntity.java index bad9d097..e1062280 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteChoiceJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteChoiceJpaEntity.java @@ -1,6 +1,7 @@ package com.tune_fun.v1.vote.adapter.output.persistence; import com.tune_fun.v1.common.entity.BaseEntity; +import io.hypersistence.utils.hibernate.id.Tsid; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -29,9 +30,9 @@ public class VoteChoiceJpaEntity extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @Tsid @Column(name = "id", nullable = false, updatable = false) - @Comment("Sequence") + @Comment("TSID") private Long id; @Size(max = 255) diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteJpaEntity.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteJpaEntity.java index 50e40802..16de15c7 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VoteJpaEntity.java @@ -2,6 +2,7 @@ import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity; import com.tune_fun.v1.common.entity.BaseEntity; +import io.hypersistence.utils.hibernate.id.Tsid; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -23,9 +24,9 @@ public class VoteJpaEntity extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @Tsid @Column(name = "id", nullable = false, updatable = false) - @Comment("Sequence") + @Comment("TSID") private Long id; @Size(max = 255) diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperJpaEntity.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperJpaEntity.java index c97a6571..1f38050b 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperJpaEntity.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperJpaEntity.java @@ -24,6 +24,7 @@ @Table(name = "vote_paper") public class VotePaperJpaEntity extends BaseEntity { + // TODO : TSID Generation으로 변경 필요하나 DummyService.initVotePaperBatch()에서 사용하므로 일단 미적용 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false, updatable = false) diff --git a/src/test/java/com/tune_fun/v1/dummy/DummyService.java b/src/test/java/com/tune_fun/v1/dummy/DummyService.java index d3ef2d3f..bd757eb2 100644 --- a/src/test/java/com/tune_fun/v1/dummy/DummyService.java +++ b/src/test/java/com/tune_fun/v1/dummy/DummyService.java @@ -31,6 +31,8 @@ import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper; import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import com.tune_fun.v1.vote.domain.value.VotePaperOption; +import io.hypersistence.tsid.TSID; +import io.hypersistence.utils.hibernate.id.TsidGenerator; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java b/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java index 1aa24793..039c1e2c 100644 --- a/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java +++ b/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java @@ -314,7 +314,7 @@ void registerVotePaperChoiceSuccess() throws Exception { assertEquals(registeredVoteChoices.size(), 3); DocumentContext parsedVoteChoices = JsonPath.parse(toJson(registeredVoteChoices)); - + List readMusic = parsedVoteChoices.read("$[*].music"); assertThat(readMusic, hasItem("이별이란 어느 별에 (Feat. 조광일)")); From 92c7d584298141bf7575878e9325f583b25290b2 Mon Sep 17 00:00:00 2001 From: habin Date: Sun, 5 May 2024 12:30:12 +0900 Subject: [PATCH 4/5] configuration(dependency) version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: 의존성 버전 업데이트 --- build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index dee30614..cff55d8a 100644 --- a/build.gradle +++ b/build.gradle @@ -77,18 +77,18 @@ dependencies { // Persistence Layer implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' - implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.4' + implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.5' implementation "io.github.openfeign.querydsl:querydsl-jpa-spring:${queryDslVersion}" implementation "io.github.openfeign.querydsl:querydsl-collections:${queryDslVersion}" implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.1' implementation 'org.flywaydb:flyway-core' - implementation 'org.flywaydb:flyway-database-postgresql:10.11.1' + implementation 'org.flywaydb:flyway-database-postgresql:10.12.0' implementation 'org.postgresql:postgresql' // development implementation 'org.springframework.retry:spring-retry' implementation 'org.springframework:spring-aspects' - implementation 'com.github.f4b6a3:ulid-creator:5.2.2' + implementation 'com.github.f4b6a3:ulid-creator:5.2.3' implementation 'org.springframework.boot:spring-boot-starter-actuator' // @see https://github.com/awspring/spring-cloud-aws/issues/657 // developmentOnly 'org.springframework.boot:spring-boot-devtools' @@ -102,7 +102,7 @@ dependencies { implementation 'com.amazonaws.secretsmanager:aws-secretsmanager-jdbc:2.0.2' implementation 'software.amazon.awssdk:kms' implementation 'com.amazonaws:aws-encryption-sdk-java:3.0.0' - implementation 'software.amazon.cryptography:aws-cryptographic-material-providers:1.2.0' + implementation 'software.amazon.cryptography:aws-cryptographic-material-providers:1.3.0' implementation 'org.springframework.boot:spring-boot-starter-quartz' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1' implementation 'com.slack.api:slack-app-backend:1.39.0' @@ -149,7 +149,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.security:spring-security-test' - testImplementation 'com.c4-soft.springaddons:spring-addons-oauth2-test:7.6.12' + testImplementation 'com.c4-soft.springaddons:spring-addons-oauth2-test:7.6.13' testImplementation 'org.springframework.kafka:spring-kafka-test' testImplementation 'org.apache.commons:commons-lang3:3.14.0' testImplementation 'com.tngtech.archunit:archunit-junit5:1.2.2' // Architecture Rule Test @@ -157,7 +157,7 @@ dependencies { testImplementation 'org.quickperf:quick-perf-junit5:1.1.0' // Performance Test testImplementation 'io.karatelabs:karate-junit5:1.5.0.RC3' // Both Test Pyramid testImplementation 'com.icegreen:greenmail-junit5:2.0.1' - testImplementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager:3.1.0' + testImplementation 'io.awspring.cloud:spring-cloud-aws-starter-secrets-manager' testImplementation 'org.awaitility:awaitility:4.2.1' testImplementation 'org.awaitility:awaitility-proxy:3.1.6' From 48f574efca09cb6d468731f76881d0ae4eabb6a9 Mon Sep 17 00:00:00 2001 From: habin Date: Sun, 5 May 2024 18:09:51 +0900 Subject: [PATCH 5/5] feat(vote-paper) detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: FullVotePaper 매핑 로직 구현 test: getVotePaper API 단위 테스트 구현 --- .../v1/common/response/BasePayload.java | 2 - .../input/rest/VotePaperController.java | 9 +- .../output/persistence/VotePaperMapper.java | 9 -- .../persistence/VotePaperRepository.java | 2 +- .../persistence/VotePersistenceAdapter.java | 11 +-- .../input/usecase/GetVotePaperUseCase.java | 4 +- .../port/output/LoadVotePaperPort.java | 3 - .../service/GetVotePaperService.java | 19 +++- .../application/service/VoteValueMapper.java | 31 ++++++ .../v1/vote/domain/value/FullVotePaper.java | 26 +++-- .../domain/value/RegisteredVoteChoice.java | 4 +- .../input/rest/VotePaperControllerIT.java | 99 +++++++++++++++++-- 12 files changed, 176 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/tune_fun/v1/vote/application/service/VoteValueMapper.java diff --git a/src/main/java/com/tune_fun/v1/common/response/BasePayload.java b/src/main/java/com/tune_fun/v1/common/response/BasePayload.java index c4e82979..95c4f8ef 100644 --- a/src/main/java/com/tune_fun/v1/common/response/BasePayload.java +++ b/src/main/java/com/tune_fun/v1/common/response/BasePayload.java @@ -1,10 +1,8 @@ package com.tune_fun.v1.common.response; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -@JsonInclude(JsonInclude.Include.NON_NULL) public interface BasePayload { } diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java b/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java index 9ff9b1fa..b76ad32f 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java @@ -10,6 +10,7 @@ import com.tune_fun.v1.common.response.ResponseMapper; import com.tune_fun.v1.vote.application.port.input.command.VotePaperCommands; import com.tune_fun.v1.vote.application.port.input.usecase.*; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; @@ -48,10 +49,10 @@ public ResponseEntity> getVotePapers(@RequestP } @GetMapping(value = Uris.VOTE_PAPER_ROOT + "/{votePaperId}") - public ResponseEntity> getVotePaper(@PathVariable("votePaperId") @NotNull(message = "{vote.paper.id.not_null}") final Long votePaperId, - @CurrentUser final User user) { - getVotePaperUseCase.getVotePaper(votePaperId); - return responseMapper.ok(MessageCode.SUCCESS); + public ResponseEntity> getVotePaper(@PathVariable("votePaperId") @NotNull(message = "{vote.paper.id.not_null}") final Long votePaperId, + @CurrentUser final User user) { + FullVotePaper votePaper = getVotePaperUseCase.getVotePaper(votePaperId); + return responseMapper.ok(MessageCode.SUCCESS, votePaper); } // TODO : Follower 로직 구현 후 테스트 재진행 예정 diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java index a1758293..5c54e548 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperMapper.java @@ -4,10 +4,8 @@ import com.tune_fun.v1.common.config.BaseMapperConfig; import com.tune_fun.v1.common.util.StringUtil; import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper; -import com.tune_fun.v1.vote.domain.value.FullVotePaper; import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; -import com.tune_fun.v1.vote.domain.value.VotePaperOption; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; @@ -52,11 +50,4 @@ public Long remainDays(final VotePaperJpaEntity votePaperJpaEntity) { @Mapping(target = "videoUrl", source = "videoUrl") public abstract VotePaperJpaEntity.VotePaperJpaEntityBuilder updateVideoUrl(final String videoUrl, @MappingTarget VotePaperJpaEntity.VotePaperJpaEntityBuilder builder); - - @Mapping(target = "authorUsername", source = "author.username") - @Mapping(target = "authorNickname", source = "author.nickname") - @Mapping(target = "remainDays", source = ".", qualifiedByName = "remainDays") - @Mapping(target = "totalVoteCount", constant = "0") - @Mapping(target = "totalLikeCount", constant = "0") - public abstract FullVotePaper fullVotePaper(VotePaperJpaEntity votePaperJpaEntity); } diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java index ab4556f2..affc3c87 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java @@ -14,7 +14,7 @@ public interface VotePaperRepository extends JpaRepository findByVoteEndAtAfterAndAuthorUsernameAndEnabledTrue(LocalDateTime voteEndAt, String author); - @EntityGraph(attributePaths = {"author", "choices"}) + @EntityGraph(attributePaths = {"author"}) Optional findByVoteEndAtAfterAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id); Optional findByVoteEndAtBeforeAndIdAndEnabledTrue(LocalDateTime voteEndAt, Long id); diff --git a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java index 15df7f28..8ab131ef 100644 --- a/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java +++ b/src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java @@ -8,7 +8,10 @@ import com.tune_fun.v1.vote.application.port.output.*; import com.tune_fun.v1.vote.domain.behavior.SaveVoteChoice; import com.tune_fun.v1.vote.domain.behavior.SaveVotePaper; -import com.tune_fun.v1.vote.domain.value.*; +import com.tune_fun.v1.vote.domain.value.RegisteredVote; +import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice; +import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; +import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.KeysetScrollPosition; import org.springframework.data.domain.Sort; @@ -88,12 +91,6 @@ public Window scrollVotePaper(final Integer lastId, final S return votePaperRepository.findFirst10ByEnabledTrue(position, sort).map(votePaperMapper::scrollableVotePaper); } - @Override - public Optional loadFullVotePaper(final Long votePaperId) { - return votePaperRepository.findByVoteEndAtAfterAndIdAndEnabledTrue(now(), votePaperId) - .map(votePaperMapper::fullVotePaper); - } - @Override public Optional loadRegisteredVotePaper(final String username) { return findProgressingVotePaperByAuthor(username).map(votePaperMapper::registeredVotePaper); diff --git a/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java b/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java index a1a69101..3f57f91e 100644 --- a/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java +++ b/src/main/java/com/tune_fun/v1/vote/application/port/input/usecase/GetVotePaperUseCase.java @@ -1,8 +1,10 @@ package com.tune_fun.v1.vote.application.port.input.usecase; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; + @FunctionalInterface public interface GetVotePaperUseCase { - void getVotePaper(final Long votePaperId); + FullVotePaper getVotePaper(final Long votePaperId); } diff --git a/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java b/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java index f97ee474..ffddc956 100644 --- a/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java +++ b/src/main/java/com/tune_fun/v1/vote/application/port/output/LoadVotePaperPort.java @@ -1,6 +1,5 @@ package com.tune_fun.v1.vote.application.port.output; -import com.tune_fun.v1.vote.domain.value.FullVotePaper; import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import com.tune_fun.v1.vote.domain.value.ScrollableVotePaper; import org.springframework.data.domain.Window; @@ -11,8 +10,6 @@ public interface LoadVotePaperPort { Window scrollVotePaper(final Integer lastId, final String sortType); - Optional loadFullVotePaper(final Long votePaperId); - Optional loadRegisteredVotePaper(final String username); Optional loadRegisteredVotePaper(final Long votePaperId); diff --git a/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java b/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java index a1ef9964..a3162139 100644 --- a/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java +++ b/src/main/java/com/tune_fun/v1/vote/application/service/GetVotePaperService.java @@ -1,20 +1,37 @@ package com.tune_fun.v1.vote.application.service; +import com.tune_fun.v1.common.exception.CommonApplicationException; import com.tune_fun.v1.common.hexagon.UseCase; import com.tune_fun.v1.vote.application.port.input.usecase.GetVotePaperUseCase; +import com.tune_fun.v1.vote.application.port.output.LoadVoteChoicePort; import com.tune_fun.v1.vote.application.port.output.LoadVotePaperPort; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; +import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice; +import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + +import static com.tune_fun.v1.common.response.MessageCode.VOTE_PAPER_NOT_FOUND; + @Service @UseCase @RequiredArgsConstructor public class GetVotePaperService implements GetVotePaperUseCase { private final LoadVotePaperPort loadVotePaperPort; + private final LoadVoteChoicePort loadVoteChoicePort; + + private final VoteValueMapper voteValueMapper; + @Override - public void getVotePaper(final Long votePaperId) { + public FullVotePaper getVotePaper(final Long votePaperId) { + RegisteredVotePaper registeredVotePaper = loadVotePaperPort.loadRegisteredVotePaper(votePaperId) + .orElseThrow(() -> new CommonApplicationException(VOTE_PAPER_NOT_FOUND)); + List registeredVoteChoices = loadVoteChoicePort.loadRegisteredVoteChoice(votePaperId); + return voteValueMapper.fullVotePaper(registeredVotePaper, registeredVoteChoices); } } diff --git a/src/main/java/com/tune_fun/v1/vote/application/service/VoteValueMapper.java b/src/main/java/com/tune_fun/v1/vote/application/service/VoteValueMapper.java new file mode 100644 index 00000000..a83691d8 --- /dev/null +++ b/src/main/java/com/tune_fun/v1/vote/application/service/VoteValueMapper.java @@ -0,0 +1,31 @@ +package com.tune_fun.v1.vote.application.service; + +import com.tune_fun.v1.common.config.BaseMapperConfig; +import com.tune_fun.v1.vote.domain.value.FullVotePaper; +import com.tune_fun.v1.vote.domain.value.RegisteredVoteChoice; +import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +import java.util.List; + +@Mapper(config = BaseMapperConfig.class) +public abstract class VoteValueMapper { + + @Mapping(target = "id", source = "votePaper.id") + @Mapping(target = "uuid", source = "votePaper.uuid") + @Mapping(target = "author", source = "votePaper.author") + @Mapping(target = "authorUsername", source = "votePaper.authorUsername") + @Mapping(target = "title", source = "votePaper.title") + @Mapping(target = "content", source = "votePaper.content") + @Mapping(target = "option", source = "votePaper.option") + @Mapping(target = "videoUrl", source = "votePaper.videoUrl") + @Mapping(target = "voteStartAt", source = "votePaper.voteStartAt") + @Mapping(target = "voteEndAt", source = "votePaper.voteEndAt") + @Mapping(target = "deliveryAt", source = "votePaper.deliveryAt") + @Mapping(target = "createdAt", source = "votePaper.createdAt") + @Mapping(target = "updatedAt", source = "votePaper.updatedAt") + @Mapping(target = "choices", source = "voteChoices") + public abstract FullVotePaper fullVotePaper(final RegisteredVotePaper votePaper, final List voteChoices); + +} diff --git a/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java index 6f382aa3..9b6fdaf5 100644 --- a/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java +++ b/src/main/java/com/tune_fun/v1/vote/domain/value/FullVotePaper.java @@ -1,23 +1,37 @@ package com.tune_fun.v1.vote.domain.value; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.tune_fun.v1.common.response.BasePayload; + import java.time.LocalDateTime; import java.util.Set; public record FullVotePaper( Long id, String uuid, + String author, String authorUsername, - String authorNickname, String title, String content, VotePaperOption option, String videoUrl, + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime voteStartAt, + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime voteEndAt, + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime deliveryAt, - Long remainDays, - String totalVoteCount, - String totalLikeCount, - Set choices -) { + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime createdAt, + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime updatedAt, + + Set choices +) implements BasePayload { + } diff --git a/src/main/java/com/tune_fun/v1/vote/domain/value/RegisteredVoteChoice.java b/src/main/java/com/tune_fun/v1/vote/domain/value/RegisteredVoteChoice.java index d182d91d..3bdd3e11 100644 --- a/src/main/java/com/tune_fun/v1/vote/domain/value/RegisteredVoteChoice.java +++ b/src/main/java/com/tune_fun/v1/vote/domain/value/RegisteredVoteChoice.java @@ -1,5 +1,7 @@ package com.tune_fun.v1.vote.domain.value; +import com.tune_fun.v1.common.response.BasePayload; + import java.util.Set; public record RegisteredVoteChoice( @@ -10,5 +12,5 @@ public record RegisteredVoteChoice( Set genres, String releaseDate, Integer durationMs -) { +) implements BasePayload { } diff --git a/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java b/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java index 039c1e2c..ea272a8b 100644 --- a/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java +++ b/src/test/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperControllerIT.java @@ -164,6 +164,89 @@ void getVotePapersSuccess() throws Exception { @Transactional @Test @Order(2) + @DisplayName("투표 게시물 상세 조회, 성공") + void getVotePaperSuccess() throws Exception { + dummyService.initAndLogin(); + dummyService.initArtistAndLogin(); + + dummyService.initVotePaper(); + dummyService.registerVote(); + + Long votePaperId = dummyService.getDefaultVotePaper().getId(); + String accessToken = dummyService.getDefaultAccessToken(); + + ParameterDescriptor pathParameter = parameterWithName("votePaperId").description("투표 게시물 ID").attributes(constraint("NOT NULL")); + + FieldDescriptor[] responseDescriptors = ArrayUtils.addAll(baseResponseFields, + fieldWithPath("data.id").description("투표 게시물 ID").attributes(constraint("NOT NULL")), + fieldWithPath("data.uuid").description("투표 게시물 UUID").attributes(constraint("NOT NULL")), + fieldWithPath("data.author").description("투표 게시물 작성자 닉네임").attributes(constraint("NOT NULL")), + fieldWithPath("data.author_username").description("투표 게시물 작성자 아이디").attributes(constraint("NOT NULL")), + fieldWithPath("data.title").description("투표 게시물 제목").attributes(constraint("NOT NULL")), + fieldWithPath("data.content").description("투표 게시물 내용").attributes(constraint("NOT NULL")), + fieldWithPath("data.option").description("투표 종류").attributes(constraint("NOT NULL")), + fieldWithPath("data.video_url").description("투표 게시물 영상 URL").attributes(constraint("NULL or NOT NULL")), + fieldWithPath("data.vote_start_at").description("투표 시작 시간").attributes(constraint("NOT NULL")), + fieldWithPath("data.vote_end_at").description("투표 종료 시간").attributes(constraint("NOT NULL")), + fieldWithPath("data.delivery_at").description("투표 게시물 영상 제공일").attributes(constraint("NULL or NOT NULL")), + fieldWithPath("data.created_at").description("투표 게시물 생성 시간").attributes(constraint("NOT NULL")), + fieldWithPath("data.updated_at").description("투표 게시물 수정 시간").attributes(constraint("NOT NULL")), + fieldWithPath("data.choices").description("투표 선택지 목록").attributes(constraint("NOT EMPTY")), + fieldWithPath("data.choices[].id").description("아이디").attributes(constraint("NOT NULL")), + fieldWithPath("data.choices[].music").description("노래명").attributes(constraint("NOT BLANK")), + fieldWithPath("data.choices[].artist_name").description("아티스트명").attributes(constraint("NOT BLANK")), + fieldWithPath("data.choices[].genres[]").description("장르").attributes(constraint("NOT EMPTY")), + fieldWithPath("data.choices[].duration_ms").description("재생 시간(ms)").attributes(constraint("NOT NULL & POSITIVE")), + fieldWithPath("data.choices[].release_date").description("발매일").attributes(constraint("NOT BLANK")), + fieldWithPath("data.choices[].vote_paper_id").description("투표 게시물 ID").attributes(constraint("NOT NULL")) + ); + + mockMvc.perform( + get(Uris.VOTE_PAPER_ROOT + "/{votePaperId}", votePaperId) + .header(AUTHORIZATION, bearerToken(accessToken)) + ) + .andExpectAll(baseAssertion(MessageCode.SUCCESS)) + .andExpect(jsonPath("data.id", notNullValue())) + .andExpect(jsonPath("data.uuid", notNullValue())) + .andExpect(jsonPath("data.author", notNullValue())) + .andExpect(jsonPath("data.author_username", notNullValue())) + .andExpect(jsonPath("data.title", notNullValue())) + .andExpect(jsonPath("data.content", notNullValue())) + .andExpect(jsonPath("data.option", notNullValue())) + .andExpect(jsonPath("data.video_url", nullValue())) + .andExpect(jsonPath("data.vote_start_at", notNullValue())) + .andExpect(jsonPath("data.vote_end_at", notNullValue())) + .andExpect(jsonPath("data.delivery_at", nullValue())) + .andExpect(jsonPath("data.created_at", notNullValue())) + .andExpect(jsonPath("data.updated_at", notNullValue())) + .andExpect(jsonPath("data.choices", notNullValue())) + .andExpect(jsonPath("data.choices[*].id", notNullValue())) + .andExpect(jsonPath("data.choices[*].music", notNullValue())) + .andExpect(jsonPath("data.choices[*].artist_name", notNullValue())) + .andExpect(jsonPath("data.choices[*].genres[*]", notNullValue())) + .andExpect(jsonPath("data.choices[*].duration_ms", notNullValue())) + .andExpect(jsonPath("data.choices[*].release_date", notNullValue())) + .andExpect(jsonPath("data.choices[*].vote_paper_id", notNullValue())) + .andDo( + restDocs.document( + requestHeaders(authorizationHeader), + pathParameters(pathParameter), + responseFields(responseDescriptors), + resource( + builder(). + description("투표 게시물 상세 조회"). + pathParameters(pathParameter). + responseFields(responseDescriptors) + .build() + ) + ) + ); + + } + + @Transactional + @Test + @Order(3) @DisplayName("투표 게시물 등록, 성공") void registerVotePaperSuccess() throws Exception { dummyService.initAndLogin(); @@ -249,7 +332,7 @@ void registerVotePaperSuccess() throws Exception { log.info("readMusic: {}", readMusic); assertThat(readMusic, hasItems("KNOCK (With 박문치)", "Orange, You're Not a Joke to Me!")); - List readArtistName = parsedChoices.read("$[*].artistName"); + List readArtistName = parsedChoices.read("$[*].artist_name"); log.info("readArtistName: {}", readArtistName); assertThat(readArtistName, hasItems("권진아", "스텔라장 (Stella Jang)")); @@ -260,7 +343,7 @@ void registerVotePaperSuccess() throws Exception { @Transactional @Test - @Order(3) + @Order(4) @DisplayName("투표 선택지 등록, 성공") void registerVotePaperChoiceSuccess() throws Exception { dummyService.initAccount(); @@ -318,22 +401,22 @@ void registerVotePaperChoiceSuccess() throws Exception { List readMusic = parsedVoteChoices.read("$[*].music"); assertThat(readMusic, hasItem("이별이란 어느 별에 (Feat. 조광일)")); - List readArtistName = parsedVoteChoices.read("$[*].artistName"); + List readArtistName = parsedVoteChoices.read("$[*].artist_name"); assertThat(readArtistName, hasItem("HYNN (박혜원)")); List> readGenres = parsedVoteChoices.read("$[*].genres"); assertThat(readGenres, hasItem(singletonList("Ballad"))); - List readDurationMs = parsedVoteChoices.read("$[*].durationMs"); + List readDurationMs = parsedVoteChoices.read("$[*].duration_ms"); assertThat(readDurationMs, hasItem(231_000)); - List readReleaseDate = parsedVoteChoices.read("$[*].releaseDate"); + List readReleaseDate = parsedVoteChoices.read("$[*].release_date"); assertThat(readReleaseDate, hasItem("2022-02-11")); } @Transactional @Test - @Order(4) + @Order(5) @DisplayName("투표 게시물 영상 제공일 등록, 성공") void updateDeliveryDateSuccess() throws Exception { dummyService.initAndLogin(); @@ -389,7 +472,7 @@ void updateDeliveryDateSuccess() throws Exception { @Transactional @Test - @Order(5) + @Order(6) @DisplayName("투표 게시물 영상 업로드, 성공") void updateVideoUrlSuccess() throws Exception { dummyService.initAndLogin(); @@ -446,7 +529,7 @@ void updateVideoUrlSuccess() throws Exception { @Transactional @Test - @Order(6) + @Order(7) @DisplayName("투표 게시물 삭제, 성공") void deleteVotePaperSuccess() throws Exception { dummyService.initAndLogin();