Skip to content

Commit

Permalink
Merge pull request #67 from fac30/feat-add-category-button
Browse files Browse the repository at this point in the history
Feature: add category button
  • Loading branch information
jackcasstlesjones authored Dec 10, 2024
2 parents c6a3263 + 5c2b6fe commit 02fb6e5
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 280 deletions.
179 changes: 87 additions & 92 deletions __tests__/ToolkitCategoryBar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,130 +1,125 @@
import { render, screen, fireEvent } from "@testing-library/react";
import CategoriesBar from "@/app/toolkit/components/CategoriesBar";
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from "react";
import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
import { useDatabase } from "@/context/DatabaseContext";
import { ToolkitProvider } from "@/context/ToolkitContext";
import { useToolkit } from "@/context/ToolkitContext";
import CategoriesBar from "@/app/toolkit/components/CategoriesBar";

// Mock DatabaseContext
// Mock contexts
jest.mock("@/context/DatabaseContext", () => ({
useDatabase: jest.fn(),
}));

// Helper function to render with ToolkitProvider
const renderWithToolkitContext = (
ui: React.ReactNode,
{ selectedCategories = [] } = {}
) => {
return render(
<ToolkitProvider initialSelectedCategories={selectedCategories}>
{ui}
</ToolkitProvider>
);
};

describe("CategoriesBar Component", () => {
const mockDatabase = {
getFromDb: jest.fn(),
};
jest.mock("@/context/ToolkitContext", () => ({
useToolkit: jest.fn(),
}));

describe("CategoriesBar", () => {
let mockDatabase: any;
let mockToolkitContext: any;
let mockOpenModal: jest.Mock;

beforeEach(() => {
jest.clearAllMocks();
(useDatabase as jest.Mock).mockImplementation(() => mockDatabase);
mockDatabase.getFromDb.mockResolvedValue([
{ id: "1", name: "Category1", timestamp: "2024-01-01" },
{ id: "2", name: "Category2", timestamp: "2024-01-02" },
]);
});

it("renders without crashing", async () => {
renderWithToolkitContext(<CategoriesBar />);
const categoriesBar = screen.getByTestId("categories-bar");
expect(categoriesBar).toBeInTheDocument();
});

it("renders all categories as buttons", async () => {
renderWithToolkitContext(<CategoriesBar />);
mockDatabase = {
getFromDb: jest.fn(),
};

// Wait for categories to load
const allButton = await screen.findByRole("button", { name: "All" });
expect(allButton).toBeInTheDocument();
mockToolkitContext = {
selectedCategories: [],
setSelectedCategories: jest.fn(),
};

const categories1Button = await screen.findByRole("button", {
name: "Category1",
});
const categories2Button = await screen.findByRole("button", {
name: "Category2",
});
mockOpenModal = jest.fn();

expect(categories1Button).toBeInTheDocument();
expect(categories2Button).toBeInTheDocument();
(useDatabase as jest.Mock).mockReturnValue(mockDatabase);
(useToolkit as jest.Mock).mockReturnValue(mockToolkitContext);
});

it("highlights the 'All' button when clicked", async () => {
renderWithToolkitContext(<CategoriesBar />);
it("renders the CategoriesBar and fetches categories", async () => {
// Mock database response
mockDatabase.getFromDb.mockResolvedValueOnce([
{ id: "1", name: "Category 1", timestamp: "2024-12-10" },
{ id: "2", name: "Category 2", timestamp: "2024-12-11" },
]);

const allButton = await screen.findByRole("button", { name: "All" });
fireEvent.click(allButton);
render(<CategoriesBar openModal={mockOpenModal} refreshCategories={false} />);

expect(allButton).toHaveClass("bg-twd-secondary-purple");
// Wait for categories to load and check if they are rendered
await waitFor(() => {
expect(screen.getByText("Category 1")).toBeInTheDocument();
expect(screen.getByText("Category 2")).toBeInTheDocument();
});
});

it("toggles selection for a single category", async () => {
renderWithToolkitContext(<CategoriesBar />);
it("triggers openModal when the '+' button is clicked", () => {
render(<CategoriesBar openModal={mockOpenModal} refreshCategories={false} />);

const categories1Button = await screen.findByRole("button", {
name: "Category1",
});
fireEvent.click(categories1Button);

expect(categories1Button).toHaveClass("bg-twd-secondary-purple");
const addButton = screen.getByText("+");
fireEvent.click(addButton);

fireEvent.click(categories1Button);
expect(categories1Button).not.toHaveClass("bg-twd-secondary-purple");
expect(mockOpenModal).toHaveBeenCalled();
});

it("clears other selections when 'All' is clicked", async () => {
renderWithToolkitContext(<CategoriesBar />);
it("handles category selection and deselection", async () => {
mockDatabase.getFromDb.mockResolvedValueOnce([
{ id: "1", name: "Category 1", timestamp: "2024-12-10" },
]);
// Initialize mock context with state tracking
mockToolkitContext = {
selectedCategories: [],
setSelectedCategories: jest.fn(),
};
(useToolkit as jest.Mock).mockReturnValue(mockToolkitContext);

// Wrap initial render in act
await act(async () => {
render(<CategoriesBar openModal={mockOpenModal} refreshCategories={false} />);
});

const categories1Button = await screen.findByRole("button", {
name: "Category1",
// Wait for initial render to complete
await waitFor(() => {
expect(screen.getByText("Category 1")).toBeInTheDocument();
});
const allButton = await screen.findByRole("button", { name: "All" });

fireEvent.click(categories1Button);
fireEvent.click(allButton);
const category1Button = screen.getByText("Category 1");
const allButton = screen.getByText("All");

expect(categories1Button).not.toHaveClass("bg-twd-secondary-purple");
expect(allButton).toHaveClass("bg-twd-secondary-purple");
});
// First click - select category
await act(async () => {
fireEvent.click(category1Button);
});

it("allows selecting multiple categories (except 'All')", async () => {
renderWithToolkitContext(<CategoriesBar />);
// Verify category is selected
expect(mockToolkitContext.setSelectedCategories).toHaveBeenCalledWith(["Category 1"]);

const categories1Button = await screen.findByRole("button", {
name: "Category1",
// Second click - should select "All"
await act(async () => {
fireEvent.click(allButton);
});
const categories2Button = await screen.findByRole("button", {
name: "Category2",
});

fireEvent.click(categories1Button);
fireEvent.click(categories2Button);

expect(categories1Button).toHaveClass("bg-twd-secondary-purple");
expect(categories2Button).toHaveClass("bg-twd-secondary-purple");
// Verify "All" is selected
expect(mockToolkitContext.setSelectedCategories).toHaveBeenCalledWith([]);
});

it("deselects 'All' when another category is selected", async () => {
renderWithToolkitContext(<CategoriesBar />);
it("handles the 'All' button click to reset categories", async () => {
mockDatabase.getFromDb.mockResolvedValueOnce([
{ id: "1", name: "Category 1", timestamp: "2024-12-10" },
]);

render(<CategoriesBar openModal={mockOpenModal} refreshCategories={false} />);

const allButton = await screen.findByRole("button", { name: "All" });
const categories1Button = await screen.findByRole("button", {
name: "Category1",
// Wait for categories to load
await waitFor(() => {
expect(screen.getByText("Category 1")).toBeInTheDocument();
});

fireEvent.click(allButton);
fireEvent.click(categories1Button);
const allButton = screen.getByText("All");

expect(allButton).not.toHaveClass("bg-twd-secondary-purple");
expect(categories1Button).toHaveClass("bg-twd-secondary-purple");
// Simulate clicking the "All" button
fireEvent.click(allButton);
expect(mockToolkitContext.setSelectedCategories).toHaveBeenCalledWith([]);
});
});
});
Loading

0 comments on commit 02fb6e5

Please sign in to comment.