From 26d91ed67ead47930a5d0d5407605f7985a698c5 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 14:33:13 -0400 Subject: [PATCH 1/8] fix: resolve sunrise-sunset test missing props --- .../components/widgets/weather/sunrise-sunset.test.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/javascript/components/widgets/weather/sunrise-sunset.test.jsx b/app/javascript/components/widgets/weather/sunrise-sunset.test.jsx index 37b658c9..952cdd9b 100644 --- a/app/javascript/components/widgets/weather/sunrise-sunset.test.jsx +++ b/app/javascript/components/widgets/weather/sunrise-sunset.test.jsx @@ -2,6 +2,8 @@ import React from 'react'; import ReactTestRenderer from 'react-test-renderer'; const location = { + cityName: 'Providence', + moonPhase: 0.5, timezone: 'America/New_York', solarCycles: [ { type: 'sunset', time: '2021-06-09T00:18:31Z' }, @@ -11,7 +13,10 @@ const location = { ], }; -const weather = { moonPhase: 1, current: { weather: { id: 803 } } }; +const weather = { + moonPhase: 1, + current: { weather: { id: 803 }, windSpeed: 1 }, +}; describe('SunriseSunset component', () => { const mockDate = new Date('2021-06-09T00:18:31Z'); From 92779fee5cee7fb4f129d76c4d8417e95c0ed904 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 14:38:21 -0400 Subject: [PATCH 2/8] chore: disallow console.error in jest tests React propType failures are signaled via console.error. This prevents propType failures by overriding the console.error behavior to throw an erorr instead of logging to STDOUT --- jest.overrides.js | 4 ++++ package.json | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 jest.overrides.js diff --git a/jest.overrides.js b/jest.overrides.js new file mode 100644 index 00000000..b8519a49 --- /dev/null +++ b/jest.overrides.js @@ -0,0 +1,4 @@ +const util = require('util'); +global.console.error = (message, ...rest) => { + throw Error(util.format(message, ...rest)); +}; diff --git a/package.json b/package.json index dd6d340e..dcd63888 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,9 @@ "moduleDirectories": [ "node_modules", "app/javascript" + ], + "setupFiles": [ + "./jest.overrides.js" ] } } From 6ff70735a4e5e1c6f99f8c431381e1a565e070c5 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 13:22:30 -0400 Subject: [PATCH 3/8] feat: add react-recompose for HoCs --- package.json | 1 + yarn.lock | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index dcd63888..fba1f9ec 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react-dom": "17.0.2", "react-highlight-words": "0.17.0", "react-hls-player": "^3.0.1", + "react-recompose": "^0.31.1", "react-router-dom": "^5.2.0", "regenerator-runtime": "^0.13.7", "resurrect-js": "^1.0.1", diff --git a/yarn.lock b/yarn.lock index c22bf760..e1bac853 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1003,6 +1003,13 @@ pirates "^4.0.0" source-map-support "^0.5.9" +"@babel/runtime@^7.0.0": + version "7.14.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" + integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" @@ -3198,6 +3205,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +change-emitter@^0.1.2: + version "0.1.6" + resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" + integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU= + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -5704,6 +5716,11 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^2.3.1: + version "2.5.5" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" + integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== + hoist-non-react-statics@^3.0.1, hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" @@ -9807,6 +9824,22 @@ react-is@^16.7.0, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== +react-lifecycles-compat@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-recompose@^0.31.1: + version "0.31.1" + resolved "https://registry.yarnpkg.com/react-recompose/-/react-recompose-0.31.1.tgz#8946fd499634183a6b0fa3adbf42e2342debe08b" + integrity sha512-FzKNgEO9aDfW4NWqKv/0QhmXXDr6qHEZRo3oyahNdJjWRSGo06KVGcvSCBZQckIcxP9o2f91eIfQmtyjwiuSGQ== + dependencies: + "@babel/runtime" "^7.0.0" + change-emitter "^0.1.2" + hoist-non-react-statics "^2.3.1" + react-lifecycles-compat "^3.0.2" + symbol-observable "^1.0.4" + react-router-dom@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" @@ -11255,7 +11288,7 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-observable@^1.0.2: +symbol-observable@^1.0.2, symbol-observable@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== From f708f4d04cbcb677be49e31aa228b8e7c2ded014 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 13:32:53 -0400 Subject: [PATCH 4/8] feat: add render-while-loading hoc --- .../components/hocs/render-while-loading.jsx | 17 +++++++ .../hocs/render-while-loading.test.jsx | 46 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 app/javascript/components/hocs/render-while-loading.jsx create mode 100644 app/javascript/components/hocs/render-while-loading.test.jsx diff --git a/app/javascript/components/hocs/render-while-loading.jsx b/app/javascript/components/hocs/render-while-loading.jsx new file mode 100644 index 00000000..685d2b43 --- /dev/null +++ b/app/javascript/components/hocs/render-while-loading.jsx @@ -0,0 +1,17 @@ +import PropTypes from 'prop-types'; +import { + branch, + compose, + renderComponent, + setPropTypes, +} from 'react-recompose'; + +export const renderWhileLoading = loadingComponent => + compose( + setPropTypes({ + loading: PropTypes.bool.isRequired, + }), + branch(({ loading }) => !!loading, renderComponent(loadingComponent)), + ); + +export default renderWhileLoading; diff --git a/app/javascript/components/hocs/render-while-loading.test.jsx b/app/javascript/components/hocs/render-while-loading.test.jsx new file mode 100644 index 00000000..a2993ecc --- /dev/null +++ b/app/javascript/components/hocs/render-while-loading.test.jsx @@ -0,0 +1,46 @@ +import React from 'react'; +import ReactTestRenderer from 'react-test-renderer'; +import renderWhileLoading from '@hocs/render-while-loading'; + +describe('renderWhileLoading higher order component', () => { + it('it renders the loading component if loading property is true', () => { + const testLoadingComponent = () => { + return 'testLoadingComponent rendered'; + }; + const testBaseComponent = () => { + return 'testBaseComponent rendered'; + }; + const WrappedComponent = renderWhileLoading(testLoadingComponent)( + testBaseComponent, + ); + + expect( + ReactTestRenderer.create().toJSON(), + ).toEqual('testLoadingComponent rendered'); + }); + it('it renders the base component if loading property is false', () => { + const testLoadingComponent = () => { + return 'testLoadingComponent rendered'; + }; + const testBaseComponent = () => { + return 'testBaseComponent rendered'; + }; + const WrappedComponent = renderWhileLoading(testLoadingComponent)( + testBaseComponent, + ); + + expect( + ReactTestRenderer.create().toJSON(), + ).toEqual('testBaseComponent rendered'); + }); + it('it has a prop error if loading property is undefined', () => { + const noop = () => {}; + const WrappedComponent = renderWhileLoading(noop)(noop); + + expect(() => { + ReactTestRenderer.create().toJSON(); + }).toThrow( + 'Failed prop type: The prop `loading` is marked as required in `branch(noop)`, but its value is `undefined`.', + ); + }); +}); From 4b70b7cefcb7a429f8eb2ae8ae4d47a3707a93e0 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 13:35:06 -0400 Subject: [PATCH 5/8] feat: add render-while-error hoc --- .../components/hocs/render-while-error.jsx | 17 +++++++ .../hocs/render-while-error.test.jsx | 46 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 app/javascript/components/hocs/render-while-error.jsx create mode 100644 app/javascript/components/hocs/render-while-error.test.jsx diff --git a/app/javascript/components/hocs/render-while-error.jsx b/app/javascript/components/hocs/render-while-error.jsx new file mode 100644 index 00000000..a24e6bf7 --- /dev/null +++ b/app/javascript/components/hocs/render-while-error.jsx @@ -0,0 +1,17 @@ +import PropTypes from 'prop-types'; +import { + branch, + compose, + renderComponent, + setPropTypes, +} from 'react-recompose'; + +export const renderWhileError = errorComponent => + compose( + setPropTypes({ + error: PropTypes.bool.isRequired, + }), + branch(({ error }) => !!error, renderComponent(errorComponent)), + ); + +export default renderWhileError; diff --git a/app/javascript/components/hocs/render-while-error.test.jsx b/app/javascript/components/hocs/render-while-error.test.jsx new file mode 100644 index 00000000..029ee7bf --- /dev/null +++ b/app/javascript/components/hocs/render-while-error.test.jsx @@ -0,0 +1,46 @@ +import React from 'react'; +import ReactTestRenderer from 'react-test-renderer'; +import renderWhileError from '@hocs/render-while-error'; + +describe('renderWhileError higher order component', () => { + it('it renders the error component if error property is true', () => { + const testErrorComponent = () => { + return 'testErrorComponent rendered'; + }; + const testBaseComponent = () => { + return 'testBaseComponent rendered'; + }; + const WrappedComponent = renderWhileError(testErrorComponent)( + testBaseComponent, + ); + + expect( + ReactTestRenderer.create().toJSON(), + ).toEqual('testErrorComponent rendered'); + }); + it('it renders the base component if error property is false', () => { + const testErrorComponent = () => { + return 'testErrorComponent rendered'; + }; + const testBaseComponent = () => { + return 'testBaseComponent rendered'; + }; + const WrappedComponent = renderWhileError(testErrorComponent)( + testBaseComponent, + ); + + expect( + ReactTestRenderer.create().toJSON(), + ).toEqual('testBaseComponent rendered'); + }); + it('it has a prop error if error property is undefined', () => { + const noop = () => {}; + const WrappedComponent = renderWhileError(noop)(noop); + + expect(() => { + ReactTestRenderer.create().toJSON(); + }).toThrow( + 'Failed prop type: The prop `error` is marked as required in `branch(noop)`, but its value is `undefined`.', + ); + }); +}); From fb31a8ab1c3520a4bac0a12a411ca8a0d36dcd46 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 13:44:46 -0400 Subject: [PATCH 6/8] refactor: withFragement should return a function that accepts a component This update withFragment to interopt with compose and react-recompose which expect all HoCs to accept a single argument that is the component. --- app/javascript/components/bathroom.jsx | 2 +- app/javascript/components/date.jsx | 2 +- app/javascript/components/hocs/with-fragment.jsx | 6 ++++-- app/javascript/components/hocs/with-fragment.test.jsx | 4 ++-- app/javascript/components/side-panel.jsx | 2 +- app/javascript/components/time-hero.jsx | 2 +- app/javascript/components/top-corner-controller.jsx | 2 +- app/javascript/components/widget-display.jsx | 2 +- app/javascript/components/widgets/weather/current-temp.jsx | 2 +- .../components/widgets/weather/current-weather.jsx | 2 +- app/javascript/components/widgets/weather/daily-weather.jsx | 2 +- app/javascript/components/widgets/weather/hourly-temps.jsx | 2 +- .../components/widgets/weather/sunrise-sunset.jsx | 4 ++-- .../components/widgets/weather/weather-effect.jsx | 2 +- app/javascript/components/widgets/weather/weather-icon.jsx | 2 +- app/javascript/components/wifi.jsx | 2 +- 16 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app/javascript/components/bathroom.jsx b/app/javascript/components/bathroom.jsx index 2a53e26d..223bcfe7 100644 --- a/app/javascript/components/bathroom.jsx +++ b/app/javascript/components/bathroom.jsx @@ -52,4 +52,4 @@ Bathroom.defaultProps = { error: false, }; -export default withFragment(Bathroom, { location: getBathroomCode }); +export default withFragment({ location: getBathroomCode })(Bathroom); diff --git a/app/javascript/components/date.jsx b/app/javascript/components/date.jsx index 23b311b9..2bc339e1 100644 --- a/app/javascript/components/date.jsx +++ b/app/javascript/components/date.jsx @@ -83,4 +83,4 @@ export class Date extends React.Component { } } -export default withFragment(Date, { location: getTimeZone }); +export default withFragment({ location: getTimeZone })(Date); diff --git a/app/javascript/components/hocs/with-fragment.jsx b/app/javascript/components/hocs/with-fragment.jsx index 23cc9768..6c9a56b2 100644 --- a/app/javascript/components/hocs/with-fragment.jsx +++ b/app/javascript/components/hocs/with-fragment.jsx @@ -5,7 +5,7 @@ import { filter } from 'graphql-anywhere'; * withFragment returns a component which expects props that match * WrappedComponent's fragment names */ -export default function withFragment(WrappedComponent, fragmentObject) { +export const withFragment = fragmentObject => WrappedComponent => { const Enhanced = React.memo(props => { const fragmentKeys = Object.keys(fragmentObject); const fragmentDataProps = fragmentKeys.reduce((accProps, fragmentKey) => { @@ -20,4 +20,6 @@ export default function withFragment(WrappedComponent, fragmentObject) { }); return Enhanced; -} +}; + +export default withFragment; diff --git a/app/javascript/components/hocs/with-fragment.test.jsx b/app/javascript/components/hocs/with-fragment.test.jsx index 4d41cd23..9eeb1055 100644 --- a/app/javascript/components/hocs/with-fragment.test.jsx +++ b/app/javascript/components/hocs/with-fragment.test.jsx @@ -43,9 +43,9 @@ describe('withFragment higher order component', () => { }); return 'testComponent rendered'; }; - const WrappedComponent = withFragment(testComponent, { + const WrappedComponent = withFragment({ location: locationQuery, - }); + })(testComponent); expect( ReactTestRenderer.create( , diff --git a/app/javascript/components/side-panel.jsx b/app/javascript/components/side-panel.jsx index e3cba3b1..7fb2f840 100644 --- a/app/javascript/components/side-panel.jsx +++ b/app/javascript/components/side-panel.jsx @@ -86,4 +86,4 @@ SidePanel.defaultProps = { error: false, }; -export default withFragment(SidePanel, { location: getSidePanel }); +export default withFragment({ location: getSidePanel })(SidePanel); diff --git a/app/javascript/components/time-hero.jsx b/app/javascript/components/time-hero.jsx index db1423b6..e6bf9899 100644 --- a/app/javascript/components/time-hero.jsx +++ b/app/javascript/components/time-hero.jsx @@ -33,4 +33,4 @@ TimeHero.defaultProps = { error: false, }; -export default withFragment(TimeHero, { location: getTimeHero }); +export default withFragment({ location: getTimeHero })(TimeHero); diff --git a/app/javascript/components/top-corner-controller.jsx b/app/javascript/components/top-corner-controller.jsx index a1f2d7a4..e48e11dd 100644 --- a/app/javascript/components/top-corner-controller.jsx +++ b/app/javascript/components/top-corner-controller.jsx @@ -75,4 +75,4 @@ TopCorner.defaultProps = { error: false, }; -export default withFragment(TopCorner, { location: getTopCorner }); +export default withFragment({ location: getTopCorner })(TopCorner); diff --git a/app/javascript/components/widget-display.jsx b/app/javascript/components/widget-display.jsx index 2a151e7b..485b9430 100644 --- a/app/javascript/components/widget-display.jsx +++ b/app/javascript/components/widget-display.jsx @@ -166,4 +166,4 @@ export const WidgetDisabledDisplay = () => ( ); -export default withFragment(WidgetDisplay, { location: getWidgetDisplay }); +export default withFragment({ location: getWidgetDisplay })(WidgetDisplay); diff --git a/app/javascript/components/widgets/weather/current-temp.jsx b/app/javascript/components/widgets/weather/current-temp.jsx index a3bba73e..1a0a8276 100644 --- a/app/javascript/components/widgets/weather/current-temp.jsx +++ b/app/javascript/components/widgets/weather/current-temp.jsx @@ -20,4 +20,4 @@ CurrentTemp.propTypes = { }).isRequired, }; -export default withFragment(CurrentTemp, { weather: getCurrentTemp }); +export default withFragment({ weather: getCurrentTemp })(CurrentTemp); diff --git a/app/javascript/components/widgets/weather/current-weather.jsx b/app/javascript/components/widgets/weather/current-weather.jsx index 4168027b..01c9964f 100644 --- a/app/javascript/components/widgets/weather/current-weather.jsx +++ b/app/javascript/components/widgets/weather/current-weather.jsx @@ -60,4 +60,4 @@ CurrentWeather.defaultProps = { useLargeIcon: false, }; -export default withFragment(CurrentWeather, { weather: getCurrentWeather }); +export default withFragment({ weather: getCurrentWeather })(CurrentWeather); diff --git a/app/javascript/components/widgets/weather/daily-weather.jsx b/app/javascript/components/widgets/weather/daily-weather.jsx index 8c5200ea..c593ff67 100644 --- a/app/javascript/components/widgets/weather/daily-weather.jsx +++ b/app/javascript/components/widgets/weather/daily-weather.jsx @@ -92,4 +92,4 @@ DailyWeather.propTypes = { }).isRequired, }; -export default withFragment(DailyWeather, { weather: getDailyWeather }); +export default withFragment({ weather: getDailyWeather })(DailyWeather); diff --git a/app/javascript/components/widgets/weather/hourly-temps.jsx b/app/javascript/components/widgets/weather/hourly-temps.jsx index 47f0779e..b8014c57 100644 --- a/app/javascript/components/widgets/weather/hourly-temps.jsx +++ b/app/javascript/components/widgets/weather/hourly-temps.jsx @@ -98,4 +98,4 @@ HourlyTemps.defaultProps = { hours: 5, }; -export default withFragment(HourlyTemps, { weather: getHourlyWeather }); +export default withFragment({ weather: getHourlyWeather })(HourlyTemps); diff --git a/app/javascript/components/widgets/weather/sunrise-sunset.jsx b/app/javascript/components/widgets/weather/sunrise-sunset.jsx index 3d71585d..302ff1c2 100644 --- a/app/javascript/components/widgets/weather/sunrise-sunset.jsx +++ b/app/javascript/components/widgets/weather/sunrise-sunset.jsx @@ -140,7 +140,7 @@ SunriseSunset.propTypes = { weather: PropTypes.shape({}).isRequired, }; -export default withFragment(SunriseSunset, { +export default withFragment({ weather: getSunriseSunsetWeather, location: getSunriseSunsetLocation, -}); +})(SunriseSunset); diff --git a/app/javascript/components/widgets/weather/weather-effect.jsx b/app/javascript/components/widgets/weather/weather-effect.jsx index 9a628070..42cc0365 100644 --- a/app/javascript/components/widgets/weather/weather-effect.jsx +++ b/app/javascript/components/widgets/weather/weather-effect.jsx @@ -509,4 +509,4 @@ WeatherEffect.propTypes = { }).isRequired, }; -export default withFragment(WeatherEffect, { weather: getWeatherEffect }); +export default withFragment({ weather: getWeatherEffect })(WeatherEffect); diff --git a/app/javascript/components/widgets/weather/weather-icon.jsx b/app/javascript/components/widgets/weather/weather-icon.jsx index f78c8b88..0149809e 100644 --- a/app/javascript/components/widgets/weather/weather-icon.jsx +++ b/app/javascript/components/widgets/weather/weather-icon.jsx @@ -26,4 +26,4 @@ CurrentIcon.propTypes = { }).isRequired, }; -export default withFragment(CurrentIcon, { weather: getCurrentIcon }); +export default withFragment({ weather: getCurrentIcon })(CurrentIcon); diff --git a/app/javascript/components/wifi.jsx b/app/javascript/components/wifi.jsx index 32225368..e88c0cf3 100644 --- a/app/javascript/components/wifi.jsx +++ b/app/javascript/components/wifi.jsx @@ -79,4 +79,4 @@ Wifi.defaultProps = { error: false, }; -export default withFragment(Wifi, { location: getWifi }); +export default withFragment({ location: getWifi })(Wifi); From ffdcdd2141e66d7e7340f3bf41e12f78487933aa Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 13:57:48 -0400 Subject: [PATCH 7/8] refactor: replace loading conditions with hoc --- app/javascript/components/bathroom.jsx | 14 +++++++------- app/javascript/components/date.jsx | 14 +++++++------- app/javascript/components/time-hero.jsx | 14 +++++++------- app/javascript/components/wifi.jsx | 14 +++++++------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/javascript/components/bathroom.jsx b/app/javascript/components/bathroom.jsx index 223bcfe7..bf3e4e06 100644 --- a/app/javascript/components/bathroom.jsx +++ b/app/javascript/components/bathroom.jsx @@ -2,8 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import gql from 'graphql-tag'; import styled from 'styled-components'; +import { compose } from 'react-recompose'; import { WhiteSubTitle, WhiteTitleLarge } from '@components/typography'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; export const getBathroomCode = gql` @@ -18,10 +20,7 @@ const Column = styled.div` margin-top: 100px; `; -export const Bathroom = ({ loading, error, location }) => { - if (loading) { - return ; - } +export const Bathroom = ({ error, location }) => { if (error) { return ; } @@ -42,14 +41,15 @@ Bathroom.propTypes = { location: PropTypes.shape({ bathroomCode: PropTypes.string, }), - loading: PropTypes.bool, error: PropTypes.bool, }; Bathroom.defaultProps = { location: {}, - loading: true, error: false, }; -export default withFragment({ location: getBathroomCode })(Bathroom); +export default compose( + renderWhileLoading(LoadingMessage), + withFragment({ location: getBathroomCode }), +)(Bathroom); diff --git a/app/javascript/components/date.jsx b/app/javascript/components/date.jsx index 2bc339e1..225ddc69 100644 --- a/app/javascript/components/date.jsx +++ b/app/javascript/components/date.jsx @@ -2,9 +2,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import gql from 'graphql-tag'; import styled from 'styled-components'; +import { compose } from 'react-recompose'; import { dateForTimezone } from '@lib/datetime'; import { colors, fontSizes, spacing, fonts } from '@lib/theme'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; export const getTimeZone = gql` @@ -22,7 +24,6 @@ export const DateText = styled.div` export class Date extends React.Component { static propTypes = { - loading: PropTypes.bool, error: PropTypes.bool, location: PropTypes.shape({ timezone: PropTypes.string, @@ -30,7 +31,6 @@ export class Date extends React.Component { }; static defaultProps = { - loading: true, error: false, }; @@ -66,10 +66,7 @@ export class Date extends React.Component { }; render() { - const { loading, error } = this.props; - if (loading) { - return ; - } + const { error } = this.props; if (error) { return ; @@ -83,4 +80,7 @@ export class Date extends React.Component { } } -export default withFragment({ location: getTimeZone })(Date); +export default compose( + renderWhileLoading(LoadingMessage), + withFragment({ location: getTimeZone }), +)(Date); diff --git a/app/javascript/components/time-hero.jsx b/app/javascript/components/time-hero.jsx index e6bf9899..eea81b5e 100644 --- a/app/javascript/components/time-hero.jsx +++ b/app/javascript/components/time-hero.jsx @@ -2,7 +2,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import gql from 'graphql-tag'; import Time from '@components/time'; +import { compose } from 'react-recompose'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; export const getTimeHero = gql` @@ -11,10 +13,7 @@ export const getTimeHero = gql` } `; -export const TimeHero = ({ loading, error, location }) => { - if (loading) { - return ; - } +export const TimeHero = ({ error, location }) => { if (error) { return ; } @@ -23,14 +22,15 @@ export const TimeHero = ({ loading, error, location }) => { }; TimeHero.propTypes = { - loading: PropTypes.bool, error: PropTypes.bool, location: PropTypes.shape({}).isRequired, }; TimeHero.defaultProps = { - loading: true, error: false, }; -export default withFragment({ location: getTimeHero })(TimeHero); +export default compose( + renderWhileLoading(LoadingMessage), + withFragment({ location: getTimeHero }), +)(TimeHero); diff --git a/app/javascript/components/wifi.jsx b/app/javascript/components/wifi.jsx index e88c0cf3..528fcf17 100644 --- a/app/javascript/components/wifi.jsx +++ b/app/javascript/components/wifi.jsx @@ -2,11 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import gql from 'graphql-tag'; +import { compose } from 'react-recompose'; import { WhiteSubTitle, WhiteTitleLarge } from '@components/typography'; import { Row } from '@components/row'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; import WifiIcon from '@assets/images/icons/icon-wifi.svg'; import LockIcon from '@assets/images/icons/icon-key.svg'; +import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; const Column = styled.div` @@ -30,10 +32,7 @@ export const getWifi = gql` } `; -export const Wifi = ({ loading, error, location }) => { - if (loading) { - return ; - } +export const Wifi = ({ error, location }) => { if (error) { return ; } @@ -70,13 +69,14 @@ Wifi.propTypes = { wifiName: PropTypes.string, wifiPassword: PropTypes.string, }).isRequired, - loading: PropTypes.bool, error: PropTypes.bool, }; Wifi.defaultProps = { - loading: true, error: false, }; -export default withFragment({ location: getWifi })(Wifi); +export default compose( + renderWhileLoading(LoadingMessage), + withFragment({ location: getWifi }), +)(Wifi); From 3582f5066962f6a965e73abefc90162e36620b98 Mon Sep 17 00:00:00 2001 From: Craig Barber Date: Wed, 4 Aug 2021 14:04:49 -0400 Subject: [PATCH 8/8] refactor: replace error conditions with hoc --- app/javascript/components/bathroom.jsx | 10 +++------- app/javascript/components/date.jsx | 13 +++---------- app/javascript/components/time-hero.jsx | 13 ++++--------- app/javascript/components/wifi.jsx | 13 +++---------- 4 files changed, 13 insertions(+), 36 deletions(-) diff --git a/app/javascript/components/bathroom.jsx b/app/javascript/components/bathroom.jsx index bf3e4e06..df6182ed 100644 --- a/app/javascript/components/bathroom.jsx +++ b/app/javascript/components/bathroom.jsx @@ -5,6 +5,7 @@ import styled from 'styled-components'; import { compose } from 'react-recompose'; import { WhiteSubTitle, WhiteTitleLarge } from '@components/typography'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileError from '@hocs/render-while-error'; import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; @@ -20,11 +21,7 @@ const Column = styled.div` margin-top: 100px; `; -export const Bathroom = ({ error, location }) => { - if (error) { - return ; - } - +export const Bathroom = ({ location }) => { const { bathroomCode } = location; if (!bathroomCode) { return null; @@ -41,15 +38,14 @@ Bathroom.propTypes = { location: PropTypes.shape({ bathroomCode: PropTypes.string, }), - error: PropTypes.bool, }; Bathroom.defaultProps = { location: {}, - error: false, }; export default compose( + renderWhileError(ErrorMessage), renderWhileLoading(LoadingMessage), withFragment({ location: getBathroomCode }), )(Bathroom); diff --git a/app/javascript/components/date.jsx b/app/javascript/components/date.jsx index 225ddc69..2ec14c97 100644 --- a/app/javascript/components/date.jsx +++ b/app/javascript/components/date.jsx @@ -6,6 +6,7 @@ import { compose } from 'react-recompose'; import { dateForTimezone } from '@lib/datetime'; import { colors, fontSizes, spacing, fonts } from '@lib/theme'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileError from '@hocs/render-while-error'; import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; @@ -24,15 +25,12 @@ export const DateText = styled.div` export class Date extends React.Component { static propTypes = { - error: PropTypes.bool, location: PropTypes.shape({ timezone: PropTypes.string, }).isRequired, }; - static defaultProps = { - error: false, - }; + static defaultProps = {}; state = { date: null }; @@ -66,12 +64,6 @@ export class Date extends React.Component { }; render() { - const { error } = this.props; - - if (error) { - return ; - } - const { date } = this.state; if (!date) { return null; @@ -81,6 +73,7 @@ export class Date extends React.Component { } export default compose( + renderWhileError(ErrorMessage), renderWhileLoading(LoadingMessage), withFragment({ location: getTimeZone }), )(Date); diff --git a/app/javascript/components/time-hero.jsx b/app/javascript/components/time-hero.jsx index eea81b5e..1973c6fb 100644 --- a/app/javascript/components/time-hero.jsx +++ b/app/javascript/components/time-hero.jsx @@ -4,6 +4,7 @@ import gql from 'graphql-tag'; import Time from '@components/time'; import { compose } from 'react-recompose'; import { LoadingMessage, ErrorMessage } from '@messages/default-messages'; +import renderWhileError from '@hocs/render-while-error'; import renderWhileLoading from '@hocs/render-while-loading'; import withFragment from './hocs/with-fragment'; @@ -13,24 +14,18 @@ export const getTimeHero = gql` } `; -export const TimeHero = ({ error, location }) => { - if (error) { - return ; - } - +export const TimeHero = ({ location }) => { return