fix: 탐색 주제 필터가 slug 를 보내고, 편집기를 넓혀 두 칸이 함께 스크롤한다
주제 필터를 걸면 「조건에 맞는 공개 기록이 없습니다」만 남았다. 선택지가
`<option>{이름}</option>` 이라 값이 없어 이름이 그대로 나갔고 — `topic=OAuth/OIDC 인증
경계` — API 는 slug 로 거르므로 0건을 돌려줬다. 프로젝트 선택지는 처음부터
`value={slug}` 였고, 그래서 프로젝트만 멀쩡했다. 주제도 같은 모양으로 맞춘다.
테스트가 이 결함을 통과시킨 이유는 픽스처의 주제 이름이 `JPA`, `Authentication` 처럼
slug 와 구분되지 않는 값이어서다. 이름과 slug 가 다른 값을 쓰는 운영에서만 드러났다.
선택지의 값이 slug 인지 직접 묻는 단언을 넣는다.
`RecordFilters.topic` 은 어댑터마다 뜻이 달랐다. 정적 어댑터는 이름으로, HTTP 어댑터는
그 값을 그대로 API 에 넘겨 slug 로 걸렀다. 프로젝트가 이미 slug/제목 둘 다 받는 것과
같이 주제도 둘 다 받게 해서 두 어댑터가 같은 값을 이해하게 한다. 주제 페이지도 이름
대신 경로의 slug 로 묻는다.
「전체」를 고른 칸은 조건이 아니다. 빈 값까지 실어 보내고 있었고, URL 이 지저분해질 뿐
아니라 이 값을 그대로 API 에 넘기는 화면에서는 `topic=` 이 "slug 가 빈 문자열인 주제"로
해석되어 0건이 된다.
편집기는 미리보기를 붙박이로 두고 자체 스크롤을 줬다. 편집기를 내려도 미리보기는
제자리였고, 보려면 그 안을 따로 굴려야 했다 — 나란히 둔 이유가 둘을 같이 보는 것인데
움직임이 갈라지면 그 이점이 없다. 둘 다 페이지 스크롤을 그대로 타게 한다.
폭도 넓힌다. `.studio-main` 은 모든 Studio 화면이 1180px 를 함께 쓰는데, 본문 두 벌이
들어가야 하는 이 화면에서는 한 칸이 566px 였다. 편집기가 놓인 경우에만 1600px 로
넓히고 헤더도 같이 넓혀 좌우 끝을 맞춘다. 다른 화면은 그대로다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0189NzCryfeqDzS81EWidnBx
This commit is contained in:
co-authored by
Claude Opus 5
parent
60c8c82097
commit
344a163d84
@@ -296,7 +296,7 @@ describe("TechLog explore discovery", () => {
|
||||
const user = userEvent.setup();
|
||||
const { router } = await renderDiscoveryRoute(
|
||||
"TECH_LOG_EXPLORE",
|
||||
"/explore?type=CASE&topic=JPA&project=backend-skeleton",
|
||||
"/explore?type=CASE&topic=jpa&project=backend-skeleton",
|
||||
);
|
||||
|
||||
expect(screen.getByRole("heading", { level: 1, name: "탐색" })).toBeVisible();
|
||||
@@ -306,22 +306,28 @@ describe("TechLog explore discovery", () => {
|
||||
// 필터의 선택지는 카탈로그가 도착한 뒤 채워지고, select 의 값도 그때 설정된다.
|
||||
await waitFor(() => {
|
||||
expect(screen.getByLabelText("유형")).toHaveValue("CASE");
|
||||
expect(screen.getByLabelText("주제")).toHaveValue("JPA");
|
||||
expect(screen.getByLabelText("주제")).toHaveValue("jpa");
|
||||
expect(screen.getByLabelText("프로젝트")).toHaveValue("backend-skeleton");
|
||||
});
|
||||
// 주제 선택지는 보이는 이름과 보내는 값이 다르다. 값이 이름이면 slug 로 거르는 API 가
|
||||
// 0건을 돌려주고, 화면은 「조건에 맞는 공개 기록이 없습니다」만 남는다 — 운영에서 실제로
|
||||
// 그랬다. 목록에서 유도한 값이라 이 단언이 없으면 조용히 되돌아간다.
|
||||
expect(
|
||||
within(screen.getByLabelText("주제")).getByRole("option", { name: "Authentication" }),
|
||||
).toHaveValue("authentication");
|
||||
expect(screen.getByText("1개의 공개 기록")).toBeVisible();
|
||||
expect(
|
||||
screen.getByRole("link", { name: /컬렉션 Fetch Join과 페이징은 왜 충돌하는가/ }),
|
||||
).toHaveAttribute("href", "/cases/collection-fetch-join-pagination");
|
||||
|
||||
await user.selectOptions(screen.getByLabelText("유형"), "QUESTION");
|
||||
await user.selectOptions(screen.getByLabelText("주제"), "Authentication");
|
||||
await user.selectOptions(screen.getByLabelText("주제"), "authentication");
|
||||
await user.selectOptions(screen.getByLabelText("프로젝트"), "auth-lab");
|
||||
await user.click(screen.getByRole("button", { name: "적용" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(router.state.location.search).toBe(
|
||||
"?project=auth-lab&topic=Authentication&type=QUESTION",
|
||||
"?project=auth-lab&topic=authentication&type=QUESTION",
|
||||
);
|
||||
});
|
||||
expect(screen.getByText("1개의 공개 기록")).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user