diff --git a/README.md b/README.md index efd49737c685c1da199470779917272947836971..3637449857ec60147379735b10842afae5e39cfb 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@   -Nama kelompok : Sprinter -Kelas : D -Anggota : -======= + The first crowdfunding platform in the toys industry. +======= ## Contributors @@ -75,4 +73,3 @@ If you aren’t satisfied with the build tool and configuration choices, you can Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. ->>>>>>> b2004baf2059a6655cd6fcbe6a7ac5f167bc2cc5 diff --git a/design/PBI-02E-Desain_Menu_Keuangan_Investor.pdf b/design/PBI-02E-Desain_Menu_Keuangan_Investor.pdf new file mode 100644 index 0000000000000000000000000000000000000000..46fc61b0bf2b71e39c2643787f9ed1f44e0aa1e6 Binary files /dev/null and b/design/PBI-02E-Desain_Menu_Keuangan_Investor.pdf differ diff --git a/package-lock.json b/package-lock.json index 60ee4edbcfa8a4533639204c3cf39f795d3cb6d4..4e90c539b30efc94dfe514cc0e8a00f99ca4df3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1372,19 +1372,6 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, - "node_modules/@emotion/is-prop-valid": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz", - "integrity": "sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==", - "dependencies": { - "@emotion/memoize": "0.7.1" - } - }, - "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.1.tgz", - "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==" - }, "node_modules/@emotion/memoize": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", @@ -6107,16 +6094,6 @@ "node": ">=6" } }, - "node_modules/css-jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/css-jss/-/css-jss-10.9.0.tgz", - "integrity": "sha512-CpYclti5ZQ18PfAeXaHQ2bEw4DEUfjC0lTS9sQcUlTRF8hC/Va0h3DIowlRm6AH/Ka/O/+tp41Q5zn9MJQoRsA==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "jss-preset-default": "10.9.0" - } - }, "node_modules/css-loader": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz", @@ -10483,11 +10460,14 @@ } }, "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dependencies": { "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-data-descriptor": { @@ -10704,6 +10684,15 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=" }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/is-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", @@ -12992,16 +12981,6 @@ "jss": "10.9.0" } }, - "node_modules/jss-plugin-compose": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-compose/-/jss-plugin-compose-10.9.0.tgz", - "integrity": "sha512-Q/0FEZhDwGUpf3/b7+PspmMi6MVSlN3YlTDmvrft7I6N346jUpd8MYkYP/6qM1ZMuVj4v8ky/XYqr1v2ganLLg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "node_modules/jss-plugin-default-unit": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz", @@ -13011,25 +12990,6 @@ "jss": "10.9.0" } }, - "node_modules/jss-plugin-expand": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-expand/-/jss-plugin-expand-10.9.0.tgz", - "integrity": "sha512-QfZ9jld0HpF1OiYU7cGWQ4q+f6+Wu93mV4X+cA1iVRssiUbSbygwdfZkUwX23UOhS1WWRJeQlLK1aJC94K8/0A==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - } - }, - "node_modules/jss-plugin-extend": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.9.0.tgz", - "integrity": "sha512-xvmosUh3RsKVsm9L14ml6PL3i0Ejj5gB6eo/jTMkGW1kIy42gNXV1EthR8cD5xiowWstnvugQ3JF0pI5+QkPMg==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "node_modules/jss-plugin-global": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz", @@ -13068,26 +13028,6 @@ "tiny-warning": "^1.0.2" } }, - "node_modules/jss-plugin-rule-value-observable": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.9.0.tgz", - "integrity": "sha512-/MWVPJVEn41+ofzQdsvH1GR4wusDqFqNnchh/98HVc580MxPy4NVkmUa2SAEpbHhnJ93sCoETZccW3HJKuvH4A==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "symbol-observable": "^1.2.0" - } - }, - "node_modules/jss-plugin-template": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-template/-/jss-plugin-template-10.9.0.tgz", - "integrity": "sha512-lxThUvdt0drCi7xhuJWxADWTgLLy1IWCeFO5k+dtba900xJsNg0IGZplpP9w9UpaJsYS3WUwWMXw8Sxn1dobfQ==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "node_modules/jss-plugin-vendor-prefixer": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz", @@ -13098,27 +13038,6 @@ "jss": "10.9.0" } }, - "node_modules/jss-preset-default": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-10.9.0.tgz", - "integrity": "sha512-Zdsj+R+UTn7OOJ1TFQi+l8PfEL7APSAM6vRPaU8mJywT8OrMjgslMKckFLrgq1k+qk1hJR1ePAMesvZ5aAXGOQ==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "jss-plugin-camel-case": "10.9.0", - "jss-plugin-compose": "10.9.0", - "jss-plugin-default-unit": "10.9.0", - "jss-plugin-expand": "10.9.0", - "jss-plugin-extend": "10.9.0", - "jss-plugin-global": "10.9.0", - "jss-plugin-nested": "10.9.0", - "jss-plugin-props-sort": "10.9.0", - "jss-plugin-rule-value-function": "10.9.0", - "jss-plugin-rule-value-observable": "10.9.0", - "jss-plugin-template": "10.9.0", - "jss-plugin-vendor-prefixer": "10.9.0" - } - }, "node_modules/jsx-ast-utils": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", @@ -13563,6 +13482,12 @@ "node": ">= 0.6" } }, + "node_modules/micro-memoize": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.0.9.tgz", + "integrity": "sha512-Z2uZi/IUMGQDCXASdujXRqrXXEwSY0XffUrAOllhqzQI3wpUyZbiZTiE2JuYC0HSG2G7DbCS5jZmsEKEGZuemg==", + "dev": true + }, "node_modules/microevent.ts": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", @@ -18365,12 +18290,6 @@ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, - "node_modules/netlify-cli/node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "node_modules/netlify-cli/node_modules/builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -22759,15 +22678,6 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "node_modules/netlify-cli/node_modules/is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, "node_modules/netlify-cli/node_modules/is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -22987,15 +22897,6 @@ "node": ">=0.10.0" } }, - "node_modules/netlify-cli/node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/netlify-cli/node_modules/is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -24243,12 +24144,6 @@ "integrity": "sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg==", "dev": true }, - "node_modules/netlify-cli/node_modules/micro-memoize": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.0.9.tgz", - "integrity": "sha512-Z2uZi/IUMGQDCXASdujXRqrXXEwSY0XffUrAOllhqzQI3wpUyZbiZTiE2JuYC0HSG2G7DbCS5jZmsEKEGZuemg==", - "dev": true - }, "node_modules/netlify-cli/node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -25870,12 +25765,6 @@ "node": ">=8" } }, - "node_modules/netlify-cli/node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "node_modules/netlify-cli/node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -27349,25 +27238,6 @@ "urix": "^0.1.0" } }, - "node_modules/netlify-cli/node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/netlify-cli/node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/netlify-cli/node_modules/source-map-url": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", @@ -29783,9 +29653,9 @@ } }, "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -34394,11 +34264,6 @@ "node": ">= 8" } }, - "node_modules/react-display-name": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz", - "integrity": "sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==" - }, "node_modules/react-dom": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", @@ -34595,27 +34460,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-10.9.0.tgz", - "integrity": "sha512-xKXTEejrSkzINF+dutFtLllIfYSN6tOA1XmnpiZGjsWZqy7Hum6fjjgAE2TbBmV9h2CW62ekmGj/Mx27ZuMjuw==", - "dependencies": { - "@babel/runtime": "^7.3.1", - "@emotion/is-prop-valid": "^0.7.3", - "css-jss": "10.9.0", - "hoist-non-react-statics": "^3.2.0", - "is-in-browser": "^1.1.3", - "jss": "10.9.0", - "jss-preset-default": "10.9.0", - "prop-types": "^15.6.0", - "shallow-equal": "^1.2.0", - "theming": "^3.3.0", - "tiny-warning": "^1.0.2" - }, - "peerDependencies": { - "react": ">=16.8.6" - } - }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -36695,9 +36539,9 @@ } }, "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -37596,23 +37440,6 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, - "node_modules/theming": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/theming/-/theming-3.3.0.tgz", - "integrity": "sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA==", - "dependencies": { - "hoist-non-react-statics": "^3.3.0", - "prop-types": "^15.5.8", - "react-display-name": "^0.2.4", - "tiny-warning": "^1.0.2" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "react": ">=16.3" - } - }, "node_modules/throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -41303,21 +41130,6 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, - "@emotion/is-prop-valid": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz", - "integrity": "sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==", - "requires": { - "@emotion/memoize": "0.7.1" - }, - "dependencies": { - "@emotion/memoize": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.1.tgz", - "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==" - } - } - }, "@emotion/memoize": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", @@ -45375,16 +45187,6 @@ } } }, - "css-jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/css-jss/-/css-jss-10.9.0.tgz", - "integrity": "sha512-CpYclti5ZQ18PfAeXaHQ2bEw4DEUfjC0lTS9sQcUlTRF8hC/Va0h3DIowlRm6AH/Ka/O/+tp41Q5zn9MJQoRsA==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "jss-preset-default": "10.9.0" - } - }, "css-loader": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz", @@ -49025,9 +48827,9 @@ } }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "requires": { "has": "^1.0.3" } @@ -49184,6 +48986,15 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=" }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, "is-regex": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", @@ -50994,16 +50805,6 @@ "jss": "10.9.0" } }, - "jss-plugin-compose": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-compose/-/jss-plugin-compose-10.9.0.tgz", - "integrity": "sha512-Q/0FEZhDwGUpf3/b7+PspmMi6MVSlN3YlTDmvrft7I6N346jUpd8MYkYP/6qM1ZMuVj4v8ky/XYqr1v2ganLLg==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "jss-plugin-default-unit": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.0.tgz", @@ -51013,25 +50814,6 @@ "jss": "10.9.0" } }, - "jss-plugin-expand": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-expand/-/jss-plugin-expand-10.9.0.tgz", - "integrity": "sha512-QfZ9jld0HpF1OiYU7cGWQ4q+f6+Wu93mV4X+cA1iVRssiUbSbygwdfZkUwX23UOhS1WWRJeQlLK1aJC94K8/0A==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0" - } - }, - "jss-plugin-extend": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.9.0.tgz", - "integrity": "sha512-xvmosUh3RsKVsm9L14ml6PL3i0Ejj5gB6eo/jTMkGW1kIy42gNXV1EthR8cD5xiowWstnvugQ3JF0pI5+QkPMg==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "jss-plugin-global": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.0.tgz", @@ -51070,26 +50852,6 @@ "tiny-warning": "^1.0.2" } }, - "jss-plugin-rule-value-observable": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.9.0.tgz", - "integrity": "sha512-/MWVPJVEn41+ofzQdsvH1GR4wusDqFqNnchh/98HVc580MxPy4NVkmUa2SAEpbHhnJ93sCoETZccW3HJKuvH4A==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "symbol-observable": "^1.2.0" - } - }, - "jss-plugin-template": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-plugin-template/-/jss-plugin-template-10.9.0.tgz", - "integrity": "sha512-lxThUvdt0drCi7xhuJWxADWTgLLy1IWCeFO5k+dtba900xJsNg0IGZplpP9w9UpaJsYS3WUwWMXw8Sxn1dobfQ==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "tiny-warning": "^1.0.2" - } - }, "jss-plugin-vendor-prefixer": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.0.tgz", @@ -51100,27 +50862,6 @@ "jss": "10.9.0" } }, - "jss-preset-default": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-10.9.0.tgz", - "integrity": "sha512-Zdsj+R+UTn7OOJ1TFQi+l8PfEL7APSAM6vRPaU8mJywT8OrMjgslMKckFLrgq1k+qk1hJR1ePAMesvZ5aAXGOQ==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.9.0", - "jss-plugin-camel-case": "10.9.0", - "jss-plugin-compose": "10.9.0", - "jss-plugin-default-unit": "10.9.0", - "jss-plugin-expand": "10.9.0", - "jss-plugin-extend": "10.9.0", - "jss-plugin-global": "10.9.0", - "jss-plugin-nested": "10.9.0", - "jss-plugin-props-sort": "10.9.0", - "jss-plugin-rule-value-function": "10.9.0", - "jss-plugin-rule-value-observable": "10.9.0", - "jss-plugin-template": "10.9.0", - "jss-plugin-vendor-prefixer": "10.9.0" - } - }, "jsx-ast-utils": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", @@ -51504,6 +51245,12 @@ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, + "micro-memoize": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.0.9.tgz", + "integrity": "sha512-Z2uZi/IUMGQDCXASdujXRqrXXEwSY0XffUrAOllhqzQI3wpUyZbiZTiE2JuYC0HSG2G7DbCS5jZmsEKEGZuemg==", + "dev": true + }, "microevent.ts": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", @@ -55494,12 +55241,6 @@ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", "dev": true }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, "builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -59082,15 +58823,6 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -59254,15 +58986,6 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -60287,12 +60010,6 @@ "integrity": "sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg==", "dev": true }, - "micro-memoize": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.0.9.tgz", - "integrity": "sha512-Z2uZi/IUMGQDCXASdujXRqrXXEwSY0XffUrAOllhqzQI3wpUyZbiZTiE2JuYC0HSG2G7DbCS5jZmsEKEGZuemg==", - "dev": true - }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -61583,12 +61300,6 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -62815,24 +62526,6 @@ "urix": "^0.1.0" } }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "source-map-url": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", @@ -64842,9 +64535,9 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "0.1.7", @@ -68574,11 +68267,6 @@ } } }, - "react-display-name": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz", - "integrity": "sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg==" - }, "react-dom": { "version": "16.14.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", @@ -68770,24 +68458,6 @@ } } }, - "react-jss": { - "version": "10.9.0", - "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-10.9.0.tgz", - "integrity": "sha512-xKXTEejrSkzINF+dutFtLllIfYSN6tOA1XmnpiZGjsWZqy7Hum6fjjgAE2TbBmV9h2CW62ekmGj/Mx27ZuMjuw==", - "requires": { - "@babel/runtime": "^7.3.1", - "@emotion/is-prop-valid": "^0.7.3", - "css-jss": "10.9.0", - "hoist-non-react-statics": "^3.2.0", - "is-in-browser": "^1.1.3", - "jss": "10.9.0", - "jss-preset-default": "10.9.0", - "prop-types": "^15.6.0", - "shallow-equal": "^1.2.0", - "theming": "^3.3.0", - "tiny-warning": "^1.0.2" - } - }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -70597,9 +70267,9 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -71345,17 +71015,6 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, - "theming": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/theming/-/theming-3.3.0.tgz", - "integrity": "sha512-u6l4qTJRDaWZsqa8JugaNt7Xd8PPl9+gonZaIe28vAhqgHMIG/DOyFPqiKN/gQLQYj05tHv+YQdNILL4zoiAVA==", - "requires": { - "hoist-non-react-statics": "^3.3.0", - "prop-types": "^15.5.8", - "react-display-name": "^0.2.4", - "tiny-warning": "^1.0.2" - } - }, "throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", diff --git a/src/components/CardMainanLaporan/CardMainanLaporan.css b/src/components/CardMainanLaporan/CardMainanLaporan.css index 1215243415a46db07471440100b23b0ab7b15bdf..343dca221ef746fa15ede13585b95d7a5ac62f95 100644 --- a/src/components/CardMainanLaporan/CardMainanLaporan.css +++ b/src/components/CardMainanLaporan/CardMainanLaporan.css @@ -8,7 +8,7 @@ } .card-lap-mainan{ - height: 430px; + height: 400px; } .lap-mainan-img{ diff --git a/src/components/CardMainanLaporan/CardMainanLaporan.js b/src/components/CardMainanLaporan/CardMainanLaporan.js index 52c98a8bab79b1ffaa6126414e064727eac8fe9f..80621342985b80aaf41e03e3b2abd0eb3e038cb7 100644 --- a/src/components/CardMainanLaporan/CardMainanLaporan.js +++ b/src/components/CardMainanLaporan/CardMainanLaporan.js @@ -6,23 +6,18 @@ export default function CardMainanLaporan ({ nama, deskripsi, id, - setState }) { return ( - <Card className="shadow card-lap-mainan mb-1 mt-4" > + <Card className="shadow card-lap-mainan mb-1 mt-4" > <Card.Img className="lap-mainan-img" variant="top" src={foto}/> <Card.Body> <Card.Title className="card-content-limit card-title"> <span className="title-mainan">{nama}</span> </Card.Title> <Card.Text> - <p className="card-content-limit content-mainan"><span style={{color:"var(--wkd-red)", fontWeight:700}}>Id Mainan: {id}</span><br></br>{deskripsi}</p> + <p className="card-content-limit content-mainan"><span style={{color:"var(--wkd-red)", fontWeight:700}}>Kode Mainan: {id}</span><br></br>{deskripsi}</p> </Card.Text> - <input type="radio" name="filter" id="pil-mainan" value={id} onChange={e => setState(e.currentTarget.value)} /> </Card.Body> </Card> - - ); } - \ No newline at end of file diff --git a/src/components/CardMesinRusak/CardMesinRusak.js b/src/components/CardMesinRusak/CardMesinRusak.js index a8dccfe3aeab98a13d0929f93fb0ed87c138d1c0..1957b723c4d2ec280c6669c40442e8929b598d3e 100644 --- a/src/components/CardMesinRusak/CardMesinRusak.js +++ b/src/components/CardMesinRusak/CardMesinRusak.js @@ -25,7 +25,6 @@ export default function CardMesinRusak ({ if (localStorage.getItem('access')) { axios.delete(`${process.env.REACT_APP_BACKEND_API_URL}/api/laporan/${pk}/delete/`, config) .then((response) => { - window.location.reload(); alert('Anda telah menghapus laporan kerusakan'); }, (error) => { alert("Terdapat kesalahan. Silakan mengecek kembali laporan yang Anda masukan dan refresh ulang halaman ini dan perbaiki pengadaan Anda.") @@ -35,29 +34,28 @@ export default function CardMesinRusak ({ } }; return ( - <Card className="shadow card-mesin mb-4"> + <Card className="shadow card-mesin mb-4"> <Card.Img className="card-pengadaan-img" variant="top" src={fotoKerusakan}/> <Card.Body> <Card.Title className="card-content-limit title-mainan-rusak card-pengadaan-image"> {nama} </Card.Title> - <Card.Text> - {status === "NAS" && <p class="py-2 px-4 badge rounded-pill bg-danger">Belum Diperbaiki</p>} - {status === "ASG" && <p class="py-2 px-4 badge rounded-pill bg-info">Sedang Diperbaiki</p>} - {status === "RSV" && <p class="py-2 px-5 badge rounded-pill bg-success">Selesai</p>} + {status === "NAS" && <p class="py-2 px-4 badge rounded-pill bg-danger">Belum Diperbaiki</p>} + {status === "ASG" && <p class="py-2 px-4 badge rounded-pill bg-info">Sedang Diperbaiki</p>} + {status === "RSV" && <p class="py-2 px-5 badge rounded-pill bg-success">Selesai</p>} - <p className=" text-ket-mainan"> - <span >Kode Laporan: {idLaporan}</span><br></br> - <span >Kode Mainan: {idMainan}</span><br></br> - <span>Level Kerusakan: {level}</span><br></br> - <span>Tanggal Pelaporan: {tanggal}</span><br></br> - <span>Operator: {operator}</span></p> - <p className="card-content-limit">{deskripsi}</p> - </Card.Text> + <p className=" text-ket-mainan"> + <span >Kode Laporan: {idLaporan}</span><br></br> + <span >Kode Mainan: {idMainan}</span><br></br> + <span>Level Kerusakan: {level}</span><br></br> + <span>Tanggal Pelaporan: {tanggal}</span><br></br> + <span>Operator: {operator}</span></p> + <p className="card-content-limit">{deskripsi}</p> <Row className='justify-content-center'> - <button onClick={() => deleteLaporan(idLaporan)} data-testid='hapus' disabled={status!=="NAS"} className={`mesin-button ${status!=="NAS" ? 'disable':'mesin-blue-border-button'}`} > + <a href="" onClick={() => deleteLaporan(idLaporan)}> + <button data-testid='hapus' disabled={status!=="NAS"} className={`mesin-button ${status!=="NAS" ? 'disable':'mesin-blue-border-button'}`} > Hapus - </button> + </button></a> <a href={"/update-laporan-kerusakan/"+idLaporan} className="custom-card-walkiddie"> <button data-testid='ubah-desc' className={`ml-2 mesin-button ${status !== "NAS" ? 'disable': 'wkd-blue-button'}`}> Ubah Deskripsi @@ -66,8 +64,5 @@ export default function CardMesinRusak ({ </Row> </Card.Body> </Card> - - ); } - \ No newline at end of file diff --git a/src/components/CardMesinRusak/CardMesinRusak.test.js b/src/components/CardMesinRusak/CardMesinRusak.test.js index f09771f9020e56120661c9895303ed6cb6d7cb0c..4cea91e3e5cc72f057d54ec0496f94cd480e8631 100644 --- a/src/components/CardMesinRusak/CardMesinRusak.test.js +++ b/src/components/CardMesinRusak/CardMesinRusak.test.js @@ -16,7 +16,14 @@ const mockStore = configureStore(middlewares) describe('<CardMesinRusak />', () => { it('loading when card test', () => { - const mockCurrentPosts = jest.fn() + const mockCurrentPosts = [ + { + "pk": 1, + "id": 1, + "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", + "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto", + }, + ] const initialState = { auth: { isAuthenticated: true, @@ -25,13 +32,6 @@ describe('<CardMesinRusak />', () => { } } } - - const mockMatch = { - params: { - pk: 1 - } - } - localStorage.setItem('access', 'token') const store = mockStore(initialState) const deleteLaporan = jest.fn() @@ -44,7 +44,7 @@ describe('<CardMesinRusak />', () => { var mock = new MockAdapter(axios); - mock.onDelete(`${process.env.REACT_APP_BACKEND_API_URL}/api/laporan/${mockMatch.params.pk}/delete/`, config).reply(200); + mock.onDelete(`${process.env.REACT_APP_BACKEND_API_URL}/api/laporan/1/delete/`, config).reply(200); render( <Provider store={store}> diff --git a/src/components/CardMesinRusak/DeleteLaporan.test.js b/src/components/CardMesinRusak/DeleteLaporan.test.js new file mode 100644 index 0000000000000000000000000000000000000000..bee58f58e3281d3eafa0ab613e8c448da0c5a750 --- /dev/null +++ b/src/components/CardMesinRusak/DeleteLaporan.test.js @@ -0,0 +1,61 @@ +import CardMesinRusak from './CardMesinRusak'; +import { fireEvent, render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { BrowserRouter } from 'react-router-dom' +import { Provider } from 'react-redux' +import configureStore from 'redux-mock-store' +import thunk from 'redux-thunk' +import axios from 'axios'; + + +jest.mock('axios') +const middlewares = [thunk] +const mockStore = configureStore(middlewares) + +describe('<CardMesinRusak />', () => { +it('test delete laporan success', () => { + const initialState = { + auth: { + isAuthenticated: true, + user: { + role: "Mitra" + } + } + } + localStorage.setItem('access', 'token') + const store = mockStore(initialState) + const deleteLaporan = jest.fn() + + const laporanData = [ + { + pk: 1, + mainanPengadaan: { + id: 23, + mainan: { + id: 1, + namaMainan: "Kiddie Ride Submarine", + deskripsiMainan: "A SpongeBob theme kid's ride in the shape of a submarine. Available colors: Red, Green, Yellow.", + harga: 11000000.0, + gambarMainan: "http://walkiddie.cs.ui.ac.id/media/mainan/media/pngfind-2.png" + }, + stringMainan: "Kiddie Ride Submarine_23", + status: "RSK", + }, + } + ] + + render( + <Provider store={store}> + <BrowserRouter> + <CardMesinRusak post={laporanData} deleteLaporan={deleteLaporan} /> + </BrowserRouter> + </Provider>); + + axios.delete.mockImplementationOnce(() => Promise.resolve(laporanData)); + const button = screen.getByTestId('hapus'); + fireEvent.click(button); + expect(axios.delete).toHaveBeenCalledTimes(1); + localStorage.removeItem('access', 'token') +}); + +}) \ No newline at end of file diff --git a/src/components/CardsLaporanMesin/CardsLaporanMesin.js b/src/components/CardsLaporanMesin/CardsLaporanMesin.js index 0594fd81aa793e1ed2e35e09635d532c20862810..e81071851d43929f1ac602dff492746f6be0799f 100644 --- a/src/components/CardsLaporanMesin/CardsLaporanMesin.js +++ b/src/components/CardsLaporanMesin/CardsLaporanMesin.js @@ -11,18 +11,17 @@ const CardsLaporanMesin = ({ posts, loading }) => { return ( <CardColumns> {posts.map(post => ( - <Card className="shadow card-flex-item" key={post.pk} + <Card className="shadow card-flex-item" key={post.id} style={{ height : '400px' }} > <Card.Img className="card-pengadaan-img" variant="top" src={post.toko.fotoProfilToko}/> <Card.Body> - <Card.Title className="card-content-limit card-title card-pengadaan-image"> - {post.toko.namaToko} {post.toko.namaCabang !== "" ? <span> - {post.toko.namaCabang}</span> : ""} - </Card.Title> - <Card.Text> - <p className="card-content-limit">{post.toko.deskripsiToko}</p> + <Card.Title className="card-content-limit card-title card-pengadaan-image"> + {post.toko.namaToko} - {post.toko.namaCabang} </Card.Title> + <Card.Text className="card-content-limit"> + {post.toko.deskripsiToko} </Card.Text> <a href={"/mesin-rusak/"+post.pk} className="custom-card-walkiddie"> <button className="wkd-nav-button wkd-blue-button"> diff --git a/src/components/CardsLaporanMesin/CardsLaporanMesin.test.js b/src/components/CardsLaporanMesin/CardsLaporanMesin.test.js index 5cd962da86a49519c497c3a75127daf528866419..e638f20f431262ba8bda0a8a0f06b2aa2c9be816 100644 --- a/src/components/CardsLaporanMesin/CardsLaporanMesin.test.js +++ b/src/components/CardsLaporanMesin/CardsLaporanMesin.test.js @@ -12,6 +12,56 @@ const middlewares = [thunk] const mockStore = configureStore(middlewares) describe('<CardsLaporanMesin />', () => { + it('not loading when card test', () => { + + const mockCurrentPosts = [ + { + "userId": 1, + "id": 1, + "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", + "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto", + "toko": { + "FotoProfilToko":new File(['bebekslamet1'], 'bebekslamet1.png', { type: 'image/png' }) + } + }, + { + "userId": 1, + "id": 2, + "title": "qui est esse", + "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla", + "toko": { + "FotoProfilToko":new File(['bebekslamet1'], 'bebekslamet1.png', { type: 'image/png' }) + } + }, + { + "userId": 1, + "id": 3, + "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut", + "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut", + "toko": { + "FotoProfilToko":new File(['bebekslamet1'], 'bebekslamet1.png', { type: 'image/png' }) + } + } + ] + const initialState = { + auth: { + isAuthenticated: true, + user: { + role: "Mitra" + } + } + } + localStorage.setItem('access', 'token') + const store = mockStore(initialState) + render( + <Provider store={store}> + <BrowserRouter> + <CardsLaporanMesin posts={mockCurrentPosts} loading={false} /> + </BrowserRouter> + </Provider>); + localStorage.removeItem('access', 'token') + }); + it('loading when card test', () => { const mockCurrentPosts = [ diff --git a/src/components/CardsPengadaanInvestor/CardsPengadaanInvestor.js b/src/components/CardsPengadaanInvestor/CardsPengadaanInvestor.js index 9d7ebed827bfe7d11bb0f4b16dd8da314586c4e1..d1c7101595359a7e7c477d5a072e10abccd438f1 100644 --- a/src/components/CardsPengadaanInvestor/CardsPengadaanInvestor.js +++ b/src/components/CardsPengadaanInvestor/CardsPengadaanInvestor.js @@ -1,7 +1,7 @@ import React from 'react'; import './CardsPengadaanInvestor.css'; import emptyIcon from './empty.svg'; -import { Link, Redirect } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import { Row } from "react-bootstrap"; const CardsPengadaanInvestor = ({ posts, loading }) => { @@ -20,7 +20,7 @@ const CardsPengadaanInvestor = ({ posts, loading }) => { <img src={ item.pengadaan.toko.fotoProfilToko } className="owned-pengadaan-profil-img" alt=""></img> <div className="owned-pengadaan-store-name"> { item.pengadaan.toko.namaToko }<br /> - <span style={{ fontWeight: "500", fontSize: "14px" }}>WKD-02ID2021 - {item.pengadaan.toko.namaCabang}</span> + <span style={{ fontWeight: "500", fontSize: "14px" }}>WKD-{item.pengadaan.pk}-{item.pengadaan.toko.namaCabang}</span> </div> </div> <div className="owned-pengadaan-profil-right" style={{color: (item.pengadaan.daftarMainan.some(mainan => mainan.status == 'RSK') ? 'red' : "#146A5F") }}> diff --git a/src/components/PopUpJualSaham/PopUpJualSaham.js b/src/components/PopUpJualSaham/PopUpJualSaham.js index 3c24f03940e3c34aaab36ce4ce2e7945e38736be..004a4e4ae0ad64e4e2e13099d37de304346efb78 100644 --- a/src/components/PopUpJualSaham/PopUpJualSaham.js +++ b/src/components/PopUpJualSaham/PopUpJualSaham.js @@ -1,78 +1,95 @@ +import { useState } from "react"; import {Modal} from 'react-bootstrap'; import React from 'react'; import './PopUpJualSaham.css'; -export default class PopUpJualSaham extends React.Component { - -constructor(props) { - super(props); - this.state = { - open: false +const PopUpJualSaham = ({data, handleSubmit}) => { + let [jumlahLot, setJumlahLot] = useState(data.nominal); + let [hargaSaham, setHargaSaham] = useState((data.pengadaan.totalBiaya * data.nominal / 100)); + const [showModal, setShowModal] = useState(false); + const handleClose = () => setShowModal(false); + const handleOpen = () => { + setShowModal(true); + setDisable(true); } -} -openModal() { - this.setState({open: true}); -} -closeModal() { - this.setState({open: false}); -} + const [disable, setDisable] = useState(true); + const buttonHandler = (e) => { + const isChecked = e.target.checked; + if (isChecked) { + setDisable(false); + } else { + setDisable(true); + } + } -render(){ - return ( + const onChange = e => { + const re = /^[0-9\b]+$/; + if (e.target.value === '' || re.test(e.target.value)) { + if (e.target.name === 'jumlahLot') { + setJumlahLot(e.target.value); + } else { + setHargaSaham(e.target.value); + } + } + } + return ( <div> - <button className="wkd-nav-button wkd-tosca-button jual" onClick={this.openModal.bind(this)}>Jual Investasi</button> - {this.state.open? - <Modal show={this.state.open} - onHide={this.closeModal.bind(this)} - aria-labelledby="ModalHeader" - data-testid="popup" - centered - > + {data.statusInvestasi !== "DJL" && <button id='btn-jual-inves' className="wkd-nav-button wkd-tosca-button" onClick={handleOpen} data-testid="jual-btn">Jual Investasi</button>} + <Modal show={showModal} onHide={handleClose} data-testid="popup" centered> <Modal.Header closeButton> - <p>Jual <span id="investasi">Investasi</span></p> + <p>Jual <span className="jual-red">Investasi</span></p> </Modal.Header> <Modal.Body> <form id="form-jual"> - <label>Jumlah Lot (minimal 1)</label> - <input - id="jumlah-lot" - name="jumlah-lot" - className="jumlah-lot" - type="number" - placeholder="Tuliskan jumlah lot yang ingin dijual..." - step="1" - min="1" - required - /> - <div id="space"></div> - <label>Harga Saham (Rp)</label> - <input - id="harga-saham" - name="harga-saham" - className="harga-saham" - type="number" - placeholder="Tuliskan harga jual saham..." - step="1" - min="0" - required - /> - <div id="space"></div> - <label id="yakin"> - <input - id="persetujuan" - name="persetujuan" - type="checkbox" - required - /><span>Saya yakin untuk menjual kepemilikan saya pada pengadaan ini</span> - </label> + <label><span className="required">*</span> Jumlah Lot (minimal 1, maksimal {data.nominal})</label> + <input + id="jumlahLot" + name="jumlahLot" + className="jumlahLot" + data-testid="jumlahLot" + type="number" + placeholder="Tuliskan jumlah lot yang ingin dijual..." + step="1" + min="1" + max={data.nominal} + value={jumlahLot} + onChange={e => onChange(e)} + required + /> + <div id="space"></div> + <label><span className="required">*</span> Harga Saham (Rp)</label> + <input + id="hargaSaham" + name="hargaSaham" + className="hargaSaham" + data-testid="hargaSaham" + type="number" + placeholder="Tuliskan harga jual saham..." + step="1" + min="0" + value={hargaSaham} + onChange={e => onChange(e)} + required + /> + <div id="space"></div> + <label id="yakin"> + <input + id="persetujuan" + name="persetujuan" + type="checkbox" + data-testid="persetujuan" + onChange={(e) => {buttonHandler(e);}} + /><span>Saya yakin untuk menjual kepemilikan saya pada pengadaan ini</span> + </label> </form> - </Modal.Body> - <Modal.Footer> - <button type="submit" className='wkd-nav-button wkd-tosca-button'>Jual Saham</button> - </Modal.Footer> - </Modal> : ''} + </Modal.Body> + <Modal.Footer> + <button type="submit" id="m-i-buat" disabled={disable} className="wkd-nav-button wkd-tosca-button" onClick={handleSubmit}>Jual Saham</button> + </Modal.Footer> + </Modal> </div> - ) -} + ); } + +export default PopUpJualSaham; diff --git a/src/components/PopUpJualSaham/PopUpJualSaham.test.js b/src/components/PopUpJualSaham/PopUpJualSaham.test.js index 9272d919cc0d6e533bf83782ecad7d7a2661ab6a..410ca6e337d8c73c343facdcc4468effabc1879b 100644 --- a/src/components/PopUpJualSaham/PopUpJualSaham.test.js +++ b/src/components/PopUpJualSaham/PopUpJualSaham.test.js @@ -1,21 +1,67 @@ import PopUpJualSaham from './PopUpJualSaham'; -import { render } from '@testing-library/react'; +import { render, act, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import userEvent from '@testing-library/user-event'; +const sahamData = + { + investor: "investor@gmail.com", + nominal: 100, + pembeli: null, + pengadaan: { toko: { namaToko: "Restoran Walkiddie" }, daftarMainan: [{ stringMainan: "Air Hockey", mainan:{gambarMainan:'', deskripsiMainan:''} }, + ], + totalBiaya:0, status:"" }, + pk: 1, + status: "TRM", + statusInvestasi: "DMK", + statusPembelian: "BDB", + timestamp: "2021-11-18T18:54:54.292187+07:00", + uangInvestasi: 27000000 + }; + describe('<PopUpJualSaham />', () => { - it('popup bisa dibuka dan ditutup', () => { - const { getByText, getByTestId } = render(<PopUpJualSaham />) + it('popup bisa dibuka', () => { + const { getByTestId } = render(<PopUpJualSaham data={sahamData} />) - const btnPopUp = getByText("Jual Investasi"); + const btnPopUp = getByTestId("jual-btn"); userEvent.click(btnPopUp); const popup = getByTestId("popup"); expect(popup).toBeInTheDocument(); - - const btnClosePopUp = getByText('×'); - userEvent.click(btnClosePopUp); - - expect(popup).not.toBeInTheDocument(); + }); + + it('button hanya bisa ditekan ketika checkbox dicentang',() => { + const { getByText, getByTestId } = render(<PopUpJualSaham data={sahamData} />) + + const btnPopUp = getByTestId("jual-btn"); + userEvent.click(btnPopUp); + + const btnJual = getByText("Jual Saham"); + expect(btnJual).toBeDisabled(); + + const checkbox = getByTestId("persetujuan"); + userEvent.click(checkbox); + expect(btnJual).not.toBeDisabled(); + + userEvent.click(checkbox); + expect(btnJual).toBeDisabled(); + }); + it('input hanya berisi angka', () => { + const { getByTestId } = render(<PopUpJualSaham data={sahamData} />); + const btnPopUp = getByTestId("jual-btn"); + userEvent.click(btnPopUp); + + const jumlahLot = getByTestId("jumlahLot"); + const hargaSaham = getByTestId("hargaSaham"); + act(() => { + fireEvent.change(jumlahLot, {target: {value : 1.0}}); + fireEvent.change(hargaSaham, {target: {value : 100000.00}}); + }); + expect(jumlahLot).toHaveValue(1); + expect(hargaSaham).toHaveValue(100000); + act(() => { + fireEvent.change(jumlahLot, {target: {value : '1a'}}); + }); + expect(jumlahLot).toHaveValue(null); }); }) diff --git a/src/page/DetailInvestasi/DetailInvestasi.css b/src/page/DetailInvestasi/DetailInvestasi.css index 9609bc296571e01795556f5ae64e555405aa65f0..b72fecadf89e39e1f37628294048173be076a9e0 100644 --- a/src/page/DetailInvestasi/DetailInvestasi.css +++ b/src/page/DetailInvestasi/DetailInvestasi.css @@ -89,6 +89,140 @@ overflow: auto; } +.modal { + width: 100%; + display: flex; + flex-direction: column; + padding: 0px 20px; + font-family: 'DM Sans', sans-serif; + border-radius: 10px; + box-shadow: 0px 0px 10px rgba(0,0,0,0.25); +} + +.modal .modal-dialog { + max-width: 600px !important; +} + +.modal-header { + font-size: 30px; + margin-top: 16px; + margin-bottom: -5px; + padding: 15px 30px; + font-family: 'DM Sans', sans-serif; + font-weight: 700; + border-bottom: 0 none; +} + +.jual-red { + color: #E94745; +} + +button.close { + color: #fc383f; + font-size: 40px; +} + +button.close:hover { + color: #FA595F; +} + +.modal-body { + padding: 10px 30px; +} + +.modal-body > form { + display: flex; + flex-direction: column; + flex-grow: 3; +} + +.modal-body > form > input { + width: 100%; + padding: 10px 15px; + border-radius: 5px; + border: 0.7px solid black; +} + +.modal-body > form > label { + font-weight: 500; + font-size: 15px; + line-height: 10px; +} + +#space { + padding: 10px; +} + +input[type='checkbox'] { + height: 15px; + width: 15px; + -webkit-appearance: none; + -moz-appearance: none; + -o-appearance: none; + appearance: none; + border: 1px solid black; + border-radius: 4px; + outline: none; + transition-duration: 0.3s; +} + +input[type='checkbox']:hover { + background-color: #d6e1e4; +} + +input[type='checkbox']:checked:hover { + background-color: #0CB6D8; + border: 1px solid #0CB6D8; +} + +input[type='checkbox']:checked { + background-color: #0DCAF0; + border: 1px solid #0DCAF0; +} + +input[type='checkbox']:checked:after { + content: '✔'; + font-size: 12px; + vertical-align: middle; + padding-top: 5px; + padding-left: 2px; + color: white; +} + +#m-i-buat:disabled { + background: #b9b9b9; +} + +#yakin { + padding-left: 10px; + display: inline-block; +} + +#yakin > span { + padding-left: 10px; + font-weight: 300; + vertical-align: middle; +} + +#yakin > input { + vertical-align: middle; +} + +.modal-footer { + border-top: 0 none; + padding: 20px 30px; +} + +.wkd-tosca-button { + background-color: #0DCAF0; + color: white; +} + +.wkd-tosca-button:hover { + background-color: #0CB6D8; + color: white; +} + #tabel-pendapatan thead th { background-color: var(--wkd-blue); color: var(--wkd-white) diff --git a/src/page/DetailInvestasi/DetailInvestasi.js b/src/page/DetailInvestasi/DetailInvestasi.js index 0d14e47632cc57e1f9cad8354debfc173ea51e95..1862812bd254dc0e2b5a332aacfa043e88234cdb 100644 --- a/src/page/DetailInvestasi/DetailInvestasi.js +++ b/src/page/DetailInvestasi/DetailInvestasi.js @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; import axios from 'axios'; -import { Row ,Dropdown} from "react-bootstrap"; +import { Row, Dropdown } from "react-bootstrap"; import { ChevronLeft } from 'react-feather'; import Table from 'react-bootstrap/Table'; import Tabs from 'react-bootstrap/Tabs' @@ -15,6 +15,11 @@ import CardMainan from '../../components/CardMainan/CardMainan'; import WalkiddieOnboarding from '../../components/OnBoarding/WalkiddieOnboarding'; import PopUpJualSaham from '../../components/PopUpJualSaham/PopUpJualSaham'; +export let utils = { + getJumlahLotVal: getJumlahLot, + getHargaSahamVal: getHargaSaham +} + function statusReadable(status) { if (status === 'RSK') { return 'Dalam Perbaikan'; @@ -77,14 +82,14 @@ const DetailInvestasi = ({ isAuthenticated, user, location }) => { target: '#total-card', }, { - content: 'Tekan untuk jual investasi ini.', + content: 'Anda juga dapat menjual investasi ini.', placement: 'bottom', styles: { options: { width: 300, }, }, - target: '#btn-jual-inves', + target: '#jual-inves', }, ]; @@ -99,7 +104,6 @@ const DetailInvestasi = ({ isAuthenticated, user, location }) => { const email = user.email; let totalPendapatan = 0; const [filter, setFilter] = useState('Harian'); - const [sellmode, setSellmode] = useState(false); const handleSelect = (e) => { setFilter(e) } @@ -217,32 +221,94 @@ const DetailInvestasi = ({ isAuthenticated, user, location }) => { ], }; - const handleSubmit = async () => { - const config1 = { - headers: { - 'Authorization': `JWT ${localStorage.getItem('access')}`, - } + const handleSubmit = () => { + jumlahLot = utils.getJumlahLotVal(); + hargaSaham = utils.getHargaSahamVal(); + if (jumlahLot == '' || hargaSaham == '' ) { + alert('Masukkan input') + } else { + jumlahLot = Number.parseInt(jumlahLot); + hargaSaham = Number.parseInt(hargaSaham); + if (jumlahLot < 1 || jumlahLot > data.nominal || hargaSaham < 0) { + alert('Input tidak valid, periksa kembali input Anda') + } else { + setFormData({jumlahLot: jumlahLot, hargaSaham:hargaSaham }); + if (jumlahLot == data.nominal) { + postJualSaham(); + } else { + postJualSahamSebagian(); } - await axios.patch(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/${data.pk}/jual/`, {}, config1); - console.log(data); - window.history.back(); + } + } + } + const config1 = { + headers: { + 'Authorization': `JWT ${localStorage.getItem('access')}`, } + } + const postJualSaham = async () => { + var formDataToSend = new FormData(); - const handleCancel = async () => { - const config2 = { - headers: { - 'Authorization': `JWT ${localStorage.getItem('access')}`, - } - } - await axios.patch(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/${data.pk}/cancel-jual/`, {}, config2); - console.log(data); + formDataToSend.append('pk', data.pk); + formDataToSend.append('hargaSaham', hargaSaham); + formDataToSend.append('nominal', data.nominal); + formDataToSend.append('pengadaan', data.pengadaan.pk); + + await axios.patch(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/${data.pk}/jual/`, formDataToSend, config1); + alert('Investasi Anda telah dijual'); + window.history.back(); + } + const config2 = { + headers: { + 'Content-Type': 'application/json', + 'Authorization': `JWT ${localStorage.getItem('access')}`, + } + } + const postJualSahamSebagian = async () => { + if (localStorage.getItem('access')) { + var formDataToSend = new FormData(); + + formDataToSend.append('pk', data.pk); + formDataToSend.append('jumlahLot', jumlahLot); + formDataToSend.append('hargaSaham', hargaSaham); + formDataToSend.append('nominal', data.nominal); + formDataToSend.append('pengadaan', data.pengadaan.pk); + console.log(jumlahLot); + console.log(hargaSaham); + try { + axios.post(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/jual-sebagian/`, formDataToSend, config2) + alert('Investasi Anda telah dijual'); window.history.back(); + }catch (error) { + console.log(error.response) + } + } else { + console.log('missing token'); + alert('Terdapat kesalahan pada autentikasi akun anda. Anda dapat melakukan refresh pada halaman ini') + } } + const handleCancel = async () => { + if (window.confirm('Apa Anda yakin ingin membatalkan penjualan saham?')) { + await axios.patch(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/${data.pk}/cancel-jual/`, {}, config1); + console.log(data); + window.history.back(); + } + } + function roundingFloat(number){ return Number(parseFloat(number).toFixed(2)) } + let [formData, setFormData] = useState({ + jumlahLot: data.nominal, + hargaSaham: (data.pengadaan.totalBiaya * data.nominal / 100) + }); + let { + jumlahLot, + hargaSaham + } = formData; + if (!isAuthenticated) return <Redirect to="/masuk" /> if (user.role !== "Investor") return <Redirect to="/" /> @@ -357,22 +423,18 @@ const DetailInvestasi = ({ isAuthenticated, user, location }) => { </Tabs> <br></br> - <div className="col-sm"> - {data.statusInvestasi === "DJL" && <> - <p>Sedang dijual.</p> - <button className="wkd-nav-button wkd-dark-green-button" onClick={() => handleCancel()}>Batalkan Jual</button> - </>} - {!sellmode && data.statusInvestasi !== "DJL" && <button id='btn-jual-inves' className="wkd-nav-button wkd-dark-green-button" onClick={() => setSellmode(true)}>Jual Investasi (Lama)</button>} - {sellmode && <> - <p>Yakin menjual kepemilikan di perusahaan ini?</p> - <br /> - <button className="wkd-nav-button wkd-light-tosca-button" onClick={() => setSellmode(false)}>Batal</button> - <button id="m-i-buat" className="wkd-nav-button wkd-dark-green-button" onClick={() => handleSubmit()}>Jual Saham</button> - </>} - </div> - <br></br> - <PopUpJualSaham/> - </div> + <div id="jual-inves"> + {data.pengadaan.statusProyek === "TRM" && <> + <div className="col-sm"> + {data.statusInvestasi === "DJL" && <> + <p>Sedang dijual.</p> + <button className="wkd-nav-button wkd-tosca-button" onClick={() => handleCancel()}>Batalkan Jual</button> + </>} + </div> + <PopUpJualSaham data={data} handleSubmit={handleSubmit}/> + </>} + </div> + </div> ); } const mapStateToProps = (state) => ({ @@ -381,3 +443,12 @@ const mapStateToProps = (state) => ({ }); export default connect(mapStateToProps)(DetailInvestasi); + + +function getJumlahLot() { + return document.getElementById("jumlahLot").value +} + +function getHargaSaham() { + return document.getElementById("hargaSaham").value +} \ No newline at end of file diff --git a/src/page/DetailInvestasi/DetailInvestasi.test.js b/src/page/DetailInvestasi/DetailInvestasi.test.js index 78f5ef6f5dc540f9d0d2d0b08847e31fb393b1c6..3e2ce94873894e43ae47b473911420986a870a7e 100644 --- a/src/page/DetailInvestasi/DetailInvestasi.test.js +++ b/src/page/DetailInvestasi/DetailInvestasi.test.js @@ -28,7 +28,9 @@ describe('<DetailInvestasi />', () => { <> <Provider store={store}> <BrowserRouter> - <DetailInvestasi location={{state:''}} /> + <DetailInvestasi location={{state: + {pengadaan : {totalBiaya: 0}} + }}/> <Route path="*" render={({location}) => { @@ -60,7 +62,9 @@ describe('<DetailInvestasi />', () => { <> <Provider store={store}> <BrowserRouter> - <DetailInvestasi location={{state:''}}/> + <DetailInvestasi location={{state: + {pengadaan : {totalBiaya: 0}} + }}/> <Route path="*" render={({location}) => { diff --git a/src/page/DetailPengadaan/DetailPengadaan.js b/src/page/DetailPengadaan/DetailPengadaan.js index fa36bfa10f775b1400e326e7f6a0ea3d00af6a6c..9dd6f745ed73323ad7d851f3a7692903d132630d 100644 --- a/src/page/DetailPengadaan/DetailPengadaan.js +++ b/src/page/DetailPengadaan/DetailPengadaan.js @@ -138,7 +138,7 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { const fetchPengadaanInfo = async () => { try { - var pengadaanObj = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/${match.params.pk}`, config); + var pengadaanObj = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/${match.params.pk}`); setPengadaan(pengadaanObj.data); setFilesPengadaan(pengadaanObj.data.files) } @@ -147,7 +147,7 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { alert('Terjadi kesalahan saat fetching data pengadaan') } try{ - const tokoObj = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/${pengadaanObj.data.toko.pk}`, config); + const tokoObj = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/${pengadaanObj.data.toko.pk}`); setToko(tokoObj.data); localStorage.setItem('lat', tokoObj.data.latitude); localStorage.setItem('long', tokoObj.data.longitude); @@ -187,21 +187,7 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { catch (err) { setDisable(false); } - // line 182 `const total = ...` creates TypeError: Reduce of empty array with no initial value. - // Try block abandons execution. Below is a bodgefix for getting disable button to work. - try { - await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/investasi/`, config) - .then(response => { - if(response.data.filter(b => b.investor === userData.email && b.pengadaan === pengadaan.pk && b.status ==="MPA" ).length !== 0){ - setDisable(true); - } else if(pengadaan.danaTerkumpul>=pengadaan.totalBiaya){ - setDisable(true); - } - }); - } - catch (err) { - setDisable(false); - } + } @@ -235,15 +221,13 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { }; - if (!isAuthenticated) { - return (<Redirect to="/masuk" />) - } else if (userData.role == 'Investor' || userData.role == 'Mitra') { + if (!isAuthenticated || userData.role == 'Investor' || userData.role == 'Mitra') { return ( <> <WalkiddieOnboarding steps={onBoardingSteps} /> <div id="wrapper" className="detail-pengadaan-wrapper"> <h3 className="back-button" onClick={() => window.history.back()}><ChevronLeft size="40" className="chevron-left"/>Kembali</h3> - {(userData.role === 'Investor') && !salesInvestasi==[] && + { isAuthenticated && (userData.role === 'Investor') && !salesInvestasi==[] && <div className="justify-content-center detail-pengadaan-content row"> <div className="col-lg-6"> <Link to={{ pathname: "/detail-investasi/"+salesInvestasi.pk, state: salesInvestasi }}> @@ -299,7 +283,7 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { <p className="detail-pengadaan-modal-desc">{pengadaan.estimasiKeuangan}</p> </div> - {(userData.role==='Investor') && + {( isAuthenticated && userData.role==='Investor') && <div id="investasi"> <h3 className="detail-pengadaan-modal-text">Jumlah Investasimu</h3> <p className="detail-pengadaan-midtext"></p> @@ -342,10 +326,13 @@ const DetailPengadaan = ({ isAuthenticated, userData, match}) => { </Row> <Row className="justify-content-center"> <div className="col-sm"> - {!disable && (userData.role === 'Investor') && <a href={"/investasi/"+match.params.pk}><button className="detail-pengadaan-ikut-invest-button" type="button"> + {!isAuthenticated && <a href={"/masuk"}><button className="detail-pengadaan-ikut-invest-button" type="button"> + Ikut Investasi + </button></a>} + {isAuthenticated && !disable && (userData.role === 'Investor') && <a href={"/investasi/"+match.params.pk}><button className="detail-pengadaan-ikut-invest-button" type="button"> Ikut Investasi </button></a>} - {disable && (userData.role === 'Investor') && <button className="detail-pengadaan-ikut-invest-button-disabled" type="button" > + {isAuthenticated && disable && (userData.role === 'Investor') && <button className="detail-pengadaan-ikut-invest-button-disabled" type="button" > Ikut Investasi </button>} </div> diff --git a/src/page/DetailPengadaan/DetailPengadaan.test.js b/src/page/DetailPengadaan/DetailPengadaan.test.js index d535fc11095ea199e9abaccf91aa3fa9d6557c1c..e68fe19bcbbe33bd8e5a9f8874b9551574d3502a 100644 --- a/src/page/DetailPengadaan/DetailPengadaan.test.js +++ b/src/page/DetailPengadaan/DetailPengadaan.test.js @@ -210,9 +210,7 @@ describe('<DetailPengadaan />', () => { localStorage.removeItem('access', 'token') }); - it('should redirect if not authenticated', () => { - let loc; - const mockUser = jest.fn() + it('should display the page if not authenticated', () => { const mockMatch = { params: { pk: 1 @@ -221,27 +219,76 @@ describe('<DetailPengadaan />', () => { const initialState = { auth: { isAuthenticated: false, - user: { - role: "Investor" - } } } + const tokoData = [ + { + daerah: "Pekalongan", + danaTerkumpul: 1500000, + deskripsiToko: "Lorem deskripsi toko. Enak maknyus.", + estimasiKeuangan: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eros justo, placerat non sagittis quis, consequat et elit.", + files: ["http://localhost:8000/media/toko/pengadaan/req1.png", + "http://localhost:8000/media/toko/pengadaan/req1_0ZBCu2D.png" + ], + fotoProfilToko: "http://localhost:8000/media/toko/profil/toko3.png", + latitude: -25.344, + lokasiToko: "Uluru, Australia", + longitude: 131.036, + namaCabang: "Cabang Maros 05", + namaToko: "Restoran Walkiddie", + nomorTelepon: "08123456789", + owner: "mitra@wkd.com", + paketMainan: "Paket A (2 claw machine, 1 kiddie ride)", + periodePengadaanAkhir: "2021-07-11", + periodePengadaanMulai: "2021-06-01", + pk: 1, + pkToko: 1, + tipeUsaha: "Restoran", + toko: 1, + totalBiaya: 1500000 + } + ] + + const pengadaanData = { + data : { + danaTerkumpul: 1500000, + estimasiKeuangan: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eros justo, placerat non sagittis quis, consequat et elit.", + files: "http://localhost:8000/media/toko/pengadaan/req1.png", + paketMainan: "Paket A (2 claw machine, 1 kiddie ride)", + periodePengadaanAkhir: "2021-07-11", + periodePengadaanMulai: "2021-06-01", + pk: 1, + pkToko: 1, + toko: 1, + totalBiaya: 1500000 + } + } + + const investasiData = [ + {}] + + localStorage.setItem('access', 'token') const store = mockStore(initialState) - render( + + var mock = new MockAdapter(axios); + + mock.onGet(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/1`).reply(200, tokoData); + mock.onGet(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/1`).reply(200, pengadaanData); + + const { getByText } = render( <Provider store={store}> <BrowserRouter> - <DetailPengadaan isAuthenticated={false} userData={mockUser} match={mockMatch} /> - <Route - path="*" - render={({ location }) => { - loc = location; - return null; - }} - /> + <DetailPengadaan match={mockMatch} /> </BrowserRouter> </Provider> ); - expect(loc.pathname).toBe('/masuk'); + + expect(getByText('Kebutuhan Modal', {selector: "h3"})).toBeInTheDocument() + expect(getByText('Estimasi Keuangan', {selector: "h3"})).toBeInTheDocument() + expect(getByText('Periode Pengadaan', {selector: "h3"})).toBeInTheDocument() + expect(getByText('Email Penggalang', {selector: "h3"})).toBeInTheDocument() + expect(getByText('Tipe Usaha', {selector: "h3"})).toBeInTheDocument() + expect(getByText('Nomor Telepon Penggalang', {selector: "h3"})).toBeInTheDocument() }); it('should redirect if not investor or mitra', () => { diff --git a/src/page/HomepageInvestor/HomepageInvestor.js b/src/page/HomepageInvestor/HomepageInvestor.js index 72284ab7919d52b35e3132dc1b9196115f02b6e5..a8f2a1fb904130e2db4d3e7bb1fba6e56ddb779c 100644 --- a/src/page/HomepageInvestor/HomepageInvestor.js +++ b/src/page/HomepageInvestor/HomepageInvestor.js @@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react'; import { Row } from "react-bootstrap"; import { connect } from 'react-redux'; import { ChevronLeft, Search } from 'react-feather'; -import { Redirect } from 'react-router-dom'; import Cards from '../../components/Cards/Cards'; import Pagination from '../../components/Pagination/Pagination'; import Card from 'react-bootstrap/Card' @@ -84,24 +83,17 @@ const HomepageInvestor = ({ isAuthenticated, user }) => { postLength = posts.length; } - const config = { - headers: { - 'Content-Type': 'multipart/form-data', - 'Authorization': `JWT ${localStorage.getItem('access')}`, - } - }; - useEffect(() => { const fetchPosts = async () => { try { - var res = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/`, config); + var res = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/`); res = res.data.filter((e) => { if (e['status'] === "TRM") { return e; } }); console.log(res[0]); - var res2 = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/`, config); + var res2 = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/`); res2 = res2.data.filter((e) => { if (e['status'] === "TRM") { return e; @@ -175,7 +167,7 @@ const HomepageInvestor = ({ isAuthenticated, user }) => { const handleChange = async e => { try{ - var res = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/`, config); + var res = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/`); res = res.data.filter((e) => { if (e['status'] === "TRM") { return e @@ -186,7 +178,7 @@ const HomepageInvestor = ({ isAuthenticated, user }) => { alert('Terdapat kesalahan pada database toko.'); }; try{ - var res2 = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/`, config); + var res2 = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/`); res2 = res2.data.filter((e) => { if (e['status'] === "TRM") { return e @@ -239,8 +231,6 @@ const HomepageInvestor = ({ isAuthenticated, user }) => { const paginate = pageNumber => setCurrentPage(pageNumber); - if (!isAuthenticated) return <Redirect to="/masuk" /> - if (user.role !== "Investor") return <Redirect to="/" /> return ( <div className='detail-pengadaan-wrapper' diff --git a/src/page/HomepageInvestor/HomepageInvestor.test.js b/src/page/HomepageInvestor/HomepageInvestor.test.js index 99298f95dfa0fdb928eea6e6a449ed0d854d34a1..c506bfa361deb422901e22371f8fdfb8c75bbdab 100644 --- a/src/page/HomepageInvestor/HomepageInvestor.test.js +++ b/src/page/HomepageInvestor/HomepageInvestor.test.js @@ -7,7 +7,6 @@ import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; -import axiosMock from 'axios'; const middlewares = [thunk] const mockStore = configureStore(middlewares) @@ -53,40 +52,6 @@ describe('<HomepageInvestor />', () => { expect(loc.pathname).toBe('/'); }) - it('should redirect if guest', () => { - let loc; - const mockUser = jest.fn() - const mockAuthenticate = jest.fn() - const initialState = { - auth: { - isAuthenticated: false - } - } - const store = mockStore(initialState) - render( - <> - <Provider store={store}> - <BrowserRouter> - <HomepageInvestor user={mockUser} isAuthenticated={mockAuthenticate} /> - <Route - path="*" - render={({location}) => { - loc = location; - return null; - }} - /> - </BrowserRouter> - </Provider>); - </>, - {initialState: {auth: { - isAuthenticated: false - } - } - } - ); - expect(loc.pathname).toBe('/masuk'); - }) - it('renders the right contents', () => { const mockUser = jest.fn() const mockAuthenticate = jest.fn() @@ -216,7 +181,74 @@ describe('<HomepageInvestor />', () => { localStorage.removeItem('access', 'token') }); + it('still renders the right contents if not authenticated', () => { + + const initialState = { + auth: { + isAuthenticated: false, + } + } + + const tokoData = [ + { + daerah: "Pekalongan", + danaTerkumpul: 1500000, + deskripsiToko: "Lorem deskripsi toko. Enak maknyus.", + estimasiKeuangan: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eros justo, placerat non sagittis quis, consequat et elit.", + files: ["http://localhost:8000/media/toko/pengadaan/req1.png", + "http://localhost:8000/media/toko/pengadaan/req1_0ZBCu2D.png" + ], + fotoProfilToko: "http://localhost:8000/media/toko/profil/toko3.png", + latitude: -25.344, + lokasiToko: "Uluru, Australia", + longitude: 131.036, + namaCabang: "Cabang Maros 05", + namaToko: "Restoran Walkiddie", + nomorTelepon: "08123456789", + owner: "mitra@wkd.com", + paketMainan: "Paket A (2 claw machine, 1 kiddie ride)", + periodePengadaanAkhir: "2021-07-11", + periodePengadaanMulai: "2021-06-01", + pk: 1, + pkToko: 1, + tipeUsaha: "Restoran", + toko: 1, + totalBiaya: 1500000 + } + ] + + const pengadaanData = [ + { + danaTerkumpul: 1500000, + estimasiKeuangan: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eros justo, placerat non sagittis quis, consequat et elit.", + files: ["http://localhost:8000/media/toko/pengadaan/req1.png", + "http://localhost:8000/media/toko/pengadaan/req1_0ZBCu2D.png" + ], + paketMainan: "Paket A (2 claw machine, 1 kiddie ride)", + periodePengadaanAkhir: "2021-07-11", + periodePengadaanMulai: "2021-06-01", + pk: 1, + pkToko: 1, + toko: 1, + totalBiaya: 1500000 + } + ] + + const store = mockStore(initialState) + var mock = new MockAdapter(axios); + + mock.onGet(`${process.env.REACT_APP_BACKEND_API_URL}/api/toko/`).reply(200, tokoData); + mock.onGet(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/`).reply(200, pengadaanData); + render( + <Provider store={store}> + <BrowserRouter> + <HomepageInvestor /> + </BrowserRouter> + </Provider>); + + expect(screen.getByText('Daftar Proyek Pengadaan')).toBeInTheDocument(); + }); test('search pengadaan by nama toko in search field empty result', async() => { diff --git a/src/page/LaporanKerusakan/FormLaporan.js b/src/page/LaporanKerusakan/FormLaporan.js index c1e694680d6ab8f9a047c05a8006a8a4ec6d4259..317cdc1919fd4f5645796f18d83cd2a33da7a034 100644 --- a/src/page/LaporanKerusakan/FormLaporan.js +++ b/src/page/LaporanKerusakan/FormLaporan.js @@ -23,13 +23,13 @@ const FormLaporan = ({ isAuthenticated, userData, navigation, formData, setFormD } const prevStep = () => { - navigation.previous(); + navigation.previous(); } const postLaporan = () => { if (localStorage.getItem('access')) { var formDataToSend = new FormData(); - + formDataToSend.append('mainan_pengadaan', formData['kode']); formDataToSend.append('deskripsi', formData['deskripsi']); formDataToSend.append('level_kerusakan', formData['level']) @@ -43,20 +43,18 @@ const FormLaporan = ({ isAuthenticated, userData, navigation, formData, setFormD window.history.back(); alert('Anda telah membuat laporan kerusakan'); }, (error) => { - alert("Terdapat kesalahan. Silakan mengecek kembali laporan yang Anda masukan dan refresh ulang halaman ini dan perbaiki pengadaan Anda.") + alert("Terdapat kesalahan. Silakan mengecek kembali laporan yang Anda buat. Pastikan mainan yang dilaporkan sudah beroperasi di Toko Anda") }); } else { - console.log('missing token'); alert('Terdapat kesalahan pada autentikasi akun anda. Anda dapat melakukan refresh pada halaman ini') } }; const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value }); - + const handleChangeFile = (event) => { setFormData({ ...formData, bukti: event.target.files }); } - console.log(formData) if (!isAuthenticated) { return <Redirect to='/masuk' /> @@ -67,7 +65,7 @@ const FormLaporan = ({ isAuthenticated, userData, navigation, formData, setFormD return ( <div className=""> <div className='form-container'> - <h3 className="my-5 text-back" onClick={prevStep}><ChevronLeft size="40" className="chevron-left"/>Ubah <span style={{color:"var(--wkd-red-hover)"}}>Mainan</span></h3> + <h3 className="my-5 text-back" data-testid="prev" onClick={prevStep}><ChevronLeft size="40" className="chevron-left"/>Ubah <span style={{color:"var(--wkd-red-hover)"}}>Mainan</span></h3> <Form className="mb-5 profile-styling" onSubmit={handleSubmit}> <Row className="justify-content-center"> <div className="col-lg-7"> @@ -95,16 +93,16 @@ const FormLaporan = ({ isAuthenticated, userData, navigation, formData, setFormD <Form.Group controlId="formFile" role="media" className="mb-3" onChange={e => handleChangeFile(e)} > <Form.Label>Bukti Kerusakan</Form.Label> <Form.Control required={true} type="file" /> - </Form.Group> + </Form.Group> </div> <div className="ml-auto px-3"> <Link to={{pathname:"/mesin-rusak/"+match}}><button className="w-50 lap-form-button mesin-blue-border-button" type="button"> Batalkan - </button></Link> - <button className="w-50 lap-form-button wkd-blue-button" data-testId="Simpan" type="submit"> + </button></Link> + <button className="w-50 lap-form-button wkd-blue-button" data-testid="Simpan" type="submit"> Submit - </button> - </div> + </button> + </div> </div> </div> </Row> diff --git a/src/page/LaporanKerusakan/FormLaporan.test.js b/src/page/LaporanKerusakan/FormLaporan.test.js index bfc0a91c2c720d306a81fc06400f5a60136d9c62..9a06aa6d5ba75ec6ea827363ffae44fe593099e9 100644 --- a/src/page/LaporanKerusakan/FormLaporan.test.js +++ b/src/page/LaporanKerusakan/FormLaporan.test.js @@ -1,20 +1,21 @@ import FormLaporan from './FormLaporan' import '@testing-library/jest-dom'; import { Provider } from 'react-redux'; -import { render, screen, fireEvent, getByTestId } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { BrowserRouter, Route } from 'react-router-dom' -import axios from 'axios' import configureStore from 'redux-mock-store' import thunk from 'redux-thunk' +import axios from 'axios' -jest.mock('axios'); +jest.mock('axios'); const middlewares = [thunk] const mockStore = configureStore(middlewares) describe('<Laporan Kerusakan />', () => { it('renders form', () => { + jest.mock(); const mockUser = jest.fn() const mockAuthenticate = jest.fn() const initialState = { @@ -40,7 +41,193 @@ describe('<Laporan Kerusakan />', () => { expect(screen.getByText("Submit")).toBeInTheDocument(); }); + it('back works', () => { + jest.mock("react-hooks-helper"); + const mockUser = jest.fn() + const mockAuthenticate = jest.fn() + const initialState = { + auth: { + isAuthenticated: true, + user: { + role: "Mitra" + } + } + } + const mockNavigation= { + previous: jest.fn() + } + + const store = mockStore(initialState) + const mockPrev = jest.fn() + render( + <Provider store={store}> + <BrowserRouter> + <FormLaporan user={mockUser} isAuthenticated={mockAuthenticate} prevStep={mockPrev} navigation={mockNavigation} /> + </BrowserRouter> + </Provider>); + const button1 = screen.getByTestId('prev'); + fireEvent.click(button1); + }); + + test('post through form', async() => { + const mockFormData={ + kode: '1', + deskripsi: '', + level: 3, + bukti: [], + } + + const mockUser = jest.fn() + const mockAuthenticate = jest.fn() + const mockSetForm = jest.fn() + //global.URL.createObjectURL = jest.fn(); + const initialState = { + auth: { + isAuthenticated: true, + user: { + email: "user12345@gmail.com", + first_name: "ihsan", + last_name: "azizi", + role: "Mitra" + } + } + } + localStorage.setItem('access', 'token') + const store = mockStore(initialState) + + const { getByLabelText, getByText } = render( + <Provider store={store}> + <BrowserRouter> + <FormLaporan isAuthenticated={mockAuthenticate} user={mockUser} formData={mockFormData} setFormData={mockSetForm}/> + </BrowserRouter> + </Provider>); + + const kerusakanData = { + data: { + mainan_pengadaan: "1", + level_kerusakan:3, + deskripsi: "Mesin Tidak Menyala", + } + } + + axios.post.mockImplementationOnce(() => Promise.resolve(kerusakanData)); + const deskripsi_kerusakan = getByLabelText('Deskripsi Kerusakan'); + const tombolSimpan = getByText("Submit"); + + + + userEvent.type(deskripsi_kerusakan, 'Mesin Tidak Menyala'); + + fireEvent.click(tombolSimpan); + + await(()=> expect(axios.post).toHaveBeenCalledTimes(1)); + localStorage.removeItem('access', 'token') + }); + + test('fail post through form', async() => { + const mockFormData={ + kode: '1', + deskripsi: '', + level: 3, + bukti: [], + } + + const mockUser = jest.fn() + const mockAuthenticate = jest.fn() + const mockSetForm = jest.fn() + const initialState = { + auth: { + isAuthenticated: true, + user: { + email: "user12345@gmail.com", + first_name: "ihsan", + last_name: "azizi", + role: "Mitra" + } + } + } + localStorage.setItem('access', 'token') + const store = mockStore(initialState) + + const { getByLabelText, getByText } = render( + <Provider store={store}> + <BrowserRouter> + <FormLaporan isAuthenticated={mockAuthenticate} user={mockUser} formData={mockFormData} setFormData={mockSetForm}/> + </BrowserRouter> + </Provider>); + + const kerusakanData = { + data: { + mainan_pengadaan: "1", + level_kerusakan:3, + deskripsi: "Mesin Tidak Menyala", + } + } + + axios.post.mockImplementationOnce(() => Promise.reject(kerusakanData)); + const deskripsi_kerusakan = getByLabelText('Deskripsi Kerusakan'); + const tombolSimpan = getByText("Submit"); + + userEvent.type(deskripsi_kerusakan, 'Mesin Tidak Menyala'); + + fireEvent.click(tombolSimpan); + + await(()=> expect(axios.post).toHaveBeenCalledTimes(1)); + localStorage.removeItem('access', 'token') + }); + + test('fail post through form if token missing', async() => { + const mockFormData={ + kode: '1', + deskripsi: '', + level: 3, + bukti: [], + } + + const mockUser = jest.fn() + const mockAuthenticate = jest.fn() + const mockSetForm = jest.fn() + const initialState = { + auth: { + isAuthenticated: true, + user: { + email: "user12345@gmail.com", + first_name: "ihsan", + last_name: "azizi", + role: "Mitra" + } + } + } + const store = mockStore(initialState) + + const { getByLabelText, getByText } = render( + <Provider store={store}> + <BrowserRouter> + <FormLaporan isAuthenticated={mockAuthenticate} user={mockUser} formData={mockFormData} setFormData={mockSetForm}/> + </BrowserRouter> + </Provider>); + + const kerusakanData = { + data: { + mainan_pengadaan: "1", + level_kerusakan:3, + deskripsi: "Mesin Tidak Menyala", + } + } + + axios.post.mockImplementationOnce(() => Promise.reject(kerusakanData)); + const deskripsi_kerusakan = getByLabelText('Deskripsi Kerusakan'); + const tombolSimpan = getByText("Submit"); + + userEvent.type(deskripsi_kerusakan, 'Mesin Tidak Menyala'); + + fireEvent.click(tombolSimpan); + + await(()=> expect(axios.post).toHaveBeenCalledTimes(1)); + }); + it('should redirect if not Mitra', () => { + jest.mock(); let loc; const mockUser = jest.fn() const mockAuthenticate = jest.fn() @@ -115,5 +302,5 @@ describe('<Laporan Kerusakan />', () => { } ); expect(loc.pathname).toBe('/masuk'); - }); + }); }); diff --git a/src/page/LaporanKerusakan/LaporanKerusakan.css b/src/page/LaporanKerusakan/LaporanKerusakan.css index 836eaa22085ce9d44e37f540c5c793012b694526..39ebb8e546335bc6abc4a0ed1cfab19fb1a00ede 100644 --- a/src/page/LaporanKerusakan/LaporanKerusakan.css +++ b/src/page/LaporanKerusakan/LaporanKerusakan.css @@ -1,5 +1,5 @@ -input[type='radio']#pil-mainan { - transform: scale(2); +input[type='radio'].pil-mainan { + transform: scale(3); } .lap-form-button { diff --git a/src/page/LaporanKerusakan/LaporanKerusakan.js b/src/page/LaporanKerusakan/LaporanKerusakan.js index 79fc79e07afe05d3676b817aacfe022b15bbdd17..a3b799c78d87db339c168aa48e7eefb88d962326 100644 --- a/src/page/LaporanKerusakan/LaporanKerusakan.js +++ b/src/page/LaporanKerusakan/LaporanKerusakan.js @@ -25,7 +25,7 @@ const LaporanKerusakan = ({ isAuthenticated, user, match }) => { const { step, navigation } = useStep({ initialStep: 0, steps }); const { id } = step; - + const config = { headers: { 'Content-Type': 'multipart/form-data', @@ -36,15 +36,10 @@ const LaporanKerusakan = ({ isAuthenticated, user, match }) => { const [daftarMainan, setDaftarMainan] = useState([]); const fetchDaftarMainan = async () => { try { - if (!isAuthenticated) return <Redirect to="/masuk" /> - if (user.role !== "Mitra") return <Redirect to="/" /> - var res = await axios.get(`${process.env.REACT_APP_BACKEND_API_URL}/api/pengadaan/${match.params.pk}`, config); - res = res.data.daftarMainan.filter((e) => { if (e.status === "BFS") return e - }); setDaftarMainan(res); @@ -54,29 +49,29 @@ const LaporanKerusakan = ({ isAuthenticated, user, match }) => { }; useEffect(() => { - fetchDaftarMainan(); + fetchDaftarMainan(); }, []); const changeData = mainan => setFormData({...formData, kode: mainan}); - + if (!isAuthenticated) return <Redirect to="/masuk" /> if (user.role !== "Mitra") return <Redirect to="/" /> - + switch (id) { case "pilih mainan": return <PilihanMainan - daftarMainan={daftarMainan} - setState={changeData} + daftarMainan={daftarMainan} + setState={changeData} formData={formData} - navigation={navigation} + navigation={navigation} match={match.params.pk} />; case "isi data": return <FormLaporan - daftarMainan={daftarMainan} + daftarMainan={daftarMainan} formData={formData} - kode={formData['kode']} - setFormData={setFormData} + kode={formData['kode']} + setFormData={setFormData} navigation={navigation} match={match.params.pk} />; diff --git a/src/page/LaporanKerusakan/LaporanKerusakan.test.js b/src/page/LaporanKerusakan/LaporanKerusakan.test.js index cc498b60736abadf9f6decdf66c8dacb6c48e2da..4526682c7122ce02ccb795452a2e3380c7733ab1 100644 --- a/src/page/LaporanKerusakan/LaporanKerusakan.test.js +++ b/src/page/LaporanKerusakan/LaporanKerusakan.test.js @@ -28,7 +28,7 @@ describe('<LaporanKerusakan />', () => { params: { pk: 1 } - } + } const store = mockStore(initialState) render( diff --git a/src/page/LaporanKerusakan/PilihanMainan.js b/src/page/LaporanKerusakan/PilihanMainan.js index 3b01a6e8c9d2ca2811a421560ac526dbce497205..c52c697eb9892c5e7810eaddd852ce8f9ac0ad96 100644 --- a/src/page/LaporanKerusakan/PilihanMainan.js +++ b/src/page/LaporanKerusakan/PilihanMainan.js @@ -5,15 +5,15 @@ import { Link } from 'react-router-dom'; import emptyIcon from '../../empty.svg'; const PilihanMainan = ({ daftarMainan, setState, formData, navigation, match }) => { - + const nextStep = () => { if (formData['kode'] !== "") - navigation.next(); + navigation.next(); else alert("Pilih mainan terlebih dahulu") - } + } console.log(daftarMainan) return ( - <div> + <div> <div className="wkd-home-sect-3-container"> {daftarMainan.length > 0 && <h2 className="midtext" >Pilih Mainan yang Ingin <span style={{color:"var(--wkd-red-hover)"}}>Dilaporkan</span></h2>} <form> @@ -26,9 +26,10 @@ const PilihanMainan = ({ daftarMainan, setState, formData, navigation, match }) deskripsi = {mainan.mainan.deskripsiMainan} id = {mainan.id} setState={setState} - /> - </Col> - )): + /> + <input type="radio" name="filter" className="mt-3 pil-mainan" value={mainan.id} onChange={e => setState(e.currentTarget.value)} /> + </Col> + )): <div className='empty-laporan'> <img src={emptyIcon} alt="empty data"></img> <h5 className="list-null">Semua Mesin Anda di Toko Ini Sedang Rusak</h5> @@ -38,9 +39,9 @@ const PilihanMainan = ({ daftarMainan, setState, formData, navigation, match }) <div className='mt-5'> <Link to={{pathname:"/mesin-rusak/"+match}}><button className="w-50 lap-form-button mesin-blue-border-button" type="button"> Batalkan - </button></Link> - {daftarMainan.length > 0 && <button id="p-m-1-selanjutnya" className=" w-50 lap-form-button wkd-blue-button" onClick={nextStep}>Selanjutnya</button>} - </div> + </button></Link> + {daftarMainan.length > 0 && <button id="p-m-1-selanjutnya" className=" w-50 lap-form-button wkd-blue-button" data-testid='next' onClick={nextStep}>Selanjutnya</button>} + </div> </div> </div> ); diff --git a/src/page/LaporanKerusakan/PilihanMainan.test.js b/src/page/LaporanKerusakan/PilihanMainan.test.js index 03dde16e80447e47f4f7693acc46233b528a5721..d4f47ee937947a39a320ba80b1981a228cf6a6de 100644 --- a/src/page/LaporanKerusakan/PilihanMainan.test.js +++ b/src/page/LaporanKerusakan/PilihanMainan.test.js @@ -1,18 +1,19 @@ import PilihanMainan from './PilihanMainan' import '@testing-library/jest-dom'; import { Provider } from 'react-redux'; -import { render } from '@testing-library/react'; -import { BrowserRouter, Route } from 'react-router-dom' +import { fireEvent, render, screen } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom' import configureStore from 'redux-mock-store' import thunk from 'redux-thunk' -jest.mock('axios'); + +jest.mock("react-hooks-helper"); const middlewares = [thunk] const mockStore = configureStore(middlewares) describe('<PilihanMainan />', () => { - it('renders page', () => { + it('renders page and next when klik button next', () => { const mockUser = jest.fn() const mockAuthenticate = jest.fn() const mockData = [{ @@ -24,6 +25,13 @@ describe('<PilihanMainan />', () => { gambarMainan: "http://walkiddie.cs.ui.ac.id/media/mainan/media/pngfind-2.png" }, }] + const mockFormData={ + kode: '1', + deskripsi: '', + level: 3, + bukti: [], + } + const initialState = { auth: { isAuthenticated: true, @@ -32,16 +40,65 @@ describe('<PilihanMainan />', () => { } } } + + const mockNavigation= { + next: jest.fn() + } + const store = mockStore(initialState) + const mockNext = jest.fn() render( <Provider store={store}> <BrowserRouter> - <PilihanMainan user={mockUser} isAuthenticated={mockAuthenticate} daftarMainan={mockData} /> + <PilihanMainan user={mockUser} isAuthenticated={mockAuthenticate} daftarMainan={mockData} formData={mockFormData} nextStep ={mockNext} navigation={mockNavigation} /> </BrowserRouter> </Provider>); - + const button = screen.getByTestId('next'); + fireEvent.click(button); }); - + it('Dont next because not choose mainan', () => { + const mockUser = jest.fn() + const mockAuthenticate = jest.fn() + const mockData = [{ + mainan: { + id: 1, + namaMainan: "Kiddie Ride Submarine", + deskripsiMainan: "A SpongeBob theme kid's ride in the shape of a submarine. Available colors: Red, Green, Yellow.", + harga: 11000000.0, + gambarMainan: "http://walkiddie.cs.ui.ac.id/media/mainan/media/pngfind-2.png" + }, + }] + const mockFormData={ + kode: '', + deskripsi: '', + level: 3, + bukti: [], + } + + const initialState = { + auth: { + isAuthenticated: true, + user: { + role: "Mitra" + } + } + } + + const mockNavigation= { + next: jest.fn() + } + + const store = mockStore(initialState) + const mockNext = jest.fn() + render( + <Provider store={store}> + <BrowserRouter> + <PilihanMainan user={mockUser} isAuthenticated={mockAuthenticate} daftarMainan={mockData} formData={mockFormData} nextStep ={mockNext} navigation={mockNavigation} /> + </BrowserRouter> + </Provider>); + const button = screen.getByTestId('next'); + fireEvent.click(button); + }); }); \ No newline at end of file diff --git a/src/page/ListLaporanMesin/ListLaporanMesin.js b/src/page/ListLaporanMesin/ListLaporanMesin.js index 696fbc1465ff85d4be80e0d64150f6694d816bb4..24881a22694c545c22376dd87db4d0af2f1dc920 100644 --- a/src/page/ListLaporanMesin/ListLaporanMesin.js +++ b/src/page/ListLaporanMesin/ListLaporanMesin.js @@ -5,7 +5,7 @@ import './ListLaporanMesin.css' import axios from 'axios'; import { Row } from "react-bootstrap"; import { connect } from 'react-redux'; -import { Redirect } from 'react-router-dom'; +import { Link, Redirect } from 'react-router-dom'; import { ChevronLeft } from 'react-feather'; import emptyIcon from '../../empty.svg'; @@ -37,8 +37,6 @@ const ListLaporanMesin = ({ isAuthenticated, user }) => { return e; } }); - console.log(res) - setDaftarPengadaanItems(res); } catch(e) { alert('Terdapat kesalahan pada database. Mohon refresh ulang halaman ini') @@ -56,7 +54,9 @@ const ListLaporanMesin = ({ isAuthenticated, user }) => { return ( <div className=""> <div className="laporan-toko-sect-2"> - <h2 className="text-align-left my-5 " onClick={() => window.history.back()} ><ChevronLeft size="40" className="chevron-left"/>Lihat Laporan Mesin Rusak <span style={{color:'var(--wkd-red-hover)'}}>di Toko Anda!</span></h2> + <Link to="/" style={{color:'black', textDecoration:"none"}}> + <h2 className="text-align-left my-5 " ><ChevronLeft size="40" className="chevron-left"/>Lihat Laporan Mesin Rusak <span style={{color:'var(--wkd-red-hover)'}}>di Toko Anda!</span></h2> + </Link> {daftarPengadaanCurrentPosts.length > 0 ? <div id="h-p-pengadaan" className="list-mesin-toko"> <CardsLaporanMesin posts={daftarPengadaanCurrentPosts} /> <Row @@ -79,7 +79,6 @@ const ListLaporanMesin = ({ isAuthenticated, user }) => { </div>} </div> </div> - ); } diff --git a/src/page/ListMesinRusak/ListMesinRusak.js b/src/page/ListMesinRusak/ListMesinRusak.js index 946c8ebf67eeb2b3d6cdd97ac324920b2ebc87c2..29daca375f36c19987f2ffb3f553a3d1db9bcb02 100644 --- a/src/page/ListMesinRusak/ListMesinRusak.js +++ b/src/page/ListMesinRusak/ListMesinRusak.js @@ -30,7 +30,6 @@ const ListMesinRusak = ({ isAuthenticated, user, match }) => { } }); setListMesinRusak(res) - } catch(e) { alert('Terdapat kesalahan pada database. Mohon refresh ulang halaman ini') } @@ -44,26 +43,26 @@ const ListMesinRusak = ({ isAuthenticated, user, match }) => { return ( <div className="mesin-wrapper my-5"> - <div className=""> + <div className=""> <Link to="/laporan-mesin" style={{color:'black', textDecoration:"none"}}> <h2 className="text-align-left mb-4"><ChevronLeft size="40" className="chevron-left"/> Laporan Mesin <span style={{color:'var(--wkd-red)'}}>Rusak</span></h2> </Link> <Row> {listMesinRusak.length > 0 ? listMesinRusak.map(item =>( <Col md={6} lg={4}> - <CardMesinRusak + <CardMesinRusak fotoKerusakan={item.fotoKerusakan} - deskripsi={item.deskripsi} + deskripsi={item.deskripsi} nama={item.mainanPengadaan.mainan.namaMainan} idLaporan={item.pk} - idMainan={item.mainanPengadaan.mainan.id} + idMainan={item.mainanPengadaan.id} status={item.status} operator={item.operator} level = {item.levelKerusakan} tanggal = {`${new Date(item.timestamp).getDate()} ${monthNames[new Date(item.timestamp).getMonth()]} ${new Date(item.timestamp).getFullYear()}`} /> </Col> - )): + )): <div className='empty-laporan'> <img src={emptyIcon} alt="empty data"></img> <h5 className="list-null">Belum Ada Laporan Kerusakan di Toko Ini</h5> diff --git a/src/page/ListOwnedPengadaan/ListOwnedPengadaan.js b/src/page/ListOwnedPengadaan/ListOwnedPengadaan.js index a36d63df0d01c6500d242a39908d0bd618ac78b7..f973a355f591ba69887d8dc7cc00f25fd1413503 100644 --- a/src/page/ListOwnedPengadaan/ListOwnedPengadaan.js +++ b/src/page/ListOwnedPengadaan/ListOwnedPengadaan.js @@ -129,7 +129,7 @@ const ListOwnedPengadaan = ({ isAuthenticated, user }) => { if (investasiObj.data[i].pengadaan.danaTerkumpul === investasiObj.data[i].pengadaan.totalBiaya && investasiObj.data[i].pengadaan.statusProyek === "TRM") { resultSaham.push(investasiObj.data[i]); } - else { + else if (investasiObj.data[i].status === "TRM") { resultPengadaan.push(investasiObj.data[i]); } } diff --git a/src/page/ListSahamDijual/ListSahamDijual.js b/src/page/ListSahamDijual/ListSahamDijual.js index a419d1de5f256991518b3fe73fe8fd02806b0261..9c7927b961aff4eae0b9529f0e6e6b7389596885 100644 --- a/src/page/ListSahamDijual/ListSahamDijual.js +++ b/src/page/ListSahamDijual/ListSahamDijual.js @@ -62,6 +62,7 @@ const ListSahamDijual = ({ isAuthenticated, user }) => { (result.length === 0) ? setEmpty(true) : setEmpty(false); const data = filterChange(result, searchTerm, 'namaToko'); + (data.length === 0) ? setEmpty(true) : setEmpty(false); setPosts(data); setFilteredPosts(); setLoading(false); diff --git a/src/page/MembuatPendapatan/MembuatPendapatan.css b/src/page/MembuatPendapatan/MembuatPendapatan.css index 0532bc0d9e6b699f3cd64a0b8422a3cf78a5f619..3e5cda2ed811b19bc247da819dd51002987c9c82 100644 --- a/src/page/MembuatPendapatan/MembuatPendapatan.css +++ b/src/page/MembuatPendapatan/MembuatPendapatan.css @@ -4,7 +4,7 @@ /* latin-ext */ .p { text-align: center ; - font-family: 'DM-Sans','sans-serif'; + font-family: 'DM-Sans',sans-serif; } .profile-form{ diff --git a/src/page/MembuatPendapatan/MembuatPendapatan.js b/src/page/MembuatPendapatan/MembuatPendapatan.js index 656505d8b3d1b59558efb88644f27c1c0a0e3f52..72aa7eb96c4b002f3e87a380dce14ab2b579a7d6 100644 --- a/src/page/MembuatPendapatan/MembuatPendapatan.js +++ b/src/page/MembuatPendapatan/MembuatPendapatan.js @@ -8,7 +8,6 @@ import { connect } from 'react-redux'; import { Link, Redirect } from 'react-router-dom'; const Profile = ({ isAuthenticated, userData }) => { - const [loading, setLoading] = useState(false); const config = { headers: { @@ -79,27 +78,9 @@ const Profile = ({ isAuthenticated, userData }) => { window.history.back(); alert('Anda telah memasukan pendapatan pengadaan mainan'); }, (error) => { - if (error.response) { - - console.log("error.response") - console.log(error.response) - - } else if (error.request) { - - console.log("error.request") - console.log(error.request) - - } else if (error.message) { - - console.log("error.message") - console.log(error.message) - - } - console.log(error); alert("Terdapat kesalahan. Pendapatan pengadaan mainan yang Anda lakukan sudah ada. Silakan mengecek kembali tanggal yang Anda masukan dan refresh ulang halaman ini dan perbaiki pengadaan Anda.") }); } else { - console.log('missing token'); alert('Terdapat kesalahan pada autentikasi akun anda. Anda dapat melakukan refresh pada halaman ini') } } @@ -111,7 +92,7 @@ const Profile = ({ isAuthenticated, userData }) => { if (!isAuthenticated) { return <Redirect to='/masuk' /> - }else if (userData.role != 'Mitra'){ + }else if (userData.role !== 'Mitra'){ return (<Redirect to="/" />) } @@ -130,7 +111,6 @@ const Profile = ({ isAuthenticated, userData }) => { </button> </div> </div> - <div className="col-lg-9"> <div className="square-box-2"> <div className="col-sm"> diff --git a/src/page/PengadaanMainan/PengadaanMainan.css b/src/page/PengadaanMainan/PengadaanMainan.css index 0824ee6468e1eb7ac7d57e4792c80906cb4a3e1b..7ab79e2f57e256b0d4603b7eff15baf90dad2f81 100644 --- a/src/page/PengadaanMainan/PengadaanMainan.css +++ b/src/page/PengadaanMainan/PengadaanMainan.css @@ -147,7 +147,7 @@ margin: 0 auto; } .banner p { - font-family: "Gentium Basic"; + font-family: "Gentium Basic", serif; font-size: 19px; text-align: center; color: rgb(0, 0, 0); diff --git a/src/page/Profile/Profile.js b/src/page/Profile/Profile.js index 302c35041cea2cfd3c7c0a174372b8e090139f5c..252325e622862555d082491af43939be88014cd5 100644 --- a/src/page/Profile/Profile.js +++ b/src/page/Profile/Profile.js @@ -55,7 +55,6 @@ const Profile = ({ userData, isAuthenticated }) => { } today = yyyy + '-' + mm + '-' + dd; const tanggalMax = today; - console.log(role) useEffect(() => { const fetchData = async () => { diff --git a/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.js b/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.js index a883f0cc62e5ea4527da3a5bdd2273a7f1f82d1b..b171171de14b2c78b81b0eefa2391292410113a2 100644 --- a/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.js +++ b/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.js @@ -55,16 +55,15 @@ const UpdateLaporanKerusakan = ({ isAuthenticated, userData, match}) => { else{ formDataToSend.append('deskripsi', deskripsi); } - + axios.put(`${process.env.REACT_APP_BACKEND_API_URL}/api/laporan/${pk}/update/`, formDataToSend, config) .then((response) => { - window.history.back(); alert('Anda telah mengubah laporan kerusakan'); + window.location.reload(); }, (error) => { alert("Terdapat kesalahan. Silakan mengecek kembali laporan yang Anda masukan dan refresh ulang halaman ini dan perbaiki pengadaan Anda.") }); } else { - console.log('missing token'); alert('Terdapat kesalahan pada autentikasi akun anda. Anda dapat melakukan refresh pada halaman ini') } }; @@ -73,7 +72,7 @@ const UpdateLaporanKerusakan = ({ isAuthenticated, userData, match}) => { if (!isAuthenticated) { return <Redirect to='/masuk' /> - }else if (userData.role != 'Mitra'){ + }else if (userData.role !== 'Mitra'){ return (<Redirect to="/" />) }else if (status === 'ASG' || status === 'RSV'){ return (<Redirect to="/laporan-mesin" />) @@ -82,7 +81,9 @@ const UpdateLaporanKerusakan = ({ isAuthenticated, userData, match}) => { return ( <div className="form-container"> <Form className="profile-styling" onSubmit={handleSubmit}> - <h3 className="profile-header" onClick={() => window.history.back()}><ChevronLeft size="40" className="chevron-left"/>Ubah Laporan Kerusakan Mesin</h3> + <Link to={{pathname:"/mesin-rusak/"+pengadaan}} style={{color:'black', textDecoration:"none"}}> + <h3 className="profile-header"><ChevronLeft size="40" className="chevron-left"/>Ubah Laporan Kerusakan Mesin</h3> + </Link> <Row className="justify-content-center"> <div className="col-lg-7"> <div className="square-box-2"> diff --git a/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.test.js b/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.test.js index b2f1567d1b2237d6b25989f9213f9f440ce3ef77..3c6389c4ccb42f12d14d075e4415b62de86ca92a 100644 --- a/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.test.js +++ b/src/page/UpdateLaporanKerusakan/UpdateLaporanKerusakan.test.js @@ -173,7 +173,7 @@ describe('<UpdateLaporanKerusakan />', () => { axios.put.mockImplementationOnce(() => Promise.resolve(kerusakanData)); userEvent.type(deskripsi_kerusakan, 'Mesin Tidak Menyala'); - + fireEvent.click(tombolSimpan); await(()=> expect(axios.put).toHaveBeenCalledTimes(1)); @@ -225,34 +225,4 @@ describe('<UpdateLaporanKerusakan />', () => { localStorage.removeItem('access', 'token') }); - test('back button work correctly', () => { - const mockUser = jest.fn() - const mockAuthenticate = jest.fn() - const initialState = { - auth: { - isAuthenticated: true, - user: { - role: "Mitra" - } - } - } - - localStorage.setItem('access', 'token') - const store = mockStore(initialState) - const historyBack = jest.spyOn(window.history, 'back'); - historyBack.mockImplementation(() => { }); - - const { getByText } = render( - <Provider store={store}> - <BrowserRouter> - <UpdateLaporanKerusakan userData={mockUser} isAuthenticated={mockAuthenticate} /> - </BrowserRouter> - </Provider>); - const backButton = getByText('Ubah Laporan Kerusakan Mesin', { selector: "h3" }); - userEvent.click(backButton); - - expect(historyBack).toHaveBeenCalledTimes(1); - historyBack.mockRestore() - }) - }); \ No newline at end of file