From 04a6a74b4166466954fe10b4783149b9637002c6 Mon Sep 17 00:00:00 2001 From: Diego Torres Date: Thu, 19 Jun 2025 20:25:22 -0500 Subject: [PATCH 1/3] feat: implement end-to-end test for order creation and update order confirmation component --- src/e2e/user-create-order.spec.ts | 57 +++++++++++++++++++++++++ src/routes/order-confirmation/index.tsx | 7 ++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/e2e/user-create-order.spec.ts diff --git a/src/e2e/user-create-order.spec.ts b/src/e2e/user-create-order.spec.ts new file mode 100644 index 0000000..8bd1454 --- /dev/null +++ b/src/e2e/user-create-order.spec.ts @@ -0,0 +1,57 @@ +import { test, expect } from "@playwright/test"; + +test("User can create an order", async ({ page }) => { + await page.goto("http://localhost:5173/"); + + await page.getByRole("link", { name: "Iniciar sesión" }).click(); + + const loginForm = { + "Correo electrónico": "testino@mail.com", + Contraseña: "supersecret", + }; + + for (const [key, value] of Object.entries(loginForm)) { + const input = await page.getByRole("textbox", { name: key }); + await input.click(); + await input.fill(value); + } + + await page.getByRole("button", { name: "Iniciar sesión" }).click(); + + // Wait for the user to be logged in + await expect( + page.getByRole("button", { name: "Cerrar sesión" }) + ).toBeVisible(); + + await page.getByRole("menuitem", { name: "Polos" }).click(); + await page.getByTestId("product-item").first().click(); + + await page.getByRole("button", { name: "Agregar al Carrito" }).click(); + await page.getByRole("link", { name: "Carrito de compras" }).click(); + + await page.getByRole("link", { name: "Continuar Compra" }).click(); + + const orderForm = { + Nombre: "Testino", + Apellido: "Diprueba", + Compañia: "", + Dirección: "Calle De Prueba 123", + Ciudad: "Lima", + "Provincia/Estado": "Lima", + "Código Postal": "51111", + Teléfono: "987456321", + }; + + for (const [key, value] of Object.entries(orderForm)) { + const input = await page.getByRole("textbox", { name: key }); + await input.click(); + await input.fill(value); + } + + await page.getByRole("combobox", { name: "País" }).selectOption("PE"); + + await page.getByRole("button", { name: "Confirmar Orden" }).click(); + + await expect(page.getByText("¡Muchas gracias por tu compra!")).toBeVisible(); + await expect(page.getByTestId("orderId")).toBeVisible(); +}); diff --git a/src/routes/order-confirmation/index.tsx b/src/routes/order-confirmation/index.tsx index fd01cd3..4ee3583 100644 --- a/src/routes/order-confirmation/index.tsx +++ b/src/routes/order-confirmation/index.tsx @@ -25,7 +25,12 @@ export default function OrderConfirmation({ Llegaremos a la puerta de tu domicilio lo antes posible

Código de seguimiento

-

{orderId}

+

+ {orderId} +

); From 20ce53b126eac4bf1401b9d41d86b03091bd1b6b Mon Sep 17 00:00:00 2001 From: Diego Torres Date: Thu, 19 Jun 2025 21:12:43 -0500 Subject: [PATCH 2/3] fix: add ON DELETE CASCADE to user_id reference in orders table and enhance end-to-end test for order creation --- src/db/migrations/initial.sql | 2 +- src/e2e/user-create-order.spec.ts | 118 +++++++++++++++++++----------- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/db/migrations/initial.sql b/src/db/migrations/initial.sql index 2d2bc31..0fe8b74 100644 --- a/src/db/migrations/initial.sql +++ b/src/db/migrations/initial.sql @@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS cart_items ( CREATE TABLE IF NOT EXISTS orders ( id SERIAL PRIMARY KEY, - user_id INTEGER REFERENCES users(id), + user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, total_amount NUMERIC(10,2) NOT NULL, -- Customer and shipping details diff --git a/src/e2e/user-create-order.spec.ts b/src/e2e/user-create-order.spec.ts index 8bd1454..20c4c55 100644 --- a/src/e2e/user-create-order.spec.ts +++ b/src/e2e/user-create-order.spec.ts @@ -1,57 +1,93 @@ import { test, expect } from "@playwright/test"; -test("User can create an order", async ({ page }) => { - await page.goto("http://localhost:5173/"); +import { hashPassword } from "@/lib/security"; +import type { CreateUserDTO } from "@/models/user.model"; +import { + createUser, + deleteUser, + getUserByEmail, +} from "@/repositories/user.repository"; - await page.getByRole("link", { name: "Iniciar sesión" }).click(); +test.describe("User", () => { + let testUserId: number; - const loginForm = { - "Correo electrónico": "testino@mail.com", - Contraseña: "supersecret", - }; + test.beforeAll(async () => { + const testUser: CreateUserDTO = { + email: "diego@codeable.com", + name: null, + password: await hashPassword("letmein"), + isGuest: false, + }; - for (const [key, value] of Object.entries(loginForm)) { - const input = await page.getByRole("textbox", { name: key }); - await input.click(); - await input.fill(value); - } + const existingUser = await getUserByEmail(testUser.email); - await page.getByRole("button", { name: "Iniciar sesión" }).click(); + if (existingUser) { + await deleteUser(existingUser.id); + } - // Wait for the user to be logged in - await expect( - page.getByRole("button", { name: "Cerrar sesión" }) - ).toBeVisible(); + const user = await createUser(testUser); + testUserId = user.id; + }); - await page.getByRole("menuitem", { name: "Polos" }).click(); - await page.getByTestId("product-item").first().click(); + test.afterAll(async () => { + await deleteUser(testUserId); + }); - await page.getByRole("button", { name: "Agregar al Carrito" }).click(); - await page.getByRole("link", { name: "Carrito de compras" }).click(); + test("User can create an order", async ({ page }) => { + await page.goto("http://localhost:5173/"); - await page.getByRole("link", { name: "Continuar Compra" }).click(); + await page.getByRole("link", { name: "Iniciar sesión" }).click(); - const orderForm = { - Nombre: "Testino", - Apellido: "Diprueba", - Compañia: "", - Dirección: "Calle De Prueba 123", - Ciudad: "Lima", - "Provincia/Estado": "Lima", - "Código Postal": "51111", - Teléfono: "987456321", - }; + const loginForm = { + "Correo electrónico": "diego@codeable.com", + Contraseña: "letmein", + }; - for (const [key, value] of Object.entries(orderForm)) { - const input = await page.getByRole("textbox", { name: key }); - await input.click(); - await input.fill(value); - } + for (const [key, value] of Object.entries(loginForm)) { + const input = await page.getByRole("textbox", { name: key }); + await input.click(); + await input.fill(value); + } - await page.getByRole("combobox", { name: "País" }).selectOption("PE"); + await page.getByRole("button", { name: "Iniciar sesión" }).click(); - await page.getByRole("button", { name: "Confirmar Orden" }).click(); + // Wait for the user to be logged in + await expect( + page.getByRole("button", { name: "Cerrar sesión" }) + ).toBeVisible(); - await expect(page.getByText("¡Muchas gracias por tu compra!")).toBeVisible(); - await expect(page.getByTestId("orderId")).toBeVisible(); + await page.getByRole("menuitem", { name: "Polos" }).click(); + await page.getByTestId("product-item").first().click(); + + await page.getByRole("button", { name: "Agregar al Carrito" }).click(); + await page.getByRole("link", { name: "Carrito de compras" }).click(); + + await page.getByRole("link", { name: "Continuar Compra" }).click(); + + const orderForm = { + Nombre: "Testino", + Apellido: "Diprueba", + Compañia: "", + Dirección: "Calle De Prueba 123", + Ciudad: "Lima", + "Provincia/Estado": "Lima", + "Código Postal": "51111", + Teléfono: "987456321", + }; + + for (const [key, value] of Object.entries(orderForm)) { + const input = await page.getByRole("textbox", { name: key }); + await input.click(); + await input.fill(value); + } + + await page.getByRole("combobox", { name: "País" }).selectOption("PE"); + + await page.getByRole("button", { name: "Confirmar Orden" }).click(); + + await expect( + page.getByText("¡Muchas gracias por tu compra!") + ).toBeVisible(); + await expect(page.getByTestId("orderId")).toBeVisible(); + }); }); From 41b0c9f5509cd9d482dff4ff591906bfabe28a5b Mon Sep 17 00:00:00 2001 From: Diego Torres Date: Thu, 19 Jun 2025 21:15:30 -0500 Subject: [PATCH 3/3] chore: remove .env file and add it to .gitignore --- .env | 12 ------------ .gitignore | 1 + 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index bc3c03d..0000000 --- a/.env +++ /dev/null @@ -1,12 +0,0 @@ -# Server -NODE_ENV=development - -# Application Database -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=fullstock -DB_USER=diego -DB_PASSWORD= - -# Admin Database (for database creation/deletion) -ADMIN_DB_NAME=diego diff --git a/.gitignore b/.gitignore index 5175288..a1533a2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ dist-ssr .react-router/ .build/ +.env # Playwright /test-results/