diff --git a/backend/cmd/api/main.go b/backend/cmd/api/main.go
index 75bdda1..70dda9f 100755
--- a/backend/cmd/api/main.go
+++ b/backend/cmd/api/main.go
@@ -85,7 +85,7 @@ func ValidateJWT(secret, env string) error {
// warning is always returned if short.
// fatal error is returned if production.
// Caller handles logging.
- return fmt.Errorf(msg)
+ return fmt.Errorf("%s", msg)
}
return nil
}
diff --git a/frontend/src/app/jobs/[id]/apply/page.test.tsx b/frontend/src/app/jobs/[id]/apply/page.test.tsx
index cd71c55..3776f15 100644
--- a/frontend/src/app/jobs/[id]/apply/page.test.tsx
+++ b/frontend/src/app/jobs/[id]/apply/page.test.tsx
@@ -1,5 +1,6 @@
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
+import { Suspense } from "react";
import JobApplicationPage from "./page";
import { jobsApi, applicationsApi } from "@/lib/api";
import { useNotify } from "@/contexts/notification-context";
@@ -40,6 +41,25 @@ jest.mock("@/components/ui/progress", () => ({
Progress: () =>
,
}));
+jest.mock("framer-motion", () => ({
+ motion: { div: ({ children }: any) => {children}
},
+ AnimatePresence: ({ children }: any) => <>{children}>,
+}));
+
+jest.mock("@/components/ui/select", () => ({
+ Select: ({ onValueChange, children }: any) => (
+
+
+ {children}
+
+ ),
+ SelectTrigger: ({ children }: any) => ,
+ SelectValue: ({ placeholder }: any) => {placeholder},
+ SelectContent: ({ children }: any) => {children}
,
+ SelectItem: ({ children }: any) => {children}
,
+}));
describe("JobApplicationPage", () => {
const mockPush = jest.fn();
@@ -59,22 +79,34 @@ describe("JobApplicationPage", () => {
window.scrollTo = jest.fn();
});
- // Since component uses `use(params)`, we need to wrap or pass a promise
- const params = Promise.resolve({ id: "job-123" });
-
it("renders job title and company info", async () => {
- render();
+ const params: any = Promise.resolve({ id: "job-123" });
+ params.status = "fulfilled";
+ params.value = { id: "job-123" };
- await waitFor(() => {
- expect(screen.getByText("Application: Software Engineer")).toBeInTheDocument();
- expect(screen.getByText(/Tech Corp/)).toBeInTheDocument();
- });
+ render(
+ Loading...}>
+
+
+ );
+
+ expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();
+ expect(screen.getByText(/Tech Corp/)).toBeInTheDocument();
});
it("validates step 1 fields", async () => {
- render();
+ const params: any = Promise.resolve({ id: "job-123" });
+ params.status = "fulfilled";
+ params.value = { id: "job-123" };
- await waitFor(() => expect(screen.getByText("Application: Software Engineer")).toBeInTheDocument());
+ render(
+ Loading...}>
+
+
+ );
+
+ // Wait for load
+ expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();
// Try next empty
const nextBtn = screen.getByRole("button", { name: /Next step/i });
@@ -91,19 +123,29 @@ describe("JobApplicationPage", () => {
expect(mockNotify.error).toHaveBeenCalledWith("Privacy policy", expect.any(String));
// Check checkbox
- // Finding checkbox by ID might be easiest or by label text click
const policyLabel = screen.getByText(/I have read and agree to the/i);
- fireEvent.click(policyLabel); // Should toggle checkbox associated with label
+ fireEvent.click(policyLabel);
fireEvent.click(nextBtn);
// Should move to step 2
- expect(screen.getByText("Resume & Documents")).toBeInTheDocument();
+ await waitFor(() => expect(screen.getByText("Resume (CV) *")).toBeInTheDocument());
});
it("submits application successfully", async () => {
- render();
- await waitFor(() => expect(jobsApi.getById).toHaveBeenCalled());
+ const params: any = Promise.resolve({ id: "job-123" });
+ params.status = "fulfilled";
+ params.value = { id: "job-123" };
+
+ render(
+ Loading...}>
+
+
+ );
+
+ // Wait for load
+ expect(await screen.findByText("Application: Software Engineer")).toBeInTheDocument();
+ await waitFor(() => expect(screen.getByLabelText(/Full name/i)).toBeInTheDocument());
// Step 1
fireEvent.change(screen.getByLabelText(/Full name/i), { target: { value: "John Doe" } });
@@ -113,21 +155,23 @@ describe("JobApplicationPage", () => {
fireEvent.click(screen.getByRole("button", { name: /Next step/i }));
// Step 2
- // Optional fields here or skip
- // Resume is technically required (Step 2 logic: case 2 returns true currently in the simplified code?
- // Looking at source: case 2: return true; (lines 122). So no validation on Step 2!)
+ await waitFor(() => expect(screen.getByText("Resume (CV) *")).toBeInTheDocument());
fireEvent.click(screen.getByRole("button", { name: /Next step/i }));
+ // Wait for Step 3
+ await waitFor(() => expect(screen.getByText("Salary expectation *")).toBeInTheDocument());
+
// Step 3
- // Salary and Experience
const trigger = screen.getByText("Select a range");
fireEvent.click(trigger);
- fireEvent.click(screen.getByText("Up to R$ 3,000")); // SelectOption
+ fireEvent.click(screen.getByTestId("select-option-3k"));
fireEvent.click(screen.getByLabelText("Yes, I do")); // Radio
fireEvent.click(screen.getByRole("button", { name: /Next step/i }));
+ await waitFor(() => expect(screen.getByLabelText(/Why do you want to work/i)).toBeInTheDocument());
+
// Step 4
// Why Us and Availability
fireEvent.change(screen.getByLabelText(/Why do you want to work/i), { target: { value: "Because I like it." } });
diff --git a/frontend/src/components/dashboard-contents/candidate-dashboard.test.tsx b/frontend/src/components/dashboard-contents/candidate-dashboard.test.tsx
index c2b9b8a..f68ce17 100644
--- a/frontend/src/components/dashboard-contents/candidate-dashboard.test.tsx
+++ b/frontend/src/components/dashboard-contents/candidate-dashboard.test.tsx
@@ -49,6 +49,14 @@ jest.mock("@/components/ui/skeleton", () => ({
Skeleton: () => Loading...
,
}))
+jest.mock("@/components/stats-card", () => ({
+ StatsCard: () => StatsCard
,
+}))
+
+jest.mock("@/components/job-card", () => ({
+ JobCard: () => JobCard
,
+}))
+
describe("CandidateDashboard", () => {
it("renders welcome message", async () => {
render()
@@ -56,6 +64,6 @@ describe("CandidateDashboard", () => {
// Assuming dashboard has "Welcome" or similar
// Or check for section headers "My Applications", "Recommended Jobs"
// Wait for potential async data loading
- expect(await screen.findByText(/Recommended Jobs/i)).toBeInTheDocument()
+ expect(await screen.findByText("candidate.dashboard.recommended.title")).toBeInTheDocument()
})
})