// @vitest-environment jsdom // // The sidebar's playlist picker: typing a name offers "Create …" — but only // once the lists have loaded. Over a failed load the create row pushed the error and its Retry out // of the list at the first keystroke, and whether the name already existed was unknown anyway. import { describe, it, expect, vi, afterEach, beforeAll } from "vitest"; import { render, cleanup, screen, fireEvent, waitFor } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { FloatingTree } from "@floating-ui/react"; vi.mock("react-i18next", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, useTranslation: () => ({ t: (key: string, o?: { name?: string }) => (o?.name != null ? `${key}:${o.name}` : key), i18n: { language: "en" }, }), }; }); vi.mock("./plexContext", () => ({ usePlex: () => ({}), usePlexActions: () => ({ setPlaylistOpen: vi.fn() }), })); import { PlaylistPicker } from "./PlexSidebar"; import { api } from "../lib/api"; beforeAll(() => { class Stub { observe() {} unobserve() {} disconnect() {} takeRecords() { return []; } } globalThis.ResizeObserver ??= Stub as unknown as typeof ResizeObserver; }); afterEach(() => { cleanup(); vi.restoreAllMocks(); }); function mount() { const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } }); render( , ); return screen.getByRole("combobox"); } describe("the sidebar playlist picker", () => { it("keeps the load error and its Retry while a name is typed, with no Create row", async () => { vi.spyOn(api, "plexPlaylists").mockRejectedValue(new TypeError("Failed to fetch")); const input = mount(); fireEvent.focus(input); fireEvent.change(input, { target: { value: "Road trip" } }); await waitFor(() => expect(screen.getByRole("alert", { hidden: true })).toBeTruthy()); expect(screen.getByText("common.retry")).toBeTruthy(); expect(screen.queryByText("plex.playlist.createNamed:Road trip")).toBeNull(); }); it("offers Create for a new name once the lists are in", async () => { vi.spyOn(api, "plexPlaylists").mockResolvedValue({ playlists: [] } as never); const input = mount(); fireEvent.focus(input); fireEvent.change(input, { target: { value: "Road trip" } }); expect(await screen.findByText("plex.playlist.createNamed:Road trip")).toBeTruthy(); }); });