Skip to content
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

Remove appBasePath from docs + add mock for AppMountParameters #58775

Merged
merged 3 commits into from
Mar 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
};