diff --git a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/JdbcPublicSiteQueryAdapter.java b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/JdbcPublicSiteQueryAdapter.java index 6648395..db3a237 100644 --- a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/JdbcPublicSiteQueryAdapter.java +++ b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/JdbcPublicSiteQueryAdapter.java @@ -180,8 +180,8 @@ public class JdbcPublicSiteQueryAdapter implements PublicSiteQueryPort { } /** - * 계약 {@code LatestEntry.entryType} 은 {@code CASE / REFERENCE / PROJECT_ACTIVITY / RELEASE} 네 값만 - * 허용한다. projection 에는 {@code QUESTION}·{@code PROJECT}·{@code PROJECT_DECISION}·{@code PROFILE} 도 + * 계약 {@code LatestEntry.entryType} 은 {@code CASE / REFERENCE / QUESTION / PROJECT_ACTIVITY / + * RELEASE} 다섯 값을 허용한다. projection 에는 {@code PROJECT}·{@code PROJECT_DECISION}·{@code PROFILE} 도 * 들어 있으므로 여기서 걸러야 한다 — 거르지 않으면 응답 매퍼가 계약 밖 값을 만나 500 이 되고, 그 500 은 홈 화면 전체를 못 쓰게 만든다. * *
{@code RELEASE} 가 결과에 없는 것은 누락이 아니다. 릴리스는 Publication 파이프라인을 거치지 않고 자체 {@code diff --git a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSql.java b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSql.java index 4d9487c..58e1fdb 100644 --- a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSql.java +++ b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSql.java @@ -16,7 +16,7 @@ final class PublicSql { * 조건도 한 곳에서 정의한다. */ static final String LATEST_ENTRY_TYPES = - " p.resource_type IN ('CASE', 'REFERENCE', 'PROJECT_ACTIVITY') "; + " p.resource_type IN ('CASE', 'REFERENCE', 'QUESTION', 'PROJECT_ACTIVITY') "; private PublicSql() {} diff --git a/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSitePersistenceIntegrationTest.java b/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSitePersistenceIntegrationTest.java index e674b84..244e69d 100644 --- a/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSitePersistenceIntegrationTest.java +++ b/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/publicsite/PublicSitePersistenceIntegrationTest.java @@ -206,12 +206,21 @@ class PublicSitePersistenceIntegrationTest { .noneMatch(entry -> entry.title().contains("숨김")); assertThat(view.latestEntries()) .as( - "계약 LatestEntry.entryType 은 네 값만 허용한다 — projection 의 QUESTION/PROJECT 등이 섞이면" - + " 응답 매퍼가 계약 밖 값을 만나 500 이 된다") + "계약 LatestEntry.entryType 이 허용하는 값만 나와야 한다 — projection 의 PROJECT/PROJECT_DECISION" + + " 등이 섞이면 응답 매퍼가 계약 밖 값을 만나 500 이 되고, 그 500 은 홈 화면 전체를 못 쓰게 만든다") .extracting("entryType") .containsAnyOf("CASE", "REFERENCE", "PROJECT_ACTIVITY") .allSatisfy( - type -> assertThat(type).isIn("CASE", "REFERENCE", "PROJECT_ACTIVITY", "RELEASE")); + type -> + assertThat(type) + .isIn("CASE", "REFERENCE", "QUESTION", "PROJECT_ACTIVITY", "RELEASE")); + assertThat(view.latestEntries()) + .as("게시한 Open Question 도 최근 기록에 나와야 한다 — 목록에서 빠지면 게시한 사실이 어디에도 보이지 않는다") + .anySatisfy( + entry -> { + assertThat(entry.entryType()).isEqualTo("QUESTION"); + assertThat(entry.path()).isEqualTo("/questions/reprocessing-latency"); + }); } /** @@ -397,10 +406,16 @@ class PublicSitePersistenceIntegrationTest { assertThat(view.relatedProjects()).extracting("title").contains("Tech Log"); assertThat(view.latestRecords()).isNotEmpty(); assertThat(view.latestRecords()) - .as("주제 상세의 최신 기록도 계약의 entryType 네 값을 벗어나면 안 된다") + .as("주제 상세의 최신 기록도 계약의 entryType 을 벗어나면 안 된다") .extracting("entryType") .allSatisfy( - type -> assertThat(type).isIn("CASE", "REFERENCE", "PROJECT_ACTIVITY", "RELEASE")); + type -> + assertThat(type) + .isIn("CASE", "REFERENCE", "QUESTION", "PROJECT_ACTIVITY", "RELEASE")); + assertThat(view.latestRecords()) + .as("주제와 홈은 같은 목록 의미를 쓴다 — 홈에 나오는 Open Question 이 여기서 빠지면 두 화면이 어긋난다") + .extracting("entryType") + .contains("QUESTION"); } @Test diff --git a/src/config/openapi/MANIFEST.sha256 b/src/config/openapi/MANIFEST.sha256 index 2e2ceb4..3320ae9 100644 --- a/src/config/openapi/MANIFEST.sha256 +++ b/src/config/openapi/MANIFEST.sha256 @@ -1,6 +1,6 @@ # source: tech-log-design-package contracts/openapi/studio-v1.yaml @ 0ffbc28 (master) 18dd46898be64b07f7e826409d19347512613ee2e22420028a4a0644f50f37dd studio-v1.yaml -# source: tech-log-design-package contracts/openapi/public-v1.yaml @ 0ffbc28 (master) -79949b286e2b4d28333d3376945960a319d247b675b23a73f50b75ce10994c5e public-v1.yaml +# source: tech-log-design-package contracts/openapi/public-v1.yaml @ ef49d3a (master) +7eb668e39e279e49767306dd36e1dd51302071c39d78495d21307bbd9676220e public-v1.yaml # source: tech-log-design-package contracts/openapi/studio-management-v1.yaml @ 0ffbc28 (master) 72650735061fde627f5037571eb986cb758f44a546f065c88408399f8eec4a55 studio-management-v1.yaml diff --git a/src/config/openapi/public-v1.yaml b/src/config/openapi/public-v1.yaml index 28dd4f5..1631d17 100644 --- a/src/config/openapi/public-v1.yaml +++ b/src/config/openapi/public-v1.yaml @@ -1022,6 +1022,7 @@ components: enum: - CASE - REFERENCE + - QUESTION - PROJECT_ACTIVITY - RELEASE title: