Skip to content

Commit

Permalink
feat: e2e login tests
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoEscaleira committed Apr 7, 2024
1 parent 27b9ed3 commit 74c343e
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 78 deletions.
14 changes: 14 additions & 0 deletions cypress/e2e/login.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Feature: Login
Scenario: User enters valid details that match with an existing account
Given I navigate to the "Home" page
Then I open the menu drawer
When I enter user email and password
When I click to login button
Then I should see the text "Hello Marco!"

Scenario: User enters unmatched details
Given I navigate to the "Home" page
Then I open the menu drawer
When I click to login button
Then I should see the text "Invalid email address."
Then I should see the text "Password is required."
10 changes: 5 additions & 5 deletions cypress/e2e/navigation.feature
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Feature: App Navigation
Scenario: View the landing page information
When I go to the "Home" page
Given I navigate to the "Home" page
Then I should see the text "Meet the Countries"
Then I should see the text "Embark on an exciting journey with us to explore uncharted territories and discover countries like never before."
Then I should see the text "Are you ready for the adventure?"
Then I should see the text "Get started"

Scenario: View the side bar drawer
When I go to the "Home" page
Given I navigate to the "Home" page
Then I open the menu drawer
Then I should see the text "Hello explorer!"
Then I should see the text "Get started and login to your account"
Expand All @@ -17,21 +17,21 @@ Feature: App Navigation
Then I should see the text "Not registered?"

Scenario: View the about page
When I go to the "Home" page
Given I navigate to the "Home" page
Then I open the menu drawer
Then I click on the text "About"
Then I should see the text "About"
Then I should see the text "Personal motivations"
Then I should see the text "The idea behind MTC"

Scenario: View the game page through the side bar drawer
When I go to the "Home" page
Given I navigate to the "Home" page
Then I open the menu drawer
Then I click on the text "Game"
Then I should see the text "Begin by choosing a country"

Scenario: View the game page through the get started button
When I go to the "Home" page
Given I navigate to the "Home" page
Then I open the menu drawer
Then I click on the text "Game"
Then I should see the text "Begin by choosing a country"
2 changes: 2 additions & 0 deletions cypress/e2e/pageDescriptors/homePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export const homePageDescriptor = {
url: "/",
getStartedBtn: () => cy.get("[data-cy='get-started']"),
menuBtn: () => cy.get("[data-cy='menu-toggle']"),
emailLoginInput: () => cy.get("input[name='email']"),
passwordLoginInput: () => cy.get("input[name='password']"),
};
14 changes: 7 additions & 7 deletions cypress/support/step_definitions/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Then, When, Before } from "@badeball/cypress-cucumber-preprocessor";
import { clickOnText, textPresence } from "./rtlDescriptors";
import { Then, When, Given, Before } from "@badeball/cypress-cucumber-preprocessor";
import { clickOnText, findByText } from "./rtlDescriptors";
import { homePageDescriptor } from "../../e2e/pageDescriptors";

const pages = {
Expand All @@ -10,15 +10,15 @@ Before(() => {
cy.ignoreThirdPartyRequests();
});

When("I go to url {string}", (url: string) => {
cy.visit(url);
Given("I navigate to the {string} page", (pageName: string) => {
cy.visit(pages[pageName].url);
});

When("I go to the {string} page", (pageName: string) => {
cy.visit(pages[pageName].url);
When("I go to url {string}", (url: string) => {
cy.visit(url);
});

Then("I should see the text {string}", textPresence);
Then("I should see the text {string}", findByText);

When("I click on the text {string}", (text: string) => {
clickOnText(text);
Expand Down
12 changes: 12 additions & 0 deletions cypress/support/step_definitions/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { When } from "@badeball/cypress-cucumber-preprocessor";
import { clickOnText } from "./rtlDescriptors";
import { homePageDescriptor } from "../../e2e/pageDescriptors";

When("I enter user email and password", () => {
homePageDescriptor.emailLoginInput().type("[email protected]");
homePageDescriptor.passwordLoginInput().type("Password@123");
});

When("I click to login button", () => {
clickOnText("Login to your account");
});
4 changes: 0 additions & 4 deletions cypress/support/step_definitions/rtlDescriptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,3 @@ export function findByText(text: string) {
export function clickOnText(text: string) {
return cy.findAllByText(new RegExp(text)).click();
}

export function textPresence(text: string) {
findByText(text);
}
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
"lint:ts": "tsc --noEmit",
"preview": "vite preview",
"compile:gql": "graphql-codegen",
"e2e:local": "cypress run --config-file ./cypress.config.ts",
"e2e:local": "cypress run --config-file ./cypress.config.ts -record --key f6b1ede9-6614-4d90-9200-45fb721c100e",
"run:e2e": "start-server-and-test dev http://localhost:3000 e2e:local",
"run:e2e:npx": "npx cypress run --record --key f6b1ede9-6614-4d90-9200-45fb721c100e",
"e2e:start:local": "cypress open --config-file ./cypress.config.ts"
},
"dependencies": {
Expand Down Expand Up @@ -66,7 +68,7 @@
"@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-react": "4.2.1",
"autoprefixer": "^10.4.18",
"cypress": "^13.7.1",
"cypress": "^13.7.2",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
Expand All @@ -81,6 +83,7 @@
"prettier-plugin-tailwindcss": "^0.5.13",
"react-simple-maps": "^4.0.0-beta.6",
"sass": "^1.71.1",
"start-server-and-test": "^2.0.3",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.3",
"vite": "5.2.7",
Expand Down
91 changes: 46 additions & 45 deletions src/components/Login/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useMutation } from "@apollo/client";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Input, Typography } from "@material-tailwind/react";
import { SubmitHandler, useForm } from "react-hook-form";
import { Button, Typography } from "@material-tailwind/react";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import { Link, useRevalidator } from "react-router-dom";
import { toast } from "react-toastify";
import { z } from "zod";
import { FormInput } from "@components/Form";
import {
LOGIN_USER,
GET_USER_ATTEMPTS,
Expand All @@ -15,24 +16,24 @@ import {
} from "@utils/queries";

const formSchema = z.object({
email: z.string().email(),
password: z.string().min(1),
email: z.string().email("Invalid email address."),
password: z.string().min(1, "Password is required."),
});

export function LoginForm({ toggleDrawer }: { toggleDrawer: () => void }) {
const revalidator = useRevalidator();
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm<z.infer<typeof formSchema>>({
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
email: "",
password: "",
},
});
const {
handleSubmit,
reset,
formState: { errors },
} = form;

const [loginMutation, { loading: isLoadingLogin, error: mutationError }] = useMutation(LOGIN_USER, {
onCompleted: async ({ loginUser }) => {
Expand Down Expand Up @@ -67,45 +68,45 @@ export function LoginForm({ toggleDrawer }: { toggleDrawer: () => void }) {
</Typography>
</div>

<form onSubmit={handleSubmit(onSubmit)} className="space-y-3 py-4">
<Input
{...register("email")}
name="email"
size="lg"
label="Email address"
placeholder="[email protected]"
error={!!errors.email}
/>
<FormProvider {...form}>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-3 py-4">
<FormInput
name="email"
size="lg"
label="Email address"
placeholder="[email protected]"
fieldError={errors.email}
/>

<Input
{...register("password")}
name="password"
size="lg"
type="password"
label="Password"
placeholder="*******"
error={!!errors.password}
/>
<FormInput
name="password"
size="lg"
type="password"
label="Password"
placeholder="*******"
fieldError={errors.password}
/>

{mutationError?.message && (
<Typography variant="small" color="red">
{mutationError.message}
</Typography>
)}
{mutationError?.message && (
<Typography variant="small" color="red">
{mutationError.message}
</Typography>
)}

<Button type="submit" fullWidth disabled={isLoadingLogin} loading={isLoadingLogin}>
Login to your account
</Button>
<Button type="submit" fullWidth disabled={isLoadingLogin} loading={isLoadingLogin}>
Login to your account
</Button>

<div className="flex items-center">
<Typography>Not registered?</Typography>&nbsp;
<Link to="/register" onClick={toggleDrawer} className="text-blue-700 hover:underline">
<Button size="sm" variant="text">
Create an account
</Button>
</Link>
</div>
</form>
<div className="flex items-center">
<Typography>Not registered?</Typography>&nbsp;
<Link to="/register" onClick={toggleDrawer} className="text-blue-700 hover:underline">
<Button size="sm" variant="text">
Create an account
</Button>
</Link>
</div>
</form>
</FormProvider>
</div>
);
}
Loading

0 comments on commit 74c343e

Please sign in to comment.