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 }, }; 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", 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 (
- + + +
); 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 ( - + ', () => { + 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'); + }); +}); 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} + + )} + +