Fakultas Ilmu Komputer UI

Commit 5e754c97 authored by Michael Wiryadinata Halim's avatar Michael Wiryadinata Halim Committed by WILLIAM GATES
Browse files

Complete the Main Application Functionalities

parent 5847bbf3
{
"presets": ["@babel/preset-react", "@babel/preset-env"]
"presets": ["@babel/preset-react", "@babel/preset-env",
[
"@emotion/babel-preset-css-prop",
{
"sourceMap": false
}
]
],
"plugins": [
[
"transform-inline-environment-variables"
],
[
"emotion"
]
]
}
......@@ -10,10 +10,13 @@
"rules": {
"react/prop-types": 0,
"react-hooks/rules-of-hooks": "error",
"no-console": "warn"
"no-console": "warn",
"emotion/no-vanilla": "error",
"emotion/import-from-emotion": "error",
"emotion/styled-import": "error"
},
"parser": "babel-eslint",
"plugins": ["react", "import", "jsx-a11y", "react-hooks"],
"plugins": ["react", "import", "jsx-a11y", "react-hooks", "emotion"],
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module",
......
......@@ -6,6 +6,7 @@
.pnp.js
/.cache
/dist
.env
# testing
/coverage
......@@ -25,4 +26,5 @@ test-report.xml
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
\ No newline at end of file
package-lock.json
/.vscode
......@@ -39,10 +39,11 @@ staging:
variables:
NETLIFY_AUTH_TOKEN: $STAGING_NETLIFY_AUTH_TOKEN
NETLIFY_SITE_ID: $STAGING_NETLIFY_SITE_ID
REACT_APP_BASE_URL: $STAGING_REACT_APP_BASE_URL
script:
- npm install
- CI=false npm run build
- npm install netlify-cli -g
- npm install netlify-cli -g --unsafe-perm
- netlify deploy --dir dist --prod
only:
- staging
......@@ -54,6 +55,7 @@ production:
AWS_ACCESS_KEY_ID: $PRODUCTION_AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $PRODUCTION_AWS_SECRET_ACCESS_KEY
AWS_STORAGE_BUCKET_NAME: $PRODUCTION_AWS_STORAGE_BUCKET_NAME
REACT_APP_BASE_URL: $PRODUCTION_REACT_APP_BASE_URL
script:
- npm install
- CI=false npm run build
......
......@@ -2,3 +2,38 @@
[![pipeline status](https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2020/ppl-c/diskominfo-depok-tpu-online/post-rpl-web/badges/master/pipeline.svg)](https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2020/ppl-c/diskominfo-depok-tpu-online/post-rpl-web/commits/master)
[![coverage report](https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2020/ppl-c/diskominfo-depok-tpu-online/post-rpl-web/badges/master/coverage.svg)](https://gitlab.cs.ui.ac.id/ppl-fasilkom-ui/2020/ppl-c/diskominfo-depok-tpu-online/post-rpl-web/commits/master)
A local e-commerce application created for ease of buying and selling transactions.
## Table of Contents
- [Install](#install)
- [Running Development Mode](#running-development-mode)
- [References](#references)
## Install
The Admin Website's frontend uses Node.js and is developed using React. You need to install the required dependencies prior to building and contributing to the project.
- [Node.js](https://nodejs.org/en/download/releases/) and npm package manager
Verify that Node.js has been successfully installed. Make sure the interpreter can be invoked from the shell. For example:
```
npm --version
```
Now install the packages required for Node.js:
```
npm install
```
## Running Development Mode
To serve the frontend:
```
npm run start
```
You can see the app running by going to localhost:1234 via your favourite web browser.
## References
- https://docs.gitlab.com/ee/user/markdown.html#wiki---direct-page-link
- https://nodejs.org/en/download/package-manager/
/* /index.html 200
......@@ -3,14 +3,28 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reach/router": "^1.3.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "3.3.1"
"@emotion/babel-preset-css-prop": "^10.0.27",
"@emotion/core": "^10.0.28",
"@emotion/styled": "^10.0.27",
"@material-ui/core": "^4.9.11",
"@material-ui/icons": "^4.9.1",
"@reach/router": "^1.3.3",
"bootstrap": "^4.4.1",
"jquery": "^3.5.0",
"moment": "^2.24.0",
"moment-timezone": "^0.5.28",
"popper.js": "^1.16.1",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1",
"react-hook-form": "^5.6.0",
"react-moment": "^0.9.7",
"react-number-format": "^4.4.1",
"react-promise-tracker": "^2.1.0"
},
"scripts": {
"start": "parcel public/index.html",
"build": "parcel build public/index.html",
"build": "parcel build public/index.html --experimental-scope-hoisting",
"test": "jest",
"test:coverage": "jest --coverage",
"lint": "eslint \"src/**/*.{js,jsx}\" --quiet",
......@@ -21,9 +35,9 @@
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
"last 3 chrome version",
"last 3 firefox version",
"last 3 safari version"
],
"development": [
"last 1 chrome version",
......@@ -32,24 +46,40 @@
]
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@babel/preset-react": "^7.8.3",
"@testing-library/react": "^9.4.0",
"@types/jest": "^25.1.2",
"babel-eslint": "^10.0.3",
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"@testing-library/dom": "^7.2.2",
"@testing-library/react": "^10.0.3",
"@types/jest": "^25.2.1",
"babel-eslint": "^10.1.0",
"babel-plugin-emotion": "^10.0.33",
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-emotion": "^10.0.27",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3",
"eslint-plugin-react-hooks": "^2.3.0",
"jest": "^25.1.0",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^2.5.1",
"jest": "^25.4.0",
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",
"jest-fetch-mock": "^3.0.3",
"jest-sonar-reporter": "^2.0.0",
"mutationobserver-shim": "^0.3.5",
"parcel-bundler": "^1.12.4",
"prettier": "^1.19.1"
"prettier": "^2.0.5",
"regenerator-runtime": "^0.13.5"
},
"jest": {
"setupFilesAfterEnv": [
"jest-enzyme",
"<rootDir>/src/__test__/setup-jest.js"
],
"testEnvironment": "enzyme",
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
......
......@@ -3,18 +3,13 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
......@@ -26,7 +21,7 @@
-->
<title>React App</title>
</head>
<body>
<body style="background-color: #F5F8F9">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
......
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
......@@ -5,3 +5,5 @@ sonar.testExecutionReportPaths=test-report.xml
sonar.scm.provider=git
sonar.sourceEncoding=UTF-8
sonar.sources=src
sonar.tests=src/__test__
sonar.exclusions=**/*-jest.js
\ No newline at end of file
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import React from "react";
import "./App.css";
import ApplicationState from "./ApplicationState";
import "bootstrap/dist/css/bootstrap.min.css";
const App = () => {
return (
<div className="App">
<header className="App-header">
<p>Hello, World!</p>
</header>
</div>
);
return <ApplicationState />;
};
export default App;
import React from "react";
import { render } from "@testing-library/react";
import App from "./App";
test("renders hello world", () => {
const { getByText } = render(<App />);
const paragraphElement = getByText(/Hello, World!/i);
expect(paragraphElement.textContent).toStrictEqual("Hello, World!");
});
import React, { useReducer } from "react";
import AuthReducer, { initialState } from "./store/reducers/auth_reducer";
import * as ACTIONS from "./store/actions/actions";
import AuthContext from "./utils/contex";
import Routes from "./routes";
import Loader from "./component/Loader";
const ApplicationState = () => {
const [stateAuthReducer, dispatchAuthReducer] = useReducer(
AuthReducer,
initialState()
);
const handleLogin = (profile) => {
dispatchAuthReducer(ACTIONS.login(profile));
};
const handleLogout = () => {
dispatchAuthReducer(ACTIONS.logout());
};
return (
<div>
<Loader />
<AuthContext.Provider
value={{
...stateAuthReducer,
handleLogin,
handleLogout,
}}
>
<Routes />
</AuthContext.Provider>
</div>
);
};
export default ApplicationState;
import React from "react";
import { cleanup } from "@testing-library/react";
import App from "../App";
import { shallow } from "enzyme";
import ApplicationState from "../ApplicationState";
afterEach(cleanup);
test("renders Application State", () => {
const wrapper = shallow(<App />);
expect(wrapper.find(ApplicationState)).toHaveLength(1);
});
import React from "react";
import { cleanup, render } from "@testing-library/react";
import DetailPengguna from "../page/pengguna/DetailPengguna";
import AuthContext from "../utils/contex";
import { waitFor } from "@testing-library/dom";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("Test detail pengguna renders", async () => {
fetch
.once(
JSON.stringify({
count: 17,
next:
"https://industripilar-staging.herokuapp.com/transactions/?page=2",
previous: null,
results: [
{
id: "0c1db3b2-48f0-4604-83ca-e8f16e8550ab",
transaction_number: "H793P5ZK",
user: "d4b98bb5-8ba4-4a41-af10-93abcf53df58",
user_username: "whtestest",
user_full_name: "Michael Wiryadinata halim",
user_phone_number: "+628192090199",
shipping_address: "ada deh test",
shipping_neighborhood: "002",
shipping_hamlet: "002",
shipping_urban_village: "penggilingan",
shipping_sub_district: "Dummy Sub-District",
transaction_items: [
{
id: "37f0298c-2e8a-4ab0-a094-e9177ddc60c4",
product: "3d403cd3-e356-4c15-9a86-8843333e2778",
product_code: "5VK6TY",
product_name: "produk barang",
product_price: "50000.00",
quantity: 7,
},
],
transaction_item_subtotal: "350000.00",
shipping_costs: "15000.00",
payment_method: "TRF",
readable_payment_method: "Transfer",
donation: "5000.00",
transaction_status: "002",
readable_transaction_status: "Waiting for seller confirmation",
proof_of_payment: null,
user_bank_account_name: "test",
user_bank_account_number: "1232131241321",
created_at: "2020-04-18T10:59:42.074386+07:00",
updated_at: "2020-04-18T11:00:18.150633+07:00",
subtotal: "370000.00",
},
],
})
)
.once(
JSON.stringify({
id: "663392ac-1dd6-462b-9301-a19c1287cefd",
username: "dummyuser",
full_name: "Dummy User",
phone_number: "+6285212345678",
address: "Jl. Dummy No.1",
neighborhood: "000",
hamlet: "000",
urban_village: "Dummy Urban Village",
sub_district: "Dummy Sub-District",
profile_picture: null,
})
);
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailPengguna />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("profile"));
const profile = getByTestId("profile");
expect(profile.textContent).toContain("dummyuser");
expect(profile.textContent).toContain("+6285212345678");
expect(profile.textContent).toContain("Jl. Dummy No.1");
expect(profile.textContent).toContain("000");
expect(profile.textContent).toContain("000");
expect(profile.textContent).toContain("Dummy Sub-District");
expect(profile.textContent).toContain("Dummy Urban Village");
});
test("Test mock return error", async () => {
fetch
.once(
JSON.stringify({
count: 17,
next:
"https://industripilar-staging.herokuapp.com/transactions/?page=2",
previous: null,
results: [
{
id: "0c1db3b2-48f0-4604-83ca-e8f16e8550ab",
transaction_number: "H793P5ZK",
user: "d4b98bb5-8ba4-4a41-af10-93abcf53df58",
user_username: "whtestest",
user_full_name: "Michael Wiryadinata halim",
user_phone_number: "+628192090199",
shipping_address: "ada deh test",
shipping_neighborhood: "002",
shipping_hamlet: "002",
shipping_urban_village: "penggilingan",
shipping_sub_district: "Dummy Sub-District",
transaction_items: [
{
id: "37f0298c-2e8a-4ab0-a094-e9177ddc60c4",
product: "3d403cd3-e356-4c15-9a86-8843333e2778",
product_code: "5VK6TY",
product_name: "produk barang",
product_price: "50000.00",
quantity: 7,
},
],
transaction_item_subtotal: "350000.00",
shipping_costs: "15000.00",
payment_method: "TRF",
readable_payment_method: "Transfer",
donation: "5000.00",
transaction_status: "002",
readable_transaction_status: "Waiting for seller confirmation",
proof_of_payment: null,
user_bank_account_name: "test",
user_bank_account_number: "1232131241321",
created_at: "2020-04-18T10:59:42.074386+07:00",
updated_at: "2020-04-18T11:00:18.150633+07:00",
subtotal: "370000.00",
},
],
})
)
.mockReject(new Error("fake error message"));
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailPengguna />
</AuthContext.Provider>
);
const page = getByTestId("page-profile");
await waitFor(() =>
expect(page.textContent).toContain("Error !, Please relogin..")
);
});
import React from "react";
import { render, cleanup } from "@testing-library/react";
import ListPengguna from "../page/pengguna/ListPengguna";
import AuthContext from "../utils/contex";
import { waitFor } from "@testing-library/dom";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("test fetching API", async () => {
fetch.mockResponseOnce(
JSON.stringify({
count: 2,
next: null,
previous: null,
results: [
{
id: "45897cc5-968c-44cf-931d-e646b095fcaf",
username: "admin-staging",
full_name: "",
phone_number: "",
address: "",
neighborhood: "",
hamlet: "",
urban_village: "",
sub_district: "",
profile_picture: null,
},
{
id: "663392ac-1dd6-462b-9301-a19c1287cefd",
username: "dummyuser",
full_name: "Dummy User",
phone_number: "+6285212345678",
address: "Jl. Dummy No.1",
neighborhood: "000",
hamlet: "000",
urban_village: "Dummy Urban Village",
sub_district: "Dummy Sub-District",
profile_picture: null,
},
],
})
);