Command processing (2/n): testing
Summary: *Stack summary*: this stack refactors plugin management actions to perform them in a dispatcher rather than in the root reducer (store.tsx) as all of these actions has side effects. To do that, we store requested plugin management actions (install/update/uninstall, star/unstar) in a queue which is then handled by pluginManager dispatcher. This dispatcher then dispatches all required state updates. *Diff summary*: refactored Flipper mocking helpers to allow testing of plugin commands, and wrote some tests for pluginManager. Reviewed By: mweststrate Differential Revision: D26450344 fbshipit-source-id: 0e8414517cc1ad353781dffd7ffb4a5f9a815d38
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8efdde08c4
commit
24aed8fd45
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {createStore} from 'redux';
|
||||
import {Provider} from 'react-redux';
|
||||
import {
|
||||
render,
|
||||
@@ -25,18 +24,14 @@ import {
|
||||
} from '../reducers/connections';
|
||||
import BaseDevice from '../devices/BaseDevice';
|
||||
|
||||
import {rootReducer} from '../store';
|
||||
import {Store} from '../reducers/index';
|
||||
import Client, {ClientQuery} from '../Client';
|
||||
|
||||
import {buildClientId} from '../utils/clientUtils';
|
||||
import {Logger} from '../fb-interfaces/Logger';
|
||||
import {PluginDefinition} from '../plugin';
|
||||
import {registerPlugins} from '../reducers/plugins';
|
||||
import PluginContainer from '../PluginContainer';
|
||||
import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils';
|
||||
import {getInstance} from '../fb-stubs/Logger';
|
||||
import {initializeFlipperLibImplementation} from '../utils/flipperLibImplementation';
|
||||
import MockFlipper from './MockFlipper';
|
||||
|
||||
export type MockFlipperResult = {
|
||||
client: Client;
|
||||
@@ -64,94 +59,35 @@ type MockOptions = Partial<{
|
||||
additionalPlugins?: PluginDefinition[];
|
||||
dontEnableAdditionalPlugins?: true;
|
||||
asBackgroundPlugin?: true;
|
||||
supportedPlugins?: string[];
|
||||
}>;
|
||||
|
||||
export async function createMockFlipperWithPlugin(
|
||||
pluginClazz: PluginDefinition,
|
||||
options?: MockOptions,
|
||||
): Promise<MockFlipperResult> {
|
||||
const store = createStore(rootReducer);
|
||||
const logger = getInstance();
|
||||
initializeFlipperLibImplementation(store, logger);
|
||||
store.dispatch(
|
||||
registerPlugins([pluginClazz, ...(options?.additionalPlugins ?? [])]),
|
||||
);
|
||||
const mockFlipper = new MockFlipper();
|
||||
await mockFlipper.init({
|
||||
plugins: [pluginClazz, ...(options?.additionalPlugins ?? [])],
|
||||
});
|
||||
const logger = mockFlipper.logger;
|
||||
const store = mockFlipper.store;
|
||||
|
||||
function createDevice(serial: string): BaseDevice {
|
||||
const device = new BaseDevice(
|
||||
serial,
|
||||
'physical',
|
||||
'MockAndroidDevice',
|
||||
'Android',
|
||||
);
|
||||
store.dispatch({
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload: device,
|
||||
});
|
||||
device.loadDevicePlugins(store.getState().plugins.devicePlugins);
|
||||
return device;
|
||||
}
|
||||
|
||||
async function createClient(
|
||||
const createDevice = (serial: string) => mockFlipper.createDevice({serial});
|
||||
const createClient = async (
|
||||
device: BaseDevice,
|
||||
name: string,
|
||||
query?: ClientQuery,
|
||||
skipRegister?: boolean,
|
||||
): Promise<Client> {
|
||||
query = query ?? {
|
||||
app: name,
|
||||
os: 'Android',
|
||||
device: device.title,
|
||||
device_id: device.serial,
|
||||
sdk_version: 4,
|
||||
};
|
||||
const id = buildClientId({
|
||||
app: query.app,
|
||||
os: query.os,
|
||||
device: query.device,
|
||||
device_id: query.device_id,
|
||||
});
|
||||
|
||||
const client = new Client(
|
||||
id,
|
||||
) => {
|
||||
const client = await mockFlipper.createClient(device, {
|
||||
name,
|
||||
query,
|
||||
null, // create a stub connection to avoid this plugin to be archived?
|
||||
logger,
|
||||
store,
|
||||
[
|
||||
...(isDevicePluginDefinition(pluginClazz) ? [] : [pluginClazz.id]),
|
||||
...(options?.dontEnableAdditionalPlugins
|
||||
? []
|
||||
: options?.additionalPlugins?.map((p) => p.id) ?? []),
|
||||
],
|
||||
device,
|
||||
);
|
||||
|
||||
client.rawCall = async (
|
||||
method: string,
|
||||
_fromPlugin: boolean,
|
||||
params: any,
|
||||
): Promise<any> => {
|
||||
const intercepted = options?.onSend?.(method, params);
|
||||
if (intercepted !== undefined) {
|
||||
return intercepted;
|
||||
}
|
||||
switch (method) {
|
||||
case 'getPlugins':
|
||||
// assuming this plugin supports all plugins for now
|
||||
return {
|
||||
plugins: [...store.getState().plugins.clientPlugins.keys()],
|
||||
};
|
||||
case 'getBackgroundPlugins':
|
||||
return {plugins: options?.asBackgroundPlugin ? [pluginClazz.id] : []};
|
||||
default:
|
||||
throw new Error(
|
||||
`Test client doesn't support rawCall method '${method}'`,
|
||||
);
|
||||
}
|
||||
};
|
||||
client.rawSend = jest.fn();
|
||||
|
||||
skipRegister,
|
||||
onSend: options?.onSend,
|
||||
supportedPlugins: options?.supportedPlugins,
|
||||
backgroundPlugins: options?.asBackgroundPlugin ? [pluginClazz.id] : [],
|
||||
});
|
||||
// enable the plugin
|
||||
if (
|
||||
!isDevicePluginDefinition(pluginClazz) &&
|
||||
@@ -180,17 +116,8 @@ export async function createMockFlipperWithPlugin(
|
||||
}
|
||||
});
|
||||
}
|
||||
await client.init();
|
||||
|
||||
// As convenience, by default we select the new client, star the plugin, and select it
|
||||
if (!skipRegister) {
|
||||
store.dispatch({
|
||||
type: 'NEW_CLIENT',
|
||||
payload: client,
|
||||
});
|
||||
}
|
||||
return client;
|
||||
}
|
||||
};
|
||||
|
||||
const device = createDevice('serial');
|
||||
const client = await createClient(device, 'TestApp');
|
||||
|
||||
Reference in New Issue
Block a user