RestaurantDetail.tsx의 isKoreaRestaurant() 게이트가 설계서 인수조건과 일치함을 확인. 국내/해외/URL-NONE/좌표없음 fallback 등 5개 경계 케이스를 자동화 RTL 테스트로 검증(수동 육안 QA를 대체). tsc 및 전체 jest 스위트 통과. Refs #545
118 lines
4.4 KiB
TypeScript
118 lines
4.4 KiB
TypeScript
/**
|
|
* #545 — 해외 식당 상세에서 테이블링/캐치테이블 예약 버튼 숨김 회귀 테스트.
|
|
* 좌표 기반(isKoreaRestaurant) 판정으로 국내/해외 식당에서 버튼 노출 여부가
|
|
* 올바르게 갈리는지 검증한다.
|
|
*/
|
|
import { act, render, screen } from "@testing-library/react";
|
|
import RestaurantDetail from "@/components/RestaurantDetail";
|
|
import type { Restaurant } from "@/lib/api";
|
|
|
|
// 컴포넌트 마운트 시 발생하는 비동기 데이터 로딩(영상/리뷰 등)을 플러시해
|
|
// act() 경고 없이 안정적으로 렌더 결과를 검증한다.
|
|
async function flush() {
|
|
await act(async () => {
|
|
await Promise.resolve();
|
|
});
|
|
}
|
|
|
|
jest.mock("@/lib/api", () => ({
|
|
getToken: jest.fn(() => null),
|
|
api: {
|
|
getRestaurantVideos: jest.fn(() => Promise.resolve([])),
|
|
getFavoriteStatus: jest.fn(() => Promise.resolve({ favorited: false })),
|
|
getReviews: jest.fn(() =>
|
|
Promise.resolve({ reviews: [], avg_rating: null, review_count: 0 })
|
|
),
|
|
getMemo: jest.fn(() => Promise.resolve(null)),
|
|
},
|
|
}));
|
|
|
|
function makeRestaurant(overrides: Partial<Restaurant>): Restaurant {
|
|
return {
|
|
id: "r1",
|
|
name: "테스트 식당",
|
|
address: null,
|
|
region: null,
|
|
latitude: 37.5,
|
|
longitude: 127.0,
|
|
cuisine_type: null,
|
|
price_range: null,
|
|
google_place_id: null,
|
|
tabling_url: null,
|
|
catchtable_url: null,
|
|
business_status: null,
|
|
rating: null,
|
|
rating_count: null,
|
|
phone: null,
|
|
website: null,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("RestaurantDetail — #545 해외 식당 예약 버튼 숨김", () => {
|
|
it("국내 식당(좌표 기반)이면 테이블링/캐치테이블 버튼이 보인다", async () => {
|
|
const restaurant = makeRestaurant({
|
|
latitude: 37.5665,
|
|
longitude: 126.978, // 서울
|
|
tabling_url: "https://tabling.example.com/1",
|
|
catchtable_url: "https://catchtable.example.com/1",
|
|
});
|
|
render(<RestaurantDetail restaurant={restaurant} onClose={() => {}} />);
|
|
await flush();
|
|
expect(screen.getByText("테이블링에서 줄서기")).toBeInTheDocument();
|
|
expect(screen.getByText("캐치테이블에서 예약하기")).toBeInTheDocument();
|
|
});
|
|
|
|
it("해외 식당(좌표가 KR bbox 밖)이면 두 버튼 모두 숨겨진다 (대표 발견 케이스)", async () => {
|
|
const restaurant = makeRestaurant({
|
|
latitude: 13.7563,
|
|
longitude: 100.5018, // 방콕
|
|
tabling_url: "https://tabling.example.com/1",
|
|
catchtable_url: "https://catchtable.example.com/1",
|
|
});
|
|
render(<RestaurantDetail restaurant={restaurant} onClose={() => {}} />);
|
|
await flush();
|
|
expect(screen.queryByText("테이블링에서 줄서기")).not.toBeInTheDocument();
|
|
expect(screen.queryByText("캐치테이블에서 예약하기")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("해외 식당이어도 예약 URL이 없으면 애초에 버튼이 없다 (회귀 없음 확인)", async () => {
|
|
const restaurant = makeRestaurant({
|
|
latitude: 35.6762,
|
|
longitude: 139.6503, // 도쿄
|
|
tabling_url: null,
|
|
catchtable_url: null,
|
|
});
|
|
render(<RestaurantDetail restaurant={restaurant} onClose={() => {}} />);
|
|
await flush();
|
|
expect(screen.queryByText("테이블링에서 줄서기")).not.toBeInTheDocument();
|
|
expect(screen.queryByText("캐치테이블에서 예약하기")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("좌표 없는 구 데이터는 region으로 fallback되어 국내로 간주된다 (기존 동작 유지)", async () => {
|
|
const restaurant = makeRestaurant({
|
|
latitude: undefined as unknown as number,
|
|
longitude: undefined as unknown as number,
|
|
region: null,
|
|
tabling_url: "https://tabling.example.com/1",
|
|
catchtable_url: null,
|
|
});
|
|
render(<RestaurantDetail restaurant={restaurant} onClose={() => {}} />);
|
|
await flush();
|
|
expect(screen.getByText("테이블링에서 줄서기")).toBeInTheDocument();
|
|
});
|
|
|
|
it("예약 URL이 'NONE' 문자열이면 국내 식당이어도 버튼이 없다 (기존 게이트 유지)", async () => {
|
|
const restaurant = makeRestaurant({
|
|
latitude: 37.5665,
|
|
longitude: 126.978,
|
|
tabling_url: "NONE",
|
|
catchtable_url: "NONE",
|
|
});
|
|
render(<RestaurantDetail restaurant={restaurant} onClose={() => {}} />);
|
|
await flush();
|
|
expect(screen.queryByText("테이블링에서 줄서기")).not.toBeInTheDocument();
|
|
expect(screen.queryByText("캐치테이블에서 예약하기")).not.toBeInTheDocument();
|
|
});
|
|
});
|