Skip to content

Commit

Permalink
Remove appBasePath from docs + add mock for AppMountParameters (#58775)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover authored Mar 2, 2020
1 parent bb6fd0b commit 48a33ab
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import { MyPluginDepsStart } from './plugin';

export renderApp = ({ element, history }: AppMountParameters) => {
ReactDOM.render(
// pass `appBasePath` to `basename`
<Router history={history}>
<Route path="/" exact component={HomePage} />
</Router>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ import { BrowserRouter, Route } from 'react-router-dom';
import { CoreStart, AppMountParams } from 'src/core/public';
import { MyPluginDepsStart } from './plugin';

export renderApp = ({ appBasePath, element, onAppLeave }: AppMountParams) => {
export renderApp = ({ element, history, onAppLeave }: AppMountParams) => {
const { renderApp, hasUnsavedChanges } = await import('./application');
onAppLeave(actions => {
if(hasUnsavedChanges()) {
return actions.confirm('Some changes were not saved. Are you sure you want to leave?');
}
return actions.default();
});
return renderApp(params);
return renderApp({ element, history });
}

```
Expand Down
4 changes: 2 additions & 2 deletions src/core/CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ import { MyAppRoot } from './components/app.ts';
/**
* This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle.
*/
export const renderApp = (core: CoreStart, deps: MyPluginDepsStart, { element, appBasePath }: AppMountParams) => {
ReactDOM.render(<MyAppRoot core={core} deps={deps} routerBasePath={appBasePath} />, element);
export const renderApp = (core: CoreStart, deps: MyPluginDepsStart, { element, history }: AppMountParams) => {
ReactDOM.render(<MyAppRoot core={core} deps={deps} routerHistory={history} />, element);
return () => ReactDOM.unmountComponentAtNode(element);
}
```
Expand Down
14 changes: 8 additions & 6 deletions src/core/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ describe('Plugin', () => {
const [coreStartMock, startDepsMock] = await coreSetup.getStartServices();
const unmountMock = jest.fn();
renderAppMock.mockReturnValue(unmountMock);
const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
const params = coreMock.createAppMountParamters('/fake/base/path');

new Plugin(coreMock.createPluginInitializerContext()).setup(coreSetup);
// Grab registered mount function
Expand All @@ -478,7 +478,7 @@ import ReactDOM from 'react-dom';
import { AppMountParams, CoreStart } from 'src/core/public';
import { AppRoot } from './components/app_root';

export const renderApp = ({ element, appBasePath }: AppMountParams, core: CoreStart, plugins: MyPluginDepsStart) => {
export const renderApp = ({ element, history }: AppMountParams, core: CoreStart, plugins: MyPluginDepsStart) => {
// Hide the chrome while this app is mounted for a full screen experience
core.chrome.setIsVisible(false);

Expand All @@ -491,7 +491,7 @@ export const renderApp = ({ element, appBasePath }: AppMountParams, core: CoreSt

// Render app
ReactDOM.render(
<AppRoot routerBasePath={appBasePath} core={core} plugins={plugins} />,
<AppRoot routerHistory={history} core={core} plugins={plugins} />,
element
);

Expand All @@ -512,12 +512,14 @@ In testing `renderApp` you should be verifying that:
```typescript
/** public/application.test.ts */
import { createMemoryHistory } from 'history';
import { ScopedHistory } from 'src/core/public';
import { coreMock } from 'src/core/public/mocks';
import { renderApp } from './application';

describe('renderApp', () => {
it('mounts and unmounts UI', () => {
const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
const params = coreMock.createAppMountParamters('/fake/base/path');
const core = coreMock.createStart();

// Verify some expected DOM element is rendered into the element
Expand All @@ -529,7 +531,7 @@ describe('renderApp', () => {
});

it('unsubscribes from uiSettings', () => {
const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
const params = coreMock.createAppMountParamters('/fake/base/path');
const core = coreMock.createStart();
// Create a fake Subject you can use to monitor observers
const settings$ = new Subject();
Expand All @@ -544,7 +546,7 @@ describe('renderApp', () => {
});

it('resets chrome visibility', () => {
const params = { element: document.createElement('div'), appBasePath: '/fake/base/path' };
const params = coreMock.createAppMountParamters('/fake/base/path');
const core = coreMock.createStart();

// Verify stateful Core API was called on mount
Expand Down
5 changes: 2 additions & 3 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ export interface AppMountParameters<HistoryLocationState = unknown> {
*
* export renderApp = ({ element, history }: AppMountParameters) => {
* ReactDOM.render(
* // pass `appBasePath` to `basename`
* <Router history={history}>
* <Route path="/" exact component={HomePage} />
* </Router>,
Expand Down Expand Up @@ -429,15 +428,15 @@ export interface AppMountParameters<HistoryLocationState = unknown> {
* import { CoreStart, AppMountParams } from 'src/core/public';
* import { MyPluginDepsStart } from './plugin';
*
* export renderApp = ({ appBasePath, element, onAppLeave }: AppMountParams) => {
* export renderApp = ({ element, history, onAppLeave }: AppMountParams) => {
* const { renderApp, hasUnsavedChanges } = await import('./application');
* onAppLeave(actions => {
* if(hasUnsavedChanges()) {
* return actions.confirm('Some changes were not saved. Are you sure you want to leave?');
* }
* return actions.default();
* });
* return renderApp(params);
* return renderApp({ element, history });
* }
* ```
*/
Expand Down
25 changes: 24 additions & 1 deletion src/core/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
import { createMemoryHistory } from 'history';

// Only import types from '.' to avoid triggering default Jest mocks.
import { CoreContext, PluginInitializerContext, AppMountParameters } from '.';
// Import values from their individual modules instead.
import { ScopedHistory } from './application';

import { applicationServiceMock } from './application/application_service.mock';
import { chromeServiceMock } from './chrome/chrome_service.mock';
import { CoreContext, PluginInitializerContext } from '.';
import { docLinksServiceMock } from './doc_links/doc_links_service.mock';
import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock';
import { httpServiceMock } from './http/http_service.mock';
Expand Down Expand Up @@ -139,10 +145,27 @@ function createStorageMock() {
return storageMock;
}

function createAppMountParametersMock(appBasePath = '') {
// Assemble an in-memory history mock using the provided basePath
const rawHistory = createMemoryHistory();
rawHistory.push(appBasePath);
const history = new ScopedHistory(rawHistory, appBasePath);

const params: jest.Mocked<AppMountParameters> = {
appBasePath,
element: document.createElement('div'),
history,
onAppLeave: jest.fn(),
};

return params;
}

export const coreMock = {
createCoreContext,
createSetup: createCoreSetupMock,
createStart: createCoreStartMock,
createPluginInitializerContext: pluginInitializerContextMock,
createStorage: createStorageMock,
createAppMountParamters: createAppMountParametersMock,
};

0 comments on commit 48a33ab

Please sign in to comment.