From 25b41aed0c8998542e74e051c9a19d711124ea3e Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:33:20 -0300 Subject: [PATCH 01/20] chore: add script ci-pipeline --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5577602..080e477 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "cy:run-e2e": "server-test 3000 'cypress run --e2e --browser chrome'", "cy:open-ct": "cypress open --component --browser chrome", "cy:run-ct": "cypress run --component --browser chrome", - "cy:run-ct-fast": "yarn cy:run-ct --config video=false screenshot=false" + "cy:run-ct-fast": "yarn cy:run-ct --config video=false screenshot=false", + "ci-pipeline": "yarn validate:ci && yarn test && yarn cy:run-ct-fast && yarn cy:run-e2e" }, "dependencies": { "@hookform/resolvers": "^3.3.1", From 241dc3abef37532d948ca29f96e19d28ef64d4bd Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:34:14 -0300 Subject: [PATCH 02/20] style: add space in curly bracket --- cypress/.eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/.eslintrc.js b/cypress/.eslintrc.js index ed1fec2..5a18f74 100644 --- a/cypress/.eslintrc.js +++ b/cypress/.eslintrc.js @@ -9,5 +9,5 @@ module.exports = { 'cypress/no-pause': 'error', '@typescript-eslint/no-var-requires': 'off', }, - env: {'cypress/globals': true}, + env: { 'cypress/globals': true }, }; From 2bcd39029a119bc37c9ea5b2ddfe456ddfbdd191 Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:34:47 -0300 Subject: [PATCH 03/20] feat: add user provider --- src/App.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 4b40953..185a097 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,13 +3,16 @@ import GlobalStyle from '@styles/global'; import Router from '@routes/Router'; import FiltersProvider from '@contexts/filters'; +import UserProvider from '@contexts/user'; export default function App() { return (
- + + +
); From 02b4079304b959b92528599f0460c043c7bd0876 Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:35:42 -0300 Subject: [PATCH 04/20] feat: add class name to auth sub header --- src/components/AuthSubHeader/AuthSubHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AuthSubHeader/AuthSubHeader.tsx b/src/components/AuthSubHeader/AuthSubHeader.tsx index 2260709..d14640f 100644 --- a/src/components/AuthSubHeader/AuthSubHeader.tsx +++ b/src/components/AuthSubHeader/AuthSubHeader.tsx @@ -15,7 +15,7 @@ const AuthSubHeader = ({ authLabel }: AuthSubHeaderProps) => { ); return ( - + Date: Mon, 9 Oct 2023 00:36:16 -0300 Subject: [PATCH 05/20] feat: login form component api --- src/components/LoginForm/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/components/LoginForm/index.ts diff --git a/src/components/LoginForm/index.ts b/src/components/LoginForm/index.ts new file mode 100644 index 0000000..1195444 --- /dev/null +++ b/src/components/LoginForm/index.ts @@ -0,0 +1 @@ +export { default } from './LoginForm'; From 299768d711015912db8ef04109937f2a19146719 Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:37:27 -0300 Subject: [PATCH 06/20] test: login form component with cypress --- src/components/LoginForm/LoginForm.cy.tsx | 53 +++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/components/LoginForm/LoginForm.cy.tsx diff --git a/src/components/LoginForm/LoginForm.cy.tsx b/src/components/LoginForm/LoginForm.cy.tsx new file mode 100644 index 0000000..5453b42 --- /dev/null +++ b/src/components/LoginForm/LoginForm.cy.tsx @@ -0,0 +1,53 @@ +import LoginForm from './LoginForm'; + +import Sut from '@utils/helpers'; + +describe('', () => { + beforeEach(() => { + cy.mount( + + + , + ); + }); + + it('should be defined', () => { + cy.getByCy('login-form-container'); + }); + + it('should render text "Faça seu login"', () => { + cy.getByCy('login-form-container').contains('Faça seu login'); + }); + + it('should render label "Seu e-mail"', () => { + cy.getByCy('login-form-container').contains('Seu e-mail'); + }); + + it('should render input email', () => { + cy.getByCy('email-input'); + }); + + it('should render label "Senha"', () => { + cy.getByCy('login-form-container').contains('Senha'); + }); + + it('should render input password', () => { + cy.getByCy('password-input'); + }); + + it('should render eye icon', () => { + cy.getByCy('eye-icon').should('have.length', 1); + }); + + it('should render button "Entrar"', () => { + cy.getByCy('login-form-container').contains('Entrar'); + }); + + it('should render text "Não é cadastrado?"', () => { + cy.getByCy('login-form-container').contains('Não é cadastrado?'); + }); + + it('should render link "Cadastre-se gratuitamente"', () => { + cy.getByCy('login-form-container').contains('Cadastre-se gratuitamente'); + }); +}); From 20ecc007b05c9fa4f7d27c9ce37b31ea473ceefe Mon Sep 17 00:00:00 2001 From: cesarhenrq Date: Mon, 9 Oct 2023 00:38:00 -0300 Subject: [PATCH 07/20] feat: login form component --- src/components/LoginForm/LoginForm.tsx | 159 +++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/components/LoginForm/LoginForm.tsx diff --git a/src/components/LoginForm/LoginForm.tsx b/src/components/LoginForm/LoginForm.tsx new file mode 100644 index 0000000..0a4c685 --- /dev/null +++ b/src/components/LoginForm/LoginForm.tsx @@ -0,0 +1,159 @@ +import { useState, useContext } from 'react'; + +import { Link, useNavigate } from 'react-router-dom'; + +import { useForm, DefaultValues } from 'react-hook-form'; + +import { yupResolver } from '@hookform/resolvers/yup'; +import { schema, LoginFormValues } from './schema'; + +import { AxiosError } from 'axios'; + +import Text from '@components/Text'; +import Button from '@components/Button'; + +import useResource from '@hooks/useResource'; + +import { userContext, actions } from '@contexts/user'; + +import * as S from './styles'; + +import eye from '@assets/eye-line.png'; + +type Response = { + token: string; + data: { + name: string; + email: string; + isActive: boolean; + }; +}; + +const defaultValues: DefaultValues = { + email: '', + password: '', +}; + +const LoginForm = () => { + const [showPassword, setShowPassword] = useState(false); + const [notification, setNotification] = useState(''); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(false); + + const { userDispatch } = useContext(userContext); + + const navigate = useNavigate(); + + const [, userService] = useResource('login'); + + const { + handleSubmit, + register, + formState: { errors }, + } = useForm({ + defaultValues, + resolver: yupResolver(schema), + mode: 'onBlur', + }); + + const onSubmit = async (data: LoginFormValues) => { + setLoading(true); + + try { + const response = (await userService.post(data)) as Response; + + userDispatch( + actions.setUser({ token: response.token, ...response.data }), + ); + + setError(false); + setNotification('Login realizado com sucesso!'); + setTimeout(() => { + setNotification(''); + navigate('/'); + }, 1000); + console.log(response); + } catch (error) { + if (error instanceof AxiosError) { + setError(true); + setNotification(error.response?.data.message); + + setTimeout(() => { + setNotification(''); + }, 3000); + } + } + + setLoading(false); + }; + + const handleError = (name: keyof Partial) => { + return ( + errors?.[name] && ( + {errors[name]?.message} + ) + ); + }; + + return ( + +
+ +
+ +
+ +
+ + {handleError('email')} +
+ + +
+ + {handleError('password')} + eye setShowPassword(!showPassword)} + data-cy="eye-icon" + /> +
+ + {notification && ( + + {notification} + + )} + +