-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #67 from fac30/feat-add-category-button
Feature: add category button
- Loading branch information
Showing
8 changed files
with
252 additions
and
280 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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([]); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.