diff --git a/src/assets/icons/ico/profile.svg b/src/assets/icons/ico/profile.svg new file mode 100644 index 0000000000000000000000000000000000000000..aff18fe54813cc5f5777ce35bf1ecfb93fc533a7 --- /dev/null +++ b/src/assets/icons/ico/profile.svg @@ -0,0 +1,5 @@ +<svg width="42" height="42" viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="18.5" cy="18.5" r="18" stroke="white"/> +<circle cx="18.5" cy="13.5" r="5.5" fill="white"/> +<path d="M8 26C8 22.4735 9.60771 19.4852 13 19C14.3163 20.1296 16.5 21 18.5 21C22 21 22.5 20 24 19C27.3923 19.4852 29 22.4735 29 26V27C29 27 25 28 18.5 28C12 28 8 27 8 27V26Z" fill="white"/> +</svg> diff --git a/src/assets/icons/visu/profileType/finish.svg b/src/assets/icons/visu/profileType/finish.svg new file mode 100644 index 0000000000000000000000000000000000000000..183f71af5baefcf5659a460b7bbab4d741b62903 --- /dev/null +++ b/src/assets/icons/visu/profileType/finish.svg @@ -0,0 +1,51 @@ +<svg width="122" height="120" viewBox="0 0 122 120" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M14.949 96.3467L47.2925 34.2589L81.1894 73.6924L14.949 96.3467Z" fill="#F1C017"/> +<path d="M14.949 96.3467L47.2925 34.2589L81.1894 73.6924L14.949 96.3467Z" fill="url(#paint0_linear)" fill-opacity="0.75"/> +<ellipse cx="64.6199" cy="53.6501" rx="26" ry="4.5" transform="rotate(49.3178 64.6199 53.6501)" fill="url(#paint1_radial)"/> +<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="14" y="34" width="68" height="63"> +<path d="M14.9481 96.3477L47.2915 34.2599L81.1884 73.6934L14.9481 96.3477Z" fill="url(#paint2_linear)"/> +</mask> +<g mask="url(#mask0)"> +<path d="M50.4959 51.6839L47.4674 53.9425L48.6796 57.5207L45.5957 55.3383L42.5672 57.5969L43.6898 53.9896L40.6059 51.8072L44.3836 51.7601L45.5061 48.1528L46.7183 51.731L50.4959 51.6839Z" fill="#E75503"/> +<path d="M53.9503 66.0391L53.4346 71.9651L58.9113 74.2867L53.1159 75.6276L52.6003 81.5536L49.5342 76.4562L43.7389 77.7971L47.6393 73.3059L44.5732 68.2086L50.0499 70.5302L53.9503 66.0391Z" fill="#E75503"/> +<path d="M73.9141 72.9168L72.5893 76.0504L75.1602 78.2787L71.7706 77.9871L70.4458 81.1207L69.6757 77.8069L66.2861 77.5153L69.1997 75.7588L68.4296 72.445L71.0005 74.6733L73.9141 72.9168Z" fill="#E75503"/> +<path d="M38.7962 69.3335L33.3093 70.209L32.4464 75.6978L29.9183 70.75L24.4314 71.6255L28.3558 67.6921L25.8276 62.7443L30.7812 65.2612L34.7056 61.3278L33.8427 66.8166L38.7962 69.3335Z" fill="#E75503"/> +<path d="M35.5569 90.1813L32.3892 90.6867L31.891 93.8555L30.4314 90.9991L27.2638 91.5045L29.5294 89.2337L28.0698 86.3772L30.9296 87.8302L33.1952 85.5594L32.6971 88.7283L35.5569 90.1813Z" fill="#E75503"/> +</g> +<g clip-path="url(#clip0)"> +<path d="M63.2257 24.0809C63.2644 22.5569 63.1814 21.033 63.1371 19.5091C63.0984 17.9741 63.1593 16.4502 63.2312 14.9207C63.2976 13.452 63.4746 11.9392 64.4207 10.7576C64.7029 10.4042 65.1123 10.1999 65.5051 9.99559C65.7707 9.85756 66.2189 9.74161 66.4236 9.52075C66.5398 9.39928 66.4236 8.95204 66.407 8.84713C66.3184 8.32811 66.1967 7.80909 66.0584 7.30112C65.9201 6.79314 65.7707 6.28516 65.5826 5.78823C65.6047 5.84345 65.3281 5.12566 65.2562 5.19743C65.0736 5.39069 64.6863 5.49559 64.4539 5.61154C64.0832 5.79928 63.6793 5.99253 63.3806 6.28516C62.3791 7.28455 62.1302 8.86921 62.0251 10.2109C61.7816 13.3195 62.0085 16.4115 61.9919 19.5257C61.9697 22.5514 61.2615 25.3453 59.6349 27.9183C58.0692 30.3864 55.8782 32.4073 53.6485 34.268C53.5323 34.3674 53.654 34.8643 53.6651 34.9416C53.7481 35.4606 53.8754 35.9796 54.0137 36.4876C54.0413 36.5981 54.7274 38.6631 54.8159 38.5913C57.0124 36.7637 59.1148 34.787 60.7027 32.3962C62.3681 29.895 63.1482 27.0735 63.2257 24.0809Z" fill="#F28D61"/> +<path d="M78.0039 62.9962C79.0164 65.4422 81.2461 65.6299 83.6639 65.9281C86.3749 66.2594 88.3003 65.4643 90.624 64.1281C91.8246 63.4379 92.9754 62.7643 94.3199 62.3999C93.999 62.3336 93.6781 62.2729 93.3572 62.2066C93.7943 62.3447 94.2314 62.4882 94.6685 62.6263C95.3988 62.8637 96.1457 63.079 96.8926 63.2281C99.1942 63.6809 102.221 64.5477 104.334 63.1563C104.251 63.2115 101.889 62.5103 101.64 62.4717C101.009 62.3778 99.4598 61.9416 98.8623 62.3336C97.5067 62.814 97.6949 63.0514 99.4377 63.0569C99.0006 62.9189 98.5635 62.7753 98.1264 62.6373C97.1582 62.3281 96.1678 62.0851 95.1719 61.8974C93.4513 61.5716 91.5093 61.1631 89.7443 61.3784C88.0292 61.5882 86.6239 62.4551 85.1577 63.3054C84.0954 63.9183 83.0442 64.487 81.8823 64.8901C80.2391 65.2269 81.1908 65.4643 84.7372 65.5968C84.0456 65.2987 83.7413 64.4373 83.4813 63.8134C82.9944 62.6539 78.2086 63.4986 78.0039 62.9962Z" fill="#F2EC61"/> +<path d="M72.952 50.0429C76.0061 51.2742 76.1278 46.3656 77.1956 44.6705C78.8942 41.976 82.3964 46.0122 84.5818 43.6877C85.3675 42.8539 85.1793 41.1975 85.2181 40.1594C85.2845 38.2656 85.799 36.1398 87.3814 34.9361C88.3939 34.1686 89.8711 34.1631 91.0772 34.0748C92.9749 33.9367 94.9501 33.749 96.5159 32.5785C99.2214 30.5521 96.3001 26.1625 98.2698 23.8766C98.906 23.1367 100.599 23.6558 101.396 23.722C103.293 23.8711 104.666 23.076 105.578 21.4472C106.336 20.0889 106.696 18.5926 107.891 17.5104C108.815 16.6766 110.198 16.8643 111.338 16.9748C112.351 17.0742 113.468 17.2785 114.425 16.8312C115.449 16.3508 115.239 14.7662 115.139 13.8883C115.106 13.6177 115.067 13.3416 115.023 13.0711C114.929 12.4306 114.868 11.5748 114.536 11.0005C114.464 10.8735 114.514 12.0827 114.536 12.2263C114.885 14.5508 110.077 13.4686 109.02 13.4962C105.883 13.5791 105.711 17.814 103.852 19.5257C102.679 20.6079 100.942 20.365 99.5036 20.1938C98.4468 20.0668 97.6833 20.1662 97.2462 21.2153C96.0069 24.2024 98.5243 28.0067 94.8782 29.8232C92.2391 31.1373 88.5764 29.8785 86.3136 31.9435C85.1793 32.9815 84.7478 34.8036 84.5929 36.2558C84.449 37.6306 84.8197 39.414 83.7906 40.5073C81.6771 42.749 78.5345 38.6907 76.5981 41.2858C75.3477 42.9643 75.4971 47.9281 72.3545 46.6582C72.6865 46.7852 72.2106 49.7447 72.952 50.0429Z" fill="#EF61F2"/> +<path d="M74.1645 31.8446C75.9405 31.7066 74.8173 29.3048 74.9225 28.2281C75.094 26.5164 77.7552 27.6318 78.2587 25.9864C78.4357 25.3956 77.9489 24.6391 77.7165 24.1256C77.296 23.1925 77.0304 22.044 77.5062 21.0833C77.8105 20.4704 78.5243 20.1115 79.0831 19.7802C79.9683 19.2612 80.8757 18.698 81.3515 17.7538C82.1703 16.125 79.7027 14.7005 80.1066 13.1269C80.2394 12.6189 81.18 12.4643 81.5839 12.3042C82.5355 11.9232 83.0113 11.2109 83.0611 10.206C83.0998 9.36673 82.9117 8.55507 83.2326 7.74894C83.4816 7.12501 84.1953 6.88206 84.7707 6.6612C85.2797 6.46795 85.8773 6.29679 86.2258 5.85507C86.6076 5.36918 86.1207 4.65691 85.8607 4.25384C85.7777 4.13237 85.6947 4.00538 85.6062 3.8839C85.407 3.59679 85.1691 3.19924 84.8703 3.00047C84.8039 2.9563 85.1193 3.53053 85.1635 3.59127C85.8939 4.6293 83.3045 5.25875 82.8011 5.52378C81.3017 6.31335 82.2423 8.40599 81.7554 9.67593C81.4455 10.4821 80.5492 10.7802 79.8134 11.0397C79.2712 11.233 78.9282 11.4649 78.9669 12.0778C79.0831 13.817 81.2187 15.0538 79.8909 16.8042C78.9282 18.0686 76.8589 18.3391 76.2614 19.8796C75.9626 20.6526 76.195 21.6354 76.4661 22.3753C76.7261 23.071 77.3347 23.8496 77.0968 24.6226C76.6155 26.2127 74.1202 25.0035 73.8104 26.7207C73.6112 27.8305 74.8727 30.1937 73.0469 30.3373C73.2516 30.3318 73.7329 31.8778 74.1645 31.8446Z" fill="#61F26F"/> +<path d="M84.3942 54.7639C85.6335 56.0393 86.7677 53.6375 87.664 53.0356C89.0915 52.0749 89.938 54.8301 91.5259 54.1565C92.0957 53.9135 92.3668 53.0577 92.6103 52.5497C93.0584 51.6277 93.7777 50.689 94.8178 50.4405C95.4873 50.2804 96.2176 50.6007 96.8317 50.816C97.8 51.1583 98.8125 51.5007 99.8471 51.2577C101.629 50.8436 101.142 48.0387 102.613 47.3375C103.089 47.1111 103.809 47.735 104.19 47.9393C105.092 48.4252 105.944 48.3313 106.752 47.7295C107.427 47.2215 107.93 46.5645 108.755 46.2884C109.397 46.0786 110.038 46.4706 110.575 46.7743C111.051 47.0393 111.565 47.3872 112.13 47.3706C112.738 47.3596 112.982 46.5313 113.126 46.0731C113.17 45.9295 113.209 45.7859 113.247 45.6424C113.341 45.3056 113.496 44.8694 113.458 44.516C113.447 44.4332 113.209 45.0461 113.192 45.1178C112.854 46.3436 110.719 44.7589 110.193 44.5436C108.628 43.9031 107.615 45.9571 106.326 46.3988C105.513 46.6804 104.705 46.178 104.035 45.7804C103.537 45.4878 103.145 45.3718 102.696 45.7915C101.435 46.9951 101.844 49.4246 99.6479 49.5295C98.06 49.6068 96.5219 48.1878 94.9561 48.7123C94.1705 48.9773 93.5564 49.7835 93.1635 50.4681C92.7929 51.1142 92.5826 52.0804 91.8357 52.3951C90.3031 53.0467 89.6337 50.3577 88.1122 51.2191C87.1273 51.7767 86.1204 54.2614 84.8423 52.9473C84.9751 53.0964 84.0899 54.4547 84.3942 54.7639Z" fill="#F26161"/> +<path d="M65.107 43.136C65.5939 43.2685 66.0753 43.1028 66.529 42.9482C67.1818 42.7219 67.807 42.4127 68.4599 42.1808C68.6148 42.1256 67.5414 40.4912 67.4806 40.4084C67.3699 40.2427 66.446 38.7519 66.1638 38.8568C65.5663 39.0722 64.9909 39.3317 64.4044 39.5636C63.912 39.7568 63.3476 39.9611 62.811 39.8176C62.7446 39.7955 63.0599 40.4415 63.0267 40.3808C63.2591 40.7949 63.5192 41.1979 63.7903 41.59C64.0614 41.982 64.3435 42.3685 64.6534 42.7329C64.764 42.8599 64.9245 43.0863 65.107 43.136Z" fill="#61F28A"/> +<path d="M65.5164 53.9793C65.8207 54.0511 66.1471 53.8523 66.4625 53.6591C66.9106 53.383 67.3477 53.0407 67.7959 52.7646C67.901 52.6984 67.3699 51.318 67.3367 51.2462C67.2813 51.1082 66.8332 49.8438 66.6395 49.9652C66.2301 50.2192 65.8262 50.5174 65.4223 50.7879C65.0848 51.0143 64.6976 51.2573 64.3601 51.18C64.3158 51.1689 64.4596 51.7266 64.4431 51.6714C64.5482 52.0303 64.681 52.3671 64.8193 52.6928C64.9521 53.0241 65.1014 53.3499 65.2619 53.6481C65.3228 53.764 65.4002 53.9517 65.5164 53.9793Z" fill="#F2B861"/> +<path d="M74.5896 7.03599C74.8884 7.10777 75.2204 6.909 75.5357 6.71575C75.9839 6.43967 76.421 6.09734 76.8691 5.82127C76.9742 5.75501 76.4431 4.37464 76.4099 4.30286C76.3546 4.16483 75.9064 2.90041 75.7128 3.02188C75.3034 3.27587 74.8995 3.57403 74.4956 3.84458C74.1526 4.07096 73.7708 4.31391 73.4333 4.23661C73.389 4.22556 73.5329 4.77771 73.5163 4.72802C73.6269 5.08691 73.7542 5.42372 73.8925 5.75501C74.0308 6.0863 74.1692 6.41207 74.3351 6.71023C74.396 6.81513 74.4735 7.00838 74.5896 7.03599Z" fill="#61F0F2"/> +<path d="M119.71 39.4413C120.014 39.5131 120.34 39.3143 120.656 39.121C121.104 38.845 121.541 38.5026 121.989 38.2265C122.094 38.1603 121.563 36.7799 121.53 36.7081C121.475 36.5701 121.027 35.3057 120.833 35.4272C120.423 35.6811 120.02 35.9793 119.616 36.2499C119.273 36.4762 118.885 36.7192 118.553 36.6419C118.509 36.6308 118.653 37.1885 118.636 37.1333C118.747 37.4922 118.874 37.829 119.013 38.1548C119.151 38.4861 119.289 38.8118 119.455 39.11C119.511 39.2259 119.594 39.4137 119.71 39.4413Z" fill="#61F0F2"/> +<path d="M53.1619 26.0022C53.4662 26.0739 53.7926 25.8752 54.108 25.6874C54.5562 25.4114 54.9932 25.069 55.4414 24.7929C55.5465 24.7267 55.0154 23.3463 54.9822 23.2745C54.9268 23.1365 54.4787 21.8721 54.2851 21.9936C53.8756 22.2475 53.4717 22.5457 53.0679 22.8163C52.7304 23.0426 52.3431 23.2856 52.0056 23.2083C51.9613 23.1972 52.1052 23.7549 52.0886 23.6997C52.1937 24.0586 52.3265 24.3954 52.4593 24.7267C52.5976 25.058 52.7414 25.3837 52.9019 25.6819C52.9683 25.7813 53.0457 25.9745 53.1619 26.0022Z" fill="#61F0F2"/> +<path d="M107.111 39.536C107.415 39.6078 107.747 39.409 108.057 39.2157C108.505 38.9397 108.942 38.5973 109.391 38.3213C109.496 38.255 108.965 36.8802 108.931 36.8029C108.876 36.6648 108.428 35.4004 108.234 35.5219C107.825 35.7759 107.426 36.074 107.017 36.3446C106.68 36.571 106.292 36.8139 105.955 36.7366C105.911 36.7256 106.054 37.2832 106.038 37.228C106.143 37.5869 106.276 37.9237 106.408 38.255C106.547 38.5863 106.691 38.9121 106.851 39.2102C106.917 39.3207 106.995 39.5084 107.111 39.536Z" fill="#F2D261"/> +<path d="M78.4188 35.7532L76.9748 35.0133L75.5418 35.7808L75.8018 34.1851L74.6289 33.0642L76.2334 32.8157L76.9361 31.3525L77.6719 32.7992L79.2764 33.02L78.1256 34.163L78.4188 35.7532Z" fill="#61F0F2"/> +<path d="M95.1603 9.68597L95.0663 8.9461L94.4023 8.60377L95.0773 8.28904L95.1991 7.55469L95.7081 8.09579L96.4439 7.97984L96.0843 8.63137L96.4218 9.29947L95.6915 9.16144L95.1603 9.68597Z" fill="#61F0F2"/> +<path d="M95.3433 42.5886L94.613 42.677L94.2755 43.334L93.9657 42.6659L93.2354 42.55L93.772 42.0475L93.6614 41.3242L94.3087 41.6776L94.9616 41.3463L94.8232 42.0641L95.3433 42.5886Z" fill="#61F0F2"/> +<path d="M110.254 60.4238L108.833 59.59L107.35 60.2857L107.698 58.6845L106.575 57.4863L108.213 57.3262L109.01 55.8906L109.668 57.3925L111.278 57.7017L110.05 58.7949L110.254 60.4238Z" fill="#61F0F2"/> +<path d="M69.0132 19.1453L68.9081 18.3116L68.1611 17.9306L68.9191 17.5717L69.0574 16.749L69.6273 17.3564L70.4572 17.2294L70.0533 17.9637L70.4296 18.7091L69.6052 18.5545L69.0132 19.1453Z" fill="#61F0F2"/> +<path d="M116.578 27.6697L115.566 26.9851L114.432 27.4268L114.769 26.2618L114 25.3176L115.217 25.2789L115.876 24.252L116.291 25.4004L117.469 25.7096L116.506 26.455L116.578 27.6697Z" fill="#61F0F2"/> +</g> +<defs> +<linearGradient id="paint0_linear" x1="59.5" y1="75" x2="46.5" y2="49.5" gradientUnits="userSpaceOnUse"> +<stop stop-color="#E28904"/> +<stop offset="1" stop-color="white" stop-opacity="0"/> +</linearGradient> +<radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(72.1199 57.6502) rotate(82.4053) scale(7.56637 43.7168)"> +<stop offset="0.1875" stop-color="#E65503"/> +<stop offset="1" stop-color="#E69709"/> +</radialGradient> +<linearGradient id="paint2_linear" x1="39.2148" y1="75.4881" x2="44.8154" y2="85.8386" gradientUnits="userSpaceOnUse"> +<stop stop-color="#61F0F2"/> +<stop offset="1" stop-color="#48C2C4"/> +</linearGradient> +<clipPath id="clip0"> +<rect width="70" height="63" fill="white" transform="translate(52 3)"/> +</clipPath> +</defs> +</svg> diff --git a/src/components/Charts/AxisBottom.spec.tsx b/src/components/Charts/AxisBottom.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c9c51f1fc3ac8019fb61d732f6b881c1f37a8c43 --- /dev/null +++ b/src/components/Charts/AxisBottom.spec.tsx @@ -0,0 +1,49 @@ +import React from 'react' +import AxisBottom from './AxisBottom' +import { graphData } from '../../../test/__mocks__/datachartData.mock' +import { TimeStep } from 'enum/timeStep.enum' +import { DateTime } from 'luxon' +import { scaleBand, ScaleBand } from 'd3-scale' +import { mount } from 'enzyme' + +const mockXScale: ScaleBand<string> = scaleBand() + .domain(['0', '10']) + .range([0, 100]) + .padding(0.2) + +const mockProps = { + data: graphData.actualData, + xScale: mockXScale, + height: 20, + marginLeft: 10, + marginBottom: 10, + selectedDate: DateTime.fromObject({ year: 2020, month: 11, day: 3 }), +} + +describe('AxisBottom component test', () => { + it('should correctly render YEAR format of AxisBottom', () => { + const wrapper = mount( + <AxisBottom {...mockProps} timeStep={TimeStep.YEAR} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render MONTH format of AxisBottom', () => { + const wrapper = mount( + <AxisBottom {...mockProps} timeStep={TimeStep.MONTH} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render DAY format of AxisBottom without duel', () => { + const wrapper = mount(<AxisBottom {...mockProps} timeStep={TimeStep.DAY} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render DAY format of AxisBottom with duel', () => { + const wrapper = mount( + <AxisBottom {...mockProps} timeStep={TimeStep.DAY} isDuel={true} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/Charts/AxisRight.spec.tsx b/src/components/Charts/AxisRight.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6cdca9d5a0e94fc51035bc5a2d54f99ac06f759b --- /dev/null +++ b/src/components/Charts/AxisRight.spec.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { scaleLinear } from 'd3' +import { FluidType } from 'enum/fluid.enum' +import { mount } from 'enzyme' +import AxisRight from './AxisRight' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const mockProps = { + yScale: scaleLinear(), + fluidTypes: [FluidType.ELECTRICITY], + width: 40, + marginRight: 5, + marginTop: 5, +} + +describe('AxisRight component test', () => { + it('should render correctly AxisRight', () => { + const wrapper = mount(<AxisRight {...mockProps} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/Charts/Bar.spec.tsx b/src/components/Charts/Bar.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6805a9109d21a4be5f5f87d01eace35c2858304d --- /dev/null +++ b/src/components/Charts/Bar.spec.tsx @@ -0,0 +1,69 @@ +import React from 'react' +import { mount } from 'enzyme' +import Bar from './Bar' +import { FluidType } from 'enum/fluid.enum' +import { TimeStep } from 'enum/timeStep.enum' +import { graphData } from '../../../test/__mocks__/datachartData.mock' +import { DateTime } from 'luxon' +import { scaleBand, ScaleBand, scaleLinear } from 'd3' + +describe('Bar component test', () => { + const mockHandleClickData = jest.fn() + const mockXScale: ScaleBand<string> = scaleBand() + .domain( + graphData.actualData.map(d => + d.date.toLocaleString(DateTime.DATETIME_SHORT) + ) + ) + .range([0, 10]) + .padding(0.2) + + const mockParam = { + index: 4, + dataload: graphData.actualData[0], + compareDataload: graphData.actualData[1], + fluidTypes: [FluidType.ELECTRICITY], + timeStep: TimeStep.DAY, + multiFluid: false, + selectedDate: DateTime.fromObject({ year: 2020, month: 11, day: 3 }), + showCompare: false, + handleClickData: mockHandleClickData, + xScale: mockXScale, + yScale: scaleLinear(), + height: 20, + isSwitching: false, + isDuel: false, + } + + it('should correctly render Electricity Bar', () => { + const wrapper = mount( + <Bar {...mockParam} fluidTypes={[FluidType.ELECTRICITY]} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render Water Bar', () => { + const wrapper = mount(<Bar {...mockParam} fluidTypes={[FluidType.WATER]} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render Gas Bar', () => { + const wrapper = mount(<Bar {...mockParam} fluidTypes={[FluidType.GAS]} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render Bar with showCompare', () => { + const wrapper = mount(<Bar {...mockParam} showCompare={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render Bar with isSwitching', () => { + const wrapper = mount(<Bar {...mockParam} isSwitching={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should correctly render Bar with isDuel', () => { + const wrapper = mount(<Bar {...mockParam} isDuel={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/Charts/__snapshots__/AxisBottom.spec.tsx.snap b/src/components/Charts/__snapshots__/AxisBottom.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..872cb0884e8a085bde387e3e186d038a9c19fb1b --- /dev/null +++ b/src/components/Charts/__snapshots__/AxisBottom.spec.tsx.snap @@ -0,0 +1,154 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AxisBottom component test should correctly render DAY format of AxisBottom with duel 1`] = ` +<AxisBottom + data={ + Array [ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + }, + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + }, + Object { + "date": "2020-10-03T00:00:00.000Z", + "value": -1, + "valueDetail": null, + }, + ] + } + height={20} + isDuel={true} + marginBottom={10} + marginLeft={10} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + timeStep={20} + xScale={[Function]} +/> +`; + +exports[`AxisBottom component test should correctly render DAY format of AxisBottom without duel 1`] = ` +<AxisBottom + data={ + Array [ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + }, + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + }, + Object { + "date": "2020-10-03T00:00:00.000Z", + "value": -1, + "valueDetail": null, + }, + ] + } + height={20} + marginBottom={10} + marginLeft={10} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + timeStep={20} + xScale={[Function]} +/> +`; + +exports[`AxisBottom component test should correctly render MONTH format of AxisBottom 1`] = ` +<AxisBottom + data={ + Array [ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + }, + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + }, + Object { + "date": "2020-10-03T00:00:00.000Z", + "value": -1, + "valueDetail": null, + }, + ] + } + height={20} + marginBottom={10} + marginLeft={10} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + timeStep={40} + xScale={[Function]} +/> +`; + +exports[`AxisBottom component test should correctly render YEAR format of AxisBottom 1`] = ` +<AxisBottom + data={ + Array [ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + }, + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + }, + Object { + "date": "2020-10-03T00:00:00.000Z", + "value": -1, + "valueDetail": null, + }, + ] + } + height={20} + marginBottom={10} + marginLeft={10} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + timeStep={50} + xScale={[Function]} +/> +`; diff --git a/src/components/Charts/__snapshots__/AxisRight.spec.tsx.snap b/src/components/Charts/__snapshots__/AxisRight.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..3db811334ff055d2843c60dfb0d82f094d6dba80 --- /dev/null +++ b/src/components/Charts/__snapshots__/AxisRight.spec.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AxisRight component test should render correctly AxisRight 1`] = ` +<AxisRight + fluidTypes={ + Array [ + 0, + ] + } + marginRight={5} + marginTop={5} + width={40} + yScale={[Function]} +/> +`; diff --git a/src/components/Charts/__snapshots__/Bar.spec.tsx.snap b/src/components/Charts/__snapshots__/Bar.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..116a60905cfc7d4a23171b14b7cf8fd3369ae1b5 --- /dev/null +++ b/src/components/Charts/__snapshots__/Bar.spec.tsx.snap @@ -0,0 +1,259 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Bar component test should correctly render Bar with isDuel 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 0, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={true} + isSwitching={false} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={false} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; + +exports[`Bar component test should correctly render Bar with isSwitching 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 0, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={false} + isSwitching={true} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={false} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; + +exports[`Bar component test should correctly render Bar with showCompare 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 0, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={false} + isSwitching={false} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={true} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; + +exports[`Bar component test should correctly render Electricity Bar 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 0, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={false} + isSwitching={false} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={false} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; + +exports[`Bar component test should correctly render Gas Bar 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 2, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={false} + isSwitching={false} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={false} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; + +exports[`Bar component test should correctly render Water Bar 1`] = ` +<Bar + compareDataload={ + Object { + "date": "2020-10-02T00:00:00.000Z", + "value": 61.65554999999999, + "valueDetail": Array [ + 40.21918999999999, + 0.8064649999999999, + 20.629894999999998, + ], + } + } + dataload={ + Object { + "date": "2020-10-01T00:00:00.000Z", + "value": 69.18029999999999, + "valueDetail": Array [ + 45.127739999999996, + 0.9048899999999999, + 23.147669999999998, + ], + } + } + fluidTypes={ + Array [ + 1, + ] + } + handleClickData={[MockFunction]} + height={20} + index={4} + isDuel={false} + isSwitching={false} + multiFluid={false} + selectedDate={"2020-11-03T00:00:00.000+01:00"} + showCompare={false} + timeStep={20} + xScale={[Function]} + yScale={[Function]} +/> +`; diff --git a/src/components/CommonKit/Card/StyledBorderCard.spec.tsx b/src/components/CommonKit/Card/StyledBorderCard.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c3dfb9703695d784cb91dbe93d4a03abff289095 --- /dev/null +++ b/src/components/CommonKit/Card/StyledBorderCard.spec.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledBorderCard from './StyledBorderCard' + +describe('StyledBorderCard component test', () => { + it('should render correctly StyleBorderCard', () => { + const wrapper = mount(<StyledBorderCard />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Card/StyledCard.spec.tsx b/src/components/CommonKit/Card/StyledCard.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5aebe397eed648346dea2183d75d1eb42a1130b1 --- /dev/null +++ b/src/components/CommonKit/Card/StyledCard.spec.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledCard from './StyledCard' +import { FluidType } from 'enum/fluid.enum' + +describe('StyledCard component test', () => { + it('should render correctly Electricty StyledCard', () => { + const wrapper = mount(<StyledCard fluidType={FluidType.ELECTRICITY} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Water StyledCard', () => { + const wrapper = mount(<StyledCard fluidType={FluidType.WATER} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Gas StyledCard', () => { + const wrapper = mount(<StyledCard fluidType={FluidType.GAS} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Card/StyledEcogestureCard.spec.tsx b/src/components/CommonKit/Card/StyledEcogestureCard.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6ea8c344056e5a811338661d24862f216b85c421 --- /dev/null +++ b/src/components/CommonKit/Card/StyledEcogestureCard.spec.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledEcogestureCard from './StyledEcogestureCard' + +describe('StyledEcogestureCard component test', () => { + it('should render correclty new ecogesture StyledEcogestureCard', () => { + const wrapper = mount(<StyledEcogestureCard newEcogesture={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly unlocked StyledEcogestureCard', () => { + const wrapper = mount(<StyledEcogestureCard unlocked={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly border StyledEcogestureCard', () => { + const wrapper = mount(<StyledEcogestureCard border={true} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Card/StyledIconCard.spec.tsx b/src/components/CommonKit/Card/StyledIconCard.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e8d742296b8e6ad23d77b006e59dae91c437089e --- /dev/null +++ b/src/components/CommonKit/Card/StyledIconCard.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledIconCard from './StyledIconCard' +import { FluidType } from 'enum/fluid.enum' + +describe('StyledIconCard component test', () => { + it('it should render correctly StyledIconCard', () => { + const wrapper = mount(<StyledIconCard fluidType={FluidType.ELECTRICITY} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Card/__snapshots__/StyledBorderCard.spec.tsx.snap b/src/components/CommonKit/Card/__snapshots__/StyledBorderCard.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..5da16e6b78dfc4aecea6d8b208df24b2bd89841c --- /dev/null +++ b/src/components/CommonKit/Card/__snapshots__/StyledBorderCard.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledBorderCard component test should render correctly StyleBorderCard 1`] = `<StyledBorderCard />`; diff --git a/src/components/CommonKit/Card/__snapshots__/StyledCard.spec.tsx.snap b/src/components/CommonKit/Card/__snapshots__/StyledCard.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..5d0d39416eca9070294430421b7e184ce602b89c --- /dev/null +++ b/src/components/CommonKit/Card/__snapshots__/StyledCard.spec.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledCard component test should render correctly Electricty StyledCard 1`] = ` +<StyledCard + fluidType={0} +/> +`; + +exports[`StyledCard component test should render correctly Gas StyledCard 1`] = ` +<StyledCard + fluidType={2} +/> +`; + +exports[`StyledCard component test should render correctly Water StyledCard 1`] = ` +<StyledCard + fluidType={1} +/> +`; diff --git a/src/components/CommonKit/Card/__snapshots__/StyledEcogestureCard.spec.tsx.snap b/src/components/CommonKit/Card/__snapshots__/StyledEcogestureCard.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..c8ef6bad8a55f6c6fef09e885210f3f603073f37 --- /dev/null +++ b/src/components/CommonKit/Card/__snapshots__/StyledEcogestureCard.spec.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledEcogestureCard component test should render correclty new ecogesture StyledEcogestureCard 1`] = ` +<StyledEcogestureCard + newEcogesture={true} +/> +`; + +exports[`StyledEcogestureCard component test should render correctly border StyledEcogestureCard 1`] = ` +<StyledEcogestureCard + border={true} +/> +`; + +exports[`StyledEcogestureCard component test should render correctly unlocked StyledEcogestureCard 1`] = ` +<StyledEcogestureCard + unlocked={true} +/> +`; diff --git a/src/components/CommonKit/Card/__snapshots__/StyledIconCard.spec.tsx.snap b/src/components/CommonKit/Card/__snapshots__/StyledIconCard.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..f9d8af05dbf5a9930b9cef8c760805c376c15b97 --- /dev/null +++ b/src/components/CommonKit/Card/__snapshots__/StyledIconCard.spec.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledIconCard component test it should render correctly StyledIconCard 1`] = ` +<StyledIconCard + fluidType={0} +/> +`; diff --git a/src/components/CommonKit/ExpansionPanel/StyledSampleExpansionPanel.spec.tsx b/src/components/CommonKit/ExpansionPanel/StyledSampleExpansionPanel.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6410c9e39135b28fb5c706eeb3ad6f5836265a4f --- /dev/null +++ b/src/components/CommonKit/ExpansionPanel/StyledSampleExpansionPanel.spec.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import { mount } from 'enzyme' +import GenericExpansionPanel from './StyledSampleExpansionPanel' + +describe('StyleSampleExpansionPanel component test', () => { + const mockOnChange = jest.fn() + + const mockProps = { + summary: <>Summary</>, + details: <>details</>, + onChange: mockOnChange, + } + + it('should render expanded panel correclty', () => { + const wrapper = mount( + <GenericExpansionPanel + summary={mockProps.summary} + details={mockProps.details} + expanded={true} + onChange={mockProps.onChange} + /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render a not expanded panel correclty', () => { + const wrapper = mount( + <GenericExpansionPanel + summary={mockProps.summary} + details={mockProps.details} + expanded={false} + onChange={mockProps.onChange} + /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/ExpansionPanel/__snapshots__/StyledSampleExpansionPanel.spec.tsx.snap b/src/components/CommonKit/ExpansionPanel/__snapshots__/StyledSampleExpansionPanel.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..9c650f553ac309cdd79626ffd357a74dfc779056 --- /dev/null +++ b/src/components/CommonKit/ExpansionPanel/__snapshots__/StyledSampleExpansionPanel.spec.tsx.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyleSampleExpansionPanel component test should render a not expanded panel correclty 1`] = ` +<GenericExpansionPanel + details={ + <React.Fragment> + details + </React.Fragment> + } + expanded={false} + onChange={[MockFunction]} + summary={ + <React.Fragment> + Summary + </React.Fragment> + } +/> +`; + +exports[`StyleSampleExpansionPanel component test should render expanded panel correclty 1`] = ` +<GenericExpansionPanel + details={ + <React.Fragment> + details + </React.Fragment> + } + expanded={true} + onChange={[MockFunction]} + summary={ + <React.Fragment> + Summary + </React.Fragment> + } +/> +`; diff --git a/src/components/CommonKit/Icon/StyledIcon.spec.tsx b/src/components/CommonKit/Icon/StyledIcon.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..737e4c756c54de1a4ee64b6c72577aa5ef299dbe --- /dev/null +++ b/src/components/CommonKit/Icon/StyledIcon.spec.tsx @@ -0,0 +1,23 @@ +import { mount } from 'enzyme' +import React from 'react' +import StyledIcon from './StyledIcon' + +describe('StyledIcon component test', () => { + it('should render correctly Icon', () => { + const mockProps = { + className: 'className', + icon: 'icon', + size: 10, + } + + const wrapper = mount( + <StyledIcon + className={mockProps.className} + icon={mockProps.icon} + size={mockProps.size} + /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Icon/__snapshots__/StyledIcon.spec.tsx.snap b/src/components/CommonKit/Icon/__snapshots__/StyledIcon.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..d0fc8b8724902ba99b9ab064d4e7b29f06822dfb --- /dev/null +++ b/src/components/CommonKit/Icon/__snapshots__/StyledIcon.spec.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledIcon component test should render correctly Icon 1`] = ` +<StyledIcon + className="className" + icon="icon" + size={10} +/> +`; diff --git a/src/components/CommonKit/IconButton/StyledIconBorderedButton.spec.tsx b/src/components/CommonKit/IconButton/StyledIconBorderedButton.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e6dd16f77facd44685da0743503f8994661458a7 --- /dev/null +++ b/src/components/CommonKit/IconButton/StyledIconBorderedButton.spec.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { shallow } from 'enzyme' +import StyledIconBorderedButton from './StyledIconBorderedButton' + +describe('StyledIconBorderedButton component test', () => { + const mockProps = { + icon: 'icon', + size: 20, + } + + it('should render correctly UnselectedIconButtonBase ', () => { + const wrapper = shallow( + <StyledIconBorderedButton icon={mockProps.icon} size={mockProps.size} /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly SelectedIconButtonBase', () => { + const wrapper = shallow( + <StyledIconBorderedButton + icon={mockProps.icon} + size={mockProps.size} + selected={true} + /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/IconButton/StyledIconButton.spec.tsx b/src/components/CommonKit/IconButton/StyledIconButton.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..11546e02eea4a27a97e478845edf43c1d7ad0562 --- /dev/null +++ b/src/components/CommonKit/IconButton/StyledIconButton.spec.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import { shallow } from 'enzyme' +import StyledIconButton from './StyledIconButton' + +describe('StyledIconButton component test', () => { + it('should render correctly StyledIconButton', () => { + const mockProps = { + icon: 'icon', + size: 15, + } + + const wrapper = shallow( + <StyledIconButton icon={mockProps.icon} size={mockProps.size} /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/IconButton/__snapshots__/StyledIconBorderedButton.spec.tsx.snap b/src/components/CommonKit/IconButton/__snapshots__/StyledIconBorderedButton.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..0dfb7695256f24e5b5e98e5fa64817030cfa1d05 --- /dev/null +++ b/src/components/CommonKit/IconButton/__snapshots__/StyledIconBorderedButton.spec.tsx.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledIconBorderedButton component test should render correctly SelectedIconButtonBase 1`] = ` +<React.Fragment> + <WithStyles(WithStyles(WithStyles(IconButton)))> + <StyledIcon + icon="icon" + size={20} + /> + </WithStyles(WithStyles(WithStyles(IconButton)))> +</React.Fragment> +`; + +exports[`StyledIconBorderedButton component test should render correctly UnselectedIconButtonBase 1`] = ` +<React.Fragment> + <WithStyles(WithStyles(WithStyles(IconButton)))> + <StyledIcon + icon="icon" + size={20} + /> + </WithStyles(WithStyles(WithStyles(IconButton)))> +</React.Fragment> +`; diff --git a/src/components/CommonKit/IconButton/__snapshots__/StyledIconButton.spec.tsx.snap b/src/components/CommonKit/IconButton/__snapshots__/StyledIconButton.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..73252ba88e3bdc33eeb5c14579713960fb0d31df --- /dev/null +++ b/src/components/CommonKit/IconButton/__snapshots__/StyledIconButton.spec.tsx.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledIconButton component test should render correctly StyledIconButton 1`] = ` +<WithStyles(WithStyles(IconButton))> + <StyledIcon + icon="icon" + size={15} + /> +</WithStyles(WithStyles(IconButton))> +`; diff --git a/src/components/CommonKit/Modal/Modal.spec.tsx b/src/components/CommonKit/Modal/Modal.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b1edc4d5519808c4adf1c9607d91b226016a4ff0 --- /dev/null +++ b/src/components/CommonKit/Modal/Modal.spec.tsx @@ -0,0 +1,60 @@ +import React, { ReactNode } from 'react' +import { mount } from 'enzyme' +import Modal from './Modal' + +describe('Modal component test', () => { + const mockHandleCloseClick = jest.fn() + + const mockProps = { + open: true, + handleCloseClick: mockHandleCloseClick(), + } + + it('should render correctly the open Modal', () => { + const wrapper = mount( + <Modal open={true} handleCloseClick={mockProps.handleCloseClick}> + <></> + </Modal> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly the closed Modal', () => { + const wrapper = mount( + <Modal open={false} handleCloseClick={mockProps.handleCloseClick}> + <></> + </Modal> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Modal without border', () => { + const wrapper = mount( + <Modal + open={true} + handleCloseClick={mockProps.handleCloseClick} + border={false} + > + <></> + </Modal> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly the yellow border open Modal', () => { + const wrapper = mount( + <Modal + open={true} + handleCloseClick={mockProps.handleCloseClick} + yellowBorder={true} + > + <></> + </Modal> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Modal/__snapshots__/Modal.spec.tsx.snap b/src/components/CommonKit/Modal/__snapshots__/Modal.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..4ee6ebb213dd1dc45865e39b4733e3a3da1348e5 --- /dev/null +++ b/src/components/CommonKit/Modal/__snapshots__/Modal.spec.tsx.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Modal component test should render correctly Modal without border 1`] = ` +<Modal + border={false} + open={true} +> + <React.Fragment /> +</Modal> +`; + +exports[`Modal component test should render correctly the closed Modal 1`] = ` +<Modal + open={false} +> + <React.Fragment /> +</Modal> +`; + +exports[`Modal component test should render correctly the open Modal 1`] = ` +<Modal + open={true} +> + <React.Fragment /> +</Modal> +`; + +exports[`Modal component test should render correctly the yellow border open Modal 1`] = ` +<Modal + open={true} + yellowBorder={true} +> + <React.Fragment /> +</Modal> +`; diff --git a/src/components/CommonKit/Spinner/Spinner.spec.tsx b/src/components/CommonKit/Spinner/Spinner.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..868a8370ca545d8d192e37d1b1571c796e0a478c --- /dev/null +++ b/src/components/CommonKit/Spinner/Spinner.spec.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import { mount } from 'enzyme' +import Spinner from './Spinner' + +describe('Spinner component test ', () => { + const mockProps = { + size: 14, + } + + it('should render correctly Spinner', () => { + const wrapper = mount(<Spinner size={mockProps.size} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Spinner/StyledBlackSpinner.spec.tsx b/src/components/CommonKit/Spinner/StyledBlackSpinner.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..80e83b0a9ff734e3f0d96d12e41d2038a43028ee --- /dev/null +++ b/src/components/CommonKit/Spinner/StyledBlackSpinner.spec.tsx @@ -0,0 +1,11 @@ +import { mount } from 'enzyme' +import React from 'react' + +import StyledBlackSpinner from './StyledBlackSpinner' + +describe('StyledBlackSpinner component test', () => { + it('should render correclty StyledBlackSpinner', () => { + const wrapper = mount(<StyledBlackSpinner />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Spinner/StyledSpinner.spec.tsx b/src/components/CommonKit/Spinner/StyledSpinner.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..04eb1d137d0af4d3ad83d5b8f3b4f761cd221280 --- /dev/null +++ b/src/components/CommonKit/Spinner/StyledSpinner.spec.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledSpinner from './StyledSpinner' +import { FluidType } from 'enum/fluid.enum' + +describe('StyledSpinner component test', () => { + it('should render correctly base StyledSpinner (with option home)', () => { + const wrapper = mount( + <StyledSpinner isHome={true} fluidTypes={[FluidType.ELECTRICITY]} /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly base StyledSpinner (with empty FluidType)', () => { + const wrapper = mount(<StyledSpinner fluidTypes={[]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Electricty StyledSpinner', () => { + const wrapper = mount( + <StyledSpinner fluidTypes={[FluidType.ELECTRICITY]} /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Water StyledSpinner', () => { + const wrapper = mount(<StyledSpinner fluidTypes={[FluidType.WATER]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Gas StyledSpinner', () => { + const wrapper = mount(<StyledSpinner fluidTypes={[FluidType.GAS]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Spinner/__snapshots__/Spinner.spec.tsx.snap b/src/components/CommonKit/Spinner/__snapshots__/Spinner.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..1d209b97fa03772a710d1b4ca6edcaaf6610f659 --- /dev/null +++ b/src/components/CommonKit/Spinner/__snapshots__/Spinner.spec.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Spinner component test should render correctly Spinner 1`] = ` +<Spinner + size={14} +/> +`; diff --git a/src/components/CommonKit/Spinner/__snapshots__/StyledBlackSpinner.spec.tsx.snap b/src/components/CommonKit/Spinner/__snapshots__/StyledBlackSpinner.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..f37195d63a69872c3d7531c7c25996d9707e66d1 --- /dev/null +++ b/src/components/CommonKit/Spinner/__snapshots__/StyledBlackSpinner.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledBlackSpinner component test should render correclty StyledBlackSpinner 1`] = `<StyledBlackSpinner />`; diff --git a/src/components/CommonKit/Spinner/__snapshots__/StyledSpinner.spec.tsx.snap b/src/components/CommonKit/Spinner/__snapshots__/StyledSpinner.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..3c24f946f43ec6972836499048631e1b1c9ecd04 --- /dev/null +++ b/src/components/CommonKit/Spinner/__snapshots__/StyledSpinner.spec.tsx.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledSpinner component test should render correctly Electricty StyledSpinner 1`] = ` +<StyledSpinner + fluidTypes={ + Array [ + 0, + ] + } +/> +`; + +exports[`StyledSpinner component test should render correctly Gas StyledSpinner 1`] = ` +<StyledSpinner + fluidTypes={ + Array [ + 2, + ] + } +/> +`; + +exports[`StyledSpinner component test should render correctly Water StyledSpinner 1`] = ` +<StyledSpinner + fluidTypes={ + Array [ + 1, + ] + } +/> +`; + +exports[`StyledSpinner component test should render correctly base StyledSpinner (with empty FluidType) 1`] = ` +<StyledSpinner + fluidTypes={Array []} +/> +`; + +exports[`StyledSpinner component test should render correctly base StyledSpinner (with option home) 1`] = ` +<StyledSpinner + fluidTypes={ + Array [ + 0, + ] + } + isHome={true} +/> +`; diff --git a/src/components/CommonKit/Switch/StyledSwitch.spec.tsx b/src/components/CommonKit/Switch/StyledSwitch.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..62636bb9d1a3d71a29ea6e3b835e5e2e398d4b3d --- /dev/null +++ b/src/components/CommonKit/Switch/StyledSwitch.spec.tsx @@ -0,0 +1,24 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledSwitch from './StyledSwitch' +import { FluidType } from 'enum/fluid.enum' + +describe('StyledSwitch component test', () => { + it('should render correctly electricty StyledSwitch', () => { + const wrapper = mount(<StyledSwitch fluidTypes={[FluidType.ELECTRICITY]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly water StyledSwitch', () => { + const wrapper = mount(<StyledSwitch fluidTypes={[FluidType.WATER]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly gas StyledSwitch', () => { + const wrapper = mount(<StyledSwitch fluidTypes={[FluidType.GAS]} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Switch/__snapshots__/StyledSwitch.spec.tsx.snap b/src/components/CommonKit/Switch/__snapshots__/StyledSwitch.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..0cc1aa2535ce3ac66822550e3cc2107161e3e309 --- /dev/null +++ b/src/components/CommonKit/Switch/__snapshots__/StyledSwitch.spec.tsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledSwitch component test should render correctly electricty StyledSwitch 1`] = ` +<StyledSwitch + fluidTypes={ + Array [ + 0, + ] + } +/> +`; + +exports[`StyledSwitch component test should render correctly gas StyledSwitch 1`] = ` +<StyledSwitch + fluidTypes={ + Array [ + 2, + ] + } +/> +`; + +exports[`StyledSwitch component test should render correctly water StyledSwitch 1`] = ` +<StyledSwitch + fluidTypes={ + Array [ + 1, + ] + } +/> +`; diff --git a/src/components/CommonKit/Tabs/StyledBlueTab.spec.tsx b/src/components/CommonKit/Tabs/StyledBlueTab.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..58176f5e596c9d36bed121c7c9b76e843eec0210 --- /dev/null +++ b/src/components/CommonKit/Tabs/StyledBlueTab.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledBlueTab from './StyledBlueTab' + +describe('StyledBlueTab component test', () => { + it('should render correctly StyledBlueTab', () => { + const wrapper = mount(<StyledBlueTab />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Tabs/StyledBlueTab.tsx b/src/components/CommonKit/Tabs/StyledBlueTab.tsx index 2cd74cecbe37b17649f9c800ef09c3ebe1c3e58b..4c02d37e99773afdafbdfd769f03c8ca4f139f1d 100644 --- a/src/components/CommonKit/Tabs/StyledBlueTab.tsx +++ b/src/components/CommonKit/Tabs/StyledBlueTab.tsx @@ -12,12 +12,12 @@ const TabBase = withStyles({ }, })(Tab) -type StyledWhiteTabProps = TabProps +type StyledBlueTabProps = TabProps -const StyledWhiteTab: React.ComponentType<StyledWhiteTabProps> = ({ +const StyledBlueTab: React.ComponentType<StyledBlueTabProps> = ({ ...props -}: StyledWhiteTabProps) => { +}: StyledBlueTabProps) => { return <TabBase {...props}>{props.children}</TabBase> } -export default StyledWhiteTab +export default StyledBlueTab diff --git a/src/components/CommonKit/Tabs/StyledBlueTabs.spec.tsx b/src/components/CommonKit/Tabs/StyledBlueTabs.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..06027fe52b3dac3c3b85de2bb30a9dcc92c003cf --- /dev/null +++ b/src/components/CommonKit/Tabs/StyledBlueTabs.spec.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledBlueTabs from './StyledBlueTabs' + +describe('StyledBlueTabs component test', () => { + it('should render correctly StyledBlueTabs', () => { + const mockValue = 'value' + const wrapper = mount(<StyledBlueTabs value={mockValue} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Tabs/StyledBlueTabs.tsx b/src/components/CommonKit/Tabs/StyledBlueTabs.tsx index cdf8671a948b7cbf1810af947f6a258c8f9b9feb..9c3f42c0fafceaeeba867e0254e9501f6b1bd48f 100644 --- a/src/components/CommonKit/Tabs/StyledBlueTabs.tsx +++ b/src/components/CommonKit/Tabs/StyledBlueTabs.tsx @@ -22,12 +22,12 @@ const TabsBase = withStyles({ }, })(Tabs) -type StyledWhiteTabsProps = TabsProps +type StyledBlueTabsProps = TabsProps -const StyledWhiteTabs: React.ComponentType<StyledWhiteTabsProps> = ({ +const StyledBlueTabs: React.ComponentType<StyledBlueTabsProps> = ({ ...props -}: StyledWhiteTabsProps) => { +}: StyledBlueTabsProps) => { return <TabsBase {...props}>{props.children}</TabsBase> } -export default StyledWhiteTabs +export default StyledBlueTabs diff --git a/src/components/CommonKit/Tabs/StyledTab.spec.tsx b/src/components/CommonKit/Tabs/StyledTab.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..35bde0a87d2c33fa322c5e8b62f13b11d099d631 --- /dev/null +++ b/src/components/CommonKit/Tabs/StyledTab.spec.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledTab from './StyledTab' +import { FluidType } from 'enum/fluid.enum' + +describe('StyledTab component test', () => { + it('should render correctly TabBase (with multiFluid option)', () => { + const wrapper = mount( + <StyledTab fluidTypes={[FluidType.ELECTRICITY]} multiFluid={true} /> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Electricty Tab', () => { + const wrapper = mount( + <StyledTab fluidTypes={[FluidType.ELECTRICITY]} multiFluid={false} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Water Tab', () => { + const wrapper = mount( + <StyledTab fluidTypes={[FluidType.WATER]} multiFluid={false} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Gas Tab', () => { + const wrapper = mount( + <StyledTab fluidTypes={[FluidType.GAS]} multiFluid={false} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly TabBase (with empty fluidType)', () => { + const wrapper = mount(<StyledTab fluidTypes={[]} multiFluid={false} />) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Tabs/StyledWhiteTab.spec.tsx b/src/components/CommonKit/Tabs/StyledWhiteTab.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..19dbef9c5377440be44773e4e90d1d1e0da16584 --- /dev/null +++ b/src/components/CommonKit/Tabs/StyledWhiteTab.spec.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledWhiteTab from './StyledBlueTab' + +describe('StyledWhiteTab component test', () => { + it('should render correctly StyledWhiteTab', () => { + const wrapper = mount(<StyledWhiteTab />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Tabs/StyledWhiteTabs.spec.tsx b/src/components/CommonKit/Tabs/StyledWhiteTabs.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..baed35f60046f41d9ae5a6c4d83ce3b885113a44 --- /dev/null +++ b/src/components/CommonKit/Tabs/StyledWhiteTabs.spec.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import { mount } from 'enzyme' +import StyledWhiteTabs from './StyledBlueTabs' + +describe('StyledWhiteTabs component test', () => { + it('should render correctly StyledWhiteTabs', () => { + const mockValue = 'value' + const wrapper = mount(<StyledWhiteTabs value={mockValue} />) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTab.spec.tsx.snap b/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTab.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..8ec3e33ae4dad0bcf960c4087c703e7c2ce36e8a --- /dev/null +++ b/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTab.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledBlueTab component test should render correctly StyledBlueTab 1`] = `<StyledBlueTab />`; diff --git a/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTabs.spec.tsx.snap b/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTabs.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..88a6718297d764142f00a6197da8aab6e1ca220b --- /dev/null +++ b/src/components/CommonKit/Tabs/__snapshots__/StyledBlueTabs.spec.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledBlueTabs component test should render correctly StyledBlueTabs 1`] = ` +<StyledBlueTabs + value="value" +/> +`; diff --git a/src/components/CommonKit/Tabs/__snapshots__/StyledTab.spec.tsx.snap b/src/components/CommonKit/Tabs/__snapshots__/StyledTab.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..92d3e9c1106685415158071e161af53313d53c12 --- /dev/null +++ b/src/components/CommonKit/Tabs/__snapshots__/StyledTab.spec.tsx.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledTab component test should render correctly Electricty Tab 1`] = ` +<StyledTab + fluidTypes={ + Array [ + 0, + ] + } + multiFluid={false} +/> +`; + +exports[`StyledTab component test should render correctly Gas Tab 1`] = ` +<StyledTab + fluidTypes={ + Array [ + 2, + ] + } + multiFluid={false} +/> +`; + +exports[`StyledTab component test should render correctly TabBase (with empty fluidType) 1`] = ` +<StyledTab + fluidTypes={Array []} + multiFluid={false} +/> +`; + +exports[`StyledTab component test should render correctly TabBase (with multiFluid option) 1`] = ` +<StyledTab + fluidTypes={ + Array [ + 0, + ] + } + multiFluid={true} +/> +`; + +exports[`StyledTab component test should render correctly Water Tab 1`] = ` +<StyledTab + fluidTypes={ + Array [ + 1, + ] + } + multiFluid={false} +/> +`; diff --git a/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTab.spec.tsx.snap b/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTab.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..b31163024e82d45716b76d5f01e3140b8b6e53ea --- /dev/null +++ b/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTab.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledWhiteTab component test should render correctly StyledWhiteTab 1`] = `<StyledBlueTab />`; diff --git a/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTabs.spec.tsx.snap b/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTabs.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..595d8ad4cb667af45278e1f52f4807050d7e27ff --- /dev/null +++ b/src/components/CommonKit/Tabs/__snapshots__/StyledWhiteTabs.spec.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StyledWhiteTabs component test should render correctly StyledWhiteTabs 1`] = ` +<StyledBlueTabs + value="value" +/> +`; diff --git a/src/components/Connection/ConnectionForm.spec.tsx b/src/components/Connection/ConnectionForm.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5f26c50d31d4584010f59b146462f7a1e38ce91b --- /dev/null +++ b/src/components/Connection/ConnectionForm.spec.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import { mount } from 'enzyme' +import ConnectionForm from './ConnectionForm' +import { fluidStatusConnectedData } from '../../../test/__mocks__/fluidStatusData.mock' + +jest.mock('./OAuthForm.tsx', () => { + return jest.fn(() => { + return <></> + }) +}) + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const mockDispatch = jest.fn() +jest.mock('react-redux', () => ({ + useDispatch: () => mockDispatch, +})) + +describe('ConnectionForm component test', () => { + it('should call ConnectionOAuthForm', () => { + const wrapper = mount( + <ConnectionForm fluidStatus={fluidStatusConnectedData[3]} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should call ConnectionLoginForm', () => { + const wrapper = mount( + <ConnectionForm fluidStatus={fluidStatusConnectedData[0]} /> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/Connection/ConnectionNotFound.spec.tsx b/src/components/Connection/ConnectionNotFound.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9d224a9d4225957c33a4a797f9e836590d98c0ab --- /dev/null +++ b/src/components/Connection/ConnectionNotFound.spec.tsx @@ -0,0 +1,39 @@ +import React from 'react' +import { shallow, mount } from 'enzyme' +import ConnectionNotFound from './ConnectionNotFound' +import StyledButton from 'components/CommonKit/Button/StyledButton' +import MuiButton from '@material-ui/core/Button' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +describe('ConnectionNotFound component test', () => { + const konnectorSlug = 'enedisgrandlyon' + + it('should correctly render connection not found', () => { + const result = shallow( + <ConnectionNotFound konnectorSlug={konnectorSlug} /> + ).getElement() + expect(result).toMatchSnapshot() + }) + + it('should open konnector url when button is clicked', () => { + global.open = jest.fn() + + const wrapper = mount(<ConnectionNotFound konnectorSlug={konnectorSlug} />) + const submitStyledButton = wrapper.find(MuiButton) + submitStyledButton.simulate('click') + + expect(global.open).toHaveBeenCalledWith( + 'http://localhost/#/discover/enedisgrandlyon', + '_blank' + ) + }) +}) diff --git a/src/components/Connection/__snapshots__/ConnectionForm.spec.tsx.snap b/src/components/Connection/__snapshots__/ConnectionForm.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..7458857cd062e7ecfec219a0217dda0fcca09b9e --- /dev/null +++ b/src/components/Connection/__snapshots__/ConnectionForm.spec.tsx.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConnectionForm component test should call ConnectionLoginForm 1`] = ` +<ConnectionForm + fluidStatus={ + Object { + "connection": Object { + "account": null, + "isUpdating": false, + "konnector": null, + "konnectorConfig": Object { + "name": "", + "oauth": false, + "siteLink": "", + "slug": "", + }, + "shouldLaunchKonnector": false, + "trigger": null, + "triggerState": null, + }, + "fluidType": 0, + "lastDataDate": "2020-09-01T00:00:00.000Z", + "status": 200, + } + } +/> +`; + +exports[`ConnectionForm component test should call ConnectionOAuthForm 1`] = ` +<ConnectionForm + fluidStatus={ + Object { + "connection": Object { + "account": null, + "isUpdating": false, + "konnector": null, + "konnectorConfig": Object { + "name": "", + "oauth": true, + "siteLink": "", + "slug": "", + }, + "shouldLaunchKonnector": false, + "trigger": null, + "triggerState": null, + }, + "fluidType": 1, + "lastDataDate": "2020-09-01T00:00:00.000Z", + "status": 200, + } + } +/> +`; diff --git a/src/components/Connection/__snapshots__/ConnectionNotFound.spec.tsx.snap b/src/components/Connection/__snapshots__/ConnectionNotFound.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..6d28de10a5b40adaa3200407a0edaef761b2c5c5 --- /dev/null +++ b/src/components/Connection/__snapshots__/ConnectionNotFound.spec.tsx.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConnectionNotFound component test should correctly render connection not found 1`] = ` +<div + className="knotfound" +> + <div + className="knotfound-text" + > + + KONNECTORCONFIG.NOT_INSTALLED + </div> + <div + className="knotfound-button" + > + <WithStyles(Button) + classes={ + Object { + "label": "text-16-bold", + "root": "btn-highlight", + } + } + onClick={[Function]} + > + KONNECTORCONFIG.BTN_INSTALL + </WithStyles(Button)> + </div> +</div> +`; diff --git a/src/components/ConsumptionNavigator/ActivateHalfHourLoad.spec.tsx b/src/components/ConsumptionNavigator/ActivateHalfHourLoad.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4fead9d01b5b40f1e0b1284329d0838e22c4160a --- /dev/null +++ b/src/components/ConsumptionNavigator/ActivateHalfHourLoad.spec.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import { mount } from 'enzyme' +import ActivateHalfHourLoad from './ActivateHalfHourLoad' +import { Provider } from 'react-redux' +import configureStore from 'redux-mock-store' +import { globalStateData } from '../../../test/__mocks__/globalStateData.mock' +import * as reactRedux from 'react-redux' +import { userChallengeExplo1OnGoing } from '../../../test/__mocks__/userChallengeData.mock' +import MuiButton from '@material-ui/core/Button' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') + +const mockConfigureStore = configureStore([]) +const mockStore = mockConfigureStore({ + ecolyo: { + gloabl: globalStateData, + }, +}) + +describe('ActivateHalfHourLoad component test', () => { + it('should open konnector website when button is clicked', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const wrapper = mount( + <Provider store={mockStore}> + <ActivateHalfHourLoad /> + </Provider> + ) + + global.open = jest.fn() + + wrapper.find(MuiButton).simulate('click') + expect(global.open).toHaveBeenCalledWith( + 'https://mon-compte-particulier.enedis.fr/donnees/', + '_blank' + ) + }) + + it('should render correctly ActivatehalfHourLoad', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const wrapper = mount( + <Provider store={mockStore}> + <ActivateHalfHourLoad /> + </Provider> + ) + + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx b/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f5c62fbfa3366eeb602ee4647882c681a86c0bc9 --- /dev/null +++ b/src/components/ConsumptionNavigator/ConsumptionNavigator.spec.tsx @@ -0,0 +1,90 @@ +import React from 'react' +import { mount } from 'enzyme' +import ConsumptionNavigator from './ConsumptionNavigator' +import { FluidType } from 'enum/fluid.enum' +import { TimeStep } from 'enum/timeStep.enum' +import configureStore from 'redux-mock-store' +import { globalStateData } from '../../../test/__mocks__/globalStateData.mock' +import { Provider } from 'react-redux' +import * as reactRedux from 'react-redux' +import { userChallengeExplo1OnGoing } from '../../../test/__mocks__/userChallengeData.mock' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') + +const mockHandleClickTimeStep = jest.fn() + +const mockConfigureStore = configureStore([]) +const mockStore = mockConfigureStore({ + ecolyo: { + gloabl: globalStateData, + }, +}) + +const mockProps = { + multiFluid: false, + timeStep: TimeStep.DAY, + handleClickTimeStep: mockHandleClickTimeStep, +} + +describe('ConsumptionNavigator component test', () => { + it('should render correctly Electricty ConsumptionNavigator', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const wrapper = mount( + <Provider store={mockStore}> + <ConsumptionNavigator + {...mockProps} + fluidTypes={[FluidType.ELECTRICITY]} + /> + </Provider> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly Water ConsumptionNavigator', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const wrapper = mount( + <Provider store={mockStore}> + <ConsumptionNavigator {...mockProps} fluidTypes={[FluidType.WATER]} /> + </Provider> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correclty Gas ConsumptionNavigator', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const wrapper = mount( + <Provider store={mockStore}> + <ConsumptionNavigator {...mockProps} fluidTypes={[FluidType.GAS]} /> + </Provider> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) + + it('should render correctly ConsumptionNavigator with multifluid option', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + + const mockMultiFluidProps = { ...mockProps, multiFluid: true } + const wrapper = mount( + <Provider store={mockStore}> + <ConsumptionNavigator + {...mockMultiFluidProps} + fluidTypes={[FluidType.MULTIFLUID]} + /> + </Provider> + ) + expect(wrapper.getElement()).toMatchSnapshot() + }) +}) diff --git a/src/components/ConsumptionNavigator/__snapshots__/ActivateHalfHourLoad.spec.tsx.snap b/src/components/ConsumptionNavigator/__snapshots__/ActivateHalfHourLoad.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..74aaecb0132b62a1ccd63118781ab466c28f21a5 --- /dev/null +++ b/src/components/ConsumptionNavigator/__snapshots__/ActivateHalfHourLoad.spec.tsx.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ActivateHalfHourLoad component test should render correctly ActivatehalfHourLoad 1`] = ` +<Provider + store={ + Object { + "clearActions": [Function], + "dispatch": [Function], + "getActions": [Function], + "getState": [Function], + "replaceReducer": [Function], + "subscribe": [Function], + } + } +> + <ActivateHalfHourLoad /> +</Provider> +`; diff --git a/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap b/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..36ba61b88766e40b3a4102cdd528d1e787970543 --- /dev/null +++ b/src/components/ConsumptionNavigator/__snapshots__/ConsumptionNavigator.spec.tsx.snap @@ -0,0 +1,105 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ConsumptionNavigator component test should render correclty Gas ConsumptionNavigator 1`] = ` +<Provider + store={ + Object { + "clearActions": [Function], + "dispatch": [Function], + "getActions": [Function], + "getState": [Function], + "replaceReducer": [Function], + "subscribe": [Function], + } + } +> + <ConsumptionNavigator + fluidTypes={ + Array [ + 2, + ] + } + handleClickTimeStep={[MockFunction]} + multiFluid={false} + timeStep={20} + /> +</Provider> +`; + +exports[`ConsumptionNavigator component test should render correctly ConsumptionNavigator with multifluid option 1`] = ` +<Provider + store={ + Object { + "clearActions": [Function], + "dispatch": [Function], + "getActions": [Function], + "getState": [Function], + "replaceReducer": [Function], + "subscribe": [Function], + } + } +> + <ConsumptionNavigator + fluidTypes={ + Array [ + 3, + ] + } + handleClickTimeStep={[MockFunction]} + multiFluid={true} + timeStep={20} + /> +</Provider> +`; + +exports[`ConsumptionNavigator component test should render correctly Electricty ConsumptionNavigator 1`] = ` +<Provider + store={ + Object { + "clearActions": [Function], + "dispatch": [Function], + "getActions": [Function], + "getState": [Function], + "replaceReducer": [Function], + "subscribe": [Function], + } + } +> + <ConsumptionNavigator + fluidTypes={ + Array [ + 0, + ] + } + handleClickTimeStep={[MockFunction]} + multiFluid={false} + timeStep={20} + /> +</Provider> +`; + +exports[`ConsumptionNavigator component test should render correctly Water ConsumptionNavigator 1`] = ` +<Provider + store={ + Object { + "clearActions": [Function], + "dispatch": [Function], + "getActions": [Function], + "getState": [Function], + "replaceReducer": [Function], + "subscribe": [Function], + } + } +> + <ConsumptionNavigator + fluidTypes={ + Array [ + 1, + ] + } + handleClickTimeStep={[MockFunction]} + multiFluid={false} + timeStep={20} + /> +</Provider> +`; diff --git a/src/components/Ecogesture/EcogestureCard.tsx b/src/components/Ecogesture/EcogestureCard.tsx index 8058d8017bffa7720e08c0458bf5d26592a20d58..fc0a85d1d58570d08777b20b9f8099d15236342c 100644 --- a/src/components/Ecogesture/EcogestureCard.tsx +++ b/src/components/Ecogesture/EcogestureCard.tsx @@ -17,12 +17,16 @@ const EcogestureCard: React.FC<EcogestureCardProps> = ({ const handleCardclick = () => { handleClick && ecogesture && handleClick(ecogesture) } - const [ecogestureIcon, setEcogestureIcon] = useState() + const [ecogestureIcon, setEcogestureIcon] = useState<string>() useEffect(() => { if (ecogesture) { importIconbyId(ecogesture.id, 'ecogesture').then(icon => { - icon && setEcogestureIcon(icon) + if (icon) { + setEcogestureIcon(icon) + } else { + setEcogestureIcon('') + } }) } }, [ecogesture]) diff --git a/src/components/Ecogesture/EcogestureList.tsx b/src/components/Ecogesture/EcogestureList.tsx index 1466cf0eabd0f84ca2494aa0f5485619741c09bb..df9b88508bbf5a70e8d1644c9a8f3d750168f554 100644 --- a/src/components/Ecogesture/EcogestureList.tsx +++ b/src/components/Ecogesture/EcogestureList.tsx @@ -29,6 +29,7 @@ const EcogesturesList: React.FC = () => { setSelectedEcogesture, ] = useState<Ecogesture | null>(null) const [ecogestures, setEcogestures] = useState<Ecogesture[] | null>(null) + const [isLoaded, setisLoaded] = useState(false) const [openEcogestureModal, setOpenEcogestureModal] = useState(false) const [openNegaWattModal, setOpenNegaWattModal] = useState(false) const [filterbyFluid, setfilterbyFluid] = useState<FluidType | null>(null) @@ -66,7 +67,12 @@ const EcogesturesList: React.FC = () => { toggleDropDown() } const toggleSort = () => { + setisLoaded(false) setascendingSort(prev => !prev) + if (openDropDown == true) { + toggleDropDown() + } + setTimeout(() => setisLoaded(true), 100) } const handleKeypress = ( e: React.KeyboardEvent<HTMLDivElement>, @@ -98,6 +104,7 @@ const EcogesturesList: React.FC = () => { } } loadEcogestures() + setisLoaded(true) return () => { subscribed = false } @@ -105,222 +112,223 @@ const EcogesturesList: React.FC = () => { return ( <div className="ecogesture-root"> - {!ecogestures ? ( - <div className="content-view-loading"> - <StyledChallengeSpinner size="5em" /> - </div> - ) : ( - <> - {openNegaWattModal && ( - <NegaWattModal handleCloseClick={handleNegaWattCloseClick} /> - )} - <div className="negawatt-button-content"> - <div className="filters text-16-normal"> + <> + {openNegaWattModal && ( + <NegaWattModal handleCloseClick={handleNegaWattCloseClick} /> + )} + <div className="negawatt-button-content"> + <div className="filters text-16-normal"> + <div + className="filter-button" + onClick={() => toggleDropDown()} + tabIndex={0} + onBlur={e => { + if (e.relatedTarget === null) toggleDropDown() + }} + > + <MuiButton + classes={{ + root: 'btn-secondary-negative', + label: 'text-14-normal', + }} + > + <StyledIcon icon={SortIcon} size={24} /> + <span + className={ + openDropDown ? 'ecogestures opened' : 'ecogestures' + } + > + {filterbyFluid === null + ? t('ECOGESTURE.FILTER_TITLE') + : t('FLUID.' + FluidType[filterbyFluid] + '.LABEL')} + </span> + </MuiButton> + </div> + <div + className={openDropDown ? 'dropdown opened' : 'dropdown'} + tabIndex={0} + > <div - className="filter-button" - onClick={() => toggleDropDown()} + className={ + filterbyFluid === null ? 'filter filter-active' : 'filter' + } + onClick={() => { + toggleFilter(null) + }} tabIndex={0} - onBlur={e => { - if (e.relatedTarget === null) toggleDropDown() + onKeyPress={e => { + handleKeypress(e, null) }} > - <MuiButton - classes={{ - root: 'btn-secondary-negative', - label: 'text-14-normal', - }} - > - <StyledIcon icon={SortIcon} size={24} /> - <span - className={ - openDropDown ? 'ecogestures opened' : 'ecogestures' - } - > - {filterbyFluid === null - ? t('ECOGESTURE.FILTER_TITLE') - : t('FLUID.' + FluidType[filterbyFluid] + '.LABEL')} - </span> - </MuiButton> + {t('ECOGESTURE.FILTER_TITLE')} + <StyledIcon + className={ + filterbyFluid === null ? 'active checkicon' : 'checkicon' + } + icon={CheckIcon} + size={18} + /> </div> + <div - className={openDropDown ? 'dropdown opened' : 'dropdown'} + onClick={() => { + toggleFilter(FluidType.ELECTRICITY) + }} + className={ + filterbyFluid === FluidType.ELECTRICITY + ? 'filter filter-active' + : 'filter' + } tabIndex={0} + onKeyPress={e => { + handleKeypress(e, FluidType.ELECTRICITY) + }} > - <div + <StyledIcon className={ - filterbyFluid === null ? 'filter filter-active' : 'filter' + filterbyFluid === FluidType.ELECTRICITY + ? 'icon' + : 'active icon' } - onClick={() => { - toggleFilter(null) - }} - tabIndex={0} - onKeyPress={e => { - handleKeypress(e, null) - }} - > - {t('ECOGESTURE.FILTER_TITLE')} - <StyledIcon - className={ - filterbyFluid === null ? 'active checkicon' : 'checkicon' - } - icon={CheckIcon} - size={18} - /> - </div> - - <div - onClick={() => { - toggleFilter(FluidType.ELECTRICITY) - }} + icon={ElecIcon} + size={30} + /> + <span>{t(`FLUID.ELECTRICITY.LABEL`)}</span> + <StyledIcon className={ filterbyFluid === FluidType.ELECTRICITY - ? 'filter filter-active' - : 'filter' + ? 'active checkicon' + : 'checkicon' } - tabIndex={0} - onKeyPress={e => { - handleKeypress(e, FluidType.ELECTRICITY) - }} - > - <StyledIcon - className={ - filterbyFluid === FluidType.ELECTRICITY - ? 'icon' - : 'active icon' - } - icon={ElecIcon} - size={30} - /> - <span>{t(`FLUID.ELECTRICITY.LABEL`)}</span> - <StyledIcon - className={ - filterbyFluid === FluidType.ELECTRICITY - ? 'active checkicon' - : 'checkicon' - } - icon={CheckIcon} - size={18} - /> - </div> - <div - onClick={() => { - toggleFilter(FluidType.WATER) - }} + icon={CheckIcon} + size={18} + /> + </div> + <div + onClick={() => { + toggleFilter(FluidType.WATER) + }} + className={ + filterbyFluid === FluidType.WATER + ? 'filter filter-active' + : 'filter' + } + tabIndex={0} + onKeyPress={e => { + handleKeypress(e, FluidType.WATER) + }} + > + <StyledIcon className={ - filterbyFluid === FluidType.WATER - ? 'filter filter-active' - : 'filter' + filterbyFluid === FluidType.WATER ? 'icon' : 'active icon' } - tabIndex={0} - onKeyPress={e => { - handleKeypress(e, FluidType.WATER) - }} - > - <StyledIcon - className={ - filterbyFluid === FluidType.WATER ? 'icon' : 'active icon' - } - icon={WaterIcon} - size={30} - /> - <span> {t(`FLUID.WATER.LABEL`)}</span> - <StyledIcon - className={ - filterbyFluid === FluidType.WATER - ? 'active checkicon' - : 'checkicon' - } - icon={CheckIcon} - size={18} - /> - </div> - <div - onClick={() => { - toggleFilter(FluidType.GAS) - }} + icon={WaterIcon} + size={30} + /> + <span> {t(`FLUID.WATER.LABEL`)}</span> + <StyledIcon className={ - filterbyFluid === FluidType.GAS - ? 'filter filter-active' - : 'filter' + filterbyFluid === FluidType.WATER + ? 'active checkicon' + : 'checkicon' } - tabIndex={0} - onKeyPress={e => { - handleKeypress(e, FluidType.GAS) - }} - > - <StyledIcon - className={ - filterbyFluid === FluidType.GAS ? 'icon' : 'active icon' - } - icon={GasIcon} - size={30} - /> - <span> {t(`FLUID.GAS.LABEL`)}</span> - <StyledIcon - className={ - filterbyFluid === FluidType.GAS - ? 'active checkicon' - : 'checkicon' - } - icon={CheckIcon} - size={18} - /> - </div> + icon={CheckIcon} + size={18} + /> </div> - - <MuiButton + <div onClick={() => { - toggleSort() + toggleFilter(FluidType.GAS) }} - classes={{ - root: 'btn-secondary-negative btn-order', - label: 'text-14-normal', + className={ + filterbyFluid === FluidType.GAS + ? 'filter filter-active' + : 'filter' + } + tabIndex={0} + onKeyPress={e => { + handleKeypress(e, FluidType.GAS) }} > - <StyledIcon icon={OrderIcon} size={28} /> - </MuiButton> - - <div className="ng-question" onClick={handleNegaWattClick}> - {t('ECOGESTURE.QUESTION_NEGAWATT')} + <StyledIcon + className={ + filterbyFluid === FluidType.GAS ? 'icon' : 'active icon' + } + icon={GasIcon} + size={30} + /> + <span> {t(`FLUID.GAS.LABEL`)}</span> + <StyledIcon + className={ + filterbyFluid === FluidType.GAS + ? 'active checkicon' + : 'checkicon' + } + icon={CheckIcon} + size={18} + /> </div> </div> + + <MuiButton + onClick={() => { + toggleSort() + }} + classes={{ + root: 'btn-secondary-negative btn-order', + label: 'text-14-normal', + }} + > + <StyledIcon icon={OrderIcon} size={28} /> + </MuiButton> + + <div className="ng-question" onClick={handleNegaWattClick}> + {t('ECOGESTURE.QUESTION_NEGAWATT')} + </div> </div> - <div className="ecogesture-content"> - {ecogestures && filterbyFluid !== null - ? ecogestures - .filter(ecogesture => - ecogesture.fluidTypes.includes(filterbyFluid) - ) - .sort( - ascendingSort - ? (a, b) => a.nwh - b.nwh - : (a, b) => b.nwh - a.nwh - ) - .map((ecogesture, index) => ( - <div key={index} className="ecogesture-list-item"> - <EcogestureCard - ecogesture={ecogesture} - handleClick={handleClick} - /> - </div> - )) - : ecogestures - .sort( - ascendingSort - ? (a, b) => a.nwh - b.nwh - : (a, b) => b.nwh - a.nwh - ) - .map((ecogesture, index) => ( - <div key={index} className="ecogesture-list-item"> - <EcogestureCard - ecogesture={ecogesture} - handleClick={handleClick} - /> - </div> - ))} - </div> - </> - )} + </div> + <div className="ecogesture-content"> + {!ecogestures || !isLoaded ? ( + <div className="content-view-loading"> + <StyledChallengeSpinner size="5em" /> + </div> + ) : ecogestures && filterbyFluid !== null ? ( + ecogestures + .filter(ecogesture => + ecogesture.fluidTypes.includes(filterbyFluid) + ) + .sort( + ascendingSort + ? (a, b) => a.nwh - b.nwh + : (a, b) => b.nwh - a.nwh + ) + .map((ecogesture, index) => ( + <div key={index} className="ecogesture-list-item"> + <EcogestureCard + ecogesture={ecogesture} + handleClick={handleClick} + /> + </div> + )) + ) : ( + ecogestures && + ecogestures + .sort( + ascendingSort + ? (a, b) => a.nwh - b.nwh + : (a, b) => b.nwh - a.nwh + ) + .map((ecogesture, index) => ( + <div key={index} className="ecogesture-list-item"> + <EcogestureCard + ecogesture={ecogesture} + handleClick={handleClick} + /> + </div> + )) + )} + </div> + </> {openEcogestureModal && selectedEcogesture && ( <EcogestureModal ecogesture={selectedEcogesture} diff --git a/src/components/Ecogesture/EcogestureModal.tsx b/src/components/Ecogesture/EcogestureModal.tsx index fab80a1ab011b13511a63083c27f118bac0f8949..f00bb1380b8e1dfbc8bbb74b1dabe8b79d5ff0ed 100644 --- a/src/components/Ecogesture/EcogestureModal.tsx +++ b/src/components/Ecogesture/EcogestureModal.tsx @@ -6,7 +6,6 @@ import { Ecogesture } from 'models' import Modal from 'components/CommonKit/Modal/Modal' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import defaultIcon from 'assets/icons/visu/ecogesture/default.svg' import { importIconbyId } from 'utils/utils' import './ecogestureModal.scss' import useExploration from 'components/Hooks/useExploration' @@ -28,7 +27,7 @@ const EcogestureModal: React.FC<EcogestureModalProps> = ({ handleCloseClick, }: EcogestureModalProps) => { const { t } = useI18n() - const [ecogestureIcon, setEcogestureIcon] = useState(defaultIcon) + const [ecogestureIcon, setEcogestureIcon] = useState('') const [isMoreDetail, setIsMoreDetail] = useState(false) const { currentChallenge } = useSelector( (state: AppStore) => state.ecolyo.challenge diff --git a/src/components/Ecogesture/ecogestureCard.scss b/src/components/Ecogesture/ecogestureCard.scss index 34fa1a3ac46622f013bd1e1b5fc92e35bc5a3079..ac631114e04b0e06075b29909ff3757ceeca24a2 100644 --- a/src/components/Ecogesture/ecogestureCard.scss +++ b/src/components/Ecogesture/ecogestureCard.scss @@ -22,7 +22,6 @@ background: $blue-radial-gradient; font-size: 12px; } - .ec-content { display: flex; flex-direction: column; diff --git a/src/components/Ecogesture/ecogestureList.scss b/src/components/Ecogesture/ecogestureList.scss index c0345aacc3554527dfeefbbe0a1eab35c5630f0d..6a56fabf5003fd9861525c5ff02fc4bd2d73a5e6 100644 --- a/src/components/Ecogesture/ecogestureList.scss +++ b/src/components/Ecogesture/ecogestureList.scss @@ -53,9 +53,7 @@ font-size: 0.95rem; padding-left: 0.25rem; text-transform: initial; - @media (min-width: $width-large-phone) { - padding-left: 0.5rem; - } + padding-left: 0.5rem; &.opened { color: $gold-shadow; } @@ -112,12 +110,15 @@ button.btn-secondary-negative { margin: 0; padding: 0.3rem 0.5rem; + min-width: 11rem; + height: 2.25rem; + justify-content: left; &.btn-order { margin: 0 0 0 1rem; padding: 0; - width: 2.5rem; - height: 2.5rem; - min-width: 2.5rem; + width: 2.25rem; + min-width: 2.25rem; + justify-content: center; } } } diff --git a/src/components/Options/OptionsView.tsx b/src/components/Options/OptionsView.tsx index 7a40b8c63d4474b824e577daef8314b0da346ef8..e58f22d61b9a40c3bd04638138f120eeb62afe80 100644 --- a/src/components/Options/OptionsView.tsx +++ b/src/components/Options/OptionsView.tsx @@ -7,6 +7,7 @@ import ReportOptions from 'components/Options/ReportOptions' import FAQLink from 'components/FAQ/FAQLink' import LegalNoticeLink from 'components/LegalNotice/LegalNoticeLink' import Version from 'components/Version/Version' +import ProfileTypeOptions from './ProfileTypeOptions' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import logoGrandLyon from 'assets/icons/tabbar/grand-lyon.svg' @@ -29,6 +30,7 @@ const OptionsView: React.FC = () => { <Content height={headerHeight}> <KonnectorViewerList isParam={true} /> <ReportOptions /> + <ProfileTypeOptions /> <FAQLink /> <LegalNoticeLink /> <div className="parameters-logos"> diff --git a/src/components/Options/ProfileTypeOptions.spec.tsx b/src/components/Options/ProfileTypeOptions.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..93c60df83a40614a976eab1b34e4cc29307caa51 --- /dev/null +++ b/src/components/Options/ProfileTypeOptions.spec.tsx @@ -0,0 +1,82 @@ +import React from 'react' +import { mount } from 'enzyme' +import { Provider } from 'react-redux' +import configureStore from 'redux-mock-store' +import ProfileTypeOptions from 'components/Options/ProfileTypeOptions' +import { profileData } from '../../../test/__mocks__/profile.mock' +import StyledCard from 'components/CommonKit/Card/StyledCard' +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' +import profileIcon from 'assets/icons/ico/profile.svg' +import { HousingType } from 'enum/profileType.enum' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) +const mockHistoryPush = jest.fn() +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: mockHistoryPush, + }), +})) + +const mockStore = configureStore([]) + +describe('ProfileTypeOptions component', () => { + it('should be rendered correctly', () => { + const store = mockStore({ + ecolyo: { + profile: profileData, + }, + }) + const wrapper = mount( + <Provider store={store}> + <ProfileTypeOptions /> + </Provider> + ) + expect(wrapper.find(StyledCard).exists()).toBeTruthy() + expect(wrapper.find(StyledIcon).exists()).toBeTruthy() + expect(wrapper.find(profileIcon)).toBeTruthy() + wrapper + .find('.profile-link') + .first() + .simulate('click') + }) + it('should be rendered when user complete profile type form', () => { + const profileTypeCompleted = { ...profileData } + profileTypeCompleted.isProfileTypeCompleted = true + const store = mockStore({ + ecolyo: { + profile: profileTypeCompleted, + }, + }) + const wrapper = mount( + <Provider store={store}> + <ProfileTypeOptions /> + </Provider> + ) + expect(wrapper.find('.profile-container').exists()).toBeTruthy() + }) + it('should be rendered when housing_type = appartment', () => { + const profileTypeCompleted = { ...profileData } + profileTypeCompleted.isProfileTypeCompleted = true + profileTypeCompleted.profileType.housingType = HousingType.APPARTMENT + const store = mockStore({ + ecolyo: { + profile: profileTypeCompleted, + }, + }) + const wrapper = mount( + <Provider store={store}> + <ProfileTypeOptions /> + </Provider> + ) + expect(wrapper.find('.floor').exists()).toBeTruthy() + }) +}) diff --git a/src/components/Options/ProfileTypeOptions.tsx b/src/components/Options/ProfileTypeOptions.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1583af0f45a672fc6259bbfaf1b96b53e190d7e3 --- /dev/null +++ b/src/components/Options/ProfileTypeOptions.tsx @@ -0,0 +1,191 @@ +import React, { useCallback } from 'react' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { AppStore } from 'store' +import { useSelector } from 'react-redux' +import StyledCard from 'components/CommonKit/Card/StyledCard' +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' +import profileIcon from 'assets/icons/ico/profile.svg' +import './profileTypeOptions.scss' +import { IndividualOrCollective, HousingType } from 'enum/profileType.enum' +import { FluidType } from 'enum/fluid.enum' +import { useHistory } from 'react-router-dom' + +const ProfileTypeOptions: React.FC = () => { + const profile = useSelector((state: AppStore) => state.ecolyo.profile) + const { t } = useI18n() + const history = useHistory() + + const goToForm = useCallback(() => { + history.push('/profileType') + }, [history]) + return ( + <div className="profile-type-root"> + <div className="profile-type-content"> + <div className="head text-14-normal-uppercase"> + {t('profile_type.title_profile')} + </div> + {profile.isProfileTypeCompleted && ( + <div className="profile-container"> + <div className="fields"> + <div className="label">{t('profile_type.title_housing')}</div> + <div className="value"> + {t( + `profile_type.housing_type.${profile.profileType.housingType}` + )} + </div> + </div> + <div className="fields"> + <div className="label"> + {t('profile_type.title_construction')} + </div> + <div className="value"> + {t( + `profile_type.construction_year.${profile.profileType.constructionYear}` + )} + </div> + </div> + <div className="fields"> + <div className="label">{t('profile_type.title_area')}</div> + <div className="value">{profile.profileType.area}</div> + </div> + <div className="fields"> + <div className="label">{t('profile_type.title_occupants')}</div> + <div className="value">{profile.profileType.occupantsNumber}</div> + </div> + <div className="fields"> + <div className="label"> + {t('profile_type.title_outsideFacingWalls')} + </div> + <div className="value"> + {profile.profileType.outsideFacingWalls} + </div> + </div> + {profile.profileType.housingType === HousingType.APPARTMENT && ( + <div className="fields floor"> + <div className="label">{t('profile_type.title_floor')}</div> + <div className="value"> + {t(`profile_type.floor.${profile.profileType.floor}`)} + </div> + </div> + )} + <div className="fields"> + <div className="label">{t('profile_type.title_heating')}</div> + <div className="value"> + {t(`profile_type.heating.${profile.profileType.heating}`)} + </div> + </div> + {profile.profileType.heating === + IndividualOrCollective.INDIVIDUAL && ( + <React.Fragment> + <div className="fields"> + <div className="label"> + {t('profile_type.title_insulation_work')} + </div> + <ul className="value"> + {profile.profileType.individualInsulationWork.map( + (work, index) => { + return ( + <li key={index}> + {t( + `profile_type.individual_insulation_work.${work}` + )} + </li> + ) + } + )} + </ul> + </div> + <div className="fields"> + <div className="label"> + {t('profile_type.title_facilities_installation')} + </div> + <ul className="value"> + {profile.profileType.facilitiesInstallation.map( + (equipment, index) => { + return ( + <li key={index}> + {t( + `profile_type.facilities_installation.${equipment}` + )} + </li> + ) + } + )} + </ul> + </div> + <div className="fields"> + <div className="label"> + {t('profile_type.title_hot_water_equipment')} + </div> + <ul className="value"> + {profile.profileType.hotWaterEquipment.map( + (equipment, index) => { + return ( + <li key={index}> + {t(`profile_type.hot_water_equipment.${equipment}`)} + </li> + ) + } + )} + </ul> + </div> + {profile.profileType.warmingFluid !== null && ( + <div className="fields"> + <div className="label"> + {t('profile_type.title_heating_source')} + </div> + <div className="value"> + {t( + `FLUID.${ + Object.values(FluidType)[ + profile.profileType.warmingFluid + ] + }.LABEL` + )} + </div> + </div> + )} + {profile.profileType.hotWaterFluid !== null && ( + <div className="fields"> + <div className="label"> + {t('profile_type.title_warm_water_source')} + </div> + <div className="value"> + {t( + `FLUID.${ + Object.values(FluidType)[ + profile.profileType.hotWaterFluid + ] + }.LABEL` + )} + </div> + </div> + )} + </React.Fragment> + )} + <div className="fields"> + <div className="label"> + {t('profile_type.title_cooking_source')} + </div> + <div className="value"> + {t( + `FLUID.${ + Object.values(FluidType)[profile.profileType.cookingFluid] + }.LABEL` + )} + </div> + </div> + </div> + )} + <StyledCard onClick={goToForm} className="profile-link"> + <StyledIcon className="profile-icon" icon={profileIcon} size={50} /> + <span className="link-label text-16-normal"> + {t('profile_type.read_profile')} + </span> + </StyledCard> + </div> + </div> + ) +} + +export default ProfileTypeOptions diff --git a/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap b/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap index 88b03afe073d35606943054b2e814c3f31d6d7f1..c4d3156eabfca8d61fd3efe22b9c7db2b2f459f4 100644 --- a/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap +++ b/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap @@ -16,6 +16,7 @@ exports[`OptionsView component should be rendered correctly 1`] = ` isParam={true} /> <ReportOptions /> + <ProfileTypeOptions /> <FAQLink /> <LegalNoticeLink /> <div diff --git a/src/components/Options/profileTypeOptions.scss b/src/components/Options/profileTypeOptions.scss new file mode 100644 index 0000000000000000000000000000000000000000..cb3bf0590ed1fd91c17bd5d1d09037662a0fb92a --- /dev/null +++ b/src/components/Options/profileTypeOptions.scss @@ -0,0 +1,62 @@ +@import 'src/styles/base/color'; +@import 'src/styles/base/breakpoint'; + +.profile-type-root { + margin-top: 2rem; + padding: 0 1.5rem; + .profile-type-content { + margin: 0 auto; + width: 100%; + @media (min-width: $width-large-phone) { + width: 45.75rem; + } + } + .value { + color: $white; + } + ul { + display: flex; + flex-wrap: wrap; + padding: 0; + margin-top: 0; + li { + list-style-type: none; + margin-right: 0.5rem; + } + } + .head { + color: $grey-bright; + } + .head { + margin-bottom: 1.5rem; + } + .label { + color: $soft-grey; + } + .profile-container { + display: flex; + flex-wrap: wrap; + white-space: nowrap; + } + .fields { + flex-basis: 50%; + margin-bottom: 1rem; + } + button.profile-link { + color: $grey-bright; + text-decoration: none; + max-height: 5rem; + .profile-icon { + vertical-align: middle; + } + .link-label { + margin-left: 1rem; + } + > button { + margin-bottom: 0; + > div { + padding: 0.3rem 1rem; + } + } + } +} diff --git a/src/components/ProfileType/ProfileTypeFinished.tsx b/src/components/ProfileType/ProfileTypeFinished.tsx new file mode 100644 index 0000000000000000000000000000000000000000..12cefc0fefd2439390f231d5fcf77cd526d4f947 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeFinished.tsx @@ -0,0 +1,67 @@ +import React, { useEffect } from 'react' +import 'components/ProfileType/profileTypeFinished.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { useDispatch } from 'react-redux' +import { useHistory } from 'react-router-dom' +import { updateProfile } from 'store/profile/profile.actions' +import { ProfileType } from 'models/profileType.model' +import MuiButton from '@material-ui/core/Button' +import StyledIcon from 'components/CommonKit/Icon/StyledIcon' +import finishIcon from 'assets/icons/visu/profileType/finish.svg' +import ProfileTypeService from 'services/profileType.service' + +interface ProfileTypeFinishedProps { + profileType: ProfileType +} + +const ProfileTypeFinished: React.FC<ProfileTypeFinishedProps> = ({ + profileType, +}: ProfileTypeFinishedProps) => { + const { t } = useI18n() + const dispatch = useDispatch() + const history = useHistory() + + const handleClick = () => { + history.push('/analysis') + } + + useEffect(() => { + const consistentProfileType = ProfileTypeService.checkConsistency( + profileType + ) + dispatch( + updateProfile({ + profileType: consistentProfileType, + isProfileTypeCompleted: true, + }) + ) + }, [dispatch, profileType]) + + return ( + <div className={'profile-type-finished-card'}> + <StyledIcon + className={'profile-type-icon'} + icon={finishIcon} + size={120} + /> + <div className={'profile-type-finished-label text-28-normal-uppercase'}> + {t('profile_type.finished.title')} + </div> + <div className={'profile-type-finished-description text-18-normal'}> + {t('profile_type.finished.label')} + </div> + <MuiButton + onClick={handleClick} + className={'profile-type-finished-button'} + classes={{ + root: 'btn-secondary-negative', + label: 'text-16-normal', + }} + > + {t('profile_type.finished.view_comparison')} + </MuiButton> + </div> + ) +} + +export default ProfileTypeFinished diff --git a/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx b/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx new file mode 100644 index 0000000000000000000000000000000000000000..039cd2a1c21e17ae3257f8e5c78228d9df24a610 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx @@ -0,0 +1,145 @@ +import React, { useCallback, useEffect, useState } from 'react' +import 'components/ProfileType/profileTypeForm.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import classNames from 'classnames' +import ProfileTypeProgress from 'components/ProfileType/ProfileTypeProgress' +import ProfileTypeNavigation from 'components/ProfileType/ProfileTypeNavigation' +import { remove } from 'lodash' +import { + FacilitiesInstallation, + IndividualInsulationWork, + ProfileTypeStepForm, +} from 'enum/profileType.enum' +import { + ProfileType, + ProfileTypeAnswer, + ProfileTypeAnswerChoices, +} from 'models/profileType.model' + +interface ProfileTypeFormMultiChoiceProps { + step: ProfileTypeStepForm + viewedStep: ProfileTypeStepForm + profileType: ProfileType + answerType: ProfileTypeAnswer + setNextStep: Function + setPrevioustStep: Function +} + +const ProfileTypeFormMultiChoice: React.FC<ProfileTypeFormMultiChoiceProps> = ({ + step, + viewedStep, + profileType, + answerType, + setNextStep, + setPrevioustStep, +}: ProfileTypeFormMultiChoiceProps) => { + const { t } = useI18n() + const [answer, setAnswer] = useState<ProfileTypeAnswerChoices[]>([]) + + const handleChange = (value: ProfileTypeAnswerChoices) => { + let tempAnswer = [...answer] + if (value === 'none' && !tempAnswer.includes(value)) { + tempAnswer = [value] + } else if (tempAnswer.includes(value)) { + remove(tempAnswer, function(n) { + return n === 'none' || n === value + }) + remove(tempAnswer, function(n) { + return n === 'collective_heater' || n === value + }) + remove(tempAnswer, function(n) { + return n === 'other' || n === value + }) + } else if (value === 'collective_heater' && !tempAnswer.includes(value)) { + tempAnswer = [value] + } else if (value === 'other' && !tempAnswer.includes(value)) { + tempAnswer = [value] + } else { + remove(tempAnswer, function(n) { + return n === 'none' + }) + remove(tempAnswer, function(n) { + return n === 'collective_heater' + }) + remove(tempAnswer, function(n) { + return n === 'other' + }) + tempAnswer.push(value) + } + setAnswer(tempAnswer) + } + + const isChecked = (value: ProfileTypeAnswerChoices): boolean => { + if (answer.includes(value)) { + return true + } else { + return false + } + } + + const handlePrevious = useCallback(() => { + setPrevioustStep(profileType) + }, [profileType, setPrevioustStep]) + + const handleNext = useCallback(() => { + profileType[answerType.attribute] = answer as + | IndividualInsulationWork[] + | FacilitiesInstallation[] + setNextStep(profileType) + }, [profileType, setNextStep, answer, answerType.attribute]) + + useEffect(() => { + if (step < viewedStep) { + const attribute = profileType[answerType.attribute] as + | IndividualInsulationWork[] + | FacilitiesInstallation[] + setAnswer(attribute) + } + }, [step, viewedStep, profileType, answerType]) + + return ( + <> + <div className={'profile-form-container'}> + <ProfileTypeProgress step={step} /> + <div className={'profile-question-label'}> + {t( + `profile_type.${ProfileTypeStepForm[step].toLowerCase()}.question` + )} + </div> + {answerType.choices.map( + (value: ProfileTypeAnswerChoices, index: number) => { + return value ? ( + <label + key={index} + className={classNames('checkbox', { + ['answer-checked']: answer.includes(value), + })} + > + <input + type={'checkbox'} + value={value} + name={value.toString()} + onChange={() => handleChange(value)} + checked={isChecked(value)} + /> + {t( + `profile_type.${ProfileTypeStepForm[ + step + ].toLowerCase()}.${value}` + )} + </label> + ) : null + } + )} + </div> + <ProfileTypeNavigation + step={step} + handlePrevious={handlePrevious} + handleNext={handleNext} + disableNextButton={answer.length < 1} + /> + </> + ) +} + +export default ProfileTypeFormMultiChoice diff --git a/src/components/ProfileType/ProfileTypeFormNumber.tsx b/src/components/ProfileType/ProfileTypeFormNumber.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1815e037eb46d2f723e6dd1d76769d657a39546c --- /dev/null +++ b/src/components/ProfileType/ProfileTypeFormNumber.tsx @@ -0,0 +1,79 @@ +import React, { useCallback, useEffect, useState } from 'react' +import 'components/ProfileType/profileTypeForm.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import ProfileTypeProgress from 'components/ProfileType/ProfileTypeProgress' +import ProfileTypeNavigation from 'components/ProfileType/ProfileTypeNavigation' +import { ProfileTypeStepForm } from 'enum/profileType.enum' +import { + ProfileType, + ProfileTypeAnswer, + ProfileTypeAnswerChoices, +} from 'models/profileType.model' + +interface ProfileTypeFormNumberProps { + step: ProfileTypeStepForm + viewedStep: ProfileTypeStepForm + profileType: ProfileType + answerType: ProfileTypeAnswer + setNextStep: Function + setPrevioustStep: Function +} + +const ProfileTypeFormNumber: React.FC<ProfileTypeFormNumberProps> = ({ + step, + viewedStep, + profileType, + answerType, + setNextStep, + setPrevioustStep, +}: ProfileTypeFormNumberProps) => { + const { t } = useI18n() + const [answer, setAnswer] = useState<ProfileTypeAnswerChoices>('') + + const handlePrevious = useCallback(() => { + setPrevioustStep(profileType) + }, [profileType, setPrevioustStep]) + + const handleNext = useCallback(() => { + profileType[answerType.attribute] = answer + setNextStep(profileType) + }, [profileType, setNextStep, answer, answerType.attribute]) + + useEffect(() => { + if (step < viewedStep) { + setAnswer(profileType[answerType.attribute]) + } + }, [step, viewedStep, profileType, answerType]) + + return ( + <> + <div className={'profile-form-container'}> + <ProfileTypeProgress step={step} /> + <div className={'profile-question-label'}> + {t( + `profile_type.${ProfileTypeStepForm[step].toLowerCase()}.question` + )} + </div> + {answer != null ? ( + <label className={'text'}> + <input + type={'number'} + value={answer} + name={answerType.attribute} + onChange={e => setAnswer(e.target.value)} + /> + m² + </label> + ) : null} + </div> + <ProfileTypeNavigation + step={step} + handlePrevious={handlePrevious} + handleNext={handleNext} + disableNextButton={answer === ''} + /> + </> + ) +} + +export default ProfileTypeFormNumber diff --git a/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx b/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx new file mode 100644 index 0000000000000000000000000000000000000000..facad6e7f7cf8727a1cdc626306af58b9478e40f --- /dev/null +++ b/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx @@ -0,0 +1,111 @@ +import React, { useCallback, useEffect, useState } from 'react' +import 'components/ProfileType/profileTypeForm.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import ProfileTypeProgress from 'components/ProfileType/ProfileTypeProgress' +import ProfileTypeNavigation from 'components/ProfileType/ProfileTypeNavigation' +import { ProfileTypeStepForm } from 'enum/profileType.enum' +import { + ProfileType, + ProfileTypeAnswer, + ProfileTypeAnswerChoices, +} from 'models/profileType.model' + +interface ProfileTypeFormNumberSelectionProps { + step: ProfileTypeStepForm + viewedStep: ProfileTypeStepForm + profileType: ProfileType + answerType: ProfileTypeAnswer + setNextStep: Function + setPrevioustStep: Function +} + +const ProfileTypeFormNumberSelection: React.FC<ProfileTypeFormNumberSelectionProps> = ({ + step, + viewedStep, + profileType, + answerType, + setNextStep, + setPrevioustStep, +}: ProfileTypeFormNumberSelectionProps) => { + const { t } = useI18n() + const [answer, setAnswer] = useState<ProfileTypeAnswerChoices>('') + const [index, setIndex] = useState<number>(0) + + const decrement = () => { + setAnswer(answerType.choices[index - 1]) + setIndex(prev => prev - 1) + } + + const increment = () => { + setAnswer(answerType.choices[index + 1]) + setIndex(prev => prev + 1) + } + + const handlePrevious = useCallback(() => { + setPrevioustStep(profileType) + }, [profileType, setPrevioustStep]) + + const handleNext = useCallback(() => { + profileType[answerType.attribute] = answer + setNextStep(profileType) + }, [profileType, setNextStep, answer, answerType.attribute]) + + useEffect(() => { + if (step < viewedStep) { + const foundIndex = answerType.choices.findIndex( + element => element && element === profileType[answerType.attribute] + ) + foundIndex > -1 && setIndex(foundIndex) + setAnswer(profileType[answerType.attribute]) + } else { + setAnswer(answerType.choices[0]) + } + }, [step, viewedStep, profileType, answerType]) + + return ( + <> + <div className={'profile-form-container'}> + <ProfileTypeProgress step={step} /> + <div className={'profile-question-label'}> + {t( + `profile_type.${ProfileTypeStepForm[step].toLowerCase()}.question` + )} + </div> + {answer !== null ? ( + <div className={'number-container'}> + <button + className={'btn-profile-number'} + onClick={() => decrement()} + disabled={index < 1} + > + - + </button> + <label className={'number'}> + <input + type={'text'} + value={answer} + name={answerType.attribute} + disabled={true} + /> + </label> + <button + className={'btn-profile-number'} + onClick={() => increment()} + disabled={index >= answerType.choices.length - 1} + > + + + </button> + </div> + ) : null} + </div> + <ProfileTypeNavigation + step={step} + handlePrevious={handlePrevious} + handleNext={handleNext} + disableNextButton={answer === ''} + /> + </> + ) +} + +export default ProfileTypeFormNumberSelection diff --git a/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx b/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9e42efe6aa4d2379d5fcd2fde61c4f4d810cf1a9 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx @@ -0,0 +1,96 @@ +import React, { useCallback, useEffect, useState } from 'react' +import 'components/ProfileType/profileTypeForm.scss' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import classNames from 'classnames' +import ProfileTypeProgress from 'components/ProfileType/ProfileTypeProgress' +import ProfileTypeNavigation from 'components/ProfileType/ProfileTypeNavigation' +import { ProfileTypeStepForm } from 'enum/profileType.enum' +import { + ProfileType, + ProfileTypeAnswer, + ProfileTypeAnswerChoices, +} from 'models/profileType.model' + +interface ProfileTypeFormSingleChoiceProps { + step: ProfileTypeStepForm + viewedStep: ProfileTypeStepForm + profileType: ProfileType + answerType: ProfileTypeAnswer + setNextStep: Function + setPrevioustStep: Function +} + +const ProfileTypeFormSingleChoice: React.FC<ProfileTypeFormSingleChoiceProps> = ({ + step, + viewedStep, + profileType, + answerType, + setNextStep, + setPrevioustStep, +}: ProfileTypeFormSingleChoiceProps) => { + const { t } = useI18n() + const [answer, setAnswer] = useState<ProfileTypeAnswerChoices>('') + + const handlePrevious = useCallback(() => { + setPrevioustStep(profileType) + }, [profileType, setPrevioustStep]) + + const handleNext = useCallback(() => { + profileType[answerType.attribute] = answer + setNextStep(profileType) + }, [profileType, setNextStep, answer, answerType.attribute]) + + useEffect(() => { + if (step < viewedStep) { + setAnswer(profileType[answerType.attribute]) + } + }, [step, viewedStep, profileType, answerType]) + + return ( + <> + <div className={'profile-form-container'}> + <ProfileTypeProgress step={step} /> + <div className={'profile-question-label'}> + {t( + `profile_type.${ProfileTypeStepForm[step].toLowerCase()}.question` + )} + </div> + {answerType.choices.map( + (value: ProfileTypeAnswerChoices, index: number) => { + return value || value === 0 ? ( + <label + key={index} + className={classNames({ + ['radio_short']: answerType.choices.length < 5, + ['radio_long']: answerType.choices.length > 4, + ['answer-checked']: answer === value, + })} + > + <input + type={'radio'} + value={value} + name={value.toString()} + onChange={() => setAnswer(value)} + checked={answer === value ? true : false} + /> + {t( + `profile_type.${ProfileTypeStepForm[ + step + ].toLowerCase()}.${value}` + )} + </label> + ) : null + } + )} + </div> + <ProfileTypeNavigation + step={step} + handlePrevious={handlePrevious} + handleNext={handleNext} + disableNextButton={answer === ''} + /> + </> + ) +} + +export default ProfileTypeFormSingleChoice diff --git a/src/components/ProfileType/ProfileTypeNavigation.tsx b/src/components/ProfileType/ProfileTypeNavigation.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e24f5ffa78b7c2dfd4ff658fa120ce43a0979115 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeNavigation.tsx @@ -0,0 +1,62 @@ +import React from 'react' +import 'components/ProfileType/profileTypeNavigation.scss' +import classNames from 'classnames' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import MuiButton from '@material-ui/core/Button' +import { ProfileTypeStepForm } from 'enum/profileType.enum' + +interface ProfileTypeNavigationProps { + step: ProfileTypeStepForm + handlePrevious: Function + handleNext: Function + disableNextButton: boolean +} + +const ProfileTypeNavigation: React.FC<ProfileTypeNavigationProps> = ({ + step, + handlePrevious, + handleNext, + disableNextButton, +}: ProfileTypeNavigationProps) => { + const { t } = useI18n() + + const handlePreviousClick = () => { + handlePrevious() + } + const handleNextClick = () => { + handleNext() + } + + return ( + <div className="profile-navigation"> + <MuiButton + onClick={handlePreviousClick} + className={'profile-navigation-button'} + disabled={step === ProfileTypeStepForm.HOUSING_TYPE} + classes={{ + root: 'btn-profile-back', + label: 'text-16-normal', + }} + > + {`< ${t('profile_type.form.previous')}`} + </MuiButton> + <MuiButton + onClick={handleNextClick} + className={classNames('profile-navigation-button', { + ['disabled']: disableNextButton, + })} + disabled={disableNextButton} + classes={{ + root: 'btn-profile-next rounded', + label: 'text-16-normal', + }} + > + {step === ProfileTypeStepForm.COOKING_FLUID + ? t('profile_type.form.end') + : `${t('profile_type.form.next')} >`} + </MuiButton> + </div> + ) +} + +export default ProfileTypeNavigation diff --git a/src/components/ProfileType/ProfileTypeProgress.tsx b/src/components/ProfileType/ProfileTypeProgress.tsx new file mode 100644 index 0000000000000000000000000000000000000000..561c12159101e58157d4685450ad58778bfe77e3 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeProgress.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import 'components/ProfileType/profileTypeProgress.scss' +import { ProfileTypeStepForm } from 'enum/profileType.enum' + +interface ProfileTypeProgressProps { + step: ProfileTypeStepForm +} + +const ProfileTypeProgress: React.FC<ProfileTypeProgressProps> = ({ + step, +}: ProfileTypeProgressProps) => { + const getProgress = () => { + const total: number = Object.values(ProfileTypeStepForm).length / 2 + const progress: number = Math.round((step / total) * 100) + return progress + } + return ( + <div className={'profile-type-progress'}> + <div className={'profile-type-progress-label'}>{getProgress()}%</div> + <div className={'profile-type-progress-bar-container'}> + <div + className={'profile-type-progress-bar-content'} + style={{ width: `${getProgress()}%` }} + ></div> + </div> + </div> + ) +} + +export default ProfileTypeProgress diff --git a/src/components/ProfileType/ProfileTypeView.spec.tsx b/src/components/ProfileType/ProfileTypeView.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0ee5bbd8895c0b9bd6c6cada99b8934042c19dbb --- /dev/null +++ b/src/components/ProfileType/ProfileTypeView.spec.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { Provider } from 'react-redux' +import { mount } from 'enzyme' +import ProfileTypeView from 'components/ProfileType/ProfileTypeView' +import CozyBar from 'components/Header/CozyBar' +import Header from 'components/Header/Header' +import Content from 'components/Content/Content' +import { + createMockStore, + mockInitialEcolyoState, +} from '../../../test/__mocks__/store' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +describe('ProfileTypeView component', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let store: any + beforeEach(() => { + store = createMockStore(mockInitialEcolyoState) + }) + + it('should be rendered correctly', () => { + const wrapper = mount( + <Provider store={store}> + <ProfileTypeView /> + </Provider> + ) + expect(wrapper.find(CozyBar)).toBeTruthy() + expect(wrapper.find(Header)).toBeTruthy() + expect(wrapper.find(Content)).toBeTruthy() + }) +}) diff --git a/src/components/ProfileType/ProfileTypeView.tsx b/src/components/ProfileType/ProfileTypeView.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0f2edca3f157ecf96987cdc8c7474ba657e02d02 --- /dev/null +++ b/src/components/ProfileType/ProfileTypeView.tsx @@ -0,0 +1,170 @@ +import React, { useCallback, useEffect, useState } from 'react' +import 'components/ProfileType/profileTypeView.scss' +import CozyBar from 'components/Header/CozyBar' +import Header from 'components/Header/Header' +import Content from 'components/Content/Content' +import ProfileTypeFormSingleChoice from 'components/ProfileType/ProfileTypeFormSingleChoice' +import ProfileTypeFormEnd from 'components/ProfileType/ProfileTypeFinished' + +import { ProfileType, ProfileTypeAnswer } from 'models/profileType.model' +import { + ConstructionYear, + FacilitiesInstallation, + Floor, + HotWaterEquipment, + HousingType, + IndividualInsulationWork, + IndividualOrCollective, + OutsideFacingWalls, + ProfileTypeFormType, +} from 'enum/profileType.enum' +import { FluidType } from 'enum/fluid.enum' +import { ProfileTypeStepForm } from 'enum/profileType.enum' +import ProfileTypeService from 'services/profileType.service' +import ProfileTypeFormMultiChoice from 'components/ProfileType/ProfileTypeFormMultiChoice' +import ProfileTypeFormNumber from 'components/ProfileType/ProfileTypeFormNumber' +import ProfileTypeFormNumberSelection from 'components/ProfileType/ProfileTypeFormNumberSelection' + +const ProfileTypeView = () => { + const [headerHeight, setHeaderHeight] = useState<number>(0) + const [profileType, setProfileType] = useState<ProfileType>({ + housingType: HousingType.INDIVIDUAL_HOUSE, + constructionYear: ConstructionYear.BETWEEN_1975_AND_1989, + area: 0, + occupantsNumber: 1, + outsideFacingWalls: OutsideFacingWalls.ONE, + floor: Floor.NOT_APPLICABLE, + heating: IndividualOrCollective.INDIVIDUAL, + individualInsulationWork: [IndividualInsulationWork.NONE], + facilitiesInstallation: [FacilitiesInstallation.NONE], + hotWater: IndividualOrCollective.INDIVIDUAL, + hotWaterEquipment: [HotWaterEquipment.OTHER], + warmingFluid: FluidType.ELECTRICITY, + hotWaterFluid: FluidType.ELECTRICITY, + cookingFluid: FluidType.ELECTRICITY, + }) + const [step, setStep] = useState<ProfileTypeStepForm>( + ProfileTypeStepForm.HOUSING_TYPE + ) + const [answerType, setAnswerType] = useState<ProfileTypeAnswer>({ + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: '', + choices: [], + }) + const [isLoading, setIsLoading] = useState<boolean>(true) + const [viewedStep, setViewedStep] = useState<number>(-1) + + const defineHeaderHeight = useCallback((height: number) => { + setHeaderHeight(height) + }, []) + + const setNextStep = useCallback( + (_profileType: ProfileType) => { + setProfileType(_profileType) + const profileTypeService = new ProfileTypeService(_profileType) + const nextStep: ProfileTypeStepForm = profileTypeService.getNextFormStep( + step + ) + setIsLoading(true) + if (nextStep > viewedStep) { + setViewedStep(nextStep) + } + setStep(nextStep) + }, + [step, viewedStep] + ) + + const setPrevioustStep = useCallback( + (_profileType: ProfileType) => { + setProfileType(_profileType) + const profileTypeService = new ProfileTypeService(_profileType) + const nextStep: ProfileTypeStepForm = profileTypeService.getPreviousFormStep( + step + ) + setIsLoading(true) + setStep(nextStep) + }, + [step] + ) + + const selectForm = () => { + if (answerType.type === ProfileTypeFormType.SINGLE_CHOICE) { + return ( + <ProfileTypeFormSingleChoice + step={step} + viewedStep={viewedStep} + profileType={profileType} + answerType={answerType} + setNextStep={setNextStep} + setPrevioustStep={setPrevioustStep} + /> + ) + } else if (answerType.type === ProfileTypeFormType.MULTI_CHOICE) { + return ( + <ProfileTypeFormMultiChoice + step={step} + viewedStep={viewedStep} + profileType={profileType} + answerType={answerType} + setNextStep={setNextStep} + setPrevioustStep={setPrevioustStep} + /> + ) + } else if (answerType.type === ProfileTypeFormType.NUMBER) { + return ( + <ProfileTypeFormNumber + step={step} + viewedStep={viewedStep} + profileType={profileType} + answerType={answerType} + setNextStep={setNextStep} + setPrevioustStep={setPrevioustStep} + /> + ) + } else if (answerType.type === ProfileTypeFormType.NUMBER_SELECTION) { + return ( + <ProfileTypeFormNumberSelection + step={step} + viewedStep={viewedStep} + profileType={profileType} + answerType={answerType} + setNextStep={setNextStep} + setPrevioustStep={setPrevioustStep} + /> + ) + } + } + + useEffect(() => { + const _answerType: ProfileTypeAnswer = ProfileTypeService.getAnswerForStep( + step + ) + setAnswerType(_answerType) + setIsLoading(false) + }, [step]) + + return ( + <> + <CozyBar + titleKey={'COMMON.APP_PROFILETYPE_TITLE'} + displayBackArrow={true} + /> + <Header + setHeaderHeight={defineHeaderHeight} + desktopTitleKey={'COMMON.APP_PROFILETYPE_TITLE'} + displayBackArrow={true} + ></Header> + <Content height={headerHeight}> + <div className={'profile-type-container'}> + {isLoading ? null : step !== ProfileTypeStepForm.END ? ( + selectForm() + ) : ( + <ProfileTypeFormEnd profileType={profileType} /> + )} + </div> + </Content> + </> + ) +} + +export default ProfileTypeView diff --git a/src/components/ProfileType/profileTypeFinished.scss b/src/components/ProfileType/profileTypeFinished.scss new file mode 100644 index 0000000000000000000000000000000000000000..5c04aa795846b0a105ee401c1e3247985f92fd38 --- /dev/null +++ b/src/components/ProfileType/profileTypeFinished.scss @@ -0,0 +1,35 @@ +@import '../../styles/base/color'; +@import '../../styles/base/breakpoint'; + +.profile-type-finished-card { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 2rem 1.25rem; + box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.55); + border-radius: 4px; + transition: all 300ms ease; + color: $white; + background: linear-gradient(180deg, #323339 0%, #25262b 100%); + width: 80%; + text-align: center; + padding: 0.5rem 1rem 1rem; + @media (min-width: $width-tablet) { + width: 50%; + min-height: 28.75rem; + } + @media (min-width: $width-large-desktop) { + width: 40%; + min-height: 28.75rem; + } + button.profile-type-finished-button{ + margin-top: 2.875rem; + } +} +.profile-type-finished-label { + color: $gold-shadow; +} +.profile-type-finished-description { + margin-top: 1.875rem; +} \ No newline at end of file diff --git a/src/components/ProfileType/profileTypeForm.scss b/src/components/ProfileType/profileTypeForm.scss new file mode 100644 index 0000000000000000000000000000000000000000..c7a487fadbe90a59c59f3f096b9f1fc28d8aaf5c --- /dev/null +++ b/src/components/ProfileType/profileTypeForm.scss @@ -0,0 +1,132 @@ +@import '../../styles/base/color'; +@import '../../styles/base/breakpoint'; + +.profile-form-container { + color: $white; + margin: 1rem; + width: 100%; + max-width: 53rem; +} +.profile-question-label { + font-weight: bold; + font-size: 1.375rem; + line-height: 150%; + padding: 1rem 0; +} + +.profile-question-answers { + display: flex; +} +.profile-question-answers-radio-long { + flex-wrap: wrap; +} + +.profile-question-answers-other { + flex-direction: column; +} +.radio_short, .radio_long, .checkbox { + background: linear-gradient(180deg, #323339 0%, #25262B 100%); + box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.55); + margin: 0.5rem 0; + display: flex; + align-items: center; + font-weight: bold; + input { + margin: 0.5rem 1rem 0.5rem 0.5rem; + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + width: 1.2rem; + height: 1.2rem; + border-radius: 50%; + background: $dark-background; + position: relative; + + &:focus { + outline: none; + } + } +} +.checkbox { + input { + border-radius: 1px; + } +} +.radio_short, .checkbox { + padding: 1.2rem; + border-radius: 4px; +} +.radio_long { + padding: .5rem 1rem; + border-radius: 20px; + text-align: center; +} +.answer-checked { + background: radial-gradient(105.25% 64.58% at 49.68% 70.83%, rgba(226, 137, 4, 0.5) 0%, rgba(255, 255, 255, 0) 100%), #F1C017; + color: $dark-light-2; + input { + &:before, &:after { + content: ''; + position: absolute; + display: inline-block; + background: $gold-shadow; + border-radius: 0.5rem; + } + &:before { + width: 3px; + height: 12px; + left: 10px; + top: 4px; + transform: rotate(41deg); + } + &:after { + width: 3px; + height: 6px; + left: 5px; + top: 8px; + transform: rotate(133deg); + } + } +} + +.text, .number { + font-size: 1.25rem; + input { + margin: 0.5rem; + background: $dark-light-2; + color: $white; + border: 1px solid $gold-shadow; + max-width: 5rem; + height: 2.5rem; + text-align: center; + &:focus { + outline: $gold-shadow 1px; + } + } +} +.number-container { + display: flex; + justify-content: left; + align-items: center; +} +.btn-profile-number { + background: $grey-linear-gradient-background; + background-color: transparent; + border: none; + border-radius: 2px; + width: 2.5rem; + height: 2.5rem; + font-size: 2rem; + color: $white; + display: flex; + align-items: center; + justify-content: center; + margin: 0.5rem; + + &:focus { + outline:none; + } +} +button:disabled { + opacity: 0.5; +} \ No newline at end of file diff --git a/src/components/ProfileType/profileTypeNavigation.scss b/src/components/ProfileType/profileTypeNavigation.scss new file mode 100644 index 0000000000000000000000000000000000000000..6f5aa7b2dc403f6792b746a4c63db6c416894ad3 --- /dev/null +++ b/src/components/ProfileType/profileTypeNavigation.scss @@ -0,0 +1,24 @@ +@import '../../styles/base/color'; + +.profile-navigation { + border-top: 1px solid $grey-dark; + position: absolute; + bottom: 0; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + .rounded { + border-radius: 22px; + margin-left: 1rem; + margin-right: 1rem; + } + .disabled { + opacity: 0.5; + } + button.profile-navigation-button{ + max-width: 12.5rem; + margin: 0.375rem 1rem; + padding: 0.5rem 1rem; + } +} diff --git a/src/components/ProfileType/profileTypeProgress.scss b/src/components/ProfileType/profileTypeProgress.scss new file mode 100644 index 0000000000000000000000000000000000000000..2a7d6d5a7690e1b621074a4a5d95dfbcb36caadd --- /dev/null +++ b/src/components/ProfileType/profileTypeProgress.scss @@ -0,0 +1,25 @@ +@import '../../styles/base/color'; + +.profile-type-progress{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + .profile-type-progress-label { + font-size: 0.938rem; + width: 1.875rem; + color: $gold-shadow; + text-align: right; + } + .profile-type-progress-bar-container { + margin-left: 0.5rem; + flex: 1; + height: 6px; + background-color: $dark-light-2; + .profile-type-progress-bar-content { + height: 100%; + background-color: $gold-shadow; + border-radius: 12px; + } + } +} \ No newline at end of file diff --git a/src/components/ProfileType/profileTypeView.scss b/src/components/ProfileType/profileTypeView.scss new file mode 100644 index 0000000000000000000000000000000000000000..3852d8fce2641aad5a42b95b358ba9746a5fb44a --- /dev/null +++ b/src/components/ProfileType/profileTypeView.scss @@ -0,0 +1,6 @@ +.profile-type-container { + height: 100%; + min-height: inherit; + display: flex; + justify-content: center; +} \ No newline at end of file diff --git a/src/components/Report/ChartReport.spec.tsx b/src/components/Report/ChartReport.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1e903ee757624efcf83161ab1f6d081ca4524995 --- /dev/null +++ b/src/components/Report/ChartReport.spec.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import { shallow } from 'enzyme' +import { DateTime } from 'luxon' +import ChartReport from './ChartReport' +import { Dataload } from 'models' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) +const chartProps: Dataload[] = [ + { + date: DateTime.fromISO('2020-09-03T00:00:00.000+02:00'), + value: -1, + valueDetail: null, + }, + { + date: DateTime.fromISO('2020-10-03T00:00:00.000+02:00'), + value: 24.812865, + valueDetail: null, + }, +] +describe('MonthlyReport component', () => { + it('should be rendered correctly', () => { + const component = shallow( + <ChartReport chartData={chartProps} /> + ).getElement() + expect(component).toMatchSnapshot() + }) +}) diff --git a/src/components/Report/MonthlyReport.spec.tsx b/src/components/Report/MonthlyReport.spec.tsx new file mode 100644 index 0000000000000000000000000000000000000000..abbd1cf3715b318273a3a262bff14c7c12153521 --- /dev/null +++ b/src/components/Report/MonthlyReport.spec.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import { shallow } from 'enzyme' + +import MonthlyReport from './MonthlyReport' +import { DateTime } from 'luxon' + +import * as reactRedux from 'react-redux' +import { userChallengeExplo1OnGoing } from '../../../test/__mocks__/userChallengeData.mock' + +jest.mock('cozy-ui/transpiled/react/I18n', () => { + return { + useI18n: jest.fn(() => { + return { + t: (str: string) => str, + } + }), + } +}) + +const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') + +const reportDate = DateTime.fromISO('2020-11-17T00:00:00.000+01:00') +describe('MonthlyReport component', () => { + mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + const setReportDate = jest.fn() + const setLoad = jest.fn() + const useStateSpy = jest.spyOn(React, 'useState') + const useStateMock: any = (init: any) => [reportDate, setReportDate] + const useStateLoad: any = (init: any) => [true, setLoad] + useStateSpy.mockImplementationOnce(useStateMock) + useStateSpy.mockImplementationOnce(useStateLoad) + it('should be rendered correctly', () => { + const component = shallow(<MonthlyReport />).getElement() + expect(component).toMatchSnapshot() + }) +}) diff --git a/src/components/Report/__snapshots__/ChartReport.spec.tsx.snap b/src/components/Report/__snapshots__/ChartReport.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..bade029beeafc44b8092bf417d76fd10e633cd52 --- /dev/null +++ b/src/components/Report/__snapshots__/ChartReport.spec.tsx.snap @@ -0,0 +1,187 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MonthlyReport component should be rendered correctly 1`] = ` +<div + className="chart-root" +> + <svg + height={225} + width={600} + > + <g + className="axis y" + transform="translate(0, 175)" + > + <g + className="tick" + opacity="1" + transform="translate(0,0)" + > + <line + stroke="currentColor" + x2={600} + /> + </g> + <g + className="tick" + opacity="1" + transform="translate(0,-70)" + > + <line + stroke="currentColor" + x2={600} + /> + </g> + <g + className="tick" + opacity="1" + transform="translate(0,-140)" + > + <line + stroke="currentColor" + x2={600} + /> + </g> + </g> + <g + transform="translate(0,10)" + > + <g + transform="translate(28.571428571428555, 115)" + > + <text + className="value-text text-16-normal" + dy="0.71em" + y="10" + > + -,-- € + </text> + </g> + <g + transform="translate(171.42857142857142, 171.6497762350297)" + > + <defs> + <linearGradient + className="bar-MULTIFLUID" + id="gradient" + x1="0" + x2="0" + y1="0" + y2="1" + > + <stop + id="stop-color-1" + offset="0%" + /> + <stop + id="stop-color-2" + offset="100%" + /> + </linearGradient> + </defs> + <path + className="bar-MULTIFLUID disabled bounce-3 delay" + d="M0,0 a0,0 0 0 1 0,0h114.28571428571429a0,0 0 0 1 0,0v0h-114.28571428571429z" + fill="url(#gradient)" + /> + </g> + <g + transform="translate(314.2857142857143, 0)" + > + <defs> + <linearGradient + className="bar-MULTIFLUID selected disabled " + id="gradient" + x1="0" + x2="0" + y1="0" + y2="1" + > + <stop + id="stop-color-1" + offset="0%" + /> + <stop + id="stop-color-2" + offset="100%" + /> + </linearGradient> + </defs> + <path + className="bar-MULTIFLUID selected disabled bounce-3 delay--0" + d="M0,4 a4,4 0 0 1 4,-4h106.28571428571429a4,4 0 0 1 4,4v161h-114.28571428571429z" + fill="url(#gradient)" + /> + </g> + <g + transform="translate(457.1428571428571, 115)" + > + <text + className="value-text selected text-16-normal" + dy="0.71em" + y="10" + > + 24,81 € + </text> + </g> + </g> + <g + className="axis x" + transform="translate(0, 175)" + > + <g + className="tick" + opacity="1" + transform="translate(228.57142857142856, 0)" + > + <text + dy="0.71em" + y="10" + > + <tspan + className="tick-text chart-ticks-x-text" + textAnchor="middle" + x="0" + > + septembre + </tspan> + <tspan + className="tick-text chart-ticks-x-text" + dy="1.2em" + textAnchor="middle" + x="0" + > + 2020 + </tspan> + </text> + </g> + <g + className="tick" + opacity="1" + transform="translate(371.42857142857144, 0)" + > + <text + dy="0.71em" + y="10" + > + <tspan + className="tick-text tick-text-selected chart-ticks-x-text" + textAnchor="middle" + x="0" + > + octobre + </tspan> + <tspan + className="tick-text tick-text-selected chart-ticks-x-text" + dy="1.2em" + textAnchor="middle" + x="0" + > + 2020 + </tspan> + </text> + </g> + </g> + </svg> +</div> +`; diff --git a/src/components/Report/__snapshots__/MonthlyReport.spec.tsx.snap b/src/components/Report/__snapshots__/MonthlyReport.spec.tsx.snap new file mode 100644 index 0000000000000000000000000000000000000000..f2a9abcb5c93fdbec30b66f603656ab04c86d201 --- /dev/null +++ b/src/components/Report/__snapshots__/MonthlyReport.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MonthlyReport component should be rendered correctly 1`] = `<React.Fragment />`; diff --git a/src/components/Routes/Routes.tsx b/src/components/Routes/Routes.tsx index e650aa2dc1abbe60b1e2d1af0d50626b7c20a201..73895f683204e8a56a63026e177f63a402eca5e0 100644 --- a/src/components/Routes/Routes.tsx +++ b/src/components/Routes/Routes.tsx @@ -20,6 +20,9 @@ const LegalNoticeView = lazy(() => import('components/LegalNotice/LegalNoticeView') ) const ReportView = lazy(() => import('components/Report/ReportView')) +const ProfileTypeView = lazy(() => + import('components/ProfileType/ProfileTypeView') +) const Routes = () => { return ( @@ -74,6 +77,7 @@ const Routes = () => { )} /> <Route path="/report" component={ReportView} /> + <Route path="/profiletype" component={ProfileTypeView} /> <Redirect from="/" to="/consumption" /> <Redirect from="*" to="/consumption" /> </Switch> diff --git a/src/constants/consumptionConstants/heating.json b/src/constants/consumptionConstants/heating.json index 08ad00456453c58e2a3df757e13906079ac8488f..1bfd6996204431ddb5536bb03bd4b4860337cb98 100644 --- a/src/constants/consumptionConstants/heating.json +++ b/src/constants/consumptionConstants/heating.json @@ -46,8 +46,7 @@ "window_replacement_and_wall_insulation": -0.2, "window_replacement_and_roof_insulation": -0.25, "roof_and_wall_insulation": -0.3, - "window_replacement_and_roof_and_wall_insulation": -0.35, - "built_after_1998": 0 + "window_replacement_and_roof_and_wall_insulation": -0.35 }, "between_1948_and_1974": { "none": 0, @@ -57,8 +56,7 @@ "window_replacement_and_wall_insulation": -0.2, "window_replacement_and_roof_insulation": -0.25, "roof_and_wall_insulation": -0.3, - "window_replacement_and_roof_and_wall_insulation": -0.35, - "built_after_1998": 0 + "window_replacement_and_roof_and_wall_insulation": -0.35 }, "between_1975_and_1989": { "none": 0, @@ -68,8 +66,7 @@ "window_replacement_and_wall_insulation": -0.25, "window_replacement_and_roof_insulation": -0.07, "roof_and_wall_insulation": -0.2, - "window_replacement_and_roof_and_wall_insulation": -0.25, - "built_after_1998": 0 + "window_replacement_and_roof_and_wall_insulation": -0.25 }, "between_1990_and_1998": { "none": 0, @@ -79,8 +76,7 @@ "window_replacement_and_wall_insulation": -0.15, "window_replacement_and_roof_insulation": -0.04, "roof_and_wall_insulation": -0.1, - "window_replacement_and_roof_and_wall_insulation": -0.15, - "built_after_1998": 0 + "window_replacement_and_roof_and_wall_insulation": -0.15 }, "after_1999": { "none": 0, @@ -90,8 +86,7 @@ "window_replacement_and_wall_insulation": 0, "window_replacement_and_roof_insulation": 0, "roof_and_wall_insulation": 0, - "window_replacement_and_roof_and_wall_insulation": 0, - "built_after_1998": 0 + "window_replacement_and_roof_and_wall_insulation": 0 } }, "adjustment_facilities": { diff --git a/src/enum/profileType.enum.ts b/src/enum/profileType.enum.ts index 424b618fcdb6e1e2070afa4d09849dbfaf3fbe53..a60de8e23764bad5355180190bf3c58b6f15e74f 100644 --- a/src/enum/profileType.enum.ts +++ b/src/enum/profileType.enum.ts @@ -34,11 +34,6 @@ export enum IndividualInsulationWork { ROOF_INSULATION = 'roof_insulation', WINDOW_REPLACEMENT = 'window_replacement', WALL_INSULATION = 'wall_insulation', - WINDOW_REPLACEMENT_AND_WALL_INSULATION = 'window_replacement_and_wall_insulation', - WINDOW_REPLACEMENT_AND_ROOF_INSULATION = 'window_replacement_and_roof_insulation', - ROOF_AND_WALL_INSULATION = 'roof_and_wall_insulation', - WINDOW_REPLACEMENT_AND_ROOF_AND_WALL_INSULATION = 'window_replacement_and_roof_and_wall_insulation', - BUILT_AFTER_1998 = 'built_after_1998', } export enum FacilitiesInstallation { @@ -46,7 +41,6 @@ export enum FacilitiesInstallation { COLLECTIVE_HEATER = 'collective_heater', INDIVIDUAL_HEATER = 'individual_heater', INDIVIDUAL_VENTILATION = 'individual_ventilation', - INDIVIDUAL_HEATER_AND_VENTILATION = 'individual_heater_and_ventilation', } export enum HotWaterEquipment { @@ -54,3 +48,28 @@ export enum HotWaterEquipment { THERMODYNAMIC = 'thermodynamic', OTHER = 'other', } + +export enum ProfileTypeStepForm { + HOUSING_TYPE = 0, + CONSTRUCTION_YEAR = 1, + AREA = 2, + OCCUPANTS_NUMBER = 3, + OUTSIDE_FACING_WALLS = 4, + FLOOR = 5, + HEATING = 6, + WARMING_FLUID = 7, + INDIVIDUAL_INSULATION_WORK = 8, + FACILITIES_INSTALLATION = 9, + HOT_WATER = 10, + HOT_WATER_FLUID = 11, + HOT_WATER_EQUIPMENT = 12, + COOKING_FLUID = 13, + END = 14, +} + +export enum ProfileTypeFormType { + SINGLE_CHOICE = 0, + MULTI_CHOICE = 1, + NUMBER_SELECTION = 2, + NUMBER = 3, +} diff --git a/src/locales/fr.json b/src/locales/fr.json index 7b59378feb3bb33db98ddb246f6088ccc07d2d8c..86df6f301ebfa46d54aabd0e27826f4ac68bb32b 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -28,6 +28,7 @@ "APP_OPTIONS_TITLE": "Options", "APP_HELLO": "Bonjour", "APP_PRESENTATION": "Consommation d'énergie", + "APP_PROFILETYPE_TITLE": "Ajuster mon profil", "CONSO_DETAILS": "détail des consommations", "NODATA": "Pas de données", "LASTDATA": "Dernières données", @@ -404,6 +405,119 @@ }, "action": { "title_action": "Action", - "select_action" : "Je choisis cette action" + "select_action": "Je choisis cette action" + }, + "profile_type": { + "title_profile": "Profil de consommation", + "read_profile": "Ajuster mon profil", + "title_housing": "Logement", + "housing_type": { + "question": "De quel type de logement disposez-vous ?", + "individual_house": "Maison individuelle", + "appartment": "Appartement" + }, + "title_construction": "Construction", + "construction_year": { + "question": "Quelle est son année de construction ?", + "before_1948": "Avant 1948", + "between_1948_and_1974": "Entre 1975 et 1989", + "between_1975_and_1989": "Entre 1975 et 1989", + "between_1990_and_1998": "Entre 1990 et 1998", + "after_1999": "Après 1999" + }, + "title_area": "Surface", + "area": { + "question": "Quelle est sa surface en m² ?" + }, + "title_occupants": "Nombre d'occupants", + "occupants_number": { + "question": "Combien y a-t-il d'occupants ?" + }, + "title_outsideFacingWalls": "Mitoyenneté", + "outside_facing_walls": { + "question": "Combien de façades donnent sur l'extérieur ?" + }, + "title_floor": "Étage", + "floor": { + "question": "À quel étage est votre appartement ?", + "ground_floor": "RDC", + "intermediate_floor": "Étage intermédiaire", + "last_floor": "Dernier étage", + "not_applicable": "Sans objet" + }, + "title_heating": "Chauffage", + "heating": { + "question": "Quel est votre type de chauffage ?", + "individual": "Individuel", + "collective": "Collectif" + }, + "title_insulation_work": "Travaux", + "individual_insulation_work": { + "question": "Quels travaux d’isolation avez-vous réalisé ces 10 dernières années ?", + "none": "Aucun", + "roof_insulation": "Isolation toîture", + "window_replacement": "Remplacement fenêtre", + "wall_insulation": "Isolation des murs", + "window_replacement_and_wall_insulation": "Rempacement fenêtre et isolation des murs", + "window_replacement_and_roof_insulation": "Remplacement fenêtre et isolation toîture", + "roof_and_wall_insulation": "Isolation toîture et murs", + "window_replacement_and_roof_and_wall_insulation": "Rempacement fenêtre et isolation des murs et isolation toîture", + "built_after_1998": "construit après 1998" + }, + "title_facilities_installation": "Équipement", + "facilities_installation": { + "question": "Quel équipement a été installé ou remplacé ces 10 dernières années ?", + "none": "Aucun", + "collective_heater": "Chauffage collectif", + "individual_heater": "Chauffage individuel", + "individual_ventilation": "Ventilation double flux individuel", + "individual_heater_and_ventilation": "Chauffage et ventilation individuel" + }, + "title_hotWaterEquipment": "Eau chaude", + "hot_water": { + "question": "Quel est votre type de production d’eau chaude ?", + "individual": "Individuel", + "collective": "Collectif" + }, + "hot_water_equipment": { + "question": "Quel équipement utilisez-vous pour produire votre eau chaude ?", + "solar": "Solaire", + "thermodynamic": "Thermodynamique", + "other": "Autre" + }, + "title_hot_water_equipment": "Eau chaude", + "title_heating_source": "Source chauffage", + "hot_water_fluid": { + "question": "Quelle source d’énergie est utilisée pour produire votre eau chaude ?", + "0": "Électricité", + "2": "Gaz" + }, + "title_warm_water_source": "Source eau chaude", + "warming_fluid": { + "question": "Quelle source d’énergie est utilisée par votre chauffage ?", + "0": "Électricité", + "2": "Gaz" + }, + "title_cooking_source": "Source cuisson", + "cooking_fluid": { + "question": "Quel mode de cuisson utilisez-vous ?", + "0": "Électricité", + "2": "Gaz" + }, + "fluidType": { + "0": "Électricité", + "1": "Eau", + "2": "Gaz" + }, + "form": { + "previous": "Précédent", + "next": "Suivant", + "end": "Terminer" + }, + "finished": { + "title": "Terminé !", + "label": "Grâce à ces nouvelles informations, votre comparaison sera bien plus précise et pertinente !", + "view_comparison": "Voir ma comparaison" + } } } diff --git a/src/models/profile.model.ts b/src/models/profile.model.ts index 111ba75efcfb08257fbe3a2be9b9ab96c7bda7c0..3ca90a5b62c0a7ad9aa32698c8cec189a4076001 100644 --- a/src/models/profile.model.ts +++ b/src/models/profile.model.ts @@ -14,6 +14,8 @@ export interface ProfileEntity { haveSeenOldFluidModal: string | boolean sendReportNotification: boolean monthlyReportDate: string + profileType: ProfileType + isProfileTypeCompleted: boolean _id?: string _rev?: string } @@ -25,6 +27,4 @@ export interface Profile lastConnectionDate: DateTime haveSeenOldFluidModal: DateTime | boolean monthlyReportDate: DateTime - profileType: ProfileType - isProfileTypeCompleted: boolean } diff --git a/src/models/profileType.model.ts b/src/models/profileType.model.ts index 66c57b36772259d786343d3d2b37c6bfd451b8b0..9e0cc3240f2cea48c1cf74c77856dff1407f0ed8 100644 --- a/src/models/profileType.model.ts +++ b/src/models/profileType.model.ts @@ -7,10 +7,26 @@ import { HotWaterEquipment, OutsideFacingWalls, IndividualOrCollective, + ProfileTypeFormType, } from 'enum/profileType.enum' import { FluidType } from 'enum/fluid.enum' -export interface ProfileType { +interface ProfileTypeIndexableTypes { + [key: string]: + | HousingType + | ConstructionYear + | OutsideFacingWalls + | Floor + | IndividualOrCollective + | IndividualInsulationWork[] + | FacilitiesInstallation[] + | HotWaterEquipment[] + | FluidType + | number + | string + | null +} +export interface ProfileType extends ProfileTypeIndexableTypes { housingType: HousingType constructionYear: ConstructionYear area: number @@ -19,8 +35,8 @@ export interface ProfileType { floor: Floor heating: IndividualOrCollective hotWater: IndividualOrCollective - individualInsulationWork: IndividualInsulationWork - facilitiesInstallation: FacilitiesInstallation + individualInsulationWork: IndividualInsulationWork[] + facilitiesInstallation: FacilitiesInstallation[] hotWaterEquipment: HotWaterEquipment[] warmingFluid: FluidType | null hotWaterFluid: FluidType | null @@ -45,3 +61,22 @@ export interface DetailsMonthlyForecast { electricSpecificConsumption: number | null coldWaterConsumption: number | null } + +export type ProfileTypeAnswerChoices = + | string + | number + | HousingType + | ConstructionYear + | OutsideFacingWalls + | Floor + | IndividualOrCollective + | IndividualInsulationWork[] + | FacilitiesInstallation[] + | HotWaterEquipment[] + | FluidType + | null +export interface ProfileTypeAnswer { + type: ProfileTypeFormType + attribute: string + choices: ProfileTypeAnswerChoices[] +} diff --git a/src/services/duel.service.spec.ts b/src/services/duel.service.spec.ts index 667c7c6030fa67fbca0ece9a04f6877d57211f8c..a4f6c51ae2d783b71fbf34903ded57a68319a290 100644 --- a/src/services/duel.service.spec.ts +++ b/src/services/duel.service.spec.ts @@ -151,7 +151,13 @@ describe('Duel service', () => { const mockUpdatedDuel: UserDuel = { ...duelData, threshold: 55, - fluidTypes: [FluidType.ELECTRICITY, FluidType.WATER, FluidType.GAS], + fluidTypes: [ + FluidType.ELECTRICITY, + FluidType.WATER, + FluidType.WATER, + FluidType.GAS, + FluidType.GAS, + ], } const result = await duelService.updateUserDuelThreshold( duelData, diff --git a/src/services/profile.service.ts b/src/services/profile.service.ts index b9b49c992ee8388e6a42e861bbae0d40a24cdc1f..489ca4e32e1d372db69e817cadae62dc0e3ae242 100644 --- a/src/services/profile.service.ts +++ b/src/services/profile.service.ts @@ -2,17 +2,6 @@ import { Client, Q, QueryDefinition, QueryResult } from 'cozy-client' import { Profile, ProfileEntity } from 'models' import { PROFILE_DOCTYPE } from 'doctypes' import { DateTime } from 'luxon' -import { - ConstructionYear, - FacilitiesInstallation, - Floor, - HotWaterEquipment, - HousingType, - IndividualOrCollective, - IndividualInsulationWork, - OutsideFacingWalls, -} from 'enum/profileType.enum' -import { FluidType } from 'enum/fluid.enum' export default class ProfileService { private readonly _client: Client @@ -43,24 +32,6 @@ export default class ProfileService { lastConnectionDate: DateTime.fromISO(profileEntity.lastConnectionDate, { zone: 'utc', }), - isProfileTypeCompleted: false, - profileType: { - housingType: HousingType.INDIVIDUAL_HOUSE, - constructionYear: ConstructionYear.BETWEEN_1975_AND_1989, - area: 100, - occupantsNumber: 4, - outsideFacingWalls: OutsideFacingWalls.TWO, - floor: Floor.NOT_APPLICABLE, - heating: IndividualOrCollective.INDIVIDUAL, - hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: - IndividualInsulationWork.WINDOW_REPLACEMENT_AND_WALL_INSULATION, - facilitiesInstallation: FacilitiesInstallation.NONE, - hotWaterEquipment: [HotWaterEquipment.SOLAR], - warmingFluid: FluidType.ELECTRICITY, - hotWaterFluid: FluidType.ELECTRICITY, - cookingFluid: FluidType.ELECTRICITY, - }, } return profile } diff --git a/src/services/profileType.service.spec.ts b/src/services/profileType.service.spec.ts index bc54bbc75ee32c1fd1f1ab33d0233f0dc9aacbd0..6ec7b7a22e4c591d3f77343ae410cc0d2f5e5591 100644 --- a/src/services/profileType.service.spec.ts +++ b/src/services/profileType.service.spec.ts @@ -1,4 +1,10 @@ -import { HotWaterEquipment } from 'enum/profileType.enum' +import { + FacilitiesInstallation, + HotWaterEquipment, + IndividualInsulationWork, + ProfileTypeStepForm, +} from 'enum/profileType.enum' +import { ProfileType } from 'models/profileType.model' import { mockCorrectedConsumption, mockEstimatedConsumption, @@ -24,9 +30,11 @@ import { mockMonthlyForecastJanuaryTestProfile3, mockMonthlyForecastJanuaryHotWaterMulti, mockTestProfileHotWaterMulti, + mockProfileTypeAnswers, + mockMonthlyForecastJanuaryTest1WithFullArrays, } from '../../test/__mocks__/profileType.mock' import ProfileTypeService from './profileType.service' - +const wrongNumber = 99999 describe('ProfileType service', () => { const profileTypeService = new ProfileTypeService(mockProfileType) @@ -167,5 +175,195 @@ describe('ProfileType service', () => { const monthlyForecast = profileTypeService4.getMonthlyForecast(1) expect(monthlyForecast).toEqual(mockMonthlyForecastJanuaryHotWaterMulti) }) + it('shoud get the monthly forecast for test profile 1 with wall and roof and window insulation', () => { + const mockProfileWithThreeInsulation: ProfileType = { + ...mockTestProfile1, + individualInsulationWork: [ + IndividualInsulationWork.ROOF_INSULATION, + IndividualInsulationWork.WALL_INSULATION, + IndividualInsulationWork.WINDOW_REPLACEMENT, + ], + facilitiesInstallation: [ + FacilitiesInstallation.INDIVIDUAL_VENTILATION, + FacilitiesInstallation.INDIVIDUAL_HEATER, + ], + } + const profileTypeService = new ProfileTypeService( + mockProfileWithThreeInsulation + ) + const monthlyForecast = profileTypeService.getMonthlyForecast(1) + expect(monthlyForecast).toEqual( + mockMonthlyForecastJanuaryTest1WithFullArrays + ) + }) + }) + describe('getNextFormStep', () => { + it('shoud get the next step in function of the current step', () => { + let nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.HOUSING_TYPE + ) + expect(nextStep).toEqual(ProfileTypeStepForm.CONSTRUCTION_YEAR) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.CONSTRUCTION_YEAR + ) + expect(nextStep).toEqual(ProfileTypeStepForm.AREA) + + nextStep = profileTypeService.getNextFormStep(ProfileTypeStepForm.AREA) + expect(nextStep).toEqual(ProfileTypeStepForm.OCCUPANTS_NUMBER) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.OCCUPANTS_NUMBER + ) + expect(nextStep).toEqual(ProfileTypeStepForm.OUTSIDE_FACING_WALLS) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.OUTSIDE_FACING_WALLS + ) + expect(nextStep).toEqual(ProfileTypeStepForm.FLOOR) + nextStep = profileTypeService.getNextFormStep(ProfileTypeStepForm.FLOOR) + expect(nextStep).toEqual(ProfileTypeStepForm.HEATING) + nextStep = profileTypeService.getNextFormStep(ProfileTypeStepForm.HEATING) + expect(nextStep).toEqual(ProfileTypeStepForm.WARMING_FLUID) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.WARMING_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.FACILITIES_INSTALLATION) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.FACILITIES_INSTALLATION + ) + + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.HOT_WATER + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER_FLUID) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.HOT_WATER_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER_EQUIPMENT) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.HOT_WATER_EQUIPMENT + ) + expect(nextStep).toEqual(ProfileTypeStepForm.COOKING_FLUID) + nextStep = profileTypeService.getNextFormStep( + ProfileTypeStepForm.COOKING_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.END) + nextStep = profileTypeService.getNextFormStep(wrongNumber) + expect(nextStep).toEqual(ProfileTypeStepForm.HOUSING_TYPE) + }) + }) + describe('getPreviousFormStep', () => { + it('shoud get the previus step in function of the current step', () => { + let nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.CONSTRUCTION_YEAR + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOUSING_TYPE) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.AREA + ) + expect(nextStep).toEqual(ProfileTypeStepForm.CONSTRUCTION_YEAR) + + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.OCCUPANTS_NUMBER + ) + expect(nextStep).toEqual(ProfileTypeStepForm.AREA) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.OUTSIDE_FACING_WALLS + ) + expect(nextStep).toEqual(ProfileTypeStepForm.OCCUPANTS_NUMBER) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.FLOOR + ) + expect(nextStep).toEqual(ProfileTypeStepForm.OUTSIDE_FACING_WALLS) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.HEATING + ) + expect(nextStep).toEqual(ProfileTypeStepForm.FLOOR) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.WARMING_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HEATING) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK + ) + expect(nextStep).toEqual(ProfileTypeStepForm.WARMING_FLUID) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.FACILITIES_INSTALLATION + ) + expect(nextStep).toEqual(ProfileTypeStepForm.WARMING_FLUID) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.HOT_WATER + ) + expect(nextStep).toEqual(ProfileTypeStepForm.FACILITIES_INSTALLATION) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.HOT_WATER_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.HOT_WATER_EQUIPMENT + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER_FLUID) + nextStep = profileTypeService.getPreviousFormStep( + ProfileTypeStepForm.COOKING_FLUID + ) + expect(nextStep).toEqual(ProfileTypeStepForm.HOT_WATER_EQUIPMENT) + nextStep = profileTypeService.getPreviousFormStep(wrongNumber) + expect(nextStep).toEqual(ProfileTypeStepForm.HOUSING_TYPE) + }) + }) + describe('getAnswerForStep', () => { + it('shoud get the good answers in function of the current step', () => { + let answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.HOUSING_TYPE + ) + expect(answers).toEqual(mockProfileTypeAnswers[0]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.CONSTRUCTION_YEAR + ) + expect(answers).toEqual(mockProfileTypeAnswers[1]) + answers = ProfileTypeService.getAnswerForStep(ProfileTypeStepForm.AREA) + expect(answers).toEqual(mockProfileTypeAnswers[2]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.OCCUPANTS_NUMBER + ) + expect(answers).toEqual(mockProfileTypeAnswers[3]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.OUTSIDE_FACING_WALLS + ) + expect(answers).toEqual(mockProfileTypeAnswers[4]) + answers = ProfileTypeService.getAnswerForStep(ProfileTypeStepForm.FLOOR) + expect(answers).toEqual(mockProfileTypeAnswers[5]) + answers = ProfileTypeService.getAnswerForStep(ProfileTypeStepForm.HEATING) + expect(answers).toEqual(mockProfileTypeAnswers[6]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK + ) + expect(answers).toEqual(mockProfileTypeAnswers[7]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.FACILITIES_INSTALLATION + ) + expect(answers).toEqual(mockProfileTypeAnswers[8]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.HOT_WATER + ) + expect(answers).toEqual(mockProfileTypeAnswers[9]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.HOT_WATER_EQUIPMENT + ) + expect(answers).toEqual(mockProfileTypeAnswers[10]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.HOT_WATER_FLUID + ) + expect(answers).toEqual(mockProfileTypeAnswers[11]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.WARMING_FLUID + ) + expect(answers).toEqual(mockProfileTypeAnswers[12]) + answers = ProfileTypeService.getAnswerForStep( + ProfileTypeStepForm.COOKING_FLUID + ) + expect(answers).toEqual(mockProfileTypeAnswers[13]) + answers = ProfileTypeService.getAnswerForStep(wrongNumber) + expect(answers).toEqual(mockProfileTypeAnswers[14]) + }) }) }) diff --git a/src/services/profileType.service.ts b/src/services/profileType.service.ts index aedb5a8674a581e8ef1c03f7f0f6a53cb673fbdc..572c490e4951dc2acfa40b6489b10cf22c86b847 100644 --- a/src/services/profileType.service.ts +++ b/src/services/profileType.service.ts @@ -3,6 +3,7 @@ import { FluidForecast, MonthlyForecast, ProfileType, + ProfileTypeAnswer, } from 'models/profileType.model' import { DateTime } from 'luxon' import heatingData from 'constants/consumptionConstants/heating.json' @@ -19,6 +20,8 @@ import { HousingType, IndividualInsulationWork, OutsideFacingWalls, + ProfileTypeStepForm, + ProfileTypeFormType, } from 'enum/profileType.enum' import { FluidType } from 'enum/fluid.enum' import ConverterService from './converter.service' @@ -57,9 +60,9 @@ export default class ProfileTypeService { const housingType: HousingType = this.profileType.housingType const floor: Floor = this.profileType.floor const constructionYear: ConstructionYear = this.profileType.constructionYear - const individualInsulationWork: IndividualInsulationWork = this.profileType - .individualInsulationWork - const facilitiesInstallation: FacilitiesInstallation = this.profileType + const individualInsulationWork: IndividualInsulationWork[] = this + .profileType.individualInsulationWork + const facilitiesInstallation: FacilitiesInstallation[] = this.profileType .facilitiesInstallation const heating = this.profileType.heating @@ -77,21 +80,72 @@ export default class ProfileTypeService { } else correctionFloor = 0 if ( - individualInsulationWork !== IndividualInsulationWork.NONE && + !individualInsulationWork.includes(IndividualInsulationWork.NONE) && constructionYear !== ConstructionYear.AFTER_1999 && heating !== IndividualOrCollective.COLLECTIVE ) { - const correctionsInsulation = + const correctionsInsulation: { [key: string]: number } = heatingData.adjustment_insulation[constructionYear] - correctionInsulation = correctionsInsulation[individualInsulationWork] + if (individualInsulationWork.length === 1) { + correctionInsulation = + correctionsInsulation[individualInsulationWork[0]] + } else { + let key = '' + if ( + individualInsulationWork.includes( + IndividualInsulationWork.ROOF_INSULATION + ) && + individualInsulationWork.includes( + IndividualInsulationWork.WINDOW_REPLACEMENT + ) && + individualInsulationWork.includes( + IndividualInsulationWork.WALL_INSULATION + ) + ) { + key = 'window_replacement_and_roof_and_wall_insulation' + } else if ( + individualInsulationWork.includes( + IndividualInsulationWork.ROOF_INSULATION + ) && + individualInsulationWork.includes( + IndividualInsulationWork.WINDOW_REPLACEMENT + ) + ) { + key = 'window_replacement_and_roof_insulation' + } else if ( + individualInsulationWork.includes( + IndividualInsulationWork.ROOF_INSULATION + ) && + individualInsulationWork.includes( + IndividualInsulationWork.WALL_INSULATION + ) + ) { + key = 'roof_and_wall_insulation' + } else if ( + individualInsulationWork.includes( + IndividualInsulationWork.WINDOW_REPLACEMENT + ) && + individualInsulationWork.includes( + IndividualInsulationWork.WALL_INSULATION + ) + ) { + key = 'window_replacement_and_wall_insulation' + } + correctionInsulation = correctionsInsulation[key] + } } else correctionInsulation = 0 if ( - facilitiesInstallation !== FacilitiesInstallation.NONE && + !facilitiesInstallation.includes(FacilitiesInstallation.NONE) && heating !== IndividualOrCollective.COLLECTIVE ) { - correctionFacilities = - heatingData.adjustment_facilities[facilitiesInstallation] + if (facilitiesInstallation.length === 1) { + correctionFacilities = + heatingData.adjustment_facilities[facilitiesInstallation[0]] + } else { + correctionFacilities = + heatingData.adjustment_facilities['individual_heater_and_ventilation'] + } } else correctionFacilities = 0 const correctedConsumption = @@ -401,4 +455,227 @@ export default class ProfileTypeService { } return monthlyForecast } + + /** + * getNextFormStep + * @param {ProfileTypeStepForm} step + * @returns {ProfileTypeStepForm} next step + */ + public getNextFormStep(step: ProfileTypeStepForm): ProfileTypeStepForm { + switch (step) { + case ProfileTypeStepForm.HOUSING_TYPE: + return ProfileTypeStepForm.CONSTRUCTION_YEAR + case ProfileTypeStepForm.CONSTRUCTION_YEAR: + return ProfileTypeStepForm.AREA + case ProfileTypeStepForm.AREA: + return ProfileTypeStepForm.OCCUPANTS_NUMBER + case ProfileTypeStepForm.OCCUPANTS_NUMBER: + return ProfileTypeStepForm.OUTSIDE_FACING_WALLS + case ProfileTypeStepForm.OUTSIDE_FACING_WALLS: + return this.profileType.housingType === HousingType.INDIVIDUAL_HOUSE + ? ProfileTypeStepForm.WARMING_FLUID + : ProfileTypeStepForm.FLOOR + case ProfileTypeStepForm.FLOOR: + return ProfileTypeStepForm.HEATING + case ProfileTypeStepForm.HEATING: + return this.profileType.heating === IndividualOrCollective.INDIVIDUAL + ? ProfileTypeStepForm.WARMING_FLUID + : ProfileTypeStepForm.HOT_WATER + case ProfileTypeStepForm.WARMING_FLUID: + return this.profileType.constructionYear === ConstructionYear.AFTER_1999 + ? ProfileTypeStepForm.FACILITIES_INSTALLATION + : ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK + case ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK: + return ProfileTypeStepForm.FACILITIES_INSTALLATION + case ProfileTypeStepForm.FACILITIES_INSTALLATION: + return this.profileType.housingType === HousingType.INDIVIDUAL_HOUSE + ? ProfileTypeStepForm.HOT_WATER_FLUID + : ProfileTypeStepForm.HOT_WATER + case ProfileTypeStepForm.HOT_WATER: + return this.profileType.hotWater === IndividualOrCollective.INDIVIDUAL + ? ProfileTypeStepForm.HOT_WATER_FLUID + : ProfileTypeStepForm.COOKING_FLUID + case ProfileTypeStepForm.HOT_WATER_FLUID: + return ProfileTypeStepForm.HOT_WATER_EQUIPMENT + case ProfileTypeStepForm.HOT_WATER_EQUIPMENT: + return ProfileTypeStepForm.COOKING_FLUID + case ProfileTypeStepForm.COOKING_FLUID: + return ProfileTypeStepForm.END + default: + return ProfileTypeStepForm.HOUSING_TYPE + } + } + + /** + * getPreviousFormStep + * @param {ProfileTypeStepForm} step + * @returns {ProfileTypeStepForm} previous step + */ + public getPreviousFormStep(step: ProfileTypeStepForm): ProfileTypeStepForm { + switch (step) { + case ProfileTypeStepForm.CONSTRUCTION_YEAR: + return ProfileTypeStepForm.HOUSING_TYPE + case ProfileTypeStepForm.AREA: + return ProfileTypeStepForm.CONSTRUCTION_YEAR + case ProfileTypeStepForm.OCCUPANTS_NUMBER: + return ProfileTypeStepForm.AREA + case ProfileTypeStepForm.OUTSIDE_FACING_WALLS: + return ProfileTypeStepForm.OCCUPANTS_NUMBER + case ProfileTypeStepForm.FLOOR: + return ProfileTypeStepForm.OUTSIDE_FACING_WALLS + case ProfileTypeStepForm.HEATING: + return ProfileTypeStepForm.FLOOR + case ProfileTypeStepForm.WARMING_FLUID: + return this.profileType.housingType === HousingType.INDIVIDUAL_HOUSE + ? ProfileTypeStepForm.OUTSIDE_FACING_WALLS + : ProfileTypeStepForm.HEATING + case ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK: + return ProfileTypeStepForm.WARMING_FLUID + case ProfileTypeStepForm.FACILITIES_INSTALLATION: + return this.profileType.constructionYear === ConstructionYear.AFTER_1999 + ? ProfileTypeStepForm.WARMING_FLUID + : ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK + case ProfileTypeStepForm.HOT_WATER: + return this.profileType.heating === IndividualOrCollective.INDIVIDUAL + ? ProfileTypeStepForm.FACILITIES_INSTALLATION + : ProfileTypeStepForm.HEATING + case ProfileTypeStepForm.HOT_WATER_FLUID: + return this.profileType.housingType === HousingType.INDIVIDUAL_HOUSE + ? ProfileTypeStepForm.FACILITIES_INSTALLATION + : ProfileTypeStepForm.HOT_WATER + case ProfileTypeStepForm.HOT_WATER_EQUIPMENT: + return ProfileTypeStepForm.HOT_WATER_FLUID + case ProfileTypeStepForm.COOKING_FLUID: + return this.profileType.hotWater === IndividualOrCollective.INDIVIDUAL + ? ProfileTypeStepForm.HOT_WATER_EQUIPMENT + : ProfileTypeStepForm.HOT_WATER + default: + return ProfileTypeStepForm.HOUSING_TYPE + } + } + + /** + * getAnswerForStep + * @param {ProfileTypeStepForm} step + * @returns {ProfileTypeAnswer} next step + */ + static getAnswerForStep(step: ProfileTypeStepForm): ProfileTypeAnswer { + switch (step) { + case ProfileTypeStepForm.HOUSING_TYPE: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'housingType', + choices: Object.values(HousingType), + } + case ProfileTypeStepForm.CONSTRUCTION_YEAR: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'constructionYear', + choices: Object.values(ConstructionYear), + } + case ProfileTypeStepForm.AREA: + return { + type: ProfileTypeFormType.NUMBER, + attribute: 'area', + choices: [], + } + case ProfileTypeStepForm.OCCUPANTS_NUMBER: + return { + type: ProfileTypeFormType.NUMBER_SELECTION, + attribute: 'occupantsNumber', + choices: [1, 2, 3, 4, 5, 6, 7, 8, 9], + } + case ProfileTypeStepForm.OUTSIDE_FACING_WALLS: + return { + type: ProfileTypeFormType.NUMBER_SELECTION, + attribute: 'outsideFacingWalls', + choices: [0, 1, 2, 3, 4], + } + case ProfileTypeStepForm.FLOOR: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'floor', + choices: Object.values(Floor), + } + case ProfileTypeStepForm.HEATING: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'heating', + choices: Object.values(IndividualOrCollective), + } + case ProfileTypeStepForm.INDIVIDUAL_INSULATION_WORK: + return { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'individualInsulationWork', + choices: Object.values(IndividualInsulationWork), + } + case ProfileTypeStepForm.FACILITIES_INSTALLATION: + return { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'facilitiesInstallation', + choices: Object.values(FacilitiesInstallation), + } + case ProfileTypeStepForm.HOT_WATER: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'hotWater', + choices: Object.values(IndividualOrCollective), + } + case ProfileTypeStepForm.HOT_WATER_EQUIPMENT: + return { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'hotWaterEquipment', + choices: Object.values(HotWaterEquipment), + } + case ProfileTypeStepForm.HOT_WATER_FLUID: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'hotWaterFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + } + case ProfileTypeStepForm.WARMING_FLUID: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'warmingFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + } + + case ProfileTypeStepForm.COOKING_FLUID: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'cookingFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + } + default: + return { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'housingType', + choices: [], + } + } + } + + /** + * checkConsistency + * @param {ProfileType} profileType + * @returns {ProfileType} consistent profile type + */ + static checkConsistency(profileType: ProfileType): ProfileType { + if (profileType.housingType === HousingType.INDIVIDUAL_HOUSE) { + profileType.floor = Floor.NOT_APPLICABLE + profileType.heating = IndividualOrCollective.INDIVIDUAL + profileType.hotWater = IndividualOrCollective.INDIVIDUAL + } else { + if (profileType.heating === IndividualOrCollective.COLLECTIVE) { + profileType.warmingFluid = null + profileType.individualInsulationWork = [] + profileType.facilitiesInstallation = [] + } + if (profileType.hotWater === IndividualOrCollective.COLLECTIVE) { + profileType.hotWaterFluid = null + profileType.hotWaterEquipment = [] + } + } + return profileType + } } diff --git a/src/store/profile/profile.reducer.ts b/src/store/profile/profile.reducer.ts index 7df6de017a9a329d513703715af3738d7c2daba1..08b99d6f629cb488c7e052e3aaf827f5451e1710 100644 --- a/src/store/profile/profile.reducer.ts +++ b/src/store/profile/profile.reducer.ts @@ -41,9 +41,11 @@ const initialState: Profile = { floor: Floor.NOT_APPLICABLE, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: - IndividualInsulationWork.WINDOW_REPLACEMENT_AND_WALL_INSULATION, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [ + IndividualInsulationWork.WINDOW_REPLACEMENT, + IndividualInsulationWork.WALL_INSULATION, + ], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, diff --git a/src/styles/base/_buttons.scss b/src/styles/base/_buttons.scss index da7481b1fc07896c92427646d58ac6e2a41962fb..231337aab3a39762a8ed3d3650be81155553195a 100644 --- a/src/styles/base/_buttons.scss +++ b/src/styles/base/_buttons.scss @@ -79,4 +79,13 @@ button { background-color: darken($dark-light-2, 12%); } } + &.btn-profile-next { + @include button($gold-shadow, #000000, none, $multi-color-radial-gradient) { + background-color: darken($gold-shadow, 12%); + } + } + &.btn-profile-back { + @include button(none, $grey-dark, none, none) { + } + } } diff --git a/test/__mocks__/fluidStatusData.mock.ts b/test/__mocks__/fluidStatusData.mock.ts index ea57a9159632ae4c333fff29ab81cf8089caa6fa..979321b72d65ee8a89faef79c6248236c0b6a57d 100644 --- a/test/__mocks__/fluidStatusData.mock.ts +++ b/test/__mocks__/fluidStatusData.mock.ts @@ -1,136 +1,178 @@ -import { FluidState } from 'enum/fluid.enum' -import { DateTime } from 'luxon' -import { FluidStatus } from 'models' - -export const fluidStatusData: FluidStatus[] = [ - { - fluidType: 0, - status: FluidState.KONNECTOR_NOT_FOUND, - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, - { - fluidType: 1, - status: FluidState.KONNECTOR_NOT_FOUND, - - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, - { - fluidType: 2, - status: FluidState.KONNECTOR_NOT_FOUND, - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, -] - -export const fluidStatusConnectedData: FluidStatus[] = [ - { - fluidType: 0, - status: FluidState.DONE, - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, - { - fluidType: 1, - status: FluidState.DONE, - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, - { - fluidType: 2, - status: FluidState.DONE, - lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { - zone: 'utc', - }), - connection: { - shouldLaunchKonnector: false, - isUpdating: false, - konnector: null, - account: null, - trigger: null, - triggerState: null, - konnectorConfig: { - name: '', - oauth: false, - slug: '', - siteLink: '', - }, - }, - }, -] +import { FluidState } from 'enum/fluid.enum' +import { DateTime } from 'luxon' +import { FluidStatus } from 'models' + +export const fluidStatusData: FluidStatus[] = [ + { + fluidType: 0, + status: FluidState.KONNECTOR_NOT_FOUND, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 1, + status: FluidState.KONNECTOR_NOT_FOUND, + + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 2, + status: FluidState.KONNECTOR_NOT_FOUND, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, +] + +export const fluidStatusConnectedData: FluidStatus[] = [ + { + fluidType: 0, + status: FluidState.DONE, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 1, + status: FluidState.DONE, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 2, + status: FluidState.DONE, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: false, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 1, + status: FluidState.DONE, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: true, + slug: '', + siteLink: '', + }, + }, + }, + { + fluidType: 2, + status: FluidState.DONE, + lastDataDate: DateTime.fromISO('2020-09-01T00:00:00.000Z', { + zone: 'utc', + }), + connection: { + shouldLaunchKonnector: false, + isUpdating: false, + konnector: null, + account: null, + trigger: null, + triggerState: null, + konnectorConfig: { + name: '', + oauth: true, + slug: '', + siteLink: '', + }, + }, + }, +] diff --git a/test/__mocks__/profile.mock.ts b/test/__mocks__/profile.mock.ts index 59cc70357411dcaebbeebcd2d13044222b42caca..03991dda04591b27c9aaf5776412f15afc895ea5 100644 --- a/test/__mocks__/profile.mock.ts +++ b/test/__mocks__/profile.mock.ts @@ -41,9 +41,11 @@ export const profileData: Profile = { floor: Floor.NOT_APPLICABLE, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: - IndividualInsulationWork.WINDOW_REPLACEMENT_AND_WALL_INSULATION, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [ + IndividualInsulationWork.WINDOW_REPLACEMENT, + IndividualInsulationWork.WALL_INSULATION, + ], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, diff --git a/test/__mocks__/profileType.mock.ts b/test/__mocks__/profileType.mock.ts index 35c95db9c8fdf3e2195177a0092768663dc996d5..a94d66cde65ebcb76b1df368560546af4a3863ce 100644 --- a/test/__mocks__/profileType.mock.ts +++ b/test/__mocks__/profileType.mock.ts @@ -9,8 +9,13 @@ import { IndividualInsulationWork, IndividualOrCollective, OutsideFacingWalls, + ProfileTypeFormType, } from 'enum/profileType.enum' -import { MonthlyForecast, ProfileType } from 'models/profileType.model' +import { + MonthlyForecast, + ProfileType, + ProfileTypeAnswer, +} from 'models/profileType.model' export const mockProfileType: ProfileType = { housingType: HousingType.APPARTMENT, @@ -21,8 +26,8 @@ export const mockProfileType: ProfileType = { floor: Floor.GROUND_FLOOR, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: IndividualInsulationWork.NONE, - facilitiesInstallation: FacilitiesInstallation.INDIVIDUAL_HEATER, + individualInsulationWork: [IndividualInsulationWork.NONE], + facilitiesInstallation: [FacilitiesInstallation.INDIVIDUAL_HEATER], hotWaterEquipment: [HotWaterEquipment.THERMODYNAMIC], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, @@ -52,8 +57,8 @@ export const mockProfileType1: ProfileType = { floor: Floor.INTERMEDIATE_FLOOR, heating: IndividualOrCollective.COLLECTIVE, hotWater: IndividualOrCollective.COLLECTIVE, - individualInsulationWork: IndividualInsulationWork.WINDOW_REPLACEMENT, - facilitiesInstallation: FacilitiesInstallation.INDIVIDUAL_HEATER, + individualInsulationWork: [IndividualInsulationWork.WINDOW_REPLACEMENT], + facilitiesInstallation: [FacilitiesInstallation.INDIVIDUAL_HEATER], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, @@ -75,8 +80,8 @@ export const mockProfileType2: ProfileType = { floor: Floor.GROUND_FLOOR, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: IndividualInsulationWork.WINDOW_REPLACEMENT, - facilitiesInstallation: FacilitiesInstallation.INDIVIDUAL_HEATER, + individualInsulationWork: [IndividualInsulationWork.WINDOW_REPLACEMENT], + facilitiesInstallation: [FacilitiesInstallation.INDIVIDUAL_HEATER], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, @@ -87,7 +92,7 @@ export const mockCorrectedConsumption2 = 15411 //For the month of january export const mockMonthConsumption2 = 3000 -export const mockTestProfile1 = { +export const mockTestProfile1: ProfileType = { housingType: HousingType.INDIVIDUAL_HOUSE, constructionYear: ConstructionYear.BETWEEN_1948_AND_1974, area: 110, @@ -96,8 +101,8 @@ export const mockTestProfile1 = { floor: Floor.NOT_APPLICABLE, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: IndividualInsulationWork.WINDOW_REPLACEMENT, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [IndividualInsulationWork.WINDOW_REPLACEMENT], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.GAS, @@ -146,7 +151,7 @@ export const mockMonthlyForecastJanuaryTestProfile1: MonthlyForecast = { totalValue: 746.921, } -export const mockTestProfile2 = { +export const mockTestProfile2: ProfileType = { housingType: HousingType.APPARTMENT, constructionYear: ConstructionYear.BETWEEN_1975_AND_1989, area: 50, @@ -155,8 +160,8 @@ export const mockTestProfile2 = { floor: Floor.GROUND_FLOOR, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: IndividualInsulationWork.NONE, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [IndividualInsulationWork.NONE], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.OTHER], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY, @@ -206,7 +211,7 @@ export const mockMonthlyForecastJanuaryTestProfile2: MonthlyForecast = { totalValue: 284.511, } -export const mockTestProfile3 = { +export const mockTestProfile3: ProfileType = { housingType: HousingType.APPARTMENT, constructionYear: ConstructionYear.BETWEEN_1948_AND_1974, area: 50, @@ -215,8 +220,8 @@ export const mockTestProfile3 = { floor: Floor.GROUND_FLOOR, heating: IndividualOrCollective.COLLECTIVE, hotWater: IndividualOrCollective.COLLECTIVE, - individualInsulationWork: IndividualInsulationWork.NONE, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [IndividualInsulationWork.NONE], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.OTHER], warmingFluid: null, hotWaterFluid: null, @@ -266,7 +271,7 @@ export const mockMonthlyForecastJanuaryTestProfile3: MonthlyForecast = { totalValue: 56.323, } -export const mockTestProfileHotWaterMulti = { +export const mockTestProfileHotWaterMulti: ProfileType = { housingType: HousingType.INDIVIDUAL_HOUSE, constructionYear: ConstructionYear.BETWEEN_1948_AND_1974, area: 110, @@ -275,8 +280,8 @@ export const mockTestProfileHotWaterMulti = { floor: Floor.NOT_APPLICABLE, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: IndividualInsulationWork.WINDOW_REPLACEMENT, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [IndividualInsulationWork.WINDOW_REPLACEMENT], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.SOLAR, HotWaterEquipment.THERMODYNAMIC], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.GAS, @@ -324,3 +329,123 @@ export const mockMonthlyForecastJanuaryHotWaterMulti: MonthlyForecast = { month: 1, totalValue: 739.229, } +export const mockProfileTypeAnswers: ProfileTypeAnswer[] = [ + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'housingType', + choices: Object.values(HousingType), + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'constructionYear', + choices: Object.values(ConstructionYear), + }, + { + type: ProfileTypeFormType.NUMBER, + attribute: 'area', + choices: [], + }, + { + type: ProfileTypeFormType.NUMBER_SELECTION, + attribute: 'occupantsNumber', + choices: [1, 2, 3, 4, 5, 6, 7, 8, 9], + }, + { + type: ProfileTypeFormType.NUMBER_SELECTION, + attribute: 'outsideFacingWalls', + choices: [0, 1, 2, 3, 4], + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'floor', + choices: Object.values(Floor), + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'heating', + choices: Object.values(IndividualOrCollective), + }, + { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'individualInsulationWork', + choices: Object.values(IndividualInsulationWork), + }, + { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'facilitiesInstallation', + choices: Object.values(FacilitiesInstallation), + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'hotWater', + choices: Object.values(IndividualOrCollective), + }, + { + type: ProfileTypeFormType.MULTI_CHOICE, + attribute: 'hotWaterEquipment', + choices: Object.values(HotWaterEquipment), + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'hotWaterFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'warmingFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'cookingFluid', + choices: [FluidType.ELECTRICITY, FluidType.GAS], + }, + { + type: ProfileTypeFormType.SINGLE_CHOICE, + attribute: 'housingType', + choices: [], + }, +] + +export const mockMonthlyForecastJanuaryTest1WithFullArrays: MonthlyForecast = { + fluidForecast: [ + { + detailsMonthlyForecast: { + coldWaterConsumption: null, + cookingConsumption: null, + ecsConsumption: null, + electricSpecificConsumption: 266, + heatingConsumption: 2479, + }, + fluidType: 0, + load: 2745, + value: 424.38, + }, + { + detailsMonthlyForecast: { + coldWaterConsumption: 14911, + cookingConsumption: null, + ecsConsumption: null, + electricSpecificConsumption: null, + heatingConsumption: null, + }, + fluidType: 1, + load: 14911, + value: 46.224, + }, + { + detailsMonthlyForecast: { + coldWaterConsumption: null, + cookingConsumption: 85, + ecsConsumption: 290, + electricSpecificConsumption: null, + heatingConsumption: null, + }, + fluidType: 2, + load: 375, + value: 29.737, + }, + ], + month: 1, + totalValue: 500.341, +} diff --git a/test/__mocks__/store.ts b/test/__mocks__/store.ts index f80ba7ba200a7212d75868fcb0bb8c057fd86316..e95201f9f1e4f6383fecc5d8e4e9a01324a9c2dd 100644 --- a/test/__mocks__/store.ts +++ b/test/__mocks__/store.ts @@ -114,9 +114,11 @@ export const mockInitialProfileState: Profile = { floor: Floor.NOT_APPLICABLE, heating: IndividualOrCollective.INDIVIDUAL, hotWater: IndividualOrCollective.INDIVIDUAL, - individualInsulationWork: - IndividualInsulationWork.WINDOW_REPLACEMENT_AND_WALL_INSULATION, - facilitiesInstallation: FacilitiesInstallation.NONE, + individualInsulationWork: [ + IndividualInsulationWork.WINDOW_REPLACEMENT, + IndividualInsulationWork.WALL_INSULATION, + ], + facilitiesInstallation: [FacilitiesInstallation.NONE], hotWaterEquipment: [HotWaterEquipment.SOLAR], warmingFluid: FluidType.ELECTRICITY, hotWaterFluid: FluidType.ELECTRICITY,