Skip to content

Commit

Permalink
[Resolver] restore function to the resolverTest plugin. (#75799)
Browse files Browse the repository at this point in the history
Restore the resolverTest plugin. This will allow us to run the test plugin and try out Resolver using our mock data access layers. Eventually this could be expanded to support multiple different data access layers. It could even be expanded to allow us to control the data access layer via the browser. Another option: we could export the APIs from the server and use those in this test plugin.

We eventually expect other plugins to use Resolver. This test plugin could allow us to test Resolver via the FTR (separately of the Security Solution.)

This would also be useful for writing tests than use the FTR but which are essentially unit tests. For example: taking screenshots, using the mouse to zoom/pan.

Start using: `yarn start --plugin-path x-pack/test/plugin_functional/plugins/resolver_test/`
  • Loading branch information
Robert Austin committed Aug 25, 2020
1 parent e12fed1 commit c90d8c6
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 137 deletions.
12 changes: 10 additions & 2 deletions x-pack/plugins/security_solution/public/common/store/epic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { combineEpics } from 'redux-observable';
import { combineEpics, Epic } from 'redux-observable';
import { Action } from 'redux';

import { createTimelineEpic } from '../../timelines/store/timeline/epic';
import { createTimelineFavoriteEpic } from '../../timelines/store/timeline/epic_favorite';
import { createTimelineNoteEpic } from '../../timelines/store/timeline/epic_note';
import { createTimelinePinnedEventEpic } from '../../timelines/store/timeline/epic_pinned_event';
import { createTimelineLocalStorageEpic } from '../../timelines/store/timeline/epic_local_storage';
import { TimelineEpicDependencies } from '../../timelines/store/timeline/types';

export const createRootEpic = <State>() =>
export const createRootEpic = <State>(): Epic<
Action,
Action,
State,
TimelineEpicDependencies<State>
> =>
combineEpics(
createTimelineEpic<State>(),
createTimelineFavoriteEpic<State>(),
Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/security_solution/public/common/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Middleware,
Dispatch,
PreloadedState,
CombinedState,
} from 'redux';

import { createEpicMiddleware } from 'redux-observable';
Expand All @@ -30,6 +31,7 @@ import { Immutable } from '../../../common/endpoint/types';
import { State } from './types';
import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { CoreStart } from '../../../../../../src/core/public';
import { TimelineEpicDependencies } from '../../timelines/store/timeline/types';

type ComposeType = typeof compose;
declare global {
Expand All @@ -56,7 +58,7 @@ export const createStore = (
): Store<State, Action> => {
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const middlewareDependencies = {
const middlewareDependencies: TimelineEpicDependencies<State> = {
apolloClient$: apolloClient,
kibana$: kibana,
selectAllTimelineQuery: inputsSelectors.globalQueryByIdSelector,
Expand All @@ -80,7 +82,7 @@ export const createStore = (
)
);

epicMiddleware.run(createRootEpic<State>());
epicMiddleware.run(createRootEpic<CombinedState<State>>());

return store;
};
Expand Down
9 changes: 7 additions & 2 deletions x-pack/plugins/security_solution/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
this.kibanaVersion = initializerContext.env.packageInfo.version;
}

public setup(core: CoreSetup<StartPlugins, PluginStart>, plugins: SetupPlugins) {
public setup(core: CoreSetup<StartPlugins, PluginStart>, plugins: SetupPlugins): PluginSetup {
initTelemetry(plugins.usageCollection, APP_ID);

plugins.home.featureCatalogue.register({
Expand Down Expand Up @@ -319,7 +319,12 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
},
});

return {};
return {
resolver: async () => {
const { resolverPluginSetup } = await import('./resolver');
return resolverPluginSetup();
},
};
}

public start(core: CoreStart, plugins: StartPlugins) {
Expand Down
30 changes: 30 additions & 0 deletions x-pack/plugins/security_solution/public/resolver/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Provider } from 'react-redux';
import { ResolverPluginSetup } from './types';
import { resolverStoreFactory } from './store/index';
import { ResolverWithoutProviders } from './view/resolver_without_providers';
import { noAncestorsTwoChildren } from './data_access_layer/mocks/no_ancestors_two_children';

/**
* These exports are used by the plugin 'resolverTest' defined in x-pack's plugin_functional suite.
*/

/**
* Provide access to Resolver APIs.
*/
export function resolverPluginSetup(): ResolverPluginSetup {
return {
Provider,
storeFactory: resolverStoreFactory,
ResolverWithoutProviders,
mocks: {
dataAccessLayer: {
noAncestorsTwoChildren,
},
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { resolverReducer } from './reducer';
import { resolverMiddlewareFactory } from './middleware';
import { ResolverAction } from './actions';

export const storeFactory = (
export const resolverStoreFactory = (
dataAccessLayer: DataAccessLayer
): Store<ResolverState, ResolverAction> => {
const actionsDenylist: Array<ResolverAction['type']> = ['userMovedPointer'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React from 'react';
import { Store, createStore, applyMiddleware } from 'redux';
import { mount, ReactWrapper } from 'enzyme';
import { createMemoryHistory, History as HistoryPackageHistoryInterface } from 'history';
import { History as HistoryPackageHistoryInterface, createMemoryHistory } from 'history';
import { CoreStart } from '../../../../../../../src/core/public';
import { coreMock } from '../../../../../../../src/core/public/mocks';
import { spyMiddlewareFactory } from '../spy_middleware_factory';
Expand Down
42 changes: 41 additions & 1 deletion x-pack/plugins/security_solution/public/resolver/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { Store } from 'redux';
import { Middleware, Dispatch } from 'redux';
import { BBox } from 'rbush';
import { Provider } from 'react-redux';
import { ResolverAction } from './store/actions';
import {
ResolverRelatedEvents,
Expand Down Expand Up @@ -410,7 +411,7 @@ export interface SideEffectSimulator {
/**
* Mocked `SideEffectors`.
*/
mock: jest.Mocked<Omit<SideEffectors, 'ResizeObserver'>> & Pick<SideEffectors, 'ResizeObserver'>;
mock: SideEffectors;
}

/**
Expand Down Expand Up @@ -532,3 +533,42 @@ export interface SpyMiddleware {
*/
debugActions: () => () => void;
}

/**
* values of this type are exposed by the Security Solution plugin's setup phase.
*/
export interface ResolverPluginSetup {
/**
* Provide access to the instance of the `react-redux` `Provider` that Resolver recognizes.
*/
Provider: typeof Provider;
/**
* Takes a `DataAccessLayer`, which could be a mock one, and returns an redux Store.
* All data acess (e.g. HTTP requests) are done through the store.
*/
storeFactory: (dataAccessLayer: DataAccessLayer) => Store<ResolverState, ResolverAction>;

/**
* The Resolver component without the required Providers.
* You must wrap this component in: `I18nProvider`, `Router` (from react-router,) `KibanaContextProvider`,
* and the `Provider` component provided by this object.
*/
ResolverWithoutProviders: React.MemoExoticComponent<
React.ForwardRefExoticComponent<ResolverProps & React.RefAttributes<unknown>>
>;

/**
* A collection of mock objects that can be used in examples or in testing.
*/
mocks: {
/**
* Mock `DataAccessLayer`s. All of Resolver's HTTP access is provided by a `DataAccessLayer`.
*/
dataAccessLayer: {
/**
* A mock `DataAccessLayer` that returns a tree that has no ancestor nodes but which has 2 children nodes.
*/
noAncestorsTwoChildren: () => { dataAccessLayer: DataAccessLayer };
};
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React, { useMemo } from 'react';
import { Provider } from 'react-redux';
import { storeFactory } from '../store';
import { resolverStoreFactory } from '../store';
import { StartServices } from '../../types';
import { useKibana } from '../../../../../../src/plugins/kibana_react/public';
import { DataAccessLayer, ResolverProps } from '../types';
Expand All @@ -24,7 +24,7 @@ export const Resolver = React.memo((props: ResolverProps) => {
]);

const store = useMemo(() => {
return storeFactory(dataAccessLayer);
return resolverStoreFactory(dataAccessLayer);
}, [dataAccessLayer]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
import { AppApolloClient } from '../../../common/lib/lib';
import { inputsModel } from '../../../common/store/inputs';
import { NotesById } from '../../../common/store/app/model';
import { StartServices } from '../../../types';

import { TimelineModel } from './model';
import { CoreStart } from '../../../../../../../src/core/public';

export interface AutoSavedWarningMsg {
timelineId: string | null;
Expand Down Expand Up @@ -55,6 +55,6 @@ export interface TimelineEpicDependencies<State> {
selectAllTimelineQuery: () => (state: State, id: string) => inputsModel.GlobalQuery;
selectNotesByIdSelector: (state: State) => NotesById;
apolloClient$: Observable<AppApolloClient>;
kibana$: Observable<StartServices>;
kibana$: Observable<CoreStart>;
storage: Storage;
}
6 changes: 4 additions & 2 deletions x-pack/plugins/security_solution/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '../../triggers_actions_ui/public';
import { SecurityPluginSetup } from '../../security/public';
import { AppFrontendLibs } from './common/lib/lib';
import { ResolverPluginSetup } from './resolver/types';

export interface SetupPlugins {
home: HomePublicPluginSetup;
Expand All @@ -46,8 +47,9 @@ export type StartServices = CoreStart &
storage: Storage;
};

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface PluginSetup {}
export interface PluginSetup {
resolver: () => Promise<ResolverPluginSetup>;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface PluginStart {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
"id": "resolver_test",
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "resolver_test"],
"requiredPlugins": ["embeddable"],
"configPath": ["xpack", "resolverTest"],
"requiredPlugins": [
"securitySolution"
],
"requiredBundles": [
"kibanaReact"
],
"server": false,
"ui": true
}
Loading

0 comments on commit c90d8c6

Please sign in to comment.