-
Notifications
You must be signed in to change notification settings - Fork 214
[Chakra v3 upgrade] @W-18672580 migrate offline components #2684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b656e9d
921af09
3bb0a95
3eee4df
3bf6378
45cfe62
73e901e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,7 @@ import React from 'react' | |
| import {useIntl} from 'react-intl' | ||
|
|
||
| // Components | ||
| import {Alert, AlertDescription, Flex} from '@chakra-ui/react' | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In chakra v3, everything imported from Alert alone, AlertDescription is not needed anymore |
||
| import {Alert, Flex} from '@chakra-ui/react' | ||
|
|
||
| // Icons | ||
| import {AlertIcon} from '../../components/icons' | ||
|
|
@@ -20,17 +20,17 @@ import {AlertIcon} from '../../components/icons' | |
| const OfflineBanner = ({...props}) => { | ||
| const intl = useIntl() | ||
| return ( | ||
| <Alert status="warning" {...props}> | ||
| <Alert.Root status="warning" colorPalette="blue" {...props}> | ||
| <Flex align="center"> | ||
| <AlertIcon mr={2} /> | ||
| <AlertDescription> | ||
| <Alert.Title> | ||
| {intl.formatMessage({ | ||
| id: 'offline_banner.description.browsing_offline_mode', | ||
| defaultMessage: "You're currently browsing in offline mode" | ||
| })} | ||
| </AlertDescription> | ||
| </Alert.Title> | ||
| </Flex> | ||
| </Alert> | ||
| </Alert.Root> | ||
| ) | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,12 +7,9 @@ | |
| import React from 'react' | ||
| import PropTypes from 'prop-types' | ||
| import {withRouter} from 'react-router-dom' | ||
| import {Button} from '@chakra-ui/react' | ||
| import {Button, Box, Heading, Text} from '@chakra-ui/react' | ||
| import {AlertIcon} from '../../components/icons' | ||
|
|
||
| // import Button from '@salesforce/pwa-kit-react-sdk/components/button' | ||
| // import Icon from '@salesforce/pwa-kit-react-sdk/components/icon' | ||
|
|
||
| /** | ||
| * OfflineBoundary is a React Error boundary that catches errors thrown when | ||
| * dynamically loading pages and renders a fallback. | ||
|
|
@@ -68,24 +65,14 @@ class OfflineBoundary extends React.Component { | |
| return ( | ||
| <React.Fragment> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every component in offline-boundary is v3 compatible already. |
||
| {chunkLoadError ? ( | ||
| <div className="c-offline-boundary u-direction-column u-text-align-center u-padding-top u-padding-bottom"> | ||
| <Box> | ||
| <AlertIcon /> | ||
|
|
||
| <h1 className="u-margin-bottom-md u-text-family"> | ||
| You are currently offline | ||
| </h1> | ||
|
|
||
| <p className="u-margin-bottom-lg"> | ||
| <Heading>You are currently offline</Heading> | ||
| <Text> | ||
| {"We couldn't load the next page on this connection. Please try again."} | ||
| </p> | ||
|
|
||
| <Button | ||
| className="u-width-block-full pw--primary qa-retry-button" | ||
| onClick={() => this.clearError()} | ||
| > | ||
| Retry Connection | ||
| </Button> | ||
| </div> | ||
| </Text> | ||
| <Button onClick={() => this.clearError()}>Retry Connection</Button> | ||
| </Box> | ||
| ) : ( | ||
| children | ||
| )} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,19 +5,27 @@ | |
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
| import React from 'react' | ||
| import {screen} from '@testing-library/react' | ||
| // import userEvent from '@testing-library/user-event' | ||
|
|
||
| import OfflineBoundary from '../../components/offline-boundary/index' | ||
| import {screen, act} from '@testing-library/react' | ||
| import userEvent from '@testing-library/user-event' | ||
| import {ChakraProvider} from '@chakra-ui/react' | ||
| import theme from '../../theme' | ||
| import {renderWithRouter} from '../../utils/test-utils' | ||
|
|
||
| // class ChunkLoadError extends Error { | ||
| // constructor(...params) { | ||
| // // Pass remaining arguments (including vendor specific ones) to parent constructor | ||
| // super(...params) | ||
| // this.name = 'ChunkLoadError' | ||
| // } | ||
| // } | ||
| import OfflineBoundary, {UnwrappedOfflineBoundary} from '../../components/offline-boundary/index' | ||
|
|
||
| // Custom render function that combines Router and Chakra contexts | ||
| const renderWithRouterAndChakra = (component) => { | ||
| const ComponentWithChakra = () => <ChakraProvider value={theme}>{component}</ChakraProvider> | ||
| return renderWithRouter(<ComponentWithChakra />) | ||
| } | ||
|
|
||
| class ChunkLoadError extends Error { | ||
| constructor(...params) { | ||
| // Pass remaining arguments (including vendor specific ones) to parent constructor | ||
| super(...params) | ||
| this.name = 'ChunkLoadError' | ||
| } | ||
| } | ||
|
|
||
| describe('The OfflineBoundary', () => { | ||
| beforeEach(() => { | ||
|
|
@@ -31,7 +39,7 @@ describe('The OfflineBoundary', () => { | |
| }) | ||
|
|
||
| test('should render its children', () => { | ||
| renderWithRouter( | ||
| renderWithRouterAndChakra( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why cant we use renderWithProviders?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In offline-boundary's index.jsx I saw
From my understanding, with withRouter, the error boundary becomes "route-aware", in which normal |
||
| <OfflineBoundary isOnline={true}> | ||
| <div id="child">child</div> | ||
| </OfflineBoundary> | ||
|
|
@@ -40,84 +48,74 @@ describe('The OfflineBoundary', () => { | |
| expect(screen.getByText(/child/i)).toBeInTheDocument() | ||
| }) | ||
|
|
||
| // TODO: Fix flaky/broken test | ||
| // eslint-disable-next-line jest/no-commented-out-tests | ||
| // test('should render the error splash when a child throws a chunk load error', () => { | ||
| // const ThrowingComponent = () => { | ||
| // throw new ChunkLoadError() | ||
| // } | ||
| // renderWithRouter( | ||
| // <OfflineBoundary isOnline={true}> | ||
| // <div> | ||
| // <ThrowingComponent /> | ||
| // <div id="child">child</div> | ||
| // </div> | ||
| // </OfflineBoundary> | ||
| // ) | ||
|
|
||
| // expect(screen.getByRole('img', {name: /offline cloud/i})).toBeInTheDocument() | ||
| // expect( | ||
| // screen.getByRole('heading', {name: /you are currently offline/i}) | ||
| // ).toBeInTheDocument() | ||
| // expect(screen.queryByText(/child/i)).not.toBeInTheDocument() | ||
| // }) | ||
|
|
||
| // TODO: Fix flaky/broken test | ||
| // eslint-disable-next-line jest/no-commented-out-tests | ||
| // test('should re-throw errors that are not chunk load errors', () => { | ||
| // const ThrowingComponent = () => { | ||
| // throw new Error('Anything else') | ||
| // } | ||
| // expect(() => { | ||
| // renderWithRouter( | ||
| // <OfflineBoundary isOnline={true}> | ||
| // <div> | ||
| // <ThrowingComponent /> | ||
| // <div id="child">child</div> | ||
| // </div> | ||
| // </OfflineBoundary> | ||
| // ) | ||
| // }).toThrow() | ||
| // }) | ||
|
|
||
| // TODO: Fix flaky/broken test | ||
| // eslint-disable-next-line jest/no-commented-out-tests | ||
| // test('should attempt to reload the page when the user clicks retry', () => { | ||
| // let firstRender = true | ||
| // const ThrowingOnceComponent = () => { | ||
| // if (firstRender) { | ||
| // firstRender = false | ||
| // throw new ChunkLoadError() | ||
| // } else { | ||
| // return <div id="child">child</div> | ||
| // } | ||
| // } | ||
| // renderWithRouter( | ||
| // <OfflineBoundary isOnline={true}> | ||
| // <ThrowingOnceComponent /> | ||
| // </OfflineBoundary> | ||
| // ) | ||
|
|
||
| // expect(screen.getByRole('img', {name: /offline cloud/i})).toBeInTheDocument() | ||
| // expect( | ||
| // screen.getByRole('heading', {name: /you are currently offline/i}) | ||
| // ).toBeInTheDocument() | ||
| // expect(screen.queryByText(/child/i)).not.toBeInTheDocument() | ||
|
|
||
| // userEvent.click(screen.getByRole('button', {name: /retry connection/i})) | ||
| // expect(screen.getByText(/child/i)).toBeInTheDocument() | ||
| // expect(screen.queryByRole('img', {name: /offline cloud/i})).not.toBeInTheDocument() | ||
| // expect( | ||
| // screen.queryByRole('heading', {name: /you are currently offline/i}) | ||
| // ).not.toBeInTheDocument() | ||
| // }) | ||
|
|
||
| // TODO: Fix flaky/broken test | ||
| // eslint-disable-next-line jest/no-commented-out-tests | ||
| // test('should derive state from a chunk load error', () => { | ||
| // const derived = UnwrappedOfflineBoundary.getDerivedStateFromError( | ||
| // new ChunkLoadError('test') | ||
| // ) | ||
| // expect(derived).toEqual({chunkLoadError: true}) | ||
| // }) | ||
| test('should render the error splash when a child throws a chunk load error', () => { | ||
| const ThrowingComponent = () => { | ||
| throw new ChunkLoadError() | ||
| } | ||
| renderWithRouterAndChakra( | ||
| <OfflineBoundary isOnline={true}> | ||
| <div> | ||
| <ThrowingComponent /> | ||
| <div id="child">child</div> | ||
| </div> | ||
| </OfflineBoundary> | ||
| ) | ||
|
|
||
| expect(screen.getByRole('img', {hidden: true})).toBeInTheDocument() | ||
| expect( | ||
| screen.getByRole('heading', {name: /you are currently offline/i}) | ||
| ).toBeInTheDocument() | ||
| expect(screen.queryByText(/child/i)).not.toBeInTheDocument() | ||
| }) | ||
|
|
||
| test('should re-throw errors that are not chunk load errors', () => { | ||
| const ThrowingComponent = () => { | ||
| throw new Error('Anything else') | ||
| } | ||
| expect(() => { | ||
| renderWithRouterAndChakra( | ||
| <OfflineBoundary isOnline={true}> | ||
| <div> | ||
| <ThrowingComponent /> | ||
| <div id="child">child</div> | ||
| </div> | ||
| </OfflineBoundary> | ||
| ) | ||
| }).toThrow() | ||
| }) | ||
|
|
||
| test('should call clearError when retry button is clicked', async () => { | ||
| const user = userEvent.setup() | ||
| const ThrowingComponent = () => { | ||
| throw new ChunkLoadError() | ||
| } | ||
| const clearErrorSpy = jest.spyOn(UnwrappedOfflineBoundary.prototype, 'clearError') | ||
|
|
||
| renderWithRouterAndChakra( | ||
| <OfflineBoundary isOnline={true}> | ||
| <ThrowingComponent /> | ||
| </OfflineBoundary> | ||
| ) | ||
|
|
||
| expect(screen.getByRole('img', {hidden: true})).toBeInTheDocument() | ||
| expect( | ||
| screen.getByRole('heading', {name: /you are currently offline/i}) | ||
| ).toBeInTheDocument() | ||
|
|
||
| const retryButton = screen.getByRole('button', {name: /retry connection/i}) | ||
| await act(async () => { | ||
| await user.click(retryButton) | ||
| }) | ||
|
|
||
| expect(clearErrorSpy).toHaveBeenCalled() | ||
|
|
||
| clearErrorSpy.mockRestore() | ||
| }) | ||
|
|
||
| test('should derive state from a chunk load error', () => { | ||
| const derived = UnwrappedOfflineBoundary.getDerivedStateFromError( | ||
| new ChunkLoadError('test') | ||
| ) | ||
| expect(derived).toEqual({chunkLoadError: true}) | ||
| }) | ||
| }) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add unit test coverage report for
extension-chakra-storefrontfolder