import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { KEYS } from "../../data/mock/keys"; import type { Opportunity } from "../../domain/types"; import { I18nProvider } from "../../i18n/I18nContext"; import { OpportunityInboxCard } from "./OpportunityInboxCard"; function opp(): Opportunity { return { id: "o1", source: "threads", external_id: "x", permalink: "https://www.threads.net/@a/post/x", author_handle: "buyer", text: "台北有人推薦美甲嗎", posted_at: Date.now() * 1e6, status: "qualified", intent_score: 80, intent_band: "high", reasons: [], region_match: "unknown", freshness_hours: 1, matched_terms: [], created_at: Date.now() * 1e6, review_state: "pending", }; } describe("OpportunityInboxCard simple", () => { it("only offers reply or skip", () => { localStorage.setItem(KEYS.uiPrefs, JSON.stringify({ locale: "zh-TW", currency: "TWD", theme: "system" })); const onComplete = vi.fn(); const onRemove = vi.fn(); render( , ); expect(screen.getByRole("button", { name: "回他" })).toBeTruthy(); expect(screen.getByRole("button", { name: "先跳過" })).toBeTruthy(); expect(screen.queryByRole("button", { name: "留下" })).toBeNull(); expect(screen.queryByRole("button", { name: "丟掉" })).toBeNull(); fireEvent.click(screen.getByRole("button", { name: "先跳過" })); expect(onRemove).toHaveBeenCalledWith(expect.objectContaining({ id: "o1" }), { reason: "pain_mismatch" }); }); it("回他同時把人加進名單,否則名單永遠是空的", () => { localStorage.setItem(KEYS.uiPrefs, JSON.stringify({ locale: "zh-TW", currency: "TWD", theme: "system" })); const onAccept = vi.fn(); const onComplete = vi.fn(); vi.spyOn(window, "open").mockReturnValue(null); render( , ); fireEvent.click(screen.getByRole("button", { name: "回他" })); expect(window.open).toHaveBeenCalledWith("https://www.threads.net/@a/post/x", "_blank", "noopener,noreferrer"); expect(onAccept).toHaveBeenCalledWith(expect.objectContaining({ id: "o1" })); expect(onComplete).not.toHaveBeenCalled(); }); });