From ae805e5d80ec322580bf43b1d880ec5fb301caae Mon Sep 17 00:00:00 2001 From: Owen Rees Date: Thu, 22 Jun 2023 09:45:07 +0200 Subject: [PATCH 1/3] map length corrected --- TODO | 4 +--- app/layout.tsx | 3 ++- components/TournamentMap.tsx | 2 +- components/TournamentTable.tsx | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/TODO b/TODO index 6724f3e..8c1f8dc 100644 --- a/TODO +++ b/TODO @@ -10,7 +10,7 @@ TESTS BUGS //TODO about page is not centred in Safari //TODO tournament page load is weird on 2nd click. On safari it pauses for a few seconds. Is it trying to load the entire page before displaying? -//TODO Nodemailer 'from' reverts to echecsfrance@gmail.com +//TODO Nodemailer 'from' reverts to echecsfrance@gmail.com - quick fix done with sender address in subject line ---------------------------------------------------------------- PAGES @@ -20,9 +20,7 @@ PAGES DESIGN CHANGES //TODO test entire site for english to french translations //TODO success and error messages into french - mailer -//TODO disable send message button while sending - isSending = true //TODO font size on mobile screen -//TODO bottom of map is a few pixels short //TODO mobile navbar is creeping into the page by a few pixels when hidden - move it to the right a bit. It is easier to see in light mode //TODO logo for navbar and favicon //TODO mobile map needs improving diff --git a/app/layout.tsx b/app/layout.tsx index f09c65b..50bb68a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -7,7 +7,8 @@ const inter = Inter({ subsets: ["latin"] }); export const metadata = { title: "Echecs France", - description: "Generated by create next app", // TODO give the website a description + maybe keywords if they go here + description: "Trouvez Vos Tournois d'Echecs en France Sur Une Carte", + keywords: "echecs, France, tournoi, tournois, FFE", }; export default function RootLayout({ diff --git a/components/TournamentMap.tsx b/components/TournamentMap.tsx index 0323030..c060eb3 100644 --- a/components/TournamentMap.tsx +++ b/components/TournamentMap.tsx @@ -24,7 +24,7 @@ export default function TournamentMap({ tournamentData }: TournamentDataProps) { return (
From 6f7b840b54ae741f176e08bcbe195ebedadf723a Mon Sep 17 00:00:00 2001 From: Owen Rees Date: Thu, 22 Jun 2023 12:52:41 +0200 Subject: [PATCH 2/3] contact form tests --- TODO | 8 +-- app/api/v1/tournaments/france/route.ts | 1 - app/tournois/page.tsx | 2 - components/ContactForm.tsx | 6 ++ cypress/component/utils.cy.ts | 55 ------------------- cypress/e2e/contactForm.cy.ts | 50 +++++++++++++++++ cypress/e2e/{data.cy.tsx => data.cy.ts} | 0 cypress/e2e/links.cy.ts | 61 ++++++++++++++++----- cypress/e2e/{navbar.cy.tsx => navbar.cy.ts} | 0 cypress/e2e/{scroll.cy.tsx => scroll.cy.ts} | 0 cypress/support/commands.ts | 12 +++- 11 files changed, 116 insertions(+), 79 deletions(-) delete mode 100644 cypress/component/utils.cy.ts create mode 100644 cypress/e2e/contactForm.cy.ts rename cypress/e2e/{data.cy.tsx => data.cy.ts} (100%) rename cypress/e2e/{navbar.cy.tsx => navbar.cy.ts} (100%) rename cypress/e2e/{scroll.cy.tsx => scroll.cy.ts} (100%) diff --git a/TODO b/TODO index 8c1f8dc..56f6f90 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,6 @@ TESTS // TODO tests for tournament page: - map and table mounts in tournament page <- get data to send to map/table -//TODO data fetching tests -//TODO redo layer groups tests -//TODO write tests for contact form -//TODO dead link tests take too long, split them into separate tests per page ----------------------------------------------------------------- BUGS @@ -21,20 +17,18 @@ DESIGN CHANGES //TODO test entire site for english to french translations //TODO success and error messages into french - mailer //TODO font size on mobile screen -//TODO mobile navbar is creeping into the page by a few pixels when hidden - move it to the right a bit. It is easier to see in light mode +//TODO mobile navbar is creeping into the page by a few pixels when hidden - move it to the right a bit. It is easier to see in light mode. I cant see this on Linux //TODO logo for navbar and favicon //TODO mobile map needs improving ---------------------------------------------------------------- LOGIC -//TODO SRP for web and API data fetching //TODO error handling //TODO consider offering GraphQL support MISC ---------------------------------------------------------------- //TODO write logger (fullstack open examples) -//TODO SEO - next headers etc //TODO multi-language i18n support - https://nextjs.org/docs/app/building-your-application/routing/internationalization //TODO move smaller ui components into a new folder, and make them reusable - such as using generic prop names //TODO readme diff --git a/app/api/v1/tournaments/france/route.ts b/app/api/v1/tournaments/france/route.ts index afcd444..0ccd2c1 100644 --- a/app/api/v1/tournaments/france/route.ts +++ b/app/api/v1/tournaments/france/route.ts @@ -14,7 +14,6 @@ export async function GET() { try { const client = await clientPromise; const db = client.db("tournamentsFranceDB"); - const results = await dateOrderingFrance(db); const data = results.map(({ _id, ...rest }) => ({ id: _id, diff --git a/app/tournois/page.tsx b/app/tournois/page.tsx index 03c69d1..c6cc6e9 100644 --- a/app/tournois/page.tsx +++ b/app/tournois/page.tsx @@ -23,9 +23,7 @@ const getTournaments = async () => { try { const client = await clientPromise; const db = client.db("tournamentsFranceDB"); - const data = await dateOrderingFrance(db); - return JSON.stringify(data); } catch (error) { throw new Error("Error fetching tournament data"); diff --git a/components/ContactForm.tsx b/components/ContactForm.tsx index d80148a..5902691 100644 --- a/components/ContactForm.tsx +++ b/components/ContactForm.tsx @@ -17,6 +17,7 @@ const ContactForm = () => { className={`${ responseMessage.isSuccessful ? "text-green-600" : "text-red-600" } italic`} + data-cy="info-message" > {responseMessage.message}

@@ -51,6 +52,7 @@ const ContactForm = () => { className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light" placeholder="nom@exemple.com" required + data-cy="email-input" />
@@ -68,6 +70,7 @@ const ContactForm = () => { className="block p-3 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 shadow-sm focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light" placeholder="Le motif de ma demande" required + data-cy="subject-input" />
@@ -84,12 +87,15 @@ const ContactForm = () => { rows={6} className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg shadow-sm border border-gray-300 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Détaillez ici votre demande..." + data-cy="message-input" + required >
diff --git a/cypress/component/utils.cy.ts b/cypress/component/utils.cy.ts deleted file mode 100644 index c3648db..0000000 --- a/cypress/component/utils.cy.ts +++ /dev/null @@ -1,55 +0,0 @@ -// import { Tournament } from "@/types"; -// import getTournaments from "@/utils/getTournamentData"; -// import { createLayerGroups } from "@/utils/layerGroups"; -// - -// // TODO rewrite this test suite since I no longer use fetch for the map -// // TODO add tests for the API once it is active -// describe("Unit tests of utils directory", () => { -// describe("Retrieve tournament data from DB", () => { -// let response: Tournament[]; -// let results: Tournament[]; -// -// describe("France", () => { -// before(async () => { -// response = await getTournaments("france"); -// results = response.splice(0, 5); -// }); -// -// it("log first 5 results", () => { -// results.forEach((result) => cy.log(JSON.stringify(result))); -// }); -// -// it("check tournament urls are active", () => { -// results.forEach((result) => cy.request(result.url)); -// }); -// }); -// }); -// -// describe("Create layer groups for map markers", () => { -// let response: Tournament[]; -// let results: Tournament[]; -// describe("France", () => { -// const timeControls = [ -// { name: "Cadence Lente", colour: "green" }, -// { name: "Rapide", colour: "blue" }, -// { name: "Blitz", colour: "yellow" }, -// { name: "1h KO", colour: "red" }, -// ]; -// -// before(async () => { -// response = await getTournaments("france"); -// results = response.splice(0, 5); -// }); -// -// it("generate layer groups", () => { -// const result = timeControls.map((timeControl) => { -// return createLayerGroups(timeControl.name, timeControl.colour, { -// tournamentData: results, -// }); -// }); -// cy.wrap(result.length).should("be.greaterThan", 0); -// }); -// }); -// }); -// }); diff --git a/cypress/e2e/contactForm.cy.ts b/cypress/e2e/contactForm.cy.ts new file mode 100644 index 0000000..7e6e068 --- /dev/null +++ b/cypress/e2e/contactForm.cy.ts @@ -0,0 +1,50 @@ +describe("Contact form", () => { + const email = "test@test.com"; + const invalidEmail = "test@"; + const subject = "Test Subject"; + const message = "Test message"; + + describe("Invalid data", () => { + beforeEach(() => { + cy.visit("/contactez-nous"); + }); + + it("invalid email address", () => { + cy.getByData("email-input").type(invalidEmail); + cy.getByData("subject-input").type(subject); + cy.getByData("message-input").type(message); + cy.getByData("submit-button").click(); + cy.getByData("info-message").should("have.text", ""); + }); + + it("missing subject", () => { + cy.getByData("email-input").type(email); + cy.getByData("message-input").type(message); + cy.getByData("submit-button").click(); + cy.getByData("info-message").should("have.text", ""); + }); + + it("missing message", () => { + cy.getByData("email-input").type(email); + cy.getByData("subject-input").type(subject); + cy.getByData("submit-button").click(); + cy.getByData("info-message").should("have.text", ""); + }); + }); + + describe("Valid data", () => { + beforeEach(() => { + cy.visit("/contactez-nous"); + }); + + it("valid input", () => { + cy.getByData("email-input").type(email); + cy.getByData("subject-input").type(subject); + cy.getByData("message-input").type(message); + cy.getByData("submit-button").click().should("be.disabled"); + cy.wait(3000); + cy.getByData("info-message").contains("Thank you"); + cy.getByData("submit-button").click().should("be.not.disabled"); + }); + }); +}); diff --git a/cypress/e2e/data.cy.tsx b/cypress/e2e/data.cy.ts similarity index 100% rename from cypress/e2e/data.cy.tsx rename to cypress/e2e/data.cy.ts diff --git a/cypress/e2e/links.cy.ts b/cypress/e2e/links.cy.ts index 72ffcd8..fe52583 100644 --- a/cypress/e2e/links.cy.ts +++ b/cypress/e2e/links.cy.ts @@ -1,11 +1,27 @@ -describe("Test all links", () => { +describe("Test links", () => { const pages = ["tournois", "qui sommes-nous", "contactez-nous"]; const navLinkToSlug = (navLink: string) => { return navLink.replace(/\s+/g, "-"); }; - it("Check navbar links point to correct pathname as a slug", () => { + const testLinks = () => { + cy.get("a:not([href*='mailto:']):not(nav a):not(footer a)").each((link) => { + if ( + !link + .prop("href") + .includes("http://www.echecs.asso.fr/FicheTournoi.aspx") // ignore every external FFE tournament link + ) { + cy.request({ + url: link.prop("href"), + failOnStatusCode: false, + }); + cy.log(link.prop("href")); + } + }); + }; + + it("navbar links point to correct pathname as a slug", () => { cy.viewport(600, 600); cy.visit("/"); pages.forEach((page) => { @@ -16,22 +32,41 @@ describe("Test all links", () => { }); }); - it("Check dead links", () => { - pages.forEach((page) => { - cy.visit(`/${navLinkToSlug(page)}`); - cy.get("a:not([href*='mailto:']").each((link) => { - if ( - !link - .prop("href") - .includes("http://www.echecs.asso.fr/FicheTournoi.aspx") // ignore every external FFE tournament link - ) { + // TODO consider doing .each from pages array once links are on each page + // TODO at present, the commented out tests have no links so fail + it("homepage dead links", () => { + cy.visit("/"); + testLinks(); + }); + + it("tournois dead links", () => { + cy.visit("/tournois"); + testLinks(); + }); + + // it("qui-sommes-nous dead links", () => {s + // cy.visit("/qui-sommes-nous"); + // testLinks(); + // }); + // + // it("contactez-nous dead links", () => { + // cy.visit("/contactez-nous"); + // testLinks(); + // }); + + //TODO consider 5 random links rather than first 5 + it("first 5 tournament external links", () => { + cy.visit("/tournois"); + cy.get("a:not([href*='mailto:']):not(nav a):not(footer a)").each( + (link, index) => { + if (index < 5) { cy.request({ url: link.prop("href"), failOnStatusCode: false, }); cy.log(link.prop("href")); } - }); - }); + } + ); }); }); diff --git a/cypress/e2e/navbar.cy.tsx b/cypress/e2e/navbar.cy.ts similarity index 100% rename from cypress/e2e/navbar.cy.tsx rename to cypress/e2e/navbar.cy.ts diff --git a/cypress/e2e/scroll.cy.tsx b/cypress/e2e/scroll.cy.ts similarity index 100% rename from cypress/e2e/scroll.cy.tsx rename to cypress/e2e/scroll.cy.ts diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 698b01a..22ec2e4 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,3 +1,13 @@ +declare namespace Cypress { + interface Chainable { + getByData(dataTestAttribute: string): Chainable>; + } +} + +Cypress.Commands.add("getByData", (selector) => { + return cy.get(`[data-cy=${selector}]`); +}); + /// // *********************************************** // This example commands.ts shows you how to @@ -34,4 +44,4 @@ // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable // } // } -// } \ No newline at end of file +// } From ef08aa3a616a1a3cfa8a0e239c8d5134c5612949 Mon Sep 17 00:00:00 2001 From: Owen Rees Date: Thu, 22 Jun 2023 13:39:50 +0200 Subject: [PATCH 3/3] updated tests --- app/contactez-nous/page.tsx | 2 +- app/page.tsx | 2 +- app/qui-sommes-nous/page.tsx | 2 +- components/ContactForm.tsx | 10 +++++----- components/Footer.tsx | 2 +- components/Hamburger.tsx | 2 +- components/Navbar.tsx | 6 +++--- components/ScrollToTopButton.tsx | 2 +- components/ThemeSwitcher.tsx | 4 ++-- components/TournamentTable.tsx | 4 ++-- cypress/component/mounting.cy.tsx | 10 +++++----- cypress/component/scroll.cy.tsx | 4 ++-- cypress/component/themeToggle.cy.tsx | 10 +++++----- cypress/e2e/data.cy.ts | 2 +- cypress/e2e/links.cy.ts | 2 +- cypress/e2e/navbar.cy.ts | 12 ++++++------ cypress/e2e/scroll.cy.ts | 6 +++--- ...to correct pathname as a slug (failed).png | Bin 283046 -> 0 bytes cypress/support/commands.ts | 2 +- cypress/support/component-index.html | 2 +- cypress/videos/contactForm.cy.ts.mp4 | Bin 0 -> 285238 bytes cypress/videos/data.cy.ts.mp4 | Bin 0 -> 76357 bytes cypress/videos/data.cy.tsx.mp4 | Bin 120382 -> 0 bytes cypress/videos/links.cy.ts.mp4 | Bin 671181 -> 347419 bytes cypress/videos/navbar.cy.ts.mp4 | Bin 0 -> 152571 bytes cypress/videos/navbar.cy.tsx.mp4 | Bin 127530 -> 0 bytes cypress/videos/scroll.cy.ts.mp4 | Bin 0 -> 216242 bytes cypress/videos/scroll.cy.tsx.mp4 | Bin 175958 -> 0 bytes 28 files changed, 43 insertions(+), 43 deletions(-) delete mode 100644 cypress/screenshots/links.cy.ts/Test all links -- Check navbar links point to correct pathname as a slug (failed).png create mode 100644 cypress/videos/contactForm.cy.ts.mp4 create mode 100644 cypress/videos/data.cy.ts.mp4 delete mode 100644 cypress/videos/data.cy.tsx.mp4 create mode 100644 cypress/videos/navbar.cy.ts.mp4 delete mode 100644 cypress/videos/navbar.cy.tsx.mp4 create mode 100644 cypress/videos/scroll.cy.ts.mp4 delete mode 100644 cypress/videos/scroll.cy.tsx.mp4 diff --git a/app/contactez-nous/page.tsx b/app/contactez-nous/page.tsx index b2e8bde..8a8a2b3 100644 --- a/app/contactez-nous/page.tsx +++ b/app/contactez-nous/page.tsx @@ -9,7 +9,7 @@ export default function Contact() {

Contactez-Nous

diff --git a/app/page.tsx b/app/page.tsx index 7fb3e4b..1f60bcd 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -16,7 +16,7 @@ export default function Home() { />
-

+

Echecs France

diff --git a/app/qui-sommes-nous/page.tsx b/app/qui-sommes-nous/page.tsx index 8c5c878..aac9bba 100644 --- a/app/qui-sommes-nous/page.tsx +++ b/app/qui-sommes-nous/page.tsx @@ -8,7 +8,7 @@ export default function About() {

Qui Sommes-Nous?

diff --git a/components/ContactForm.tsx b/components/ContactForm.tsx index 5902691..6a2a3c0 100644 --- a/components/ContactForm.tsx +++ b/components/ContactForm.tsx @@ -17,7 +17,7 @@ const ContactForm = () => { className={`${ responseMessage.isSuccessful ? "text-green-600" : "text-red-600" } italic`} - data-cy="info-message" + data-test="info-message" > {responseMessage.message}

@@ -52,7 +52,7 @@ const ContactForm = () => { className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light" placeholder="nom@exemple.com" required - data-cy="email-input" + data-test="email-input" />
@@ -70,7 +70,7 @@ const ContactForm = () => { className="block p-3 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 shadow-sm focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light" placeholder="Le motif de ma demande" required - data-cy="subject-input" + data-test="subject-input" />
@@ -87,7 +87,7 @@ const ContactForm = () => { rows={6} className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg shadow-sm border border-gray-300 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder="Détaillez ici votre demande..." - data-cy="message-input" + data-test="message-input" required >
@@ -95,7 +95,7 @@ const ContactForm = () => { disabled={isSending} type="submit" className="py-3 px-5 text-sm font-medium text-center text-white rounded-lg bg-teal-600 sm:w-fit hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 dark:hover:bg-primary-700 dark:focus:ring-primary-800 dark:text-white disabled:opacity-25" - data-cy="submit-button" + data-test="submit-button" > {isSending ? "Sending..." : "Send Message"} diff --git a/components/Footer.tsx b/components/Footer.tsx index 540e283..3df5be8 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -5,7 +5,7 @@ export default function Footer() { return (