diff --git a/examples/twd-test-app/src/components/Pagination.tsx b/examples/twd-test-app/src/components/Pagination.tsx new file mode 100644 index 0000000..cc0344d --- /dev/null +++ b/examples/twd-test-app/src/components/Pagination.tsx @@ -0,0 +1,107 @@ +import React from 'react'; +import { Link } from 'react-router'; + +type PaginationProps = { + currentPage: number; + totalPages: number; + getPageHref: (page: number) => string; +}; + +const buttonBaseStyle: React.CSSProperties = { + minWidth: '38px', + height: '38px', + padding: '0 12px', + borderRadius: '10px', + border: '1px solid #cbd5e1', + backgroundColor: '#ffffff', + color: '#334155', + fontSize: '14px', + fontWeight: 600, + cursor: 'pointer', +}; + +const Pagination: React.FC = ({ + currentPage, + totalPages, + getPageHref, +}) => { + if (totalPages <= 1) { + return null; + } + + const pages = Array.from({ length: totalPages }, (_, index) => index + 1); + + return ( +
+

+ Pagina {currentPage} de {totalPages} +

+ +
+ + Anterior + + + {pages.map((page) => ( + + {page} + + ))} + + + Siguiente + +
+
+ ); +}; + +export default Pagination; diff --git a/examples/twd-test-app/src/loaders/contactsLoader.ts b/examples/twd-test-app/src/loaders/contactsLoader.ts new file mode 100644 index 0000000..e4be061 --- /dev/null +++ b/examples/twd-test-app/src/loaders/contactsLoader.ts @@ -0,0 +1,31 @@ +import type { LoaderFunctionArgs } from "react-router"; + +export type Contact = { + id: number; + name: string; + email: string; +}; + +type ContactResponse = { + contacts: Contact[]; + currentPage: number; + totalPages: number; +} + +export const contactsLoader = async ({ request }: LoaderFunctionArgs) => { + const url = new URL(request.url); + const pageParam = url.searchParams.get("page"); + console.log(pageParam) + const response = await fetch("http://localhost:3000/v1/contacts"); + + if (!response.ok) { + throw new Response("Failed to load contacts", { + status: response.status, + statusText: response.statusText, + }); + } + + const contactsResponse = (await response.json()) as ContactResponse; + + return contactsResponse; +}; diff --git a/examples/twd-test-app/src/pages/Contacts.tsx b/examples/twd-test-app/src/pages/Contacts.tsx new file mode 100644 index 0000000..1673eae --- /dev/null +++ b/examples/twd-test-app/src/pages/Contacts.tsx @@ -0,0 +1,138 @@ +import React from 'react'; +import { useLoaderData, } from 'react-router'; +import type { contactsLoader } from '../loaders/contactsLoader'; +import Pagination from '../components/Pagination'; + +const Contacts: React.FC = () => { + const { contacts, currentPage, totalPages } = useLoaderData(); + + + const getPageHref = (page: number) => `/contacts?page=${page}`; + + return ( +
+
+
+

+ Agenda mock +

+

+ Contactos +

+

+ Una lista simple de contactos con nombre y correo. +

+
+ +
+ {contacts.length === 0 ? ( +
+ No hay contactos disponibles. +
+ ) : ( + contacts.map((contact) => ( +
+
+

+ {contact.name} +

+

+ {contact.email} +

+
+ + + Contacto + +
+ )) + )} +
+ + + + +
+
+ ); +}; + +export default Contacts; diff --git a/examples/twd-test-app/src/routes.tsx b/examples/twd-test-app/src/routes.tsx index bc82654..f2a4466 100644 --- a/examples/twd-test-app/src/routes.tsx +++ b/examples/twd-test-app/src/routes.tsx @@ -8,12 +8,19 @@ import MockComponent from "./pages/MockComponent"; import Responsive from "./pages/Responsive"; import BlurValidation from "./pages/BlurValidation"; import ComboboxSelect from "./pages/ComboboxSelect"; +import Contacts from "./pages/Contacts"; +import { contactsLoader } from "./loaders/contactsLoader"; const router = createBrowserRouter([ { path: "/", Component: App, }, + { + path: "/contacts", + loader: contactsLoader, + Component: Contacts, + }, { path: "/assertions", Component: Assertions, diff --git a/examples/twd-test-app/src/twd-tests/contacts.twd.test.ts b/examples/twd-test-app/src/twd-tests/contacts.twd.test.ts new file mode 100644 index 0000000..7b5f415 --- /dev/null +++ b/examples/twd-test-app/src/twd-tests/contacts.twd.test.ts @@ -0,0 +1,48 @@ +import { twd, expect, screenDom, userEvent } from "../../../../src"; +import { describe, it, beforeEach } from "../../../../src/runner"; + +const contactsResponse = [ + { id: 1, name: "Ana Garcia", email: "ana.garcia@example.com" }, + { id: 2, name: "Luis Martinez", email: "luis.martinez@example.com" }, + { id: 3, name: "Carmen Lopez", email: "carmen.lopez@example.com" }, + { id: 4, name: "Javier Romero", email: "javier.romero@example.com" }, +]; + +describe("contactsPage", () => { + beforeEach(() => { + twd.clearRequestMockRules(); + }); + + it("renders the contacts list from the loader response", async () => { + await twd.mockRequest("contactsList", { + method: "GET", + response: { + contacts: contactsResponse, + currentPage: 2, + totalPages: 2, + }, + url: "/v1/contacts", + }); + + await twd.visit("/contacts"); + await twd.waitForRequest("contactsList"); + + const heading = screenDom.getByRole("heading", { name: /contactos/i }); + twd.should(heading, "be.visible"); + + for (const contact of contactsResponse.slice(0, 2)) { + const name = screenDom.getByText(contact.name); + const email = screenDom.getByText(contact.email); + + twd.should(name, "be.visible"); + twd.should(email, "be.visible"); + } + + const pageTwoLink = screenDom.getByRole("link", { name: "2" }); + await userEvent.click(pageTwoLink); + + // TODO: there is a bug with twd assertion + // await twd.url().should("contain.url", "/contacts?page=2"); + + }); +});