Compare commits

...

6 Commits

14 changed files with 38 additions and 8 deletions

View File

@@ -99,15 +99,15 @@ tasks.withType<KotlinCompile> {
}
}
tasks.withType<Test>().configureEach {
maxParallelForks = 1
forkEvery = 100
tasks.withType<Test> {
useJUnitPlatform()
maxHeapSize = "1024m"
val springContextCacheMaxSize = (project.findProperty("test.springContextCacheMaxSize") as String?) ?: "1"
maxHeapSize = (project.findProperty("testMaxHeap") as String?) ?: "1536m"
jvmArgs(
"-XX:MaxMetaspaceSize=512m",
"-Dfile.encoding=UTF-8"
"-Dfile.encoding=UTF-8",
"-Dspring.test.context.cache.maxSize=$springContextCacheMaxSize"
)
}

View File

@@ -186,6 +186,8 @@ data class CreatorChannelCommunityCommentResponse(
val writerProfileImageUrl: String,
val writerNickname: String,
val content: String,
@JsonProperty("isSecret")
val isSecret: Boolean,
val createdAtUtc: String,
val latestReply: CreatorChannelCommunityReplyResponse?
) {
@@ -197,6 +199,7 @@ data class CreatorChannelCommunityCommentResponse(
writerProfileImageUrl = comment.writerProfileImageUrl,
writerNickname = comment.writerNickname,
content = comment.content,
isSecret = comment.isSecret,
createdAtUtc = comment.createdAt.toUtcIso(),
latestReply = comment.latestReply?.let(CreatorChannelCommunityReplyResponse::from)
)
@@ -278,6 +281,7 @@ data class CreatorChannelCommunityComment(
val writerProfileImageUrl: String,
val writerNickname: String,
val content: String,
val isSecret: Boolean,
val createdAt: LocalDateTime,
val latestReply: CreatorChannelCommunityReply?
)
@@ -353,6 +357,7 @@ data class CreatorChannelCommunityCommentRecord(
val writerProfilePath: String?,
val writerNickname: String,
val content: String,
val isSecret: Boolean,
val createdAt: LocalDateTime
)

View File

@@ -173,6 +173,7 @@ data class CreatorChannelCommunityPostDetailResponse(
- `comments`는 조회자가 볼 수 있는 활성 최상위 댓글 목록이다.
- 댓글 작성자가 조회자와 차단/피차단 관계이면 목록과 전체 개수에서 제외한다.
- 비밀 댓글은 게시물 작성자 또는 댓글 작성자 본인에게만 노출한다.
- 각 댓글에는 비밀 댓글 여부인 `isSecret`을 포함한다.
- 댓글 정렬은 최신순 `createdAt desc`, `id desc`를 따른다.
- 각 댓글에는 최신 답글 1개를 `latestReply`로 포함한다.
- 최신 답글은 해당 댓글의 활성 답글 중 조회자가 볼 수 있는 답글을 `createdAt desc`, `id desc`로 정렬했을 때 첫 번째 항목이다.
@@ -198,6 +199,8 @@ data class CreatorChannelCommunityCommentResponse(
val writerProfileImageUrl: String,
val writerNickname: String,
val content: String,
@JsonProperty("isSecret")
val isSecret: Boolean,
val createdAtUtc: String,
val latestReply: CreatorChannelCommunityReplyResponse?
)

View File

@@ -81,6 +81,8 @@ data class CreatorChannelCommunityCommentResponse(
val writerProfileImageUrl: String,
val writerNickname: String,
val content: String,
@JsonProperty("isSecret")
val isSecret: Boolean,
val createdAtUtc: String,
val latestReply: CreatorChannelCommunityReplyResponse?
) {
@@ -92,6 +94,7 @@ data class CreatorChannelCommunityCommentResponse(
writerProfileImageUrl = comment.writerProfileImageUrl,
writerNickname = comment.writerNickname,
content = comment.content,
isSecret = comment.isSecret,
createdAtUtc = comment.createdAt.toUtcIso(),
latestReply = comment.latestReply?.let(CreatorChannelCommunityReplyResponse::from)
)

View File

@@ -260,6 +260,7 @@ class DefaultCreatorChannelCommunityQueryRepository(
creatorCommunityComment.member.profileImage,
creatorCommunityComment.member.nickname,
creatorCommunityComment.comment,
creatorCommunityComment.isSecret,
creatorCommunityComment.createdAt
)
@@ -556,6 +557,7 @@ class DefaultCreatorChannelCommunityQueryRepository(
writerProfilePath = get(creatorCommunityComment.member.profileImage),
writerNickname = get(creatorCommunityComment.member.nickname)!!,
content = get(creatorCommunityComment.comment)!!,
isSecret = get(creatorCommunityComment.isSecret)!!,
createdAt = get(creatorCommunityComment.createdAt)!!
)
}

View File

@@ -257,6 +257,7 @@ class CreatorChannelCommunityQueryService(
writerProfileImageUrl = writerProfilePath.toCdnUrl(cloudFrontHost) ?: defaultProfileImageUrl(),
writerNickname = writerNickname.removeDeletedNicknamePrefix(),
content = content,
isSecret = isSecret,
createdAt = createdAt,
latestReply = latestReply
)

View File

@@ -21,6 +21,7 @@ data class CreatorChannelCommunityComment(
val writerProfileImageUrl: String,
val writerNickname: String,
val content: String,
val isSecret: Boolean,
val createdAt: LocalDateTime,
val latestReply: CreatorChannelCommunityReply?
)

View File

@@ -106,6 +106,7 @@ data class CreatorChannelCommunityCommentRecord(
val writerProfilePath: String?,
val writerNickname: String,
val content: String,
val isSecret: Boolean,
val createdAt: LocalDateTime
)

View File

@@ -181,6 +181,7 @@ class CreatorChannelCommunityControllerTest @Autowired constructor(
.andExpect(jsonPath("$.data.isLiked").value(true))
.andExpect(jsonPath("$.data.comments.commentCount").value(1))
.andExpect(jsonPath("$.data.comments.comments[0].writerId").value(20))
.andExpect(jsonPath("$.data.comments.comments[0].isSecret").value(true))
.andExpect(jsonPath("$.data.comments.comments[0].latestReply.commentId").value(202))
.andExpect(jsonPath("$.data.comments.comments[0].latestReply.writerId").value(21))
}
@@ -206,6 +207,7 @@ class CreatorChannelCommunityControllerTest @Autowired constructor(
.andExpect(status().isOk)
.andExpect(jsonPath("$.data.commentCount").value(1))
.andExpect(jsonPath("$.data.comments[0].writerId").value(20))
.andExpect(jsonPath("$.data.comments[0].isSecret").value(true))
.andExpect(jsonPath("$.data.comments[0].latestReply.commentId").value(202))
.andExpect(jsonPath("$.data.comments[0].latestReply.writerId").value(21))
.andExpect(jsonPath("$.data.hasNext").value(false))
@@ -377,6 +379,7 @@ class CreatorChannelCommunityControllerTest @Autowired constructor(
writerProfileImageUrl = "https://cdn.test/writer.png",
writerNickname = "writer",
content = "comment",
isSecret = true,
createdAtUtc = "2026-07-06T03:00:00Z",
latestReply = CreatorChannelCommunityReplyResponse(
commentId = 202L,

View File

@@ -204,7 +204,9 @@ class CreatorChannelCommunityEndToEndTest @Autowired constructor(
.andExpect(jsonPath("$.data.commentCount").value(2))
.andExpect(jsonPath("$.data.comments.length()").value(2))
.andExpect(jsonPath("$.data.comments[0].commentId").value(fixture.ownSecretCommentId))
.andExpect(jsonPath("$.data.comments[0].isSecret").value(true))
.andExpect(jsonPath("$.data.comments[1].commentId").value(fixture.publicCommentId))
.andExpect(jsonPath("$.data.comments[1].isSecret").value(false))
.andExpect(jsonPath("$.data.comments[1].latestReply.commentId").value(fixture.publicReplyId))
}

View File

@@ -107,6 +107,7 @@ class CreatorChannelCommunityFacadeTest {
assertTrue(response.isLiked)
assertEquals(1, response.comments.commentCount)
assertEquals(20L, response.comments.comments.first().writerId)
assertTrue(response.comments.comments.first().isSecret)
assertEquals(21L, response.comments.comments.first().latestReply?.writerId)
assertEquals(201L, response.comments.comments.first().latestReply?.commentId)
}
@@ -126,6 +127,7 @@ class CreatorChannelCommunityFacadeTest {
assertEquals(0, response.page)
assertEquals(20, response.size)
assertEquals(20L, response.comments.first().writerId)
assertTrue(response.comments.first().isSecret)
assertEquals(21L, response.comments.first().latestReply?.writerId)
assertEquals(201L, response.comments.first().latestReply?.commentId)
}
@@ -217,6 +219,7 @@ class CreatorChannelCommunityFacadeTest {
writerProfileImageUrl = "https://cdn.test/writer.png",
writerNickname = "writer",
content = "comment",
isSecret = true,
createdAt = LocalDateTime.of(2026, 7, 6, 3, 0),
latestReply = createReplies().replies.first()
)

View File

@@ -32,6 +32,7 @@ class CreatorChannelCommunityPostDetailResponseTest {
assertTrue(detailJson["comments"]["hasNext"].asBoolean())
assertTrue(detailJson["comments"]["comments"][0].has("latestReply"))
assertTrue(detailJson["comments"]["comments"][0].has("writerId"))
assertTrue(detailJson["comments"]["comments"][0]["isSecret"].asBoolean())
assertTrue(detailJson["comments"]["comments"][0]["latestReply"].has("commentId"))
assertTrue(detailJson["comments"]["comments"][0]["latestReply"].has("writerId"))
assertTrue(repliesJson["hasNext"].asBoolean())
@@ -75,6 +76,7 @@ class CreatorChannelCommunityPostDetailResponseTest {
writerProfileImageUrl = "https://cdn.test/comment.png",
writerNickname = "comment-writer",
content = "comment",
isSecret = true,
createdAt = LocalDateTime.of(2026, 7, 6, 3, 0),
latestReply = reply
)

View File

@@ -195,6 +195,7 @@ class CreatorChannelCommunityQueryServiceTest {
assertEquals(20, detail.comments.comments.size)
assertEquals(true, detail.comments.hasNext)
assertEquals(101L, detail.comments.comments.first().writerId)
assertEquals(false, detail.comments.comments.first().isSecret)
assertEquals("reply-writer", detail.comments.comments.first().latestReply?.writerNickname)
assertEquals(200L, detail.comments.comments.first().latestReply?.writerId)
assertEquals("https://cdn.test/profile/default-profile.png", detail.comments.comments.first().writerProfileImageUrl)
@@ -237,6 +238,7 @@ class CreatorChannelCommunityQueryServiceTest {
assertEquals(50, comments.comments.size)
assertEquals(true, comments.hasNext)
assertEquals(101L, comments.comments.first().writerId)
assertEquals(false, comments.comments.first().isSecret)
assertEquals("https://cdn.test/profile/1.png", comments.comments.first().writerProfileImageUrl)
assertEquals(100L, comments.comments[1].latestReply?.commentId)
assertEquals(200L, comments.comments[1].latestReply?.writerId)
@@ -499,7 +501,8 @@ private fun communityCommentRecord(
commentId: Long,
parentCommentId: Long? = null,
writerProfilePath: String? = null,
writerNickname: String = "writer-$commentId"
writerNickname: String = "writer-$commentId",
isSecret: Boolean = false
): CreatorChannelCommunityCommentRecord {
return CreatorChannelCommunityCommentRecord(
commentId = commentId,
@@ -509,6 +512,7 @@ private fun communityCommentRecord(
writerProfilePath = writerProfilePath,
writerNickname = writerNickname,
content = "comment-$commentId",
isSecret = isSecret,
createdAt = LocalDateTime.of(2026, 7, 6, 10, 0).plusMinutes(commentId)
)
}

View File

@@ -92,7 +92,7 @@ spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:sodalive-test;MODE=MySQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
url: jdbc:h2:mem:sodalive-test-${random.uuid};MODE=MySQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
password: