diff --git a/src/features/popular-requests/components/PopularRequestsPanel.test.tsx b/src/features/popular-requests/components/PopularRequestsPanel.test.tsx
index 829663ab..6dc96ed8 100644
--- a/src/features/popular-requests/components/PopularRequestsPanel.test.tsx
+++ b/src/features/popular-requests/components/PopularRequestsPanel.test.tsx
@@ -1,6 +1,14 @@
+/**
+ * Tests for PopularRequestsPanel component.
+ *
+ * Covers all 5 request modes, loading/error states, keyboard
+ * accessibility, and the 4-item display limit.
+ *
+ * @vitest-environment jsdom
+ */
+
import { describe, it, expect, vi, beforeEach } from "vitest";
-import { render, screen, waitFor } from "@testing-library/react";
-import userEvent from "@testing-library/user-event";
+import { render, screen, fireEvent } from "@testing-library/react";
import { PopularRequestsPanel } from "./PopularRequestsPanel";
import type { PopularRequest } from "../types";
@@ -8,7 +16,6 @@ import type { PopularRequest } from "../types";
// Mocks
// ---------------------------------------------------------------------------
-// Mock the usePopularRequests hook
const mockUsePopularRequests = vi.fn<
() => { requests: PopularRequest[]; loading: boolean; error: Error | null }
>();
@@ -17,7 +24,6 @@ vi.mock("../hooks/usePopularRequests.js", () => ({
usePopularRequests: () => mockUsePopularRequests(),
}));
-// Mock i18n
vi.mock("@/i18n/provider.js", () => ({
useTranslation: () => ({
t: (key: string) => key,
@@ -25,7 +31,6 @@ vi.mock("@/i18n/provider.js", () => ({
}),
}));
-// Mock useCityName
vi.mock("@/shared/hooks/useDictionaries.js", () => ({
useCityName: (code: string) => code,
}));
@@ -121,15 +126,14 @@ describe("PopularRequestsPanel", () => {
render();
- expect(screen.getByText("BOARD.POPULAR-CHAPTERS")).toBeInTheDocument();
- // Should render 4 items
+ expect(screen.getByText("BOARD.POPULAR-CHAPTERS")).toBeTruthy();
const items = screen.getAllByRole("button");
expect(items).toHaveLength(4);
});
- it("calls onRequestClick when a flight number item is clicked", async () => {
+ it("calls onRequestClick when a flight number item is clicked", () => {
mockUsePopularRequests.mockReturnValue({
- requests: [mockRequests[0]!],
+ requests: [mockRequests[0] as PopularRequest],
loading: false,
error: null,
});
@@ -138,34 +142,42 @@ describe("PopularRequestsPanel", () => {
render();
const button = screen.getByRole("button");
- await userEvent.click(button);
+ fireEvent.click(button);
expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
});
it("renders flight number with carrier and number", () => {
mockUsePopularRequests.mockReturnValue({
- requests: [mockRequests[0]!],
+ requests: [mockRequests[0] as PopularRequest],
loading: false,
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- // SU\u00a09027 (non-breaking space)
- expect(screen.getByText("SU\u00a09027")).toBeInTheDocument();
+ // The span contains "SU\u00a09027" — check the button text
+ const button = screen.getByRole("button");
+ expect(button.textContent).toContain("SU");
+ expect(button.textContent).toContain("9027");
+ // Also check the container has the FLIGHT_NUMBER label
+ expect(container.textContent).toContain("BOARD.FLIGHT_NUMBER");
});
it("renders route request with departure and arrival", () => {
mockUsePopularRequests.mockReturnValue({
- requests: [mockRequests[2]!],
+ requests: [mockRequests[2] as PopularRequest],
loading: false,
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- expect(screen.getByText("KUF - ABA")).toBeInTheDocument();
+ expect(container.textContent).toContain("KUF - ABA");
});
it("limits display to 4 items even with more data", () => {
@@ -203,10 +215,12 @@ describe("PopularRequestsPanel", () => {
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- expect(screen.getByText("BOARD.ARRIVAL")).toBeInTheDocument();
- expect(screen.getByText("SVO")).toBeInTheDocument();
+ expect(container.textContent).toContain("BOARD.ARRIVAL");
+ expect(screen.getByRole("button").textContent).toBe("SVO");
});
it("renders departure request mode", () => {
@@ -222,10 +236,12 @@ describe("PopularRequestsPanel", () => {
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- expect(screen.getByText("BOARD.DEPARTURE")).toBeInTheDocument();
- expect(screen.getByText("DME")).toBeInTheDocument();
+ expect(container.textContent).toContain("BOARD.DEPARTURE");
+ expect(screen.getByRole("button").textContent).toBe("DME");
});
it("renders schedule route with correct label", () => {
@@ -242,9 +258,11 @@ describe("PopularRequestsPanel", () => {
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- expect(screen.getByText("SCHEDULE.SCHEDULE-OUTBOUND")).toBeInTheDocument();
+ expect(container.textContent).toContain("SCHEDULE.SCHEDULE-OUTBOUND");
});
it("renders RouteWithBack with full-route label", () => {
@@ -261,16 +279,16 @@ describe("PopularRequestsPanel", () => {
error: null,
});
- render();
+ const { container } = render(
+ ,
+ );
- expect(
- screen.getByText("SCHEDULE.SCHEDULE-FULL-ROUTE"),
- ).toBeInTheDocument();
+ expect(container.textContent).toContain("SCHEDULE.SCHEDULE-FULL-ROUTE");
});
- it("supports keyboard activation (Enter key)", async () => {
+ it("supports keyboard activation (Enter key)", () => {
mockUsePopularRequests.mockReturnValue({
- requests: [mockRequests[0]!],
+ requests: [mockRequests[0] as PopularRequest],
loading: false,
error: null,
});
@@ -279,8 +297,23 @@ describe("PopularRequestsPanel", () => {
render();
const button = screen.getByRole("button");
- button.focus();
- await userEvent.keyboard("{Enter}");
+ fireEvent.keyDown(button, { key: "Enter" });
+
+ expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
+ });
+
+ it("supports keyboard activation (Space key)", () => {
+ mockUsePopularRequests.mockReturnValue({
+ requests: [mockRequests[0] as PopularRequest],
+ loading: false,
+ error: null,
+ });
+
+ const onRequestClick = vi.fn();
+ render();
+
+ const button = screen.getByRole("button");
+ fireEvent.keyDown(button, { key: " " });
expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
});
diff --git a/src/shared/hooks/useSearchHistory.test.ts b/src/shared/hooks/useSearchHistory.test.ts
index 90389f98..9545c866 100644
--- a/src/shared/hooks/useSearchHistory.test.ts
+++ b/src/shared/hooks/useSearchHistory.test.ts
@@ -1,3 +1,7 @@
+/**
+ * @vitest-environment jsdom
+ */
+
import { describe, it, expect, beforeEach, vi } from "vitest";
import { renderHook, act } from "@testing-library/react";
import { useSearchHistory } from "./useSearchHistory";
@@ -42,12 +46,6 @@ const routeItem: SearchHistoryItem = {
label: "SVO - JFK",
};
-const scheduleItem: SearchHistoryItem = {
- type: "schedule-route",
- url: "/ru/schedule/route/SVO-LED/20250601-20250607",
- label: "SVO - LED",
-};
-
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
diff --git a/src/shared/hooks/useSearchHistory.ts b/src/shared/hooks/useSearchHistory.ts
index dcbe394c..8c3f3767 100644
--- a/src/shared/hooks/useSearchHistory.ts
+++ b/src/shared/hooks/useSearchHistory.ts
@@ -48,8 +48,6 @@ const searchHistoryItemSchema = z.object({
const searchHistorySchema = z.array(searchHistoryItemSchema);
-type SearchHistoryData = z.infer;
-
// ---------------------------------------------------------------------------
// Storage key
// ---------------------------------------------------------------------------