Skip to content

Commit

Permalink
Migrate ui/notify/fatal_error to new platform (#20752)
Browse files Browse the repository at this point in the history
Fixes #20695

Extracts the "fatal error" handling logic from the `ui/notify` module and reimplements it in the new platform, using EUI for the fatal error page and continuing to support the `fatalError()` and `addFatalErrorCallback()` methods exported by the `ui/notify` module.

![image](https://user-images.githubusercontent.com/1329312/43032175-d37fbafc-8c65-11e8-8f1f-da71f0dac014.png)
  • Loading branch information
Spencer authored Jul 30, 2018
1 parent 3b74158 commit 1532c5e
Show file tree
Hide file tree
Showing 34 changed files with 1,293 additions and 223 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
"@types/bluebird": "^3.1.1",
"@types/chance": "^1.0.0",
"@types/classnames": "^2.2.3",
"@types/enzyme": "^3.1.12",
"@types/eslint": "^4.16.2",
"@types/execa": "^0.9.0",
"@types/fetch-mock": "^5.12.2",
Expand Down
20 changes: 20 additions & 0 deletions packages/kbn-test-subj-selector/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export default function(selector: string): string;
6 changes: 6 additions & 0 deletions packages/kbn-test-subj-selector/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "../../tsconfig.json",
"include": [
"index.d.ts"
],
}
62 changes: 61 additions & 1 deletion src/core/public/core_system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
* under the License.
*/

import { FatalErrorsService } from './fatal_errors';
import { InjectedMetadataService } from './injected_metadata';
import { LegacyPlatformService } from './legacy_platform';

const MockLegacyPlatformService = jest.fn<LegacyPlatformService>(
function _MockLegacyPlatformService(this: any) {
this.start = jest.fn();
this.stop = jest.fn();
}
);
jest.mock('./legacy_platform', () => ({
Expand All @@ -39,7 +41,19 @@ jest.mock('./injected_metadata', () => ({
InjectedMetadataService: MockInjectedMetadataService,
}));

const mockFatalErrorsStartContract = {};
const MockFatalErrorsService = jest.fn<FatalErrorsService>(function _MockFatalErrorsService(
this: any
) {
this.start = jest.fn().mockReturnValue(mockFatalErrorsStartContract);
this.add = jest.fn();
});
jest.mock('./fatal_errors', () => ({
FatalErrorsService: MockFatalErrorsService,
}));

import { CoreSystem } from './core_system';
jest.spyOn(CoreSystem.prototype, 'stop');

const defaultCoreSystemParams = {
rootDomElement: null!,
Expand Down Expand Up @@ -97,6 +111,44 @@ describe('constructor', () => {
useLegacyTestHarness,
});
});

it('passes injectedMetadata, rootDomElement, and a stopCoreSystem function to FatalErrorsService', () => {
const rootDomElement = { rootDomElement: true } as any;
const injectedMetadata = { injectedMetadata: true } as any;

const coreSystem = new CoreSystem({
...defaultCoreSystemParams,
rootDomElement,
injectedMetadata,
});

expect(MockFatalErrorsService).toHaveBeenCalledTimes(1);
expect(MockFatalErrorsService).toHaveBeenLastCalledWith({
rootDomElement,
injectedMetadata: expect.any(MockInjectedMetadataService),
stopCoreSystem: expect.any(Function),
});

const [{ stopCoreSystem }] = MockFatalErrorsService.mock.calls[0];

expect(coreSystem.stop).not.toHaveBeenCalled();
stopCoreSystem();
expect(coreSystem.stop).toHaveBeenCalled();
});
});

describe('#stop', () => {
it('call legacyPlatform.stop()', () => {
const coreSystem = new CoreSystem({
...defaultCoreSystemParams,
});

const legacyPlatformService = MockLegacyPlatformService.mock.instances[0];

expect(legacyPlatformService.stop).not.toHaveBeenCalled();
coreSystem.stop();
expect(legacyPlatformService.stop).toHaveBeenCalled();
});
});

describe('#start()', () => {
Expand All @@ -115,12 +167,20 @@ describe('#start()', () => {
expect(mockInstance.start).toHaveBeenCalledWith();
});

it('calls lifecycleSystem#start()', () => {
it('calls fatalErrors#start()', () => {
startCore();
const [mockInstance] = MockFatalErrorsService.mock.instances;
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith();
});

it('calls legacyPlatform#start()', () => {
startCore();
const [mockInstance] = MockLegacyPlatformService.mock.instances;
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith({
injectedMetadata: mockInjectedMetadataStartContract,
fatalErrors: mockFatalErrorsStartContract,
});
});
});
24 changes: 21 additions & 3 deletions src/core/public/core_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import { FatalErrorsService } from './fatal_errors';
import { InjectedMetadataParams, InjectedMetadataService } from './injected_metadata';
import { LegacyPlatformParams, LegacyPlatformService } from './legacy_platform';

Expand All @@ -34,6 +35,7 @@ interface Params {
* platform the CoreSystem will get many more Services.
*/
export class CoreSystem {
private fatalErrors: FatalErrorsService;
private injectedMetadata: InjectedMetadataService;
private legacyPlatform: LegacyPlatformService;

Expand All @@ -44,6 +46,14 @@ export class CoreSystem {
injectedMetadata,
});

this.fatalErrors = new FatalErrorsService({
rootDomElement,
injectedMetadata: this.injectedMetadata,
stopCoreSystem: () => {
this.stop();
},
});

this.legacyPlatform = new LegacyPlatformService({
rootDomElement,
requireLegacyFiles,
Expand All @@ -52,8 +62,16 @@ export class CoreSystem {
}

public start() {
this.legacyPlatform.start({
injectedMetadata: this.injectedMetadata.start(),
});
try {
const injectedMetadata = this.injectedMetadata.start();
const fatalErrors = this.fatalErrors.start();
this.legacyPlatform.start({ injectedMetadata, fatalErrors });
} catch (error) {
this.fatalErrors.add(error);
}
}

public stop() {
this.legacyPlatform.stop();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`rendering render matches snapshot 1`] = `
<EuiPage
restrictWidth={false}
style={
Object {
"minHeight": "100vh",
}
}
>
<EuiPageBody
restrictWidth={false}
>
<EuiPageContent
horizontalPosition="center"
panelPaddingSize="l"
verticalPosition="center"
>
<EuiEmptyPrompt
actions={
Array [
<EuiButton
color="primary"
data-test-subj="clearSession"
fill={true}
iconSide="left"
onClick={[Function]}
type="button"
>
Clear your session
</EuiButton>,
<EuiButtonEmpty
color="primary"
data-test-subj="goBack"
iconSide="left"
onClick={[Function]}
type="button"
>
Go back
</EuiButtonEmpty>,
]
}
body={
<p>
Try refreshing the page. If that doesn't work, go back to the previous page or clear your session data.
</p>
}
iconColor="danger"
iconType="alert"
title={
<h2>
Something went wrong
</h2>
}
/>
<EuiCallOut
color="danger"
iconType="alert"
key="0"
size="m"
title="foo"
>
<EuiCodeBlock
className="eui-textBreakAll"
language="bash"
>
Version: bar
Build: 123
Error: foo
stack...foo.js:1:1
</EuiCodeBlock>
</EuiCallOut>
<EuiCallOut
color="danger"
iconType="alert"
key="1"
size="m"
title="bar"
>
<EuiCodeBlock
className="eui-textBreakAll"
language="bash"
>
Version: bar
Build: 123
Error: bar
stack...bar.js:1:1
</EuiCodeBlock>
</EuiCallOut>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`#add() deletes all children of rootDomElement and renders <FatalErrorScreen /> into it: fatal error screen component 1`] = `
Array [
Array [
<FatalErrorsScreen
buildNumber="kibanaBuildNumber"
errorInfo$={Rx.Observable}
kibanaVersion="kibanaVersion"
/>,
<div />,
],
]
`;

exports[`#add() deletes all children of rootDomElement and renders <FatalErrorScreen /> into it: fatal error screen container 1`] = `
<div>
<div />
</div>
`;
Loading

0 comments on commit 1532c5e

Please sign in to comment.