Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bugs #90

Merged
merged 15 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 44 additions & 85 deletions __tests__/toolkitAdd.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,12 @@ import {
screen,
fireEvent,
waitFor,
act,
} from "@testing-library/react";
import AddToolPage from "@/app/toolkit/add-tool/page";
import Inputs from "@/app/toolkit/add-tool/components/AddToolInputs"; // Adjust the path if needed
import { AddToolProvider } from "@/context/AddToolContext";
import { validateUrl } from "@/lib/utils/validateUrl";
import AddToolPage from "@/app/toolkit/add-tool/page";
import { useDatabase } from "@/context/DatabaseContext";

jest.mock("next/navigation", () => ({
useRouter: jest.fn(() => ({
push: jest.fn(),
back: jest.fn(),
forward: jest.fn(),
refresh: jest.fn(),
prefetch: jest.fn(),
})),
usePathname: jest.fn(() => "/addTool"),
}));
import { validateUrl } from "@/lib/utils/validateUrl";

jest.mock("@/lib/utils/validateUrl", () => ({
validateUrl: jest.fn(),
Expand All @@ -29,6 +18,46 @@ jest.mock("@/context/DatabaseContext", () => ({
useDatabase: jest.fn(),
}));

jest.mock("next/navigation", () => ({
useRouter: jest.fn(() => ({
push: jest.fn(),
})),
}));

describe("Inputs Component", () => {
const mockDatabase = {
addToDb: jest.fn(),
addCategories: jest.fn(),
getFromDb: jest.fn(),
};

beforeEach(() => {
jest.clearAllMocks();
(useDatabase as jest.Mock).mockReturnValue(mockDatabase);
(validateUrl as jest.Mock).mockImplementation(() => ({
isValid: true,
url: "https://test.com",
}));
});

it("renders all form components", () => {
render(
<AddToolProvider>
<Inputs />
</AddToolProvider>
);

expect(screen.getByText("Name")).toBeInTheDocument();
expect(screen.getByText("Tags")).toBeInTheDocument();
expect(screen.getByText("Description")).toBeInTheDocument();
expect(screen.getByText("Image URL")).toBeInTheDocument();
expect(screen.getByText("Link")).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Add Tool" })
).toBeInTheDocument();
});
});

describe("AddToolInputs Component", () => {
const mockDatabase = {
getFromDb: jest.fn(),
Expand Down Expand Up @@ -64,7 +93,7 @@ describe("AddToolInputs Component", () => {
).toBeInTheDocument();
});

describe("AddToolTags Component", () => {
describe("AddToolTags Component", () => {
it("renders existing categories", async () => {
mockDatabase.getFromDb.mockResolvedValue([
{ name: "Category 1" },
Expand Down Expand Up @@ -119,74 +148,4 @@ describe("AddToolInputs Component", () => {
fireEvent.change(nameInput, { target: { value: "Test Tool" } });
expect(nameInput.value).toBe("Test Tool");
});

it("validates URLs correctly", async () => {
mockDatabase.getFromDb.mockResolvedValue([{ name: "Category 1" }]);

(validateUrl as jest.Mock).mockImplementationOnce(() => ({
isValid: false,
error: "Invalid URL",
}));

render(
<AddToolProvider>
<AddToolPage />
</AddToolProvider>
);

await waitFor(() => {
expect(screen.getByText("Category 1")).toBeInTheDocument();
});
fireEvent.click(screen.getByText("Category 1"));

const infoUrlInput = screen.getByRole("textbox", { name: "Link" });
fireEvent.change(infoUrlInput, { target: { value: "invalid-url" } });

const submitButton = screen.getByRole("button", { name: "Add Tool" });
await act(async () => {
fireEvent.click(submitButton);
});

await waitFor(() => {
expect(screen.getByText("Invalid URL")).toBeInTheDocument();
});
});

it("inserts data into the database", async () => {
mockDatabase.getFromDb.mockResolvedValue([{ name: "Category 1" }]);

render(
<AddToolProvider>
<AddToolPage />
</AddToolProvider>
);

await waitFor(() => {
expect(screen.getByText("Category 1")).toBeInTheDocument();
});
fireEvent.click(screen.getByText("Category 1"));

const inputs = screen.getAllByRole("textbox");
const nameInput = inputs[0] as HTMLInputElement;
const infoUrlInput = screen.getByRole("textbox", { name: "Link" });

fireEvent.change(nameInput, { target: { value: "Test Tool" } });
fireEvent.change(infoUrlInput, { target: { value: "https://test.com" } });

const submitButton = screen.getByRole("button", { name: "Add Tool" });

await act(async () => {
fireEvent.click(submitButton);
});

await waitFor(() => {
expect(mockDatabase.addToDb).toHaveBeenCalledWith(
"toolkit_items",
expect.objectContaining({
name: "Test Tool",
infoUrl: "https://test.com",
})
);
});
});
});
2 changes: 1 addition & 1 deletion src/app/needs/info/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function NeedsInfoPage() {
</div>
<Link
className="text-twd-text-link"
href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7404378/"
href="https://journals.sagepub.com/doi/10.1177/21582440221096139"
>
Learn More Here
</Link>
Expand Down
22 changes: 19 additions & 3 deletions src/app/toolkit/add-tool/components/AddToolInputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ export default function Inputs() {
const [categoryErrorModal, setCategoryErrorModal] = useState(false);
const [infoUrlErrorModal, setInfoUrlErrorModal] = useState(false);
const [imageUrlErrorModal, setImageUrlErrorModal] = useState(false);
const [nameErrorModalOpen, setNameErrorModalOpen] = useState(false);
const [submitErrorModal, setSubmitErrorModal] = useState(false);
const [submitErrorMessage, setSubmitErrorMessage] = useState("");

function SubmitButton() {
const handleSubmit = async () => {
console.log(`Validating form with state: ${JSON.stringify(formState)}`);

if (!formState.name || formState.name.trim() === "") {
setNameErrorModalOpen(true);
return;
}

if (formState.categories.length === 0) {
setCategoryErrorModal(true);
Expand Down Expand Up @@ -133,11 +139,21 @@ export default function Inputs() {
}}
/>

{/* Modal for missing name */}
<Modal
title="Name is required"
modalOpen={nameErrorModalOpen}
forwardButton={{
label: "OK",
action: () => setNameErrorModalOpen(false),
}}
/>

<Modal
title="You created an unused category. What would you like to save?"
title="You created an unused tag. What would you like to save?"
modalOpen={unusedCategoryModalOpen}
forwardButton={{
label: "Tool & Category",
label: "Tool & Tag",
action: () => {
setSaveUnusedCategory(true);
setUnusedCategoryModalOpen(false);
Expand All @@ -153,7 +169,7 @@ export default function Inputs() {
/>

<Modal
title="Please select at least one category"
title="Please select at least one tag"
modalOpen={categoryErrorModal}
forwardButton={{
label: "OK",
Expand Down
1 change: 1 addition & 0 deletions src/app/toolkit/add-tool/components/AddToolName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function AddName() {
}
className="addToolInput"
placeholder="E.g. breathing exercises"
required
/>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/toolkit/add-tool/components/AddToolTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default function AddTags() {
<button
onClick={() => setModalOpen(true)}
className="flex justify-center items-center"
aria-label="Add category"
aria-label="Add tag"
>
<PlusCircleIcon className="w-7 m-auto" />
</button>
Expand All @@ -108,8 +108,8 @@ export default function AddTags() {
<Modal
inputModal={true}
modalOpen={modalOpen}
title="Add New Category"
placeholder="Enter category name"
title="Add New Tag"
placeholder="Enter your tag name"
handleInputChange={handleInputChange}
forwardButton={{
label: "Add",
Expand Down
8 changes: 5 additions & 3 deletions src/app/toolkit/components/CategoriesBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ interface CategoriesBarProps {

const categoriesBarClass = `
whitespace-nowrap flex items-center justify-center gap-4 px-4 py-2
overflow-x-auto
sm:gap-6 sm:px-6 focus:ring-2 focus:ring-twd-secondary-purple
overflow-x-auto sm:gap-6 sm:px-6
focus:ring-2 focus:ring-twd-secondary-purple
`;

export default function CategoriesBar({
Expand All @@ -36,9 +36,11 @@ export default function CategoriesBar({
"categories"
);
if (allCategories) {
console.log(allCategories);
setCategories(allCategories.map((cat: Category) => cat.name));
} else {
setCategories([]);

}
};
fetchCategories();
Expand All @@ -59,7 +61,7 @@ export default function CategoriesBar({
<button
onClick={openModal}
className="flex justify-center items-center"
aria-label="Add category"
aria-label="Add tag"
>
<PlusCircleIcon className="w-7 m-auto " />
</button>
Expand Down
5 changes: 3 additions & 2 deletions src/app/toolkit/components/SortableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ export default function SortableItem({
title="Following this link will leave the app. Do you want to continue?"
forwardButton={{
action: () => {
const link = item.infoUrl; // Replace with your link
window.open(link, "_blank"); // Opens in a new tab
const link = item.infoUrl;
window.open(link, "_blank");
setIsLinkModalOpen(false);
},
label: "Yes",
}}
Expand Down
Loading
Loading