Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 39 additions & 98 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,39 @@
# zipBoard Junior Position Test Project

This is a test repository for the zipBoard junior position application process. This project demonstrates a simple React application with a login form and Cypress testing setup.

## Important Note

This repository is for testing purposes only. Please fork this repository to your own account and do not modify this original repository. All your work should be done in your forked version.

## Required Technologies

To run this project locally, you need to have the following installed:

- Node.js (version 18 or higher)
- npm (comes with Node.js)
- Git

## Getting Started

1. Fork this repository to your own account
2. Clone your forked repository:
```bash
git clone <your-forked-repo-url>
```
3. Install dependencies:
```bash
npm install
```
4. Start the development server:
```bash
npm start
```
The application will be available at [http://localhost:3000](http://localhost:3000)

## Testing with Cypress

This project uses Cypress for end-to-end testing. To run the tests:

1. Make sure the development server is running (`npm start`)
2. In a new terminal, you can run Cypress in two ways:

### Open Cypress Test Runner (Interactive Mode)
```bash
npm run cypress:open
```
This will open the Cypress Test Runner UI where you can:
- Choose your preferred browser
- See all test files
- Run tests interactively
- Watch tests run in real-time

### Run Tests in Headless Mode
```bash
npm run cypress:run
```
This will run all tests in the terminal without opening the UI.

### Run Tests with Dev Server
```bash
npm run test:e2e
```
This command will:
1. Start the development server
2. Wait for it to be available
3. Run all Cypress tests
4. Shut down the server when done

## Project Structure

```
├── src/
│ ├── components/
│ │ ├── LoginForm.js
│ │ ├── LoginForm.css
│ │ ├── Welcome.js
│ │ └── Welcome.css
│ ├── App.js
│ └── App.css
├── cypress/
│ ├── e2e/
│ │ └── login.cy.js
│ └── support/
│ ├── commands.js
│ └── e2e.js
└── package.json
```

## Available Scripts

- `npm start` - Runs the app in development mode
- `npm test` - Runs the React testing suite
- `npm run build` - Builds the app for production
- `npm run cypress:open` - Opens Cypress Test Runner
- `npm run cypress:run` - Runs Cypress tests in headless mode
- `npm run test:e2e` - Runs Cypress tests with the dev server

## License

This project is for testing purposes only and is not licensed for public use.
# 🧪 React Login App: Cypress Test + Bug Fix

This project is a simple login application built with React. It includes a basic login form and a welcome screen. The project also includes Cypress end-to-end (E2E) tests to ensure that the login flow works as expected.

---

## ✅ Bug Fix: Login Redirect Not Working

### 🔍 Problem

The login form did not redirect the user to the welcome screen after submitting valid input. Clicking "Login" did not cause any state change in the app.

### 🛠️ Fix

The form inside `LoginForm.jsx` was missing an `onSubmit` handler. This caused the `onLogin` callback (passed from the parent `App` component) to never execute.
**Solution:** Added a `handleSubmit` function with `e.preventDefault()` to stop the form’s default submission behavior (page reload). This allows the `onLogin(formData)` function to execute properly, which updates the `isLoggedIn` state in `App.js` and conditionally renders the welcome screen.

---

## 🧪 Cypress Tests

Cypress test file is located at:
cypress/e2e/login.cy.js

## Cypress Test Overview

Cypress tests were written to cover the end-to-end login flow, including:

- Verifying that the login form renders correctly with empty inputs initially.
- Simulating user input into the name and password fields.
- Submitting the form and checking that the welcome screen appears with the correct user name.
- Testing the logout flow to ensure the app returns to the login form.

## 🤖 AI Tool Usage

I used **ChatGPT** to assist in generating the Cypress test cases. Specifically:

- I provided all three components: `LoginForm.jsx`, `Welcome.jsx`, and `App.js`.
- I asked ChatGPT to create **end-to-end (E2E) test scripts** that cover the login, welcome screen, and logout flow.
41 changes: 39 additions & 2 deletions cypress/e2e/login.cy.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,39 @@
describe('Login Component', () => {
})
/**
* End‑to‑end tests for the basic login flow
*/
describe("Login flow", () => {
const user = { name: "admin", password: "admin" };

beforeEach(() => {
cy.visit("/");
});

it("renders the empty form", () => {
cy.get("[data-cy=login-form]").within(() => {
cy.get('input[name="name"]').should("have.value", "");
cy.get('input[name="password"]').should("have.value", "");
cy.contains("Login");
});
});

it("logs in and shows the welcome screen", () => {
cy.get('input[name="name"]').type(user.name);
cy.get('input[name="password"]').type(user.password);
cy.get("[data-cy=login-submit]").click();

// The component‐level “redirect” is a conditional render,
// so we verify that the welcome card appears and the form disappears.
cy.contains(`Welcome, ${user.name}!`).should("be.visible");
cy.get("[data-cy=login-form]").should("not.exist");
});

it("logs out and returns to the form", () => {
// log in first
cy.get('input[name="name"]').type(user.name);
cy.get('input[name="password"]').type(user.password);
cy.get("[data-cy=login-submit]").click();

cy.contains("Logout").click();
cy.get("[data-cy=login-form]").should("exist");
});
});
25 changes: 15 additions & 10 deletions src/components/LoginForm.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import React, { useState } from 'react';
import './LoginForm.css';
import React, { useState } from "react";
import "./LoginForm.css";

function LoginForm({ onLogin }) {
const [formData, setFormData] = useState({
name: '',
password: ''
name: "",
password: "",
});

const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prevState => ({
setFormData((prevState) => ({
...prevState,
[name]: value
[name]: value,
}));
};

const handleSubmit = (e) => {
e.preventDefault();
onLogin(formData);
};

return (
<div className="login-form-container">
<form className="login-form">
<div className="login-form-container" data-cy="login-form">
<form className="login-form" onSubmit={handleSubmit}>
<h2>Login</h2>
<div className="form-group">
<label htmlFor="name">Name:</label>
Expand All @@ -41,12 +46,12 @@ function LoginForm({ onLogin }) {
required
/>
</div>
<button type="submit" className="login-button">
<button type="submit" className="login-button" data-cy="login-submit">
Login
</button>
</form>
</div>
);
}

export default LoginForm;
export default LoginForm;