Skip to content

Commit

Permalink
feat(demos): add React Error Handling demo (#447)
Browse files Browse the repository at this point in the history
  • Loading branch information
unstubbable authored Apr 3, 2019
1 parent 0912b4e commit 05fbb75
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/demos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ Demonstrates:
yarn watch:demo custom-logging
```

### [React Error Handling](src/react-error-handling)

Demonstrates:

- how to define a `renderError` prop for the React `FeatureAppLoader` to render
a custom error UI when a Feature App can not be rendered
- how to define an `onError` prop for the React `FeatureAppLoader` to customize
error handling (e.g. logging) for a Feature App that can not be rendered

```sh
yarn watch:demo react-error-handling
```

### [TodoMVC](src/todomvc)

Demonstrates:
Expand Down
11 changes: 11 additions & 0 deletions packages/demos/src/react-error-handling/feature-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {FeatureAppDefinition} from '@feature-hub/core';
import {ReactFeatureApp} from '@feature-hub/react';

const featureAppDefinition: FeatureAppDefinition<ReactFeatureApp> = {
id: 'test:invalid',

// tslint:disable-next-line:no-any intentionally invalid create function
create: () => ({} as any)
};

export default featureAppDefinition;
34 changes: 34 additions & 0 deletions packages/demos/src/react-error-handling/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @jest-environment puppeteer
*/

import {Server} from 'http';
import {AddressInfo} from 'net';
import {Browser} from '../browser';
import {startServer} from '../start-server';
import {stubConsole} from '../stub-console';
import webpackConfigs from './webpack-config';

jest.setTimeout(60000);

stubConsole();

describe('integration test: "react error handling"', () => {
const browser = new Browser(5000);

let server: Server;

beforeAll(async () => {
server = await startServer(webpackConfigs, undefined);

const {port} = server.address() as AddressInfo;

await browser.goto(`http://localhost:${port}`, 60000);
});

afterAll(done => server.close(done));

it('shows a custom error UI for the invalid Feature App', async () => {
await expect(page).toMatch('Example Error UI');
});
});
33 changes: 33 additions & 0 deletions packages/demos/src/react-error-handling/integrator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {Callout, H4, Intent} from '@blueprintjs/core';
import {createFeatureHub} from '@feature-hub/core';
import {loadAmdModule} from '@feature-hub/module-loader-amd';
import {FeatureAppLoader, FeatureHubContextProvider} from '@feature-hub/react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import '../blueprint-css';

const {featureAppManager} = createFeatureHub('test:integrator', {
moduleLoader: loadAmdModule
});

function Error({error}: {error: Error}): JSX.Element {
return (
<Callout intent={Intent.DANGER}>
<H4>Example Error UI</H4>
<p>{error.message}</p>
</Callout>
);
}

ReactDOM.render(
<div style={{padding: '20px'}}>
<FeatureHubContextProvider value={{featureAppManager}}>
<FeatureAppLoader
src="feature-app.umd.js"
onError={console.warn}
renderError={error => <Error error={error} />}
/>
</FeatureHubContextProvider>
</div>,
document.querySelector('main')
);
31 changes: 31 additions & 0 deletions packages/demos/src/react-error-handling/webpack-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// @ts-check
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const webpackBaseConfig = require('../webpack-base-config');

/**
* @type {webpack.Configuration[]}
*/
const configs = [
merge.smart(webpackBaseConfig, {
entry: path.join(__dirname, './feature-app.ts'),
externals: {
react: 'react'
},
output: {
filename: 'feature-app.umd.js',
libraryTarget: 'umd',
publicPath: '/'
}
}),
merge.smart(webpackBaseConfig, {
entry: path.join(__dirname, './integrator.tsx'),
output: {
filename: 'integrator.js',
publicPath: '/'
}
})
];

module.exports = configs;

0 comments on commit 05fbb75

Please sign in to comment.