-
Notifications
You must be signed in to change notification settings - Fork 1
fix(server): handle unhandledRejection and catch sync SSR error #322
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
base: develop
Are you sure you want to change the base?
Changes from 4 commits
0cd54e0
dcb6bfe
6aaab04
db402f5
7af4a93
a56d7d4
974ca27
c6ae82e
c35da3e
df9d465
ecff183
cb23dc8
c59da27
cddfd3f
c976d8a
a51032c
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 |
|---|---|---|
| @@ -0,0 +1,286 @@ | ||
| import React from 'react'; | ||
| import renderer from 'react-test-renderer'; | ||
| import { Provider } from 'react-intl-redux'; | ||
| import configureStore from 'redux-mock-store'; | ||
| import { render } from '@testing-library/react'; | ||
| import { MemoryRouter } from 'react-router-dom'; | ||
| import UniversalLink from './UniversalLink'; | ||
| import config from '@plone/volto/registry'; | ||
|
|
||
| const mockStore = configureStore(); | ||
| const store = mockStore({ | ||
| userSession: { | ||
| token: null, | ||
| }, | ||
| intl: { | ||
| locale: 'en', | ||
| messages: {}, | ||
| }, | ||
| }); | ||
|
|
||
| global.console.error = jest.fn(); | ||
|
|
||
| describe('UniversalLink', () => { | ||
ichim-david marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| it('renders a UniversalLink component with internal link', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href={'/en/welcome-to-volto'}> | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('renders a UniversalLink component with external link', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href="https://github.com/plone/volto"> | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('renders a UniversalLink component if no external(href) link passed', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| item={{ | ||
| '@id': 'http://localhost:3000/en/welcome-to-volto', | ||
| }} | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('check UniversalLink set rel attribute for ext links', () => { | ||
ichim-david marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const { getByTitle } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| href="https://github.com/plone/volto" | ||
| title="Volto GitHub repository" | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
|
|
||
| expect(getByTitle('Volto GitHub repository').getAttribute('rel')).toBe( | ||
| 'noopener', | ||
| ); | ||
| }); | ||
|
|
||
| it('check UniversalLink set target attribute for ext links', () => { | ||
ichim-david marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const { getByTitle } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| href="https://github.com/plone/volto" | ||
| title="Volto GitHub repository" | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
|
|
||
| expect(getByTitle('Volto GitHub repository').getAttribute('target')).toBe( | ||
| '_blank', | ||
| ); | ||
| }); | ||
|
|
||
| it('check UniversalLink can unset target for ext links with prop', () => { | ||
| const { getByTitle } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| href="https://github.com/plone/volto" | ||
| title="Volto GitHub repository" | ||
| openLinkInNewTab={false} | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
|
|
||
| expect(getByTitle('Volto GitHub repository').getAttribute('target')).toBe( | ||
| null, | ||
| ); | ||
| }); | ||
|
|
||
| it('check UniversalLink renders ext link for blacklisted urls', () => { | ||
ichim-david marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| config.settings.externalRoutes = [ | ||
| { | ||
| match: { | ||
| path: '/external-app', | ||
| exact: true, | ||
| strict: false, | ||
| }, | ||
| url(payload) { | ||
| return payload.location.pathname; | ||
| }, | ||
| }, | ||
| ]; | ||
|
Comment on lines
+132
to
+143
|
||
|
|
||
| const { getByTitle } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| href="http://localhost:3000/external-app" | ||
| title="Blacklisted route" | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
|
|
||
| expect(getByTitle('Blacklisted route').getAttribute('target')).toBe( | ||
| '_blank', | ||
| ); | ||
| }); | ||
|
|
||
| it('UniversalLink renders external link where link is blacklisted', () => { | ||
| const notInEN = | ||
| /^(?!.*(#|\/en|\/static|\/controlpanel|\/cypress|\/login|\/logout|\/contact-form)).*$/; | ||
| config.settings.externalRoutes = [ | ||
| { | ||
| match: { | ||
| path: notInEN, | ||
| exact: false, | ||
| strict: false, | ||
| }, | ||
| url(payload) { | ||
| return payload.location.pathname; | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| const { getByTitle } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| href="http://localhost:3000/blacklisted-app" | ||
| title="External blacklisted app" | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
|
|
||
| expect(getByTitle('External blacklisted app').getAttribute('target')).toBe( | ||
| '_blank', | ||
| ); | ||
| expect(getByTitle('External blacklisted app').getAttribute('rel')).toBe( | ||
| 'noopener', | ||
| ); | ||
| }); | ||
|
|
||
| it('check UniversalLink does not break with error in item', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink | ||
| item={{ | ||
| error: 'Error while fetching content', | ||
| message: 'Something went wrong', | ||
| }} | ||
| > | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toMatchSnapshot(); | ||
| expect(global.console.error).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('renders a UniversalLink component when url ends with @@display-file', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href="http://localhost:3000/en/welcome-to-volto/@@display-file"> | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('returns null when href is an empty array', () => { | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href={[]}> | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toBeNull(); | ||
| expect(global.console.error).toHaveBeenCalledWith( | ||
| 'Invalid href passed to UniversalLink, received an array as href instead of a string', | ||
| [], | ||
| ); | ||
| }); | ||
|
|
||
| it('returns null when href is a non-empty array', () => { | ||
| const invalidHref = ['http://localhost:3000/en/page1', '/en/page2']; | ||
| const component = renderer.create( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href={invalidHref}> | ||
| <h1>Title</h1> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| const json = component.toJSON(); | ||
| expect(json).toBeNull(); | ||
| expect(global.console.error).toHaveBeenCalledWith( | ||
| 'Invalid href passed to UniversalLink, received an array as href instead of a string', | ||
| invalidHref, | ||
| ); | ||
| }); | ||
|
|
||
| it('returns null when href is an array with children elements', () => { | ||
| const invalidHref = ['/en/page']; | ||
| const { container } = render( | ||
| <Provider store={store}> | ||
| <MemoryRouter> | ||
| <UniversalLink href={invalidHref}> | ||
| <h1>Title</h1> | ||
| <p>Description</p> | ||
| </UniversalLink> | ||
| </MemoryRouter> | ||
| </Provider>, | ||
| ); | ||
| expect(container.firstChild).toBeNull(); | ||
| expect(global.console.error).toHaveBeenCalledWith( | ||
| 'Invalid href passed to UniversalLink, received an array as href instead of a string', | ||
| invalidHref, | ||
| ); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`UniversalLink check UniversalLink does not break with error in item 1`] = ` | ||
| <a | ||
| className={null} | ||
| href="/" | ||
| onClick={[Function]} | ||
| target={null} | ||
| title={null} | ||
| > | ||
| <h1> | ||
| Title | ||
| </h1> | ||
| </a> | ||
| `; | ||
|
|
||
| exports[`UniversalLink renders a UniversalLink component if no external(href) link passed 1`] = ` | ||
| <a | ||
| className={null} | ||
| href="/en/welcome-to-volto" | ||
| onClick={[Function]} | ||
| target={null} | ||
| title={null} | ||
| > | ||
| <h1> | ||
| Title | ||
| </h1> | ||
| </a> | ||
| `; | ||
|
|
||
| exports[`UniversalLink renders a UniversalLink component when url ends with @@display-file 1`] = ` | ||
| <a | ||
| className={null} | ||
| href="/en/welcome-to-volto/@@display-file" | ||
| rel="noopener" | ||
| target="_blank" | ||
| title={null} | ||
| > | ||
| <h1> | ||
| Title | ||
| </h1> | ||
| </a> | ||
| `; | ||
|
|
||
| exports[`UniversalLink renders a UniversalLink component with external link 1`] = ` | ||
| <a | ||
| className={null} | ||
| href="https://github.com/plone/volto" | ||
| rel="noopener" | ||
| target="_blank" | ||
| title={null} | ||
| > | ||
| <h1> | ||
| Title | ||
| </h1> | ||
| </a> | ||
| `; | ||
|
|
||
| exports[`UniversalLink renders a UniversalLink component with internal link 1`] = ` | ||
| <a | ||
| className={null} | ||
| href="/en/welcome-to-volto" | ||
| onClick={[Function]} | ||
| target={null} | ||
| title={null} | ||
| > | ||
| <h1> | ||
| Title | ||
| </h1> | ||
| </a> | ||
| `; |
Uh oh!
There was an error while loading. Please reload this page.