Skip to content

Commit 4747348

Browse files
committed
refactor: improve NotFound component structure and enhance product service tests with type annotations
1 parent c5fc62e commit 4747348

File tree

3 files changed

+29
-39
lines changed

3 files changed

+29
-39
lines changed

src/routes/not-found/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import { Button, Container, Section } from "@/components/ui";
55
export default function NotFound() {
66
return (
77
<Container>
8-
<Section className='flex justify-center items-center'>
9-
<div className='text-center'>
10-
<p className='text-base font-semibold text-accent-foreground'>404</p>
11-
<h1 className='text-4xl leading-9 font-bold tracking-tight text-foreground mt-4 sm:text-6xl sm:leading-none'>Página no encontrada</h1>
12-
<p className='text-lg font-medium text-muted-foreground mt-6 sm:text-xl leading-none'>
8+
<Section className="flex justify-center items-center">
9+
<div className="text-center" data-testid="not-found">
10+
<p className="text-base font-semibold text-accent-foreground">404</p>
11+
<h1 className="text-4xl leading-9 font-bold tracking-tight text-foreground mt-4 sm:text-6xl sm:leading-none">
12+
Página no encontrada
13+
</h1>
14+
<p className="text-lg font-medium text-muted-foreground mt-6 sm:text-xl leading-none">
1315
No pudimos encontrar la página que estás buscando.
1416
</p>
15-
<Button className='mt-10' asChild size="xl">
17+
<Button className="mt-10" asChild size="xl">
1618
<Link to="/">Regresar al inicio</Link>
1719
</Button>
1820
</div>

src/routes/product/product.test.tsx

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { useNavigation } from "react-router";
13
import { describe, expect, it, vi } from "vitest";
24

35
import { createTestProduct } from "@/lib/utils.tests";
46
import type { Product as ProductType } from "@/models/product.model";
5-
import { render, screen } from "@testing-library/react";
67

7-
import { useNavigation } from "react-router";
88
import Product from ".";
9-
import type { Route } from "./+types";
109

11-
// Mock Container component since we just want to verify it's used correctly
12-
vi.mock("@/components/ui", () => ({
13-
Container: vi.fn(({ children }) => (
14-
<div data-testid="mock-container">{children}</div>
15-
)),
16-
Button: vi.fn(({ children, ...props }) => (
17-
<button data-testid="mock-button" {...props}>
18-
{children}
19-
</button>
20-
)),
21-
Separator: vi.fn(() => <hr data-testid="mock-separator" />),
22-
}));
10+
import type { Route } from "./+types";
2311

2412
// Helper function to create a test navigation object
2513
const createTestNavigation = (overrides = {}) => ({
@@ -38,6 +26,7 @@ const createTestNavigation = (overrides = {}) => ({
3826
vi.mock("react-router", () => ({
3927
Form: vi.fn(({ children }) => <form>{children}</form>),
4028
useNavigation: vi.fn(() => createTestNavigation()),
29+
Link: vi.fn(({ children, ...props }) => <a {...props}>{children}</a>),
4130
}));
4231

4332
const createTestProps = (
@@ -68,7 +57,7 @@ describe("Product Component", () => {
6857
// Step 3: Call - Render component
6958
render(<Product {...props} />);
7059
// Step 4: Verify - Check price is rendered correctly
71-
expect(screen.getByText("$150.99")).toBeInTheDocument();
60+
expect(screen.queryByText("$150.99")).toBeInTheDocument();
7261
});
7362

7463
it("should render product description", () => {
@@ -80,7 +69,7 @@ describe("Product Component", () => {
8069
// Step 3: Call - Render component
8170
render(<Product {...props} />);
8271
// Step 4: Verify - Check description is rendered
83-
expect(screen.getByText("Amazing product")).toBeInTheDocument();
72+
expect(screen.queryByText("Amazing product")).toBeInTheDocument();
8473
});
8574

8675
it("should render product image with correct src and alt attributes", () => {
@@ -107,7 +96,7 @@ describe("Product Component", () => {
10796
render(<Product {...props} />);
10897
// Step 4: Verify - Check features are rendered
10998
features.forEach((feature) => {
110-
expect(screen.getByText(feature)).toBeInTheDocument();
99+
expect(screen.queryByText(feature)).toBeInTheDocument();
111100
});
112101
});
113102

@@ -119,7 +108,7 @@ describe("Product Component", () => {
119108
render(<Product {...props} />);
120109
// Step 4: Verify - Check button is present
121110
expect(
122-
screen.getByRole("button", { name: "Agregar al Carrito" })
111+
screen.queryByRole("button", { name: "Agregar al Carrito" })
123112
).toBeInTheDocument();
124113
});
125114
});
@@ -133,7 +122,9 @@ describe("Product Component", () => {
133122
// Step 3: Call
134123
render(<Product {...props} />);
135124
// Step 4: Verify
136-
const redirectInput = screen.getByDisplayValue(`/products/${productId}`);
125+
const redirectInput = screen.queryByDisplayValue(
126+
`/products/${productId}`
127+
);
137128
expect(redirectInput).toBeInTheDocument();
138129
});
139130

@@ -159,9 +150,9 @@ describe("Product Component", () => {
159150
props.loaderData.product = undefined;
160151

161152
// Step 2: Mock - Mock NotFound component
162-
vi.mock("../not-found", () => ({
163-
default: () => <div data-testid="not-found">Not Found Page</div>,
164-
}));
153+
// vi.mock("../not-found", () => ({
154+
// default: () => <div data-testid="not-found">Not Found Page</div>,
155+
// }));
165156
// Step 3: Call
166157
render(<Product {...props} />);
167158
// Step 4: Verify

src/services/product.service.test.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe("Product Service", () => {
2121
it("should return products for a valid category slug", async () => {
2222
// Step 1: Setup - Create test data with valid category and products
2323
const testCategory = createTestCategory();
24-
const mockedProducts = [
24+
const mockedProducts: Product[] = [
2525
createTestProduct({ id: 1, categoryId: testCategory.id }),
2626
createTestProduct({
2727
id: 2,
@@ -33,7 +33,7 @@ describe("Product Service", () => {
3333
// Step 2: Mock - Configure repository responses
3434
vi.mocked(getCategoryBySlug).mockResolvedValue(testCategory);
3535
vi.mocked(productRepository.getProductsByCategory).mockResolvedValue(
36-
mockedProducts as Product[]
36+
mockedProducts
3737
);
3838

3939
// Step 3: Call service function
@@ -52,19 +52,16 @@ describe("Product Service", () => {
5252
const invalidSlug = "invalid-slug";
5353

5454
// Step 2: Mock - Configure error response
55-
vi.mocked(getCategoryBySlug).mockRejectedValue(
56-
new Error(`Category with slug "${invalidSlug}" not found`)
57-
);
55+
const errorMessage = `Category with slug "${invalidSlug}" not found`;
56+
vi.mocked(getCategoryBySlug).mockRejectedValue(new Error(errorMessage));
5857

5958
// Step 3: Call service function
6059
const getProducts = getProductsByCategorySlug(
6160
invalidSlug as Category["slug"]
6261
);
6362

6463
// Step 4: Verify expected behavior
65-
await expect(getProducts).rejects.toThrow(
66-
`Category with slug "${invalidSlug}" not found`
67-
);
64+
await expect(getProducts).rejects.toThrow(errorMessage);
6865
expect(productRepository.getProductsByCategory).not.toHaveBeenCalled();
6966
});
7067
});
@@ -97,10 +94,10 @@ describe("Product Service", () => {
9794
vi.mocked(productRepository.getProductById).mockResolvedValue(null);
9895

9996
// Step 3: Call service function
100-
const getProduct = getProductById(nonExistentId);
97+
const productPromise = getProductById(nonExistentId);
10198

10299
// Step 4: Verify expected behavior
103-
await expect(getProduct).rejects.toThrow("Product not found");
100+
await expect(productPromise).rejects.toThrow("Product not found");
104101
});
105102
});
106103
});

0 commit comments

Comments
 (0)