- Add Supplier Map component to suppliers page and reorganize sidebar navigation - Implement picking slip PDF generation with supplier per line item and picked-by signature footer - Add invoice bulk print tracking API and view models to track printed invoice state - Extend company search and form to support email/telephone fields and improve searchability - Fix data table debounce race condition by using useRef for onSearch handler - Fix supplier page fetch race condition with debounced timeout - Reduce list page item counts to 10 per page for customers, companies, and suppliers - Update company search filter to include email and telephone in search queries - Add comprehensive test suite for new and existing components and APIs - Add pdf-lib dependency for PDF generation and update related tooling - Clean up unused code and fix minor linting issues
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import { render, screen, waitFor, within } from "@testing-library/react";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { PricelistCatalogue } from "./pricelist-catalogue";
|
|
|
|
const { getPriceListsMock, getAllSuppliersMock } = vi.hoisted(() => ({
|
|
getPriceListsMock: vi.fn(),
|
|
getAllSuppliersMock: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@/lib/pb-helpers", () => ({
|
|
getPriceLists: getPriceListsMock,
|
|
getAllSuppliers: getAllSuppliersMock,
|
|
formatDate: (value: string) => value,
|
|
}));
|
|
|
|
vi.mock("@/lib/pocketbase", () => ({
|
|
__esModule: true,
|
|
default: () => ({
|
|
collection: () => ({
|
|
subscribe: vi.fn(),
|
|
unsubscribe: vi.fn(),
|
|
}),
|
|
}),
|
|
}));
|
|
|
|
describe("PricelistCatalogue", () => {
|
|
beforeEach(() => {
|
|
getPriceListsMock.mockReset();
|
|
getAllSuppliersMock.mockReset();
|
|
|
|
getPriceListsMock.mockResolvedValue({
|
|
items: [],
|
|
totalPages: 1,
|
|
totalItems: 0,
|
|
});
|
|
getAllSuppliersMock.mockResolvedValue([]);
|
|
});
|
|
|
|
it("loads catalogue rows with 10 per page", async () => {
|
|
render(<PricelistCatalogue />);
|
|
|
|
await waitFor(() => {
|
|
expect(getPriceListsMock).toHaveBeenNthCalledWith(2, 1, 10, "", {
|
|
category: undefined,
|
|
brand: undefined,
|
|
});
|
|
});
|
|
});
|
|
|
|
it("renders denser catalogue rows with structured description metadata and source action", async () => {
|
|
const catalogueRow = {
|
|
id: "pl-1",
|
|
sku: "JEI-TD-06",
|
|
description: "TurboSteel twist drill for stainless applications",
|
|
category: "twist_drill",
|
|
subcategory: "jobber_drill",
|
|
brand: "JEI",
|
|
supplier: "sup-1",
|
|
cost_price: 120,
|
|
selling_price: 156,
|
|
markup: 30,
|
|
unit: "ea",
|
|
stock_qty: 0,
|
|
specifications: {},
|
|
source_file: "raw-1",
|
|
search_text: "",
|
|
created: "2026-07-09 10:00:00.000Z",
|
|
updated: "2026-07-09 10:00:00.000Z",
|
|
};
|
|
getPriceListsMock.mockImplementation(async (_page: number, perPage: number) => ({
|
|
items: perPage === 10 ? [catalogueRow] : [catalogueRow],
|
|
totalPages: 1,
|
|
totalItems: 1,
|
|
}));
|
|
getAllSuppliersMock.mockResolvedValue([{ id: "sup-1", suppliername: "Turbo Supplies" }]);
|
|
|
|
render(<PricelistCatalogue />);
|
|
|
|
const sourceLinks = await screen.findAllByRole("link", { name: /Source PDF/i });
|
|
expect(sourceLinks.length).toBeGreaterThan(0);
|
|
|
|
const descriptionText = screen.getAllByText("TurboSteel twist drill for stainless applications")[0];
|
|
const descriptionCell = descriptionText.closest("td");
|
|
expect(descriptionCell).not.toBeNull();
|
|
expect(within(descriptionCell as HTMLElement).getByText("jobber drill")).toBeInTheDocument();
|
|
expect(within(descriptionCell as HTMLElement).getByText("ea")).toBeInTheDocument();
|
|
});
|
|
});
|