Command processing (5/n): Star plugin
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 "star plugin" operation to perform it in pluginManager dispatcher. Reviewed By: mweststrate Differential Revision: D26305576 fbshipit-source-id: 90516af4e9ba8504720ddfa587f691f53e71b702
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0b803f810e
commit
19f2fccc79
@@ -9,13 +9,18 @@
|
||||
|
||||
jest.mock('../plugins');
|
||||
jest.mock('../../utils/electronModuleCache');
|
||||
import {loadPlugin, uninstallPlugin} from '../../reducers/pluginManager';
|
||||
import {
|
||||
loadPlugin,
|
||||
starPlugin,
|
||||
uninstallPlugin,
|
||||
} from '../../reducers/pluginManager';
|
||||
import {requirePlugin} from '../plugins';
|
||||
import {mocked} from 'ts-jest/utils';
|
||||
import {TestUtils} from 'flipper-plugin';
|
||||
import * as TestPlugin from '../../test-utils/TestPlugin';
|
||||
import {_SandyPluginDefinition as SandyPluginDefinition} from 'flipper-plugin';
|
||||
import MockFlipper from '../../test-utils/MockFlipper';
|
||||
import Client from '../../Client';
|
||||
|
||||
const pluginDetails1 = TestUtils.createMockPluginDetails({
|
||||
id: 'plugin1',
|
||||
@@ -43,6 +48,7 @@ const pluginDefinition2 = new SandyPluginDefinition(pluginDetails2, TestPlugin);
|
||||
const mockedRequirePlugin = mocked(requirePlugin);
|
||||
|
||||
let mockFlipper: MockFlipper;
|
||||
let mockClient: Client;
|
||||
|
||||
beforeEach(async () => {
|
||||
mockedRequirePlugin.mockImplementation(
|
||||
@@ -56,9 +62,10 @@ beforeEach(async () => {
|
||||
: undefined)!,
|
||||
);
|
||||
mockFlipper = new MockFlipper();
|
||||
await mockFlipper.initWithDeviceAndClient({
|
||||
const initResult = await mockFlipper.initWithDeviceAndClient({
|
||||
clientOptions: {supportedPlugins: ['plugin1', 'plugin2']},
|
||||
});
|
||||
mockClient = initResult.client;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -76,7 +83,7 @@ test('load plugin when no other version loaded', async () => {
|
||||
expect(mockFlipper.getState().plugins.loadedPlugins.get('plugin1')).toBe(
|
||||
pluginDetails1,
|
||||
);
|
||||
expect(mockFlipper.clients[0].sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('load plugin when other version loaded', async () => {
|
||||
@@ -96,7 +103,7 @@ test('load plugin when other version loaded', async () => {
|
||||
expect(mockFlipper.getState().plugins.loadedPlugins.get('plugin1')).toBe(
|
||||
pluginDetails1V2,
|
||||
);
|
||||
expect(mockFlipper.clients[0].sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('load and enable Sandy plugin', async () => {
|
||||
@@ -109,7 +116,7 @@ test('load and enable Sandy plugin', async () => {
|
||||
expect(mockFlipper.getState().plugins.loadedPlugins.get('plugin1')).toBe(
|
||||
pluginDetails1,
|
||||
);
|
||||
expect(mockFlipper.clients[0].sandyPluginStates.has('plugin1')).toBeTruthy();
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('uninstall plugin', async () => {
|
||||
@@ -126,7 +133,7 @@ test('uninstall plugin', async () => {
|
||||
expect(
|
||||
mockFlipper.getState().plugins.uninstalledPlugins.has('flipper-plugin1'),
|
||||
).toBeTruthy();
|
||||
expect(mockFlipper.clients[0].sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('uninstall bundled plugin', async () => {
|
||||
@@ -152,7 +159,43 @@ test('uninstall bundled plugin', async () => {
|
||||
.getState()
|
||||
.plugins.uninstalledPlugins.has('flipper-bundled-plugin'),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
mockFlipper.clients[0].sandyPluginStates.has('bundled-plugin'),
|
||||
).toBeFalsy();
|
||||
expect(mockClient.sandyPluginStates.has('bundled-plugin')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('star plugin', async () => {
|
||||
mockFlipper.dispatch(
|
||||
loadPlugin({plugin: pluginDetails1, enable: false, notifyIfFailed: false}),
|
||||
);
|
||||
mockFlipper.dispatch(
|
||||
starPlugin({
|
||||
plugin: pluginDefinition1,
|
||||
selectedApp: mockClient.query.app,
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
mockFlipper.getState().connections.userStarredPlugins[mockClient.query.app],
|
||||
).toContain('plugin1');
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('unstar plugin', async () => {
|
||||
mockFlipper.dispatch(
|
||||
loadPlugin({plugin: pluginDetails1, enable: false, notifyIfFailed: false}),
|
||||
);
|
||||
mockFlipper.dispatch(
|
||||
starPlugin({
|
||||
plugin: pluginDefinition1,
|
||||
selectedApp: mockClient.query.app,
|
||||
}),
|
||||
);
|
||||
mockFlipper.dispatch(
|
||||
starPlugin({
|
||||
plugin: pluginDefinition1,
|
||||
selectedApp: mockClient.query.app,
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
mockFlipper.getState().connections.userStarredPlugins[mockClient.query.app],
|
||||
).not.toContain('plugin1');
|
||||
expect(mockClient.sandyPluginStates.has('plugin1')).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
UninstallPluginActionPayload,
|
||||
UpdatePluginActionPayload,
|
||||
pluginCommandsProcessed,
|
||||
StarPluginActionPayload,
|
||||
} from '../reducers/pluginManager';
|
||||
import {
|
||||
getInstalledPlugins,
|
||||
@@ -41,8 +42,13 @@ import {
|
||||
} from '../reducers/plugins';
|
||||
import {_SandyPluginDefinition} from 'flipper-plugin';
|
||||
import type BaseDevice from '../devices/BaseDevice';
|
||||
import {pluginStarred} from '../reducers/connections';
|
||||
import {defaultEnabledBackgroundPlugins} from '../utils/pluginUtils';
|
||||
import {pluginStarred, pluginUnstarred} from '../reducers/connections';
|
||||
import {deconstructClientId} from '../utils/clientUtils';
|
||||
import {clearMessageQueue} from '../reducers/pluginMessageQueue';
|
||||
import {
|
||||
getPluginKey,
|
||||
defaultEnabledBackgroundPlugins,
|
||||
} from '../utils/pluginUtils';
|
||||
|
||||
const maxInstalledPluginVersionsToKeep = 2;
|
||||
|
||||
@@ -101,6 +107,9 @@ export function processPluginCommandsQueue(
|
||||
case 'UPDATE_PLUGIN':
|
||||
updatePlugin(store, command.payload);
|
||||
break;
|
||||
case 'STAR_PLUGIN':
|
||||
starPlugin(store, command.payload);
|
||||
break;
|
||||
default:
|
||||
console.error('Unexpected plugin command', command);
|
||||
break;
|
||||
@@ -159,6 +168,39 @@ function updatePlugin(store: Store, payload: UpdatePluginActionPayload) {
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedAppId(store: Store) {
|
||||
const {connections} = store.getState();
|
||||
const selectedApp = connections.selectedApp
|
||||
? deconstructClientId(connections.selectedApp).app
|
||||
: undefined;
|
||||
return selectedApp;
|
||||
}
|
||||
|
||||
function starPlugin(store: Store, payload: StarPluginActionPayload) {
|
||||
const {plugin, selectedApp} = payload;
|
||||
const {connections} = store.getState();
|
||||
const clients = connections.clients.filter(
|
||||
(client) => client.query.app === selectedApp,
|
||||
);
|
||||
if (connections.userStarredPlugins[selectedApp]?.includes(plugin.id)) {
|
||||
clients.forEach((client) => {
|
||||
stopPlugin(client, plugin.id);
|
||||
const pluginKey = getPluginKey(
|
||||
client.id,
|
||||
{serial: client.query.device_id},
|
||||
plugin.id,
|
||||
);
|
||||
store.dispatch(clearMessageQueue(pluginKey));
|
||||
});
|
||||
store.dispatch(pluginUnstarred(plugin, selectedApp));
|
||||
} else {
|
||||
clients.forEach((client) => {
|
||||
startPlugin(client, plugin);
|
||||
});
|
||||
store.dispatch(pluginStarred(plugin, selectedApp));
|
||||
}
|
||||
}
|
||||
|
||||
function updateClientPlugin(
|
||||
store: Store,
|
||||
plugin: typeof FlipperPlugin,
|
||||
@@ -166,7 +208,10 @@ function updateClientPlugin(
|
||||
) {
|
||||
const clients = store.getState().connections.clients;
|
||||
if (enable) {
|
||||
store.dispatch(pluginStarred(plugin));
|
||||
const selectedApp = getSelectedAppId(store);
|
||||
if (selectedApp) {
|
||||
store.dispatch(pluginStarred(plugin, selectedApp));
|
||||
}
|
||||
}
|
||||
const clientsWithEnabledPlugin = clients.filter((c) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user