|
| 1 | +/* eslint react/prop-types: off */ |
| 2 | + |
1 | 3 | import React from 'react';
|
2 |
| -import { ErrorBoundary } from 'react-error-boundary'; |
3 | 4 | import { render } from '@testing-library/react';
|
4 | 5 | import { fireEvent } from '@testing-library/dom';
|
5 | 6 | import '@testing-library/jest-dom';
|
6 | 7 |
|
| 8 | +import { initializeMockApp } from '..'; |
7 | 9 | import PluginContainer from './PluginContainer';
|
8 | 10 | import Plugin from './Plugin';
|
9 | 11 | import {
|
@@ -34,25 +36,21 @@ describe('PluginContainer', () => {
|
34 | 36 | expect(container.firstChild).toBeNull();
|
35 | 37 | });
|
36 | 38 |
|
37 |
| - it('should render the desired fallback when the iframe fails to render', () => { |
38 |
| - |
39 |
| - }); |
40 |
| - |
41 |
| - it('should render a PluginIFrame when given an iFrame config', async () => { |
| 39 | + it('should render a Plugin iFrame Container when given an iFrame config', async () => { |
42 | 40 | const title = 'test plugin';
|
43 | 41 | const component = (
|
44 |
| - <PluginContainer config={iframeConfig} title={title} fallback={<div>Fallback</div>} /> |
| 42 | + <PluginContainer config={iframeConfig} title={title} fallback={<div>Loading</div>} /> |
45 | 43 | );
|
46 | 44 |
|
47 | 45 | const { container } = render(component);
|
48 | 46 |
|
49 |
| - const iframeElement = await container.querySelector('iframe'); |
| 47 | + const iframeElement = container.querySelector('iframe'); |
50 | 48 | const fallbackElement = container.querySelector('div');
|
51 | 49 |
|
52 | 50 | expect(iframeElement).toBeInTheDocument();
|
53 | 51 | expect(fallbackElement).toBeInTheDocument();
|
54 | 52 |
|
55 |
| - expect(fallbackElement.innerHTML).toEqual('Fallback'); |
| 53 | + expect(fallbackElement.innerHTML).toEqual('Loading'); |
56 | 54 |
|
57 | 55 | // Ensure the iframe has the proper attributes
|
58 | 56 | expect(iframeElement.attributes.getNamedItem('allow').value).toEqual(IFRAME_FEATURE_POLICY);
|
@@ -98,18 +96,88 @@ describe('PluginContainer', () => {
|
98 | 96 | });
|
99 | 97 |
|
100 | 98 | describe('Plugin', () => {
|
101 |
| - const breakingArray = null; |
102 |
| - const failingMap = () => breakingArray.map(a => a); |
103 |
| - it('should render the desired fallback when the error boundary receives a React error', () => { |
| 99 | + let logError = jest.fn(); |
| 100 | + |
| 101 | + beforeEach(async () => { |
| 102 | + // This is a gross hack to suppress error logs in the invalid parentSelector test |
| 103 | + jest.spyOn(console, 'error'); |
| 104 | + global.console.error.mockImplementation(() => {}); |
| 105 | + |
| 106 | + const { loggingService } = initializeMockApp(); |
| 107 | + logError = loggingService.logError; |
| 108 | + }); |
| 109 | + |
| 110 | + afterEach(() => { |
| 111 | + global.console.error.mockRestore(); |
| 112 | + jest.clearAllMocks(); |
| 113 | + }); |
| 114 | + |
| 115 | + const ExplodingComponent = () => { |
| 116 | + throw new Error('booyah'); |
| 117 | + }; |
| 118 | + |
| 119 | + function HealthyComponent() { |
| 120 | + return ( |
| 121 | + <div>Hello World!</div> |
| 122 | + ); |
| 123 | + } |
| 124 | + |
| 125 | + const errorFallback = () => ( |
| 126 | + <div> |
| 127 | + <p> |
| 128 | + Oh geez, this is not good at all. |
| 129 | + </p> |
| 130 | + <br /> |
| 131 | + </div> |
| 132 | + ); |
| 133 | + |
| 134 | + it('should render children if no error', () => { |
| 135 | + const component = ( |
| 136 | + <Plugin errorFallbackProp={errorFallback}> |
| 137 | + <HealthyComponent /> |
| 138 | + </Plugin> |
| 139 | + ); |
| 140 | + const { container } = render(component); |
| 141 | + expect(container).toHaveTextContent('Hello World!'); |
| 142 | + }); |
| 143 | + |
| 144 | + it('should throw an error if the child component fails', () => { |
| 145 | + const component = ( |
| 146 | + <Plugin className="bg-light" errorFallbackProp={errorFallback}> |
| 147 | + <ExplodingComponent /> |
| 148 | + </Plugin> |
| 149 | + ); |
| 150 | + |
| 151 | + render(component); |
| 152 | + |
| 153 | + expect(logError).toHaveBeenCalledTimes(1); |
| 154 | + expect(logError).toHaveBeenCalledWith( |
| 155 | + new Error('booyah'), |
| 156 | + expect.objectContaining({ |
| 157 | + stack: expect.stringContaining('ExplodingComponent'), |
| 158 | + }), |
| 159 | + ); |
| 160 | + }); |
| 161 | + |
| 162 | + it('should render the passed in fallback component when the error boundary receives a React error', () => { |
| 163 | + const component = ( |
| 164 | + <Plugin errorFallbackProp={errorFallback}> |
| 165 | + <ExplodingComponent /> |
| 166 | + </Plugin> |
| 167 | + ); |
| 168 | + |
| 169 | + const { container } = render(component); |
| 170 | + expect(container).toHaveTextContent('Oh geez'); |
| 171 | + }); |
| 172 | + |
| 173 | + it('should render the default fallback component when one is not passed into the Plugin', () => { |
104 | 174 | const component = (
|
105 |
| - <ErrorBoundary fallback={<div>Something went wrong</div>}> |
106 |
| - <Plugin className="bg-light" ready> |
107 |
| - { failingMap } |
108 |
| - </Plugin> |
109 |
| - </ErrorBoundary> |
| 175 | + <Plugin> |
| 176 | + <ExplodingComponent /> |
| 177 | + </Plugin> |
110 | 178 | );
|
111 | 179 |
|
112 | 180 | const { container } = render(component);
|
113 |
| - expect(container.firstChild).toHaveTextContent('Something went wrong'); |
| 181 | + expect(container).toHaveTextContent('Oops! An error occurred.'); |
114 | 182 | });
|
115 | 183 | });
|
0 commit comments