Skip to content

Commit

Permalink
Feat: Allow user to Login issue#14
Browse files Browse the repository at this point in the history
  • Loading branch information
mtreacy002 committed Jun 25, 2020
1 parent 82c4093 commit 128e9ae
Show file tree
Hide file tree
Showing 11 changed files with 957 additions and 713 deletions.
1,090 changes: 674 additions & 416 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"msw": "^0.19.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
Expand Down Expand Up @@ -34,7 +35,6 @@
]
},
"devDependencies": {
"react-bootstrap": "^1.0.1",
"react-test-renderer": "^16.13.1"
"react-bootstrap": "^1.0.1"
}
}
7 changes: 0 additions & 7 deletions src/Login.jsx

This file was deleted.

5 changes: 4 additions & 1 deletion src/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "./Home";
import Register from "./register/Register";
import Login from "./Login";
import Login from "./login/Login";
import MySpace from "./myspace/MySpace";
import { Navbar, Nav } from "react-bootstrap";


Expand All @@ -24,6 +25,7 @@ export default (
<Nav.Link href="/programs">Programs</Nav.Link>
<Nav.Link href="/organizations">Organizations</Nav.Link>
<Nav.Link href="/members">Members</Nav.Link>
<Nav.Link href="/my-space">My Space</Nav.Link>
<Nav.Link href="/register">Register</Nav.Link>
<Nav.Link href="/login">Login</Nav.Link>
</Nav>
Expand All @@ -33,6 +35,7 @@ export default (
<Route exact path="/" component={Home} />
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Route path="/my-space" component={MySpace} />
</Switch>
</div>
</BrowserRouter>
Expand Down
48 changes: 48 additions & 0 deletions src/login/Login.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.container {
background: #f7f9fa;
height: auto;
width: 70%;
margin: 5em auto;
-webkit-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.4);
box-shadow: 5px 5px 5px 0px rgba(0, 0, 0, 0.4);
}

label {
color: #24b9b6;
font-size: 1.2em;
font-weight: 400;
}

h1 {
color: #24b9b6;
padding-top: 0.5em;
}

.error {
color: red;
}
.error-message {
color: #ff6565;
padding: 0.5em 0.2em;
height: 1em;
position: absolute;
font-size: 0.8em;
}

.field {
border: 1px solid #1c6ea4;
width: 100%;
height: 2em;
}

.button-group {
width: 100%;
}

.login-form {
width: 80%;
text-align: left;
padding-top: 2em;
padding-bottom: 2em;
}
122 changes: 122 additions & 0 deletions src/login/Login.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React, { useState } from "react";
import "./Login.css";
import { Redirect } from "react-router-dom";
import "../myspace/MySpace";


export default function Login() {
const [errorMessage, setResponseMessage] = useState(null);
const [accessToken, setAccessToken] = useState(null);
const [accessExpiry, setAccessExpiry] = useState(null);
const [isAuthenticated, setIsAuthenticated] = useState(false);


const handleSubmit = async e => {
e.preventDefault();
let payload = {}

new FormData(e.target).forEach((value, key) => {
payload[key] = value;

});

const requestLogin = {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(payload)

};
let data = "";
let resStatus = 0;
fetch("http://127.0.0.1:5000/login", requestLogin)
.then(async response => {
resStatus = response.status
data = await response.json();
})
.then(res => {
switch (resStatus) {
case 200:
setAccessToken(data["access_token"]);
setAccessExpiry(data["access_expiry"]);
setIsAuthenticated(true);
break
default:
setResponseMessage(data["message"]);
break
}
})
.catch(error => {
setResponseMessage(data["message"]);
});
}

if (isAuthenticated === true) {
return <Redirect to="/my-space" />
}

return (
<div className="container">
<div className="row mb-5">
<div className="col-lg-12 text-center">
<h1 className="mt-5">Login</h1>
</div>
</div>
<div className="row">
<div className="col-lg-12">
<form className="login-form mx-auto" onSubmit={handleSubmit}>
<form-group controlId="formUserame">
<p className="input-control">
<label htmlFor="username">Username or Email:</label>
<input className="field"
type="text"
name="username"
placeholder="Username or Email"
required
/>
</p>
</form-group>
<div><br></br></div>
<form-group controlId="formPassword">
<p className="input-control">
<label htmlFor="password">Password :</label>
<input className="field"
type="password"
name="password"
placeholder="Password"
required
/>
</p>
</form-group>
<div><br></br></div>
<div>
{errorMessage !== null && <span className="error" name="errorMessage" aria-label="errorMessage" role="alert">{errorMessage}</span>}
</div>
<div className="row">
<label>Not yet register? Sign Up here.</label>
</div>
<div className="row button-group">
<div className="col-sm">
<div className="row">
<a className="btn btn-primary" id="registerbtn" href="/register" role="button">Sign Up</a>
</div>
</div>
<div className="col-sm"></div>
<div className="col-sm">
<button className="btn btn-success"
variant="success"
type="submit"
name="submit"
value="Login"
>Login
</button>
</div>
</div>
</form>
</div>
</div>
</div>
);
}
23 changes: 23 additions & 0 deletions src/myspace/MySpace.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

export default function MySpace() {
return (
<div className="container-fluid" id="myspace">
<div className="top">
<h1>
This will be the Member Portfolio page
</h1>
</div>
<div className="middle">
<h2>The site is currently under construction...</h2>
</div>
<div className="bottom">
<h3>
Thank you for your patience and understanding.
</h3>
</div>
</div>
)
}


9 changes: 6 additions & 3 deletions src/register/Register.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ export default function Register() {
.then(async response => {

data = await response.json();
setResponseMessage(data.slice(12, -1));
setResponseMessage(data["message"]);

})
.catch(error => {
setResponseMessage(data.slice(12, -1));
setResponseMessage(data["message"]);
});

}
Expand Down Expand Up @@ -189,6 +189,7 @@ export default function Register() {
<div className="col-sm">
<input
name="available_to_mentor"
aria-label="mentor"
type={type}
value={"on" ? true : false}
onChange={e => setAvailableToMentor(e.target.value)}
Expand All @@ -198,6 +199,7 @@ export default function Register() {
<div className="col-sm">
<input
name="need_mentoring"
aria-label="mentee"
type={type}
value={"on" ? true : false}
onChange={e => setNeedMentoring(e.target.value)}
Expand All @@ -218,6 +220,7 @@ export default function Register() {
<input
type="checkbox"
name="terms_and_conditions_checked"
aria-label="termsCheck"
value={"on" ? true : false}
onChange={e => setTermsAndConditionsChecked(e.target.value)}
required
Expand All @@ -235,7 +238,7 @@ export default function Register() {
</div>
</form-group>
<div>
{responseMessage !== null && <span className="error">{responseMessage}</span>}
{responseMessage !== null && <span className="error" name="response" aria-label="response" role="alert">{responseMessage}</span>}
</div>
<div className="row">
<label>Already register? Login here.</label>
Expand Down
78 changes: 78 additions & 0 deletions src/tests/Login.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { render, fireEvent, screen, waitForElement } from '@testing-library/react';
import '@testing-library/jest-dom';
import Login from "../login/Login";
import { act } from 'react-dom/test-utils';


const server = setupServer(
rest.post('http://127.0.0.1:5000/login', (req, res, ctx) => {
const payload = {
username: "MyUsername",
password: "12345678",
};
expect(req.body).toEqual(payload)
return res(ctx.json({
access_token: "fake_access_token",
access_expiry: 1594771200
}))
})
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())



it('allows the user to login successfully', async () => {
render(<Login />)

fireEvent.change(screen.getByPlaceholderText('Username or Email'), {
target: { value: 'MyUsername' },
})
fireEvent.change(screen.getByPlaceholderText('Password'), {
target: { value: '12345678' },
})
expect(screen.queryByLabelText("errorMessage")).not.toBeInTheDocument();

act(() => {
fireEvent.click(screen.getByRole('button', { name: "Login" }), {
target: { value: 'true' },
})
});
expect(screen.queryByLabelText("errorMessage")).not.toBeInTheDocument();
})

it('handles wrong credentials', async () => {
server.use(
rest.post('http://127.0.0.1:5000/login', (req, res, ctx) => {
const wrongPayload = {
username: "MyUsername",
password: "87654321",
};
expect(req.body).toEqual(wrongPayload)
return res(ctx.status(401), ctx.json({message: 'Username or password is wrong.'}))
}),
)

render(<Login />)

fireEvent.change(screen.getByPlaceholderText('Username or Email'), {
target: { value: 'MyUsername' },
})
fireEvent.change(screen.getByPlaceholderText('Password'), {
target: { value: '87654321' },
})
expect(screen.queryByLabelText("errorMessage")).not.toBeInTheDocument();

fireEvent.click(screen.getByRole('button', { name: "Login" }), {
target: { value: 'true' },
})

await waitForElement(() => screen.getByLabelText('errorMessage'))

expect(screen.getByLabelText('errorMessage')).toHaveTextContent("Username or password is wrong.")
})
11 changes: 0 additions & 11 deletions src/tests/Register.test.js

This file was deleted.

Loading

0 comments on commit 128e9ae

Please sign in to comment.