Adds capability to select plugins for which the data would be exported
Summary: This diff adds `selectedPlugins` property in the redux store. With this diff now you can pass the list of plugins to headless so that it exports only the selected plugin's data Reviewed By: passy Differential Revision: D16280167 fbshipit-source-id: b03a1c49a7f51547470e0bcfa43083e52efabdd0
This commit is contained in:
committed by
Facebook Github Bot
parent
9d813dce80
commit
e8a8f87086
@@ -39,6 +39,7 @@ type UserArguments = {|
|
||||
listDevices: boolean,
|
||||
device: string,
|
||||
listPlugins: boolean,
|
||||
selectPlugins: Array<string>,
|
||||
|};
|
||||
|
||||
yargs
|
||||
@@ -89,6 +90,12 @@ yargs
|
||||
describe: 'Will print the list of supported plugins in the terminal',
|
||||
type: 'boolean',
|
||||
});
|
||||
yargs.option('select-plugins', {
|
||||
default: [],
|
||||
describe:
|
||||
'The data/metrics would be exported only for the selected plugins',
|
||||
type: 'array',
|
||||
});
|
||||
yargs.option('device', {
|
||||
default: undefined,
|
||||
describe:
|
||||
@@ -327,6 +334,21 @@ async function startFlipper(userArguments: UserArguments) {
|
||||
exit: false,
|
||||
});
|
||||
},
|
||||
(userArguments: UserArguments, store: Store) => {
|
||||
const {selectPlugins} = userArguments;
|
||||
const selectedPlugins = selectPlugins.filter(selectPlugin => {
|
||||
return selectPlugin != undefined;
|
||||
});
|
||||
if (selectedPlugins) {
|
||||
store.dispatch({
|
||||
type: 'SELECTED_PLUGINS',
|
||||
payload: selectedPlugins,
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
exit: false,
|
||||
});
|
||||
},
|
||||
];
|
||||
|
||||
const exitActionClosures: Array<
|
||||
@@ -352,6 +374,7 @@ async function startFlipper(userArguments: UserArguments) {
|
||||
return exportMetricsFromTrace(
|
||||
metrics,
|
||||
pluginsClassMap(store.getState().plugins),
|
||||
store.getState().plugins.selectedPlugins,
|
||||
)
|
||||
.then(payload => {
|
||||
return {exit: true, result: payload ? payload.toString() : ''};
|
||||
|
||||
@@ -36,6 +36,7 @@ test('add clientPlugin', () => {
|
||||
gatekeepedPlugins: [],
|
||||
failedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
selectedPlugins: [],
|
||||
},
|
||||
registerPlugins([testPlugin]),
|
||||
);
|
||||
@@ -50,6 +51,7 @@ test('add devicePlugin', () => {
|
||||
gatekeepedPlugins: [],
|
||||
failedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
selectedPlugins: [],
|
||||
},
|
||||
registerPlugins([testDevicePlugin]),
|
||||
);
|
||||
@@ -64,6 +66,7 @@ test('do not add plugin twice', () => {
|
||||
gatekeepedPlugins: [],
|
||||
failedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
selectedPlugins: [],
|
||||
},
|
||||
registerPlugins([testPlugin, testPlugin]),
|
||||
);
|
||||
@@ -78,6 +81,7 @@ test('do not add other classes', () => {
|
||||
gatekeepedPlugins: [],
|
||||
failedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
selectedPlugins: [],
|
||||
},
|
||||
// $FlowFixMe testing wrong classes on purpose here
|
||||
registerPlugins([testBasePlugin]),
|
||||
@@ -95,6 +99,7 @@ test('add gatekeeped plugin', () => {
|
||||
gatekeepedPlugins: [],
|
||||
failedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
selectedPlugins: [],
|
||||
},
|
||||
addGatekeepedPlugins(gatekeepedPlugins),
|
||||
);
|
||||
|
||||
@@ -15,6 +15,7 @@ export type State = {
|
||||
gatekeepedPlugins: Array<PluginDefinition>,
|
||||
disabledPlugins: Array<PluginDefinition>,
|
||||
failedPlugins: Array<[PluginDefinition, string]>,
|
||||
selectedPlugins: Array<string>,
|
||||
};
|
||||
|
||||
type P = Class<FlipperPlugin<> | FlipperDevicePlugin<>>;
|
||||
@@ -35,6 +36,10 @@ export type Action =
|
||||
| {
|
||||
type: 'FAILED_PLUGINS',
|
||||
payload: Array<[PluginDefinition, string]>,
|
||||
}
|
||||
| {
|
||||
type: 'SELECTED_PLUGINS',
|
||||
payload: Array<string>,
|
||||
};
|
||||
|
||||
const INITIAL_STATE: State = {
|
||||
@@ -43,6 +48,7 @@ const INITIAL_STATE: State = {
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
failedPlugins: [],
|
||||
selectedPlugins: [],
|
||||
};
|
||||
|
||||
export default function reducer(
|
||||
@@ -87,6 +93,12 @@ export default function reducer(
|
||||
...state,
|
||||
failedPlugins: state.failedPlugins.concat(action.payload),
|
||||
};
|
||||
} else if (action.type === 'SELECTED_PLUGINS') {
|
||||
const {selectedPlugins} = state;
|
||||
return {
|
||||
...state,
|
||||
selectedPlugins: selectedPlugins.concat(action.payload),
|
||||
};
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ test('test generateNotifications helper function', () => {
|
||||
});
|
||||
|
||||
test('test processStore function for empty state', () => {
|
||||
const json = processStore([], null, {}, [], new Map(), 'salt');
|
||||
const json = processStore([], null, {}, [], new Map(), 'salt', []);
|
||||
expect(json).resolves.toBeNull();
|
||||
});
|
||||
|
||||
@@ -162,6 +162,7 @@ test('test processStore function for an iOS device connected', async () => {
|
||||
[],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
// $FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
@@ -194,6 +195,7 @@ test('test processStore function for an iOS device connected with client plugin
|
||||
[generateClientFromDevice(device, 'testapp')],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
@@ -252,6 +254,7 @@ test('test processStore function to have only the client for the selected device
|
||||
],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
|
||||
expect(json).toBeDefined();
|
||||
@@ -308,6 +311,7 @@ test('test processStore function to have multiple clients for the selected devic
|
||||
],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already added
|
||||
@@ -350,6 +354,7 @@ test('test processStore function for device plugin state and no clients', async
|
||||
[],
|
||||
new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
@@ -382,6 +387,7 @@ test('test processStore function for unselected device plugin state and no clien
|
||||
[],
|
||||
new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
@@ -420,6 +426,7 @@ test('test processStore function for notifications for selected device', async (
|
||||
[client],
|
||||
new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
|
||||
expect(json).toBeDefined();
|
||||
@@ -477,6 +484,7 @@ test('test processStore function for notifications for unselected device', async
|
||||
[client, unselectedclient],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
@@ -487,3 +495,96 @@ test('test processStore function for notifications for unselected device', async
|
||||
const {activeNotifications} = json.store;
|
||||
expect(activeNotifications).toEqual([]);
|
||||
});
|
||||
|
||||
test('test processStore function for selected plugins', async () => {
|
||||
const selectedDevice = new ArchivedDevice(
|
||||
'serial',
|
||||
'emulator',
|
||||
'TestiPhone',
|
||||
'iOS',
|
||||
[],
|
||||
);
|
||||
|
||||
const client = generateClientFromDevice(selectedDevice, 'app');
|
||||
const pluginstates = {
|
||||
[generateClientIdentifier(selectedDevice, 'app') + '#plugin1']: {
|
||||
msg: 'Test plugin1',
|
||||
},
|
||||
[generateClientIdentifier(selectedDevice, 'app') + '#plugin2']: {
|
||||
msg: 'Test plugin2',
|
||||
},
|
||||
};
|
||||
const json = await processStore(
|
||||
[],
|
||||
selectedDevice,
|
||||
pluginstates,
|
||||
[client],
|
||||
new Map(),
|
||||
'salt',
|
||||
['plugin2'],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
const {pluginStates} = json.store;
|
||||
const {clients} = json;
|
||||
expect(pluginStates).toEqual({
|
||||
[generateClientIdentifierWithSalt(
|
||||
generateClientIdentifier(selectedDevice, 'app'),
|
||||
'salt',
|
||||
) + '#plugin2']: {
|
||||
msg: 'Test plugin2',
|
||||
},
|
||||
});
|
||||
expect(clients).toEqual([generateClientFromClientWithSalt(client, 'salt')]);
|
||||
const {activeNotifications} = json.store;
|
||||
expect(activeNotifications).toEqual([]);
|
||||
});
|
||||
|
||||
test('test processStore function for no selected plugins', async () => {
|
||||
const selectedDevice = new ArchivedDevice(
|
||||
'serial',
|
||||
'emulator',
|
||||
'TestiPhone',
|
||||
'iOS',
|
||||
[],
|
||||
);
|
||||
const client = generateClientFromDevice(selectedDevice, 'app');
|
||||
const pluginstates = {
|
||||
[generateClientIdentifier(selectedDevice, 'app') + '#plugin1']: {
|
||||
msg: 'Test plugin1',
|
||||
},
|
||||
[generateClientIdentifier(selectedDevice, 'app') + '#plugin2']: {
|
||||
msg: 'Test plugin2',
|
||||
},
|
||||
};
|
||||
const json = await processStore(
|
||||
[],
|
||||
selectedDevice,
|
||||
pluginstates,
|
||||
[client],
|
||||
new Map(),
|
||||
'salt',
|
||||
[],
|
||||
);
|
||||
expect(json).toBeDefined();
|
||||
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
|
||||
const {pluginStates} = json.store;
|
||||
const {clients} = json;
|
||||
expect(pluginStates).toEqual({
|
||||
[generateClientIdentifierWithSalt(
|
||||
generateClientIdentifier(selectedDevice, 'app'),
|
||||
'salt',
|
||||
) + '#plugin2']: {
|
||||
msg: 'Test plugin2',
|
||||
},
|
||||
[generateClientIdentifierWithSalt(
|
||||
generateClientIdentifier(selectedDevice, 'app'),
|
||||
'salt',
|
||||
) + '#plugin1']: {
|
||||
msg: 'Test plugin1',
|
||||
},
|
||||
});
|
||||
expect(clients).toEqual([generateClientFromClientWithSalt(client, 'salt')]);
|
||||
const {activeNotifications} = json.store;
|
||||
expect(activeNotifications).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -30,6 +30,7 @@ function mockPluginState(
|
||||
gatekeepedPlugins,
|
||||
disabledPlugins,
|
||||
failedPlugins,
|
||||
selectedPlugins: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ export function processPluginStates(
|
||||
serial: string,
|
||||
allPluginStates: PluginStatesState,
|
||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||
selectedPlugins: Array<string>,
|
||||
statusUpdate?: (msg: string) => void,
|
||||
): PluginStatesState {
|
||||
let pluginStates = {};
|
||||
@@ -81,6 +82,9 @@ export function processPluginStates(
|
||||
for (const key in allPluginStates) {
|
||||
const keyArray = key.split('#');
|
||||
const pluginName = keyArray.pop();
|
||||
if (selectedPlugins.length > 0 && !selectedPlugins.includes(pluginName)) {
|
||||
continue;
|
||||
}
|
||||
const filteredClients = clients.filter(client => {
|
||||
// Remove the last entry related to plugin
|
||||
return client.id.includes(keyArray.join('#'));
|
||||
@@ -194,6 +198,7 @@ export const processStore = async (
|
||||
clients: Array<ClientExport>,
|
||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||
salt: string,
|
||||
selectedPlugins: Array<string>,
|
||||
statusUpdate?: (msg: string) => void,
|
||||
): Promise<?ExportType> => {
|
||||
if (device) {
|
||||
@@ -204,6 +209,7 @@ export const processStore = async (
|
||||
serial,
|
||||
pluginStates,
|
||||
devicePlugins,
|
||||
selectedPlugins,
|
||||
statusUpdate,
|
||||
);
|
||||
const processedActiveNotifications = processNotificationStates(
|
||||
@@ -245,7 +251,12 @@ export async function fetchMetadata(
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
for (const plugin of client.plugins) {
|
||||
const selectedPlugins = store.getState().plugins.selectedPlugins;
|
||||
const selectedFilteredPlugins =
|
||||
selectedPlugins.length > 0
|
||||
? client.plugins.filter(plugin => selectedPlugins.includes(plugin))
|
||||
: client.plugins;
|
||||
for (const plugin of selectedFilteredPlugins) {
|
||||
const pluginClass: ?Class<
|
||||
FlipperDevicePlugin<> | FlipperPlugin<>,
|
||||
> = plugin ? pluginsMap.get(plugin) : null;
|
||||
@@ -315,6 +326,7 @@ export async function getStoreExport(
|
||||
clients.map(client => client.toJSON()),
|
||||
devicePlugins,
|
||||
uuid.v4(),
|
||||
store.getState().plugins.selectedPlugins,
|
||||
statusUpdate,
|
||||
);
|
||||
return {exportData, errorArray};
|
||||
|
||||
@@ -20,12 +20,16 @@ export type ExportMetricType = {[clientID: string]: MetricPluginType};
|
||||
async function exportMetrics(
|
||||
pluginStates: PluginStatesState,
|
||||
pluginsMap: Map<string, Class<FlipperDevicePlugin<> | FlipperPlugin<>>>,
|
||||
selectedPlugins: Array<string>,
|
||||
): Promise<string> {
|
||||
const metrics: ExportMetricType = {};
|
||||
for (const key in pluginStates) {
|
||||
const pluginStateData = pluginStates[key];
|
||||
const arr = key.split('#');
|
||||
const pluginName = arr.pop();
|
||||
if (!selectedPlugins.includes(pluginName)) {
|
||||
continue;
|
||||
}
|
||||
const clientID = arr.join('#');
|
||||
const metricsReducer: ?(
|
||||
persistedState: any,
|
||||
@@ -60,7 +64,11 @@ export async function exportMetricsWithoutTrace(
|
||||
console.error(errorArray);
|
||||
}
|
||||
|
||||
const metrics = await exportMetrics(newPluginStates, pluginsMap);
|
||||
const metrics = await exportMetrics(
|
||||
newPluginStates,
|
||||
pluginsMap,
|
||||
store.getState().plugins.selectedPlugins,
|
||||
);
|
||||
return metrics;
|
||||
}
|
||||
|
||||
@@ -76,6 +84,7 @@ function parseJSON(str: string): ?any {
|
||||
export async function exportMetricsFromTrace(
|
||||
trace: string,
|
||||
pluginsMap: Map<string, Class<FlipperDevicePlugin<> | FlipperPlugin<>>>,
|
||||
selectedPlugins: Array<string>,
|
||||
): Promise<string> {
|
||||
const data = fs.readFileSync(trace, 'utf8');
|
||||
const parsedJSONData = parseJSON(data);
|
||||
@@ -103,5 +112,5 @@ export async function exportMetricsFromTrace(
|
||||
),
|
||||
);
|
||||
}
|
||||
return await exportMetrics(pluginStates, pluginsMap);
|
||||
return await exportMetrics(pluginStates, pluginsMap, selectedPlugins);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user