diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..55e9040
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,17 @@
+module.exports = {
+ env: {
+ browser: true,
+ node: true,
+ 'cypress/globals': true,
+ },
+ plugins: ['cypress'],
+ rules: {
+ 'cypress/no-assigning-return-values': 'error', // Prevents assigning return values from Cypress commands
+ 'cypress/no-unnecessary-waiting': 'warn', // Warns against using cy.wait() unnecessarily
+ 'cypress/assertion-before-screenshot': 'error', // Ensures assertions are made before taking screenshots
+ 'cypress/no-async-tests': 'error', // Prevents using async/await in Cypress tests
+ },
+ extends: [
+ 'plugin:cypress/recommended'
+ ],
+};
\ No newline at end of file
diff --git a/cypress/e2e/login.cy.js b/cypress/e2e/login.cy.js
index c2fbb3a..27655ba 100644
--- a/cypress/e2e/login.cy.js
+++ b/cypress/e2e/login.cy.js
@@ -1,2 +1,27 @@
+///
describe('Login Component', () => {
-})
\ No newline at end of file
+ beforeEach(() => {
+ cy.visit('/'); // Adjust if needed (e.g. localhost:3000 or specific route)
+ });
+
+ it('displays login form elements', () => {
+ cy.get('h2').should('contain', 'Login');
+ cy.get('input[name="name"]').should('exist');
+ cy.get('input[name="password"]').should('exist');
+ cy.get('button[type="submit"]').should('contain', 'Login');
+ });
+
+ it('shows error message if fields are empty', () => {
+ cy.get('button[type="submit"]').click();
+ cy.get('.error-message').should('contain', 'Name and Password cannot be empty');
+ });
+
+ it('logs in successfully and shows welcome message', () => {
+ cy.get('input[name="name"]').type('Habeeb');
+ cy.get('input[name="password"]').type('supersecret');
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Welcome, Habeeb!'); // Assuming Welcome component renders this
+ cy.get('button').contains('Logout').should('exist'); // Logout button from Welcome
+ });
+});
diff --git a/src/components/LoginForm.css b/src/components/LoginForm.css
index eeae4c2..f345088 100644
--- a/src/components/LoginForm.css
+++ b/src/components/LoginForm.css
@@ -28,6 +28,7 @@
.form-group label {
display: block;
margin-bottom: 0.5rem;
+ text-align: start;
color: #555;
}
@@ -64,4 +65,25 @@
.login-button:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2);
-}
\ No newline at end of file
+}
+
+.error-container {
+ color: white;
+ background: #f00;
+ font-size: 0.875rem;
+ margin-top: 0.5rem;
+ padding: .8rem;
+ padding-block: .5rem;
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+ align-items: center;
+}
+
+.error-container button {
+ background: none;
+ outline: none;
+ border: none;
+ cursor: pointer;
+ color: white;
+}
\ No newline at end of file
diff --git a/src/components/LoginForm.js b/src/components/LoginForm.js
index 26c8cc3..01400c3 100644
--- a/src/components/LoginForm.js
+++ b/src/components/LoginForm.js
@@ -6,6 +6,19 @@ function LoginForm({ onLogin }) {
name: '',
password: ''
});
+ const [error, setError] = useState(null);
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+
+ if (formData.name.trim() === "" || formData.password.trim() === "") {
+ setError("Name and Password cannot be empty");
+ return;
+ }
+
+
+ onLogin(formData);
+ }
const handleChange = (e) => {
const { name, value } = e.target;
@@ -17,8 +30,14 @@ function LoginForm({ onLogin }) {
return (