Refactor Plugin Selection sheet and add snapshot test
Summary:
This diff fixes a UI bug in export data sheet where the plugin names are stuck to the left and also the bottom buttons are stuck together with no padding. I have also added snapshot test for the same. In order to write test and reduce the complexity I changed the `ExportDataPluginSheet`'s connect method.
Bug:
{F231521086}
Reviewed By: mweststrate
Differential Revision: D20459692
fbshipit-source-id: 1047d6b38738691d682ad6e4ccec45c05e14cbbe
This commit is contained in:
committed by
Facebook GitHub Bot
parent
18915ba43c
commit
f889dc5e40
@@ -25,7 +25,7 @@ import {
|
||||
import ListView from './ListView';
|
||||
import {Dispatch, Action} from 'redux';
|
||||
import {unsetShare} from '../reducers/application';
|
||||
import {FlexColumn, styled} from 'flipper';
|
||||
import {FlexColumn, styled} from '../ui';
|
||||
import Client from '../Client';
|
||||
|
||||
type OwnProps = {
|
||||
@@ -34,10 +34,8 @@ type OwnProps = {
|
||||
|
||||
type StateFromProps = {
|
||||
share: ShareType | null;
|
||||
plugins: PluginState;
|
||||
pluginStates: PluginStatesState;
|
||||
pluginMessageQueue: PluginMessageQueueState;
|
||||
selectedClient: Client | undefined;
|
||||
selectedPlugins: Array<string>;
|
||||
availablePluginsToExport: Array<{id: string; label: string}>;
|
||||
};
|
||||
|
||||
type DispatchFromProps = {
|
||||
@@ -58,25 +56,7 @@ const Container = styled(FlexColumn)({
|
||||
padding: 8,
|
||||
});
|
||||
|
||||
type State = {
|
||||
availablePluginsToExport: Array<{id: string; label: string}>;
|
||||
};
|
||||
|
||||
class ExportDataPluginSheet extends Component<Props, State> {
|
||||
state: State = {availablePluginsToExport: []};
|
||||
static getDerivedStateFromProps(props: Props, _state: State): State {
|
||||
const {plugins, pluginStates, pluginMessageQueue, selectedClient} = props;
|
||||
const availablePluginsToExport = getActivePersistentPlugins(
|
||||
pluginStates,
|
||||
pluginMessageQueue,
|
||||
plugins,
|
||||
selectedClient,
|
||||
);
|
||||
return {
|
||||
availablePluginsToExport,
|
||||
};
|
||||
}
|
||||
|
||||
class ExportDataPluginSheet extends Component<Props, {}> {
|
||||
render() {
|
||||
const {onHide} = this.props;
|
||||
const onHideWithUnsettingShare = () => {
|
||||
@@ -88,6 +68,7 @@ class ExportDataPluginSheet extends Component<Props, State> {
|
||||
<ListView
|
||||
type="multiple"
|
||||
title="Select the plugins for which you want to export the data"
|
||||
leftPadding={8}
|
||||
onSubmit={() => {
|
||||
const {share} = this.props;
|
||||
if (!share) {
|
||||
@@ -116,8 +97,8 @@ class ExportDataPluginSheet extends Component<Props, State> {
|
||||
onChange={selectedArray => {
|
||||
this.props.setSelectedPlugins(selectedArray);
|
||||
}}
|
||||
elements={this.state.availablePluginsToExport}
|
||||
selectedElements={new Set(this.props.plugins.selectedPlugins)}
|
||||
elements={this.props.availablePluginsToExport}
|
||||
selectedElements={new Set(this.props.selectedPlugins)}
|
||||
onHide={onHideWithUnsettingShare}
|
||||
/>
|
||||
</Container>
|
||||
@@ -136,12 +117,16 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
const selectedClient = clients.find(o => {
|
||||
return o.id === selectedApp;
|
||||
});
|
||||
return {
|
||||
share,
|
||||
plugins,
|
||||
const availablePluginsToExport = getActivePersistentPlugins(
|
||||
pluginStates,
|
||||
pluginMessageQueue,
|
||||
plugins,
|
||||
selectedClient,
|
||||
);
|
||||
return {
|
||||
share,
|
||||
selectedPlugins: plugins.selectedPlugins,
|
||||
availablePluginsToExport,
|
||||
};
|
||||
},
|
||||
(dispatch: Dispatch<Action<any>>) => ({
|
||||
|
||||
@@ -46,6 +46,7 @@ type Props = {
|
||||
onHide: () => any;
|
||||
elements: Array<Element>;
|
||||
title?: string;
|
||||
leftPadding?: number;
|
||||
} & SubType;
|
||||
|
||||
const Title = styled(Text)({
|
||||
@@ -94,6 +95,7 @@ type RowComponentProps = {
|
||||
disabled: boolean;
|
||||
toolTipMessage?: string;
|
||||
type: SelectionType;
|
||||
leftPadding?: number;
|
||||
};
|
||||
|
||||
class RowComponent extends Component<RowComponentProps> {
|
||||
@@ -106,6 +108,7 @@ class RowComponent extends Component<RowComponentProps> {
|
||||
disabled,
|
||||
toolTipMessage,
|
||||
type,
|
||||
leftPadding,
|
||||
} = this.props;
|
||||
return (
|
||||
<FlexColumn>
|
||||
@@ -116,7 +119,7 @@ class RowComponent extends Component<RowComponentProps> {
|
||||
paddingRight={0}
|
||||
paddingTop={8}
|
||||
paddingBottom={8}
|
||||
paddingLeft={0}>
|
||||
paddingLeft={leftPadding || 0}>
|
||||
<FlexRow style={{alignItems: 'center'}}>
|
||||
<Text color={disabled ? colors.light20 : undefined}>{label}</Text>
|
||||
<Spacer />
|
||||
@@ -191,7 +194,7 @@ export default class ListView extends Component<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {onSubmit, type} = this.props;
|
||||
const {onSubmit, type, leftPadding} = this.props;
|
||||
return (
|
||||
<Container>
|
||||
<FlexColumn>
|
||||
@@ -208,6 +211,7 @@ export default class ListView extends Component<Props, State> {
|
||||
onChange={this.handleChange}
|
||||
disabled={unselectable != null}
|
||||
toolTipMessage={unselectable?.toolTipMessage}
|
||||
leftPadding={leftPadding}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -217,9 +221,11 @@ export default class ListView extends Component<Props, State> {
|
||||
<Padder paddingTop={8} paddingBottom={2}>
|
||||
<FlexRow>
|
||||
<Spacer />
|
||||
<Button compact padded onClick={this.props.onHide}>
|
||||
Close
|
||||
</Button>
|
||||
<Padder paddingRight={8}>
|
||||
<Button compact padded onClick={this.props.onHide}>
|
||||
Close
|
||||
</Button>
|
||||
</Padder>
|
||||
<Tooltip
|
||||
title={
|
||||
this.state.selectedElements.size <= 0
|
||||
|
||||
108
src/chrome/__tests__/ExportDataPluginSheet.node.tsx
Normal file
108
src/chrome/__tests__/ExportDataPluginSheet.node.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Client from '../../Client';
|
||||
import {create, act, ReactTestRenderer} from 'react-test-renderer';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import {Provider} from 'react-redux';
|
||||
import {default as BaseDevice} from '../../devices/BaseDevice';
|
||||
import ExportDataPluginSheet from '../ExportDataPluginSheet';
|
||||
import {FlipperPlugin, FlipperDevicePlugin} from '../../plugin';
|
||||
|
||||
function generateClientIdentifier(device: BaseDevice, app: string): string {
|
||||
const {os, deviceType, serial} = device;
|
||||
const identifier = `${app}#${os}#${deviceType}#${serial}`;
|
||||
return identifier;
|
||||
}
|
||||
|
||||
class TestPlugin extends FlipperPlugin<any, any, any> {}
|
||||
TestPlugin.title = 'TestPlugin';
|
||||
TestPlugin.id = 'TestPlugin';
|
||||
TestPlugin.defaultPersistedState = {msg: 'Test plugin'};
|
||||
class TestDevicePlugin extends FlipperDevicePlugin<any, any, any> {}
|
||||
TestDevicePlugin.title = 'TestDevicePlugin';
|
||||
TestDevicePlugin.id = 'TestDevicePlugin';
|
||||
TestDevicePlugin.defaultPersistedState = {msg: 'TestDevicePlugin'};
|
||||
|
||||
function getStore(selectedPlugins: Array<string>) {
|
||||
const logger = {
|
||||
track: () => {},
|
||||
info: () => {},
|
||||
warn: () => {},
|
||||
error: () => {},
|
||||
debug: () => {},
|
||||
trackTimeSince: () => {},
|
||||
};
|
||||
let mockStore = configureStore([])();
|
||||
const selectedDevice = new BaseDevice(
|
||||
'serial',
|
||||
'emulator',
|
||||
'TestiPhone',
|
||||
'iOS',
|
||||
);
|
||||
const client = new Client(
|
||||
generateClientIdentifier(selectedDevice, 'app'),
|
||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial'},
|
||||
null,
|
||||
logger,
|
||||
// @ts-ignore
|
||||
mockStore,
|
||||
['TestPlugin', 'TestDevicePlugin'],
|
||||
);
|
||||
|
||||
const pluginStates: {[key: string]: any} = {};
|
||||
pluginStates[`${client.id}#TestDevicePlugin`] = {
|
||||
msg: 'Test Device plugin',
|
||||
};
|
||||
pluginStates[`${client.id}#TestPlugin`] = {
|
||||
msg: 'Test plugin',
|
||||
};
|
||||
mockStore = configureStore([])({
|
||||
application: {share: {closeOnFinish: false, type: 'link'}},
|
||||
plugins: {
|
||||
clientPlugins: new Map([['TestPlugin', TestPlugin]]),
|
||||
devicePlugins: new Map([['TestDevicePlugin', TestDevicePlugin]]),
|
||||
gatekeepedPlugins: [],
|
||||
disabledPlugins: [],
|
||||
failedPlugins: [],
|
||||
selectedPlugins,
|
||||
},
|
||||
pluginStates,
|
||||
pluginMessageQueue: [],
|
||||
connections: {selectedApp: client.id, clients: [client]},
|
||||
});
|
||||
return mockStore;
|
||||
}
|
||||
|
||||
test('SettingsSheet snapshot with nothing enabled', async () => {
|
||||
let root: ReactTestRenderer;
|
||||
await act(async () => {
|
||||
root = create(
|
||||
<Provider store={getStore([])}>
|
||||
<ExportDataPluginSheet onHide={() => {}} />
|
||||
</Provider>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root!.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('SettingsSheet snapshot with one plugin enabled', async () => {
|
||||
let root: ReactTestRenderer;
|
||||
await act(async () => {
|
||||
root = create(
|
||||
<Provider store={getStore(['TestPlugin'])}>
|
||||
<ExportDataPluginSheet onHide={() => {}} />
|
||||
</Provider>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root!.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,291 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SettingsSheet snapshot with nothing enabled 1`] = `
|
||||
<div
|
||||
className="css-1alsdwv"
|
||||
>
|
||||
<div
|
||||
className="css-14m1iua"
|
||||
>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<span
|
||||
className="css-15682x"
|
||||
>
|
||||
Select the plugins for which you want to export the data
|
||||
</span>
|
||||
<div
|
||||
className="css-9dmkpi"
|
||||
>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1jrm6r3"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="css-1cegttb"
|
||||
>
|
||||
TestDevicePlugin
|
||||
</span>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<input
|
||||
checked={false}
|
||||
className="css-1y77uts"
|
||||
disabled={false}
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1nj3es"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1jrm6r3"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="css-1cegttb"
|
||||
>
|
||||
TestPlugin
|
||||
</span>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<input
|
||||
checked={false}
|
||||
className="css-1y77uts"
|
||||
disabled={false}
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1nj3es"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1yqvjo0"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<div
|
||||
className="css-12n892b"
|
||||
>
|
||||
<div
|
||||
className="css-1ee9nwd"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
>
|
||||
Close
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-6lxjsf"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
type="primary"
|
||||
>
|
||||
Submit
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`SettingsSheet snapshot with one plugin enabled 1`] = `
|
||||
<div
|
||||
className="css-1alsdwv"
|
||||
>
|
||||
<div
|
||||
className="css-14m1iua"
|
||||
>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<span
|
||||
className="css-15682x"
|
||||
>
|
||||
Select the plugins for which you want to export the data
|
||||
</span>
|
||||
<div
|
||||
className="css-9dmkpi"
|
||||
>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1jrm6r3"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="css-1cegttb"
|
||||
>
|
||||
TestDevicePlugin
|
||||
</span>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<input
|
||||
checked={false}
|
||||
className="css-1y77uts"
|
||||
disabled={false}
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1nj3es"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1k4677w"
|
||||
>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1jrm6r3"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="css-1cegttb"
|
||||
>
|
||||
TestPlugin
|
||||
</span>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<input
|
||||
checked={true}
|
||||
className="css-1y77uts"
|
||||
disabled={false}
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1nj3es"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1yqvjo0"
|
||||
>
|
||||
<div
|
||||
className="css-a1glw"
|
||||
>
|
||||
<div
|
||||
className="css-12zzrdt"
|
||||
/>
|
||||
<div
|
||||
className="css-12n892b"
|
||||
>
|
||||
<div
|
||||
className="css-1ee9nwd"
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
>
|
||||
Close
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="css-1obf64m"
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1ee9nwd"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseUp={[Function]}
|
||||
type="primary"
|
||||
>
|
||||
Submit
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
Reference in New Issue
Block a user