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 @@
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"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/"
},
"eslintConfig": {
......
import Homepage from './pages/homepage'
import Register from './components/Registrasi/Register'
import Login from './components/Autentikasi/Login'
import FormPendirianPT from './pages/FormPendirianPT'
import FormIUMK from './pages/formiumk'
import {Router} from '@reach/router'
......@@ -11,6 +12,7 @@ function App() {
<Homepage path="/" />
<Register path="/register" />
<Login path="/login" />
<FormPendirianPT path="/form-pt" />
<FormIUMK path="/form-iumk" />
</Router>
</div>
......
......@@ -31,8 +31,10 @@ const Login = () => {
useEffect(() => {
if (loggedIn) {
navigate('/')
} else {
navigate('/login')
}
// eslint-disable-next-line
// eslint-disable-next-line
}, [])
const onSubmit = (input) => {
......@@ -49,7 +51,7 @@ const Login = () => {
.catch((error) => {
handleError(error.response.data.non_field_errors)
})
} else if (submitPhase == 2) {
} else {
setData({...data, ...input})
axios
.post(`${BASE_URL.API_BASE_URL}/api/v1/auth/login/`, {
......@@ -70,12 +72,8 @@ const Login = () => {
}
const handleError = (error) => {
if(error) {
toast.error(
<span data-testid="toast-error-login">
{error}
</span>,
)
if (error) {
toast.error(<span data-testid="toast-error-login">{error}</span>)
}
}
......
......@@ -5,6 +5,12 @@ import {fireEvent, screen} from '@testing-library/react'
import Login from './Login'
import {testRender, makeTestStore} from '../../testUtils'
import BASE_URL from '../../api/config'
import {navigate} from '@reach/router'
jest.mock('@reach/router', () => ({
navigate: jest.fn(),
Link: 'Link',
}))
const server = setupServer(
rest.post(
......@@ -19,10 +25,12 @@ beforeEach(() => server.listen())
afterEach(() => server.resetHandlers())
afterEach(() => server.close())
test('renders login page', () => {
test('renders login page if not login', () => {
const store = makeTestStore()
testRender(<Login />, {store})
expect(navigate).toHaveBeenCalledTimes(1)
expect(navigate).toHaveBeenCalledWith('/login')
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 PropTypes from 'prop-types'
import {Link} from '@reach/router'
const Card = ({index, image, title, text, url}) => {
return (
......@@ -19,11 +20,11 @@ const Card = ({index, image, title, text, url}) => {
</div>
<div>
<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">
Mulai
</button>
</a>
</Link>
</div>
</div>
)
......
......@@ -40,6 +40,7 @@ const EmployeeDropdown = ({setEmployeeData, defaultValue, dataTestId}) => {
className="py-2.5 px-6 border-grey border-b-2 cursor-pointer"
onClick={() => selectValue(value)}
key={index}
data-testid={`data-employee-${index}`}
>
<p className="heading-3">{value}</p>
</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 Logo from '../../assets/logo-footer.png'
import {Link} from '@reach/router'
const Footer = () => {
return (
......@@ -27,16 +28,16 @@ const Footer = () => {
Konsultasi Hukum dengan Pengacara
</p>
</a>
<a href="#">
<Link to="/form-iumk">
<p className="medium-text hover:underline">
Izin Usaha Mikro Kecil Paling Mudah
</p>
</a>
<a href="#">
</Link>
<Link to="/form-pt">
<p className="medium-text hover:underline">
Pendirian Perizinan PT
</p>
</a>
</Link>
</div>
<div>
<h1 className="heading-3 mb-4">Support</h1>
......
......@@ -73,6 +73,7 @@ const FormIUMK2 = ({
},
})}
defaultValue={data.kbli}
data-testid="form-iumk-2-kbli"
/>
<div>
{errors.kbli && (
......@@ -83,7 +84,7 @@ const FormIUMK2 = ({
</div>
<br></br>
</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">
Catatan{' '}
<span className="medium-text text-black ml-1">(opsional)</span>
......@@ -96,6 +97,7 @@ const FormIUMK2 = ({
required: false,
})}
defaultValue={data.catatan}
data-testid="form-iumk-2-catatan"
/>
</div>
</div>
......
import React from 'react'
import PropTypes from 'prop-types'
import {getEmail, getPhoneNumber} from '../../store/auth/authSlice'
import {useSelector} from 'react-redux'
const FormIUMK3 = ({data, onSubmit, handleSubmit}) => {
const email = useSelector(getEmail)
const phoneNumber = useSelector(getPhoneNumber)
const FormIUMK3 = ({data, onSubmit, handleSubmit, konstan}) => {
const urutan = [
'nama',
'email',
......@@ -34,13 +30,6 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => {
'Harga',
'Catatan',
]
const konstan = {
paket: 'Izin UMK',
waktu: '19 Hari',
harga: 'Rp8,500,000',
email: email,
no_telepon: phoneNumber,
}
data = {...data, ...konstan}
......@@ -104,6 +93,7 @@ const FormIUMK3 = ({data, onSubmit, handleSubmit}) => {
FormIUMK3.propTypes = {
data: PropTypes.object,
konstan: PropTypes.object,
handleSubmit: PropTypes.func,
onSubmit: PropTypes.func,
}
......
......@@ -15,9 +15,18 @@ test('renders FormIUMK3 Element', () => {
kbli: '',
catatan: null,
}
const konstan = {
paket: 'Izin UMK',
waktu: '19 Hari',
harga: 'Rp8,500,000',
email: 'sigendud@gmail.com',
no_telepon: '8123456789',
}
const store = makeTestStore()
testRender(
<FormIUMK3 data={data} handleSubmit={handleSubmit} onSubmit={onSubmit} />,
<FormIUMK3 data={data} konstan={konstan} handleSubmit={handleSubmit} onSubmit={onSubmit} />,
{store},
)
expect(screen.getByTestId('form-iumk-3')).toBeInTheDocument()
......@@ -66,9 +75,17 @@ test('renders FormIUMK3 Element with catatan', () => {
kbli: '',
catatan: 'Contoh catatan',
}
const konstan = {
paket: 'Izin UMK',
waktu: '19 Hari',
harga: 'Rp8,500,000',
email: 'sigendud@gmail.com',
no_telepon: '8123456789',
}
const store = makeTestStore()
testRender(
<FormIUMK3 data={data} handleSubmit={handleSubmit} onSubmit={onSubmit} />,
<FormIUMK3 data={data} konstan={konstan} handleSubmit={handleSubmit} onSubmit={onSubmit} />,
{store},
)
expect(screen.getByTestId('form-iumk-3')).toBeInTheDocument()
......
import React from 'react'
const FormPendirianPT1 = () => {
return (
<form className="px-4" data-testid="form-pt-1">
<div className="flex flex-col justify-center items-center">
<h1 className="heading-2 mb-4" data-testid="form-pt-1-judul">
Jelaskan Industri Anda
</h1>
<p className="reguler-text" data-testid="form-pt-1-deskripsi">
Mengetahui Industri Anda membantu partner kami memahami tipe <br></br>
dokumen yang dibutuhkan dan lisensi apa yang perlu didapatkan usaha
Anda.
</p>
</div>
<div className="flex flex-col py-3" data-testid="form-pt-1-nama">
<label className="heading-3 mb-2">
Nama atau Calon Nama Usaha<span className="text-popred">*</span>
</label>
<input
className="px-2 py-2.5 w-full border-2 border-gray-200 rounded"
type="text"
id="nama"
required
name="nama"
placeholder="e.g PT ABC"
/>
</div>
<div className="flex flex-col py-3" data-testid="form-pt-1-status">
<label className="heading-3 mb-2">
Status Entitas<span className="text-popred">*</span>
</label>
<div className="flex flex-row justify-between">
<label className="heading-3 text-charchoal">
<input className="mr-2" type="radio" value="PT" />
PT
</label>
<label className="heading-3 text-charchoal">
<input className="mr-2" type="radio" value="CV" />
CV
</label>