mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
ai-canvas-expand was added to constants.ts and route files but never added to the landing page bento grid, causing all hardcoded counts to remain at 51. This updates all references across source, docs, i18n, and tests to reflect the correct count of 52 tools.
120 lines
4.0 KiB
TypeScript
120 lines
4.0 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
import type React from "react";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("framer-motion", () => ({
|
|
motion: {
|
|
div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => (
|
|
<div {...props}>{children}</div>
|
|
),
|
|
},
|
|
AnimatePresence: ({ children }: React.PropsWithChildren) => <>{children}</>,
|
|
}));
|
|
|
|
import { BentoGrid } from "@landing/components/bento-grid";
|
|
|
|
afterEach(cleanup);
|
|
|
|
function getCountText(): string {
|
|
const el = screen.getByText(/^Showing/);
|
|
return el.textContent ?? "";
|
|
}
|
|
|
|
describe("BentoGrid", () => {
|
|
it("renders the section heading", () => {
|
|
render(<BentoGrid />);
|
|
expect(screen.getByText("52 tools. Zero cloud dependency.")).toBeDefined();
|
|
});
|
|
|
|
it("renders the search input", () => {
|
|
render(<BentoGrid />);
|
|
expect(screen.getByPlaceholderText("Search tools...")).toBeDefined();
|
|
});
|
|
|
|
it("shows all tools by default", () => {
|
|
render(<BentoGrid />);
|
|
const text = getCountText();
|
|
expect(text).toMatch(/Showing 52 of 52 tools/);
|
|
});
|
|
|
|
it("renders category filter pills including All", () => {
|
|
render(<BentoGrid />);
|
|
expect(screen.getByText((_, el) => el?.textContent === "All (52)")).toBeDefined();
|
|
expect(screen.getByText(/Essentials/)).toBeDefined();
|
|
expect(screen.getByText(/AI Tools/)).toBeDefined();
|
|
expect(screen.getByText(/Optimization/)).toBeDefined();
|
|
});
|
|
|
|
it("filters tools by search query", () => {
|
|
render(<BentoGrid />);
|
|
const input = screen.getByPlaceholderText("Search tools...");
|
|
fireEvent.change(input, { target: { value: "resize" } });
|
|
expect(screen.getByText("Resize")).toBeDefined();
|
|
const text = getCountText();
|
|
expect(text).toMatch(/Showing \d+ of 52 tools/);
|
|
expect(screen.queryByText("OCR / Text Extraction")).toBeNull();
|
|
});
|
|
|
|
it("filters tools by category", () => {
|
|
render(<BentoGrid />);
|
|
const aiButton = screen.getByText(/AI Tools/);
|
|
fireEvent.click(aiButton);
|
|
const text = getCountText();
|
|
expect(text).toMatch(/Showing 16 of 52 tools/);
|
|
expect(screen.getByText("Remove Background")).toBeDefined();
|
|
expect(screen.queryByText("Resize")).toBeNull();
|
|
});
|
|
|
|
it("shows empty state when search matches nothing", () => {
|
|
render(<BentoGrid />);
|
|
const input = screen.getByPlaceholderText("Search tools...");
|
|
fireEvent.change(input, { target: { value: "xyznonexistent" } });
|
|
expect(screen.getByText("No tools found. Try a different search.")).toBeDefined();
|
|
const text = getCountText();
|
|
expect(text).toMatch(/Showing 0 of 52 tools/);
|
|
});
|
|
|
|
it("combines search and category filter", () => {
|
|
render(<BentoGrid />);
|
|
const aiButton = screen.getByText(/AI Tools/);
|
|
fireEvent.click(aiButton);
|
|
const input = screen.getByPlaceholderText("Search tools...");
|
|
fireEvent.change(input, { target: { value: "background" } });
|
|
expect(screen.getByText("Remove Background")).toBeDefined();
|
|
expect(screen.queryByText("Image Upscaling")).toBeNull();
|
|
});
|
|
|
|
it("clicking All resets category filter", () => {
|
|
render(<BentoGrid />);
|
|
fireEvent.click(screen.getByText(/AI Tools/));
|
|
expect(getCountText()).toMatch(/Showing 16 of 52 tools/);
|
|
fireEvent.click(screen.getByText((_, el) => el?.textContent === "All (52)"));
|
|
expect(getCountText()).toMatch(/Showing 52 of 52 tools/);
|
|
});
|
|
|
|
it("renders each tool with name and description", () => {
|
|
render(<BentoGrid />);
|
|
expect(screen.getByText("Crop")).toBeDefined();
|
|
expect(screen.getByText("Freeform crop, aspect ratio presets, shape crop")).toBeDefined();
|
|
});
|
|
|
|
it("renders all 8 category pills", () => {
|
|
render(<BentoGrid />);
|
|
const categoryNames = [
|
|
"Essentials",
|
|
"Optimization",
|
|
"Adjustments",
|
|
"AI Tools",
|
|
"Watermark & Overlay",
|
|
"Utilities",
|
|
"Layout & Composition",
|
|
"Format & Conversion",
|
|
];
|
|
for (const name of categoryNames) {
|
|
expect(screen.getByText(new RegExp(name))).toBeDefined();
|
|
}
|
|
});
|
|
});
|