Fakultas Ilmu Komputer UI

Commit dcf286a3 authored by WILLIAM GATES's avatar WILLIAM GATES
Browse files

Merge branch 'staging' into 'master'

Complete Donation Functionality

See merge request !61
parents 1b7ec6d8 8588c98e
Pipeline #49113 passed with stages
in 6 minutes and 15 seconds
{ {
"presets": ["@babel/preset-react", "@babel/preset-env", "presets": ["@babel/preset-react", "@babel/preset-env",
[ [
"@emotion/babel-preset-css-prop", "@emotion/babel-preset-css-prop"
{
"sourceMap": false
}
] ]
], ],
"plugins": [ "plugins": [
[ [
"transform-inline-environment-variables" "transform-inline-environment-variables"
], ],
[
"emotion" "emotion"
]
] ]
} }
...@@ -26,5 +26,5 @@ test-report.xml ...@@ -26,5 +26,5 @@ test-report.xml
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
package-lock.json
/.vscode /.vscode
.parcel-cache
\ No newline at end of file
image: node:12.16.3-buster-slim
stages: stages:
- lint - lint
- test - test
...@@ -5,14 +6,12 @@ stages: ...@@ -5,14 +6,12 @@ stages:
- deploy - deploy
lint: lint:
image: node:latest
stage: lint stage: lint
script: script:
- npm install - npm install
- npm run lint - npm run lint
test: test:
image: node:latest
stage: test stage: test
artifacts: artifacts:
expire_in: 1 hour expire_in: 1 hour
...@@ -34,7 +33,6 @@ sonar_scanner_test: ...@@ -34,7 +33,6 @@ sonar_scanner_test:
- sonar-scanner -Dsonar.projectKey=$SONARQUBE_PROJECT_KEY -Dsonar.host.url=$SONARQUBE_HOST_URL -Dsonar.login=$SONARQUBE_TOKEN -Dsonar.branch.name=$CI_COMMIT_REF_NAME - sonar-scanner -Dsonar.projectKey=$SONARQUBE_PROJECT_KEY -Dsonar.host.url=$SONARQUBE_HOST_URL -Dsonar.login=$SONARQUBE_TOKEN -Dsonar.branch.name=$CI_COMMIT_REF_NAME
staging: staging:
image: node:latest
stage: deploy stage: deploy
variables: variables:
NETLIFY_AUTH_TOKEN: $STAGING_NETLIFY_AUTH_TOKEN NETLIFY_AUTH_TOKEN: $STAGING_NETLIFY_AUTH_TOKEN
...@@ -49,7 +47,6 @@ staging: ...@@ -49,7 +47,6 @@ staging:
- staging - staging
production: production:
image: node:latest
stage: deploy stage: deploy
variables: variables:
AWS_ACCESS_KEY_ID: $PRODUCTION_AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_ID: $PRODUCTION_AWS_ACCESS_KEY_ID
......
This diff is collapsed.
...@@ -11,20 +11,19 @@ ...@@ -11,20 +11,19 @@
"@reach/router": "^1.3.3", "@reach/router": "^1.3.3",
"bootstrap": "^4.4.1", "bootstrap": "^4.4.1",
"jquery": "^3.5.0", "jquery": "^3.5.0",
"moment": "^2.24.0", "moment": "2.24.0",
"moment-timezone": "^0.5.28", "moment-timezone": "^0.5.28",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"react": "^16.13.1", "react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-hook-form": "^5.6.0", "react-hook-form": "^5.6.1",
"react-moment": "^0.9.7", "react-moment": "^0.9.7",
"react-number-format": "^4.4.1", "react-number-format": "^4.4.1",
"react-promise-tracker": "^2.1.0" "react-promise-tracker": "^2.1.0"
}, },
"scripts": { "scripts": {
"start": "parcel public/index.html", "start": "cross-env REACT_APP_BASE_URL=https://industripilar-staging.herokuapp.com parcel public/index.html",
"build": "parcel build public/index.html --experimental-scope-hoisting", "build": "parcel build public/index.html",
"test": "jest", "test": "jest",
"test:coverage": "jest --coverage", "test:coverage": "jest --coverage",
"lint": "eslint \"src/**/*.{js,jsx}\" --quiet", "lint": "eslint \"src/**/*.{js,jsx}\" --quiet",
...@@ -46,15 +45,16 @@ ...@@ -46,15 +45,16 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.9.6",
"@babel/preset-env": "^7.9.5", "@babel/preset-env": "^7.9.6",
"@babel/preset-react": "^7.9.4", "@babel/preset-react": "^7.9.4",
"@testing-library/dom": "^7.2.2", "@testing-library/dom": "^7.2.2",
"@testing-library/react": "^10.0.3", "@testing-library/react": "^10.0.4",
"@types/jest": "^25.2.1", "@types/jest": "^25.2.1",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-plugin-emotion": "^10.0.33", "babel-plugin-emotion": "^10.0.33",
"babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-inline-environment-variables": "^0.4.3",
"cross-env": "^7.0.2",
"enzyme": "^3.11.0", "enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2", "enzyme-adapter-react-16": "^1.15.2",
"eslint": "^6.8.0", "eslint": "^6.8.0",
...@@ -63,14 +63,14 @@ ...@@ -63,14 +63,14 @@
"eslint-plugin-import": "^2.20.2", "eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.19.0", "eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^2.5.1", "eslint-plugin-react-hooks": "^4.0.0",
"jest": "^25.4.0", "jest": "^25.5.4",
"jest-environment-enzyme": "^7.1.2", "jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2", "jest-enzyme": "^7.1.2",
"jest-fetch-mock": "^3.0.3", "jest-fetch-mock": "^3.0.3",
"jest-sonar-reporter": "^2.0.0", "jest-sonar-reporter": "^2.0.0",
"mutationobserver-shim": "^0.3.5", "mutationobserver-shim": "^0.3.5",
"parcel-bundler": "^1.12.4", "parcel": "^2.0.0-alpha.3.2",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"regenerator-runtime": "^0.13.5" "regenerator-runtime": "^0.13.5"
}, },
......
...@@ -4,6 +4,7 @@ import * as ACTIONS from "./store/actions/actions"; ...@@ -4,6 +4,7 @@ import * as ACTIONS from "./store/actions/actions";
import AuthContext from "./utils/contex"; import AuthContext from "./utils/contex";
import Routes from "./routes"; import Routes from "./routes";
import Loader from "./component/Loader"; import Loader from "./component/Loader";
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
const ApplicationState = () => { const ApplicationState = () => {
const [stateAuthReducer, dispatchAuthReducer] = useReducer( const [stateAuthReducer, dispatchAuthReducer] = useReducer(
...@@ -19,8 +20,10 @@ const ApplicationState = () => { ...@@ -19,8 +20,10 @@ const ApplicationState = () => {
dispatchAuthReducer(ACTIONS.logout()); dispatchAuthReducer(ACTIONS.logout());
}; };
const theme = createMuiTheme();
return ( return (
<div> <ThemeProvider theme={theme}>
<Loader /> <Loader />
<AuthContext.Provider <AuthContext.Provider
value={{ value={{
...@@ -31,7 +34,7 @@ const ApplicationState = () => { ...@@ -31,7 +34,7 @@ const ApplicationState = () => {
> >
<Routes /> <Routes />
</AuthContext.Provider> </AuthContext.Provider>
</div> </ThemeProvider>
); );
}; };
export default ApplicationState; export default ApplicationState;
...@@ -11,6 +11,25 @@ afterEach(cleanup); ...@@ -11,6 +11,25 @@ afterEach(cleanup);
test("Test detail pengguna renders", async () => { test("Test detail pengguna renders", async () => {
fetch fetch
.once({
id: "8e9a8f94-cb5c-4b2d-b4f1-81ccfb9f1b0a",
donation_number: "7NGVBN",
user: "45897cc5-968c-44cf-931d-e646b095fcaf",
user_username: "admin-staging",
program: "6d7462da-6a85-4e2b-9930-69567090a5d5",
program_code: "3MXZ9T",
user_full_name: "Hello",
user_phone_number: "012345",
program_name: "dummy 2",
amount: "10000.00",
donation_status: "001",
readable_donation_status: "Menunggu konfirmasi admin",
proof_of_bank_transfer: "a",
user_bank_account_name: "Jeffrey",
user_bank_account_number: "12345678",
created_at: "2020-04-28T21:34:15.565614+07:00",
updated_at: "2020-04-28T21:34:15.565651+07:00",
})
.once( .once(
JSON.stringify({ JSON.stringify({
count: 17, count: 17,
......
import { act, cleanup, fireEvent, render } from "@testing-library/react";
import AuthContext from "../../utils/contex";
import React from "react";
import DetailDonasi from "../../page/donasi/DetailDonasi";
import { waitFor } from "@testing-library/dom";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("Test detail loaded donasi", async () => {
fetch.mockResponseOnce(
JSON.stringify({
id: "8e9a8f94-cb5c-4b2d-b4f1-81ccfb9f1b0a",
donation_number: "7NGVBN",
user: "45897cc5-968c-44cf-931d-e646b095fcaf",
user_username: "admin-staging",
program: "6d7462da-6a85-4e2b-9930-69567090a5d5",
program_code: "3MXZ9T",
user_full_name: "Hello",
user_phone_number: "012345",
program_name: "dummy 2",
amount: "10000.00",
donation_status: "001",
readable_donation_status: "Menunggu konfirmasi admin",
proof_of_bank_transfer: "a",
user_bank_account_name: "Jeffrey",
user_bank_account_number: "12345678",
created_at: "2020-04-28T21:34:15.565614+07:00",
updated_at: "2020-04-28T21:34:15.565651+07:00",
})
);
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "tester" } }}>
<DetailDonasi idDonasi={"8e9a8f94-cb5c-4b2d-b4f1-81ccfb9f1b0a"} />
</AuthContext.Provider>
);
const wait = getByTestId("waiting-detail-donasi");
expect(wait.textContent).toContain("Fetching data..");
await waitFor(() => getByTestId("page-detail-donasi"));
const data = getByTestId("page-detail-donasi");
expect(data.textContent).toContain("DONASI");
await act(async () => {
await fireEvent.click(getByTestId("button-see-proof"));
});
const close = getByTestId("button-close-proof");
expect(close.textContent).toContain("Close");
await act(async () => {
await fireEvent.click(close);
});
const dropdown = getByTestId("dropdown-status");
expect(dropdown.children.length).toEqual(4);
});
import { act, cleanup, fireEvent, render } from "@testing-library/react";
import AuthContext from "../../utils/contex";
import React from "react";
import ListDonasi from "../../page/donasi/ListDonasi";
import { waitFor } from "@testing-library/dom";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("Test List donasi", async () => {
fetch.mockResponseOnce(
JSON.stringify({
count: 1,
next: null,
previous: null,
results: [
{
id: "8e9a8f94-cb5c-4b2d-b4f1-81ccfb9f1b0a",
donation_number: "7NGVBN",
user: "45897cc5-968c-44cf-931d-e646b095fcaf",
program: "6d7462da-6a85-4e2b-9930-69567090a5d5",
program_code: "3MXZ9T",
user_username: "admin-staging",
user_full_name: "",
user_phone_number: "",
program_name: "dummy 2",
amount: "10000.00",
donation_status: "001",
readable_donation_status: "Menunggu konfirmasi admin",
proof_of_bank_transfer: null,
user_bank_account_name: "Jeffrey",
user_bank_account_number: "12345678",
created_at: "2020-04-28T21:34:15.565614+07:00",
updated_at: "2020-04-28T21:34:15.565651+07:00",
},
],
})
);
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "tester" } }}>
<ListDonasi />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("tableList"));
const data = getByTestId("tableList");
expect(data.textContent).toContain("admin-staging");
expect(data.textContent).toContain("Menunggu konfirmasi admin");
expect(fetch.mock.calls.length).toEqual(1);
});
test(" Test List transaksi filter", async () => {
fetch.once(
JSON.stringify({
count: 1,
next: null,
previous: null,
results: [
{
id: "8e9a8f94-cb5c-4b2d-b4f1-81ccfb9f1b0a",
donation_number: "7NGVBN",
user: "45897cc5-968c-44cf-931d-e646b095fcaf",
program: "6d7462da-6a85-4e2b-9930-69567090a5d5",
program_code: "3MXZ9T",
user_username: "admin-staging",
user_full_name: "",
user_phone_number: "",
program_name: "dummy 2",
amount: "10000.00",
donation_status: "001",
readable_donation_status: "Menunggu konfirmasi admin",
proof_of_bank_transfer: null,
user_bank_account_name: "Jeffrey",
user_bank_account_number: "12345678",
created_at: "2020-04-28T21:34:15.565614+07:00",
updated_at: "2020-04-28T21:34:15.565651+07:00",
},
],
})
);
const { getByTestId, getByLabelText } = render(
<AuthContext.Provider value={{ profile: { token: "tester" } }}>
<ListDonasi />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("tableList"));
const data = getByTestId("tableList");
expect(data.textContent).toContain("admin-staging");
expect(data.textContent).toContain("Menunggu konfirmasi admin");
expect(fetch.mock.calls.length).toEqual(1);
await act(async () => {
await fireEvent.click(getByTestId("filter-button"));
});
await act(async () => {
await fireEvent.input(
getByLabelText("Status Donasi:", { target: { value: "001" } })
);
await fireEvent.click(getByTestId("submit-filter"));
});
expect(data.textContent).toContain("admin-staging");
expect(fetch.mock.calls.length).toEqual(2);
});
import { act, cleanup, render, fireEvent } from "@testing-library/react";
import AuthContext from "../../utils/contex";
import React from "react";
import DetailProgram from "../../page/program/DetailProgram";
import { waitFor } from "@testing-library/dom";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("Test detail program renders", async () => {
fetch.mockResponseOnce(
JSON.stringify({
id: "6d7462da-6a85-4e2b-9930-69567090a5d5",
code: "3MXZ9T",
name: "dummy 2",
description: "yeyyy",
start_date_time: null,
end_date_time: null,
location: "Depok",
speaker: "Eddrick",
poster_image:
"https://industripilar-api-staging.s3.amazonaws.com/media/uploads/programs/1_txtcYocQEGtOFN33ZCTDbw.png",
})
);
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailProgram />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("program"));
const program = getByTestId("program");
expect(program.textContent).toContain("Eddrick");
expect(fetch.mock.calls.length).toEqual(1);
});
test("Test mock detail program return error", async () => {
fetch.mockReject(new Error("fake error message"));
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailProgram />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("page"));
const page = getByTestId("page");
expect(page.textContent).toContain("Error !, Please relogin..");
});
test("Test detail program delete", async () => {
fetch.mockResponseOnce(
JSON.stringify({
id: "6d7462da-6a85-4e2b-9930-69567090a5d5",
code: "3MXZ9T",
name: "dummy 2",
description: "yeyyy",
start_date_time: null,
end_date_time: null,
location: "Depok",
speaker: "Eddrick",
poster_image:
"https://industripilar-api-staging.s3.amazonaws.com/media/uploads/programs/1_txtcYocQEGtOFN33ZCTDbw.png",
})
);
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailProgram />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("page"));
const produk = getByTestId("page");
expect(produk.textContent).toContain("dummy 2");
expect(fetch.mock.calls.length).toEqual(1);
const btnDeleteModal = getByTestId("button-delete-program-modal");
await act(async () => {
await fireEvent.click(btnDeleteModal);
});
const btnDelete = getByTestId("button-delete-program");
await act(async () => {
await fireEvent.click(btnDelete);
});
expect(fetch.mock.calls.length).toEqual(2);
});
test("Test detail produk delete error", async () => {
fetch
.mockResponseOnce(
JSON.stringify({
id: "6d7462da-6a85-4e2b-9930-69567090a5d5",
code: "3MXZ9T",
name: "dummy 2",
description: "yeyyy",
start_date_time: null,
end_date_time: null,
location: "Depok",
speaker: "Eddrick",
poster_image:
"https://industripilar-api-staging.s3.amazonaws.com/media/uploads/programs/1_txtcYocQEGtOFN33ZCTDbw.png",
})
)
.mockReject(new Error("fake error message"));
const { getByTestId } = render(
<AuthContext.Provider value={{ profile: { token: "BEBAS" } }}>
<DetailProgram />
</AuthContext.Provider>
);
await waitFor(() => getByTestId("page"));
const produk = getByTestId("page");
expect(produk.textContent).toContain("Eddrick");
expect(fetch.mock.calls.length).toEqual(1);
const btnDeleteModal = getByTestId("button-delete-program-modal");
await act(async () => {
await fireEvent.click(btnDeleteModal);
});
const btnDelete = getByTestId("button-delete-program");
await act(async () => {
await fireEvent.click(btnDelete);
});
expect(fetch.mock.calls.length).toEqual(2);
expect(produk.textContent).toContain(
"Tidak dapat menghapus program, mohon periksa apakah ada program ini."
);
});
import { act, cleanup, fireEvent, render } from "@testing-library/react";
import AuthContext from "../../utils/contex";
import React from "react";
import TambahProgram from "../../page/program/TambahProgram";
beforeEach(() => {
fetch.resetMocks();
});
afterEach(cleanup);
test("Test tambah program renders", async () => {
fetch.once(
JSON.stringify({
count: 5,
next: null,
previous: null,
results: [
{
id: "6d7462da-6a85-4e2b-9930-69567090a5d5",
code: "3MXZ9T",
name: "dummy 2",
description: "yeyyy",
start_date_time: null,
end_date_time: null,
location: "Depok",
speaker: "Eddrick",
poster_image:
"https://industripilar-api-staging.s3.amazonaws.com/media/uploads/programs/1_txtcYocQEGtOFN33ZCTDbw.png",
},
{
id: "282007ff-d0be-4d68-823e-03bde086ee79",
code: "89Z6GX",
name: "Sample",
description: "Sample",
start_date_time: null,