Fakultas Ilmu Komputer UI

Commit 9f894ce4 authored by Shafiya Adzhani's avatar Shafiya Adzhani
Browse files

Add PBI 5 and improve others

parent dc7a62df
import '../support/commands'
describe('Submit to Backend PT (Success Case)', () => {
beforeEach(() => {
cy.login()
cy.visit('/form-pt')
cy.get('[data-testid="form-1-nama-field"]').type('PT Justika')
cy.get('[data-testid="form-1-status-pt"]').click()
cy.get('[data-testid="form-1-alamat-field"]').type('Jalan Terbang Layang')
cy.get('[data-testid="form-1-barang-jasa-field"]').type('Layanan hukum')
cy.get('[data-testid="lanjut-button"]').click()
cy.get('[data-testid="form-iumk-2-jumlah-karyawan"]').click()
cy.get('[data-testid="data-employee-1"]').click()
cy.get('[data-testid="form-iumk-2-kbli"]').type('12345')
cy.get('[data-testid="form-iumk-2-catatan"]').type(
'Saya sudah memiliki dokumen A, B',
)
cy.get('[data-testid="lanjut-button"]').click()
cy.intercept(
{
method: 'POST',
url: '**/api/v1/pt/',
},
{
statusCode: 200,
},
).as('postCreatePTSukses')
cy.get('[data-testid="submit-button"]').click()
})
it('should have correct body response', () => {
cy.wait('@postCreatePTSukses').should(({request}) => {
expect(request.body).to.have.property('nama_usaha')
expect(request.body).to.have.property('alamat')
expect(request.body).to.have.property('barang_jasa')
expect(request.body).to.have.property('status_entitas')
expect(request.body).to.have.property('jumlah_karyawan')
expect(request.body).to.have.property('kode_kbli')
expect(request.body).to.have.property('catatan')
})
})
it('should directed to / and show success toast after success register', () => {
cy.wait('@postCreatePTSukses')
cy.url().should('include', '/')
cy.get('[data-testid=toast-homepage]').should('be.visible')
})
})
describe('Submit to Backend PT (Error Case)', () => {
beforeEach(() => {
cy.login()
cy.visit('/form-pt')
cy.get('[data-testid="form-1-nama-field"]').type('PT Justika')
cy.get('[data-testid="form-1-status-pt"]').click()
cy.get('[data-testid="form-1-alamat-field"]').type('Jalan Terbang Layang')
cy.get('[data-testid="form-1-barang-jasa-field"]').type('Layanan hukum')
cy.get('[data-testid="lanjut-button"]').click()
cy.get('[data-testid="form-iumk-2-jumlah-karyawan"]').click()
cy.get('[data-testid="data-employee-1"]').click()
cy.get('[data-testid="form-iumk-2-kbli"]').type('12345')
cy.get('[data-testid="form-iumk-2-catatan"]').type(
'Saya sudah memiliki dokumen A, B',
)
cy.get('[data-testid="lanjut-button"]').click()
cy.intercept(
{
method: 'POST',
url: '**/api/v1/pt/',
},
{
statusCode: 400,
body: {non_field_errors: 'Kode KBLI hanya boleh angka'},
},
).as('postCreatePTError')
cy.get('[data-testid="submit-button"]').click()
})
it('show error toast after error register', () => {
cy.wait('@postCreatePTError')
cy.url().should('include', '/')
cy.get('[data-testid=toast-error]').should('be.visible')
})
})
import '../support/commands'
describe('Submit to Backend IUMK (Success Case)', () => {
beforeEach(() => {
cy.login()
cy.visit('/form-iumk')
cy.get('[data-testid="form-1-nama-field"]').type('PT Justika')
cy.get('[data-testid="form-1-status-pt"]').click()
cy.get('[data-testid="form-1-alamat-field"]').type('Jalan Terbang Layang')
cy.get('[data-testid="form-1-barang-jasa-field"]').type('Layanan hukum')
cy.get('[data-testid="lanjut-button"]').click()
cy.get('[data-testid="form-iumk-2-jumlah-karyawan"]').click()
cy.get('[data-testid="data-employee-1"]').click()
cy.get('[data-testid="form-iumk-2-kbli"]').type('12345')
cy.get('[data-testid="form-iumk-2-catatan"]').type(
'Saya sudah memiliki dokumen A, B',
)
cy.get('[data-testid="lanjut-button"]').click()
cy.intercept(
{
method: 'POST',
url: '**/api/v1/iumk/',
},
{
statusCode: 200,
},
).as('postCreateIumkSukses')
cy.get('[data-testid="submit-button"]').click()
})
it('should have correct body response', () => {
cy.wait('@postCreateIumkSukses').should(({request}) => {
expect(request.body).to.have.property('nama_usaha')
expect(request.body).to.have.property('alamat')
expect(request.body).to.have.property('barang_jasa')
expect(request.body).to.have.property('status_entitas')
expect(request.body).to.have.property('jumlah_karyawan')
expect(request.body).to.have.property('kode_kbli')
expect(request.body).to.have.property('catatan')
})
})
it('should directed to / and show success toast after success register', () => {
cy.wait('@postCreateIumkSukses')
cy.url().should('include', '/')
cy.get('[data-testid=toast-homepage]').should('be.visible')
})
})
describe('Submit to Backend IUMK (Error Case)', () => {
beforeEach(() => {
cy.login()
cy.visit('/form-iumk')
cy.get('[data-testid="form-1-nama-field"]').type('PT Justika')
cy.get('[data-testid="form-1-status-pt"]').click()
cy.get('[data-testid="form-1-alamat-field"]').type('Jalan Terbang Layang')
cy.get('[data-testid="form-1-barang-jasa-field"]').type('Layanan hukum')
cy.get('[data-testid="lanjut-button"]').click()
cy.get('[data-testid="form-iumk-2-jumlah-karyawan"]').click()
cy.get('[data-testid="data-employee-1"]').click()
cy.get('[data-testid="form-iumk-2-kbli"]').type('12345')
cy.get('[data-testid="form-iumk-2-catatan"]').type(
'Saya sudah memiliki dokumen A, B',
)
cy.get('[data-testid="lanjut-button"]').click()
cy.intercept(
{
method: 'POST',
url: '**/api/v1/iumk/',
},
{
statusCode: 400,
body: {non_field_errors: 'Kode KBLI hanya boleh angka'},
},
).as('postCreateIumkError')
cy.get('[data-testid="submit-button"]').click()
})
it('show error toast after error register', () => {
cy.wait('@postCreateIumkError')
cy.url().should('include', '/')
cy.get('[data-testid=toast-error]').should('be.visible')
})
})
function adaptToReduxPersist(mockValue) {
// redux-persist converts total value and top-level properties to //string:
// Es: {a: {foo: 'bar'}} -> {a: JSON.stringify({foo: 'bar'})} -> //JSON.stringify({a: JSON.stringify({foo: 'bar'})});
// so in order for the tests to work properly, we need to simulate //this behavior
const partialConversion = Object.keys(mockValue).reduce((acc, key) => {
acc[key] = JSON.stringify(mockValue[key])
return acc
}, {})
return JSON.stringify(partialConversion)
}
Cypress.Commands.add('login', () => {
window.localStorage.setItem(
'persist:root',
adaptToReduxPersist({
auth: {
token: 'contoh',
email: 'a@gmail.com',
phone_number: '08123456789',
},
}),
)
})
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
"cypress:open": "cypress open", "cypress:open": "cypress open",
"cypress:run": "cypress run", "cypress:run": "cypress run",
"cypress:install": "cypress install", "cypress:install": "cypress install",
"cypress:gitlab": "CYPRESS_BASE_URL=http://172.17.0.3:3000/ DEBUG=cypress:* xvfb-run cypress run --headed --browser chrome", "cypress:gitlab": "CYPRESS_BASE_URL=http://172.17.0.3:3000/ xvfb-run cypress run --headed --browser chrome",
"start:gitlab": "npm start & wait-on http://172.17.0.3:3000/" "start:gitlab": "npm start & wait-on http://172.17.0.3:3000/"
}, },
"eslintConfig": { "eslintConfig": {
......
import Homepage from './pages/homepage' import Homepage from './pages/homepage'
import Register from './components/Registrasi/Register' import Register from './components/Registrasi/Register'
import Login from './components/Autentikasi/Login' import Login from './components/Autentikasi/Login'
import FormPendirianPT from './pages/FormPendirianPT'
import FormIUMK from './pages/formiumk' import FormIUMK from './pages/formiumk'
import {Router} from '@reach/router' import {Router} from '@reach/router'
...@@ -11,6 +12,7 @@ function App() { ...@@ -11,6 +12,7 @@ function App() {
<Homepage path="/" /> <Homepage path="/" />
<Register path="/register" /> <Register path="/register" />
<Login path="/login" /> <Login path="/login" />
<FormPendirianPT path="/form-pt" />
<FormIUMK path="/form-iumk" /> <FormIUMK path="/form-iumk" />
</Router> </Router>
</div> </div>
......
...@@ -31,6 +31,8 @@ const Login = () => { ...@@ -31,6 +31,8 @@ const Login = () => {
useEffect(() => { useEffect(() => {
if (loggedIn) { if (loggedIn) {
navigate('/') navigate('/')
} else {
navigate('/login')
} }
// eslint-disable-next-line // eslint-disable-next-line
}, []) }, [])
...@@ -49,7 +51,7 @@ const Login = () => { ...@@ -49,7 +51,7 @@ const Login = () => {
.catch((error) => { .catch((error) => {
handleError(error.response.data.non_field_errors) handleError(error.response.data.non_field_errors)
}) })
} else if (submitPhase == 2) { } else {
setData({...data, ...input}) setData({...data, ...input})
axios axios
.post(`${BASE_URL.API_BASE_URL}/api/v1/auth/login/`, { .post(`${BASE_URL.API_BASE_URL}/api/v1/auth/login/`, {
...@@ -70,12 +72,8 @@ const Login = () => { ...@@ -70,12 +72,8 @@ const Login = () => {
} }
const handleError = (error) => { const handleError = (error) => {
if(error) { if (error) {
toast.error( toast.error(<span data-testid="toast-error-login">{error}</span>)
<span data-testid="toast-error-login">
{error}
</span>,
)
} }
} }
......
...@@ -5,6 +5,12 @@ import {fireEvent, screen} from '@testing-library/react' ...@@ -5,6 +5,12 @@ import {fireEvent, screen} from '@testing-library/react'
import Login from './Login' import Login from './Login'
import {testRender, makeTestStore} from '../../testUtils' import {testRender, makeTestStore} from '../../testUtils'
import BASE_URL from '../../api/config' import BASE_URL from '../../api/config'
import {navigate} from '@reach/router'
jest.mock('@reach/router', () => ({
navigate: jest.fn(),
Link: 'Link',
}))
const server = setupServer( const server = setupServer(
rest.post( rest.post(
...@@ -19,10 +25,12 @@ beforeEach(() => server.listen()) ...@@ -19,10 +25,12 @@ beforeEach(() => server.listen())
afterEach(() => server.resetHandlers()) afterEach(() => server.resetHandlers())
afterEach(() => server.close()) afterEach(() => server.close())
test('renders login page', () => { test('renders login page if not login', () => {
const store = makeTestStore() const store = makeTestStore()
testRender(<Login />, {store}) testRender(<Login />, {store})
expect(navigate).toHaveBeenCalledTimes(1)
expect(navigate).toHaveBeenCalledWith('/login')
expect(screen.getByTestId('daftar-url-link')).toBeInTheDocument() expect(screen.getByTestId('daftar-url-link')).toBeInTheDocument()
}) })
......
import '@testing-library/jest-dom'
import Login from './Login'
import {testRender, makeTestStore, fixtureSet} from '../../testUtils'
import {navigate} from '@reach/router'
import {screen} from '@testing-library/react'
import {login} from '../../store/auth/authSlice'
jest.mock('@reach/router', () => ({
navigate: jest.fn(),
Link: 'Link',
}))
test('redirects to homepage if already login', () => {
const store = makeTestStore()
store.dispatch(login(fixtureSet))
testRender(<Login />, {store})
expect(navigate).toHaveBeenCalledTimes(1)
expect(navigate).toHaveBeenCalledWith('/')
expect(screen.getByTestId('daftar-url-link')).toBeInTheDocument()
})
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {Link} from '@reach/router'
const Card = ({index, image, title, text, url}) => { const Card = ({index, image, title, text, url}) => {
return ( return (
...@@ -19,11 +20,11 @@ const Card = ({index, image, title, text, url}) => { ...@@ -19,11 +20,11 @@ const Card = ({index, image, title, text, url}) => {
</div> </div>
<div> <div>
<p className="medium-text mb-3.5">{text}</p> <p className="medium-text mb-3.5">{text}</p>
<a href={url} data-testid={`card-url-link-${index}`}> <Link to={url} data-testid={`card-url-link-${index}`}>
<button className="text-lg text-white bg-popblue font-Lato py-2 w-full rounded-lg"> <button className="text-lg text-white bg-popblue font-Lato py-2 w-full rounded-lg">
Mulai Mulai
</button> </button>
</a> </Link>
</div> </div>
</div> </div>
) )
......
...@@ -40,6 +40,7 @@ const EmployeeDropdown = ({setEmployeeData, defaultValue, dataTestId}) => { ...@@ -40,6 +40,7 @@ const EmployeeDropdown = ({setEmployeeData, defaultValue, dataTestId}) => {
className="py-2.5 px-6 border-grey border-b-2 cursor-pointer" className="py-2.5 px-6 border-grey border-b-2 cursor-pointer"
onClick={() => selectValue(value)} onClick={() => selectValue(value)}
key={index} key={index}
data-testid={`data-employee-${index}`}
> >
<p className="heading-3">{value}</p> <p className="heading-3">{value}</p>
</div> </div>
......
import React from 'react'
import PropTypes from 'prop-types'
import {Link} from '@reach/router'
const ServiceDropdown = ({className, dataTest}) => {
return (
<ul
data-testid={dataTest}
className={`heading-3 w-40 text-left absolute border bg-white border-gray-200 rounded-md mt-4 ${className} -right-20 top-2`}
>
<li>
<Link to="/">
<p className="p-3 w-full h-full block" data-testid="konsultasi">
Konsultasi
</p>
</Link>
</li>
<li>
<Link to="/form-iumk">
<p
className="p-3 w-full h-full block"
data-testid="dropdown-izin-umk"
>
Izin UMK
</p>
</Link>
</li>
<li>
<Link to="/form-pt">
<p
className="p-3 w-full h-full block"
data-testid="dropdown-pendirian-pt"
>
Pendirian PT
</p>
</Link>
</li>
</ul>
)
}
ServiceDropdown.propTypes = {
className: PropTypes.string,
dataTest: PropTypes.string,
state: PropTypes.bool,
}
export default ServiceDropdown
import {screen, render} from '@testing-library/react'
import ServiceDropdown from './ServiceDropdown'
test('renders Service Dropdown Dropdown', () => {
render(<ServiceDropdown dataTest={'service-dropdown'} />)
expect(screen.getByTestId('service-dropdown')).toBeInTheDocument()
})
import React from 'react' import React from 'react'
import Logo from '../../assets/logo-footer.png' import Logo from '../../assets/logo-footer.png'
import {Link} from '@reach/router'
const Footer = () => { const Footer = () => {
return ( return (
...@@ -27,16 +28,16 @@ const Footer = () => { ...@@ -27,16 +28,16 @@ const Footer = () => {
Konsultasi Hukum dengan Pengacara Konsultasi Hukum dengan Pengacara
</p> </p>
</a> </a>
<a href="#"> <Link to="/form-iumk">
<p className="medium-text hover:underline"> <p className="medium-text hover:underline">
Izin Usaha Mikro Kecil Paling Mudah Izin Usaha Mikro Kecil Paling Mudah
</p> </p>
</a> </Link>
<a href="#"> <Link to="/form-pt">
<p className="medium-text hover:underline"> <p className="medium-text hover:underline">
Pendirian Perizinan PT Pendirian Perizinan PT
</p> </p>
</a> </Link>
</div> </div>
<div> <div>
<h1 className="heading-3 mb-4">Support</h1> <h1 className="heading-3 mb-4">Support</h1>
......
...@@ -73,6 +73,7 @@ const FormIUMK2 = ({ ...@@ -73,6 +73,7 @@ const FormIUMK2 = ({
}, },
})} })}
defaultValue={data.kbli} defaultValue={data.kbli}
data-testid="form-iumk-2-kbli"
/> />
<div> <div>
{errors.kbli && ( {errors.kbli && (
...@@ -83,7 +84,7 @@ const FormIUMK2 = ({ ...@@ -83,7 +84,7 @@ const FormIUMK2 = ({
</div> </div>
<br></br> <br></br>
</div> </div>
<div className="flex flex-col pb-8" data-testid="form-iumk-2-catatan"> <div className="flex flex-col pb-8">
<label className="mb-2 heading-3 text-black"> <label className="mb-2 heading-3 text-black">
Catatan{' '} Catatan{' '}
<span className="medium-text text-black ml-1">(opsional)</span> <span className="medium-text text-black ml-1">(opsional)</span>
...@@ -96,6 +97,7 @@ const FormIUMK2 = ({ ...@@ -96,6 +97,7 @@ const FormIUMK2 = ({
required: false, required: false,
})} })}
defaultValue={data.catatan} defaultValue={data.catatan}
data-testid="form-iumk-2-catatan"
/> />
</div> </div>
</div> </div>
......
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {getEmail, getPhoneNumber} from '../../store/auth/authSlice'
import {useSelector} from 'react-redux'
const FormIUMK3 = ({data, onSubmit, handleSubmit}) => { const FormIUMK3 = ({data, onSubmit, handleSubmit, konstan}) => {
const email = useSelector(getEmail)
const phoneNumber = useSelector(getPhoneNumber)
const urutan = [ const urutan = [
'nama', 'nama',
'email', 'email',
...@@ -34,13 +30,6 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => { ...@@ -34,13 +30,6 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => {
'Harga', 'Harga',
'Catatan', 'Catatan',
] ]
const konstan = {
paket: 'Izin UMK',
waktu: '19 Hari',
harga: 'Rp8,500,000',
email: email,
no_telepon: phoneNumber,
}
data = {...data, ...konstan} data = {...data, ...konstan}
...@@ -104,6 +93,7 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => { ...@@ -104,6 +93,7 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => {
FormIUMK3.propTypes = { FormIUMK3.propTypes = {
data: PropTypes.object, data: PropTypes.object,