Minor improvements
Summary: Some styling fixes and minor improvements in DataTable, used by network plugin: - be able to customise the context menu - be able to customise how entire rows are copied and presented on the clipboard to be able to deviate from the standard JSON - deeplink handling was made async, this gives the plugin the opportunity to first handle initial setup and rendering before trying to jump somewhere which is a typical use case for deeplinking Reviewed By: passy Differential Revision: D27947186 fbshipit-source-id: a56f081d60520c4bc2ad3c547a8ca5b9357e71a1
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ae88f5d200
commit
faf8588097
@@ -24,6 +24,7 @@ import {
|
|||||||
import {selectPlugin} from '../reducers/connections';
|
import {selectPlugin} from '../reducers/connections';
|
||||||
import {updateSettings} from '../reducers/settings';
|
import {updateSettings} from '../reducers/settings';
|
||||||
import {switchPlugin} from '../reducers/pluginManager';
|
import {switchPlugin} from '../reducers/pluginManager';
|
||||||
|
import {sleep} from 'flipper-plugin/src/utils/sleep';
|
||||||
|
|
||||||
interface PersistedState {
|
interface PersistedState {
|
||||||
count: 1;
|
count: 1;
|
||||||
@@ -528,6 +529,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual(['universe!']);
|
expect(linksSeen).toEqual(['universe!']);
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -558,6 +560,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual(['universe!']);
|
expect(linksSeen).toEqual(['universe!']);
|
||||||
|
|
||||||
// ...nor does a random other store update that does trigger a plugin container render
|
// ...nor does a random other store update that does trigger a plugin container render
|
||||||
@@ -580,6 +583,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual(['universe!', 'london!']);
|
expect(linksSeen).toEqual(['universe!', 'london!']);
|
||||||
|
|
||||||
// and same link does trigger if something else was selected in the mean time
|
// and same link does trigger if something else was selected in the mean time
|
||||||
@@ -601,6 +605,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual(['universe!', 'london!', 'london!']);
|
expect(linksSeen).toEqual(['universe!', 'london!', 'london!']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -802,6 +807,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual([theUniverse]);
|
expect(linksSeen).toEqual([theUniverse]);
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -832,6 +838,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual([theUniverse]);
|
expect(linksSeen).toEqual([theUniverse]);
|
||||||
|
|
||||||
// ...nor does a random other store update that does trigger a plugin container render
|
// ...nor does a random other store update that does trigger a plugin container render
|
||||||
@@ -854,6 +861,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual([theUniverse, 'london!']);
|
expect(linksSeen).toEqual([theUniverse, 'london!']);
|
||||||
|
|
||||||
// and same link does trigger if something else was selected in the mean time
|
// and same link does trigger if something else was selected in the mean time
|
||||||
@@ -875,6 +883,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
await sleep(10);
|
||||||
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -977,6 +986,7 @@ test('Sandy plugins support isPluginSupported + selectPlugin', async () => {
|
|||||||
pluginInstance.selectPlugin(definition.id, 'data');
|
pluginInstance.selectPlugin(definition.id, 'data');
|
||||||
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
|
await sleep(10);
|
||||||
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
<h1>
|
<h1>
|
||||||
Plugin1
|
Plugin1
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ test('plugins can receive deeplinks', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(plugin.instance.field1.get()).toBe('');
|
expect(plugin.instance.field1.get()).toBe('');
|
||||||
plugin.triggerDeepLink('test');
|
await plugin.triggerDeepLink('test');
|
||||||
expect(plugin.instance.field1.get()).toBe('test');
|
expect(plugin.instance.field1.get()).toBe('test');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ test('device plugins can receive deeplinks', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(plugin.instance.field1.get()).toBe('');
|
expect(plugin.instance.field1.get()).toBe('');
|
||||||
plugin.triggerDeepLink('test');
|
await plugin.triggerDeepLink('test');
|
||||||
expect(plugin.instance.field1.get()).toBe('test');
|
expect(plugin.instance.field1.get()).toBe('test');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ test('plugins can register menu entries', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(plugin.instance.counter.get()).toBe(0);
|
expect(plugin.instance.counter.get()).toBe(0);
|
||||||
plugin.triggerDeepLink('test');
|
await plugin.triggerDeepLink('test');
|
||||||
plugin.triggerMenuEntry('createPaste');
|
plugin.triggerMenuEntry('createPaste');
|
||||||
plugin.triggerMenuEntry('Custom Action');
|
plugin.triggerMenuEntry('Custom Action');
|
||||||
expect(plugin.instance.counter.get()).toBe(4);
|
expect(plugin.instance.counter.get()).toBe(4);
|
||||||
|
|||||||
@@ -325,7 +325,14 @@ export abstract class BasePluginInstance {
|
|||||||
this.assertNotDestroyed();
|
this.assertNotDestroyed();
|
||||||
if (deepLink !== this.lastDeeplink) {
|
if (deepLink !== this.lastDeeplink) {
|
||||||
this.lastDeeplink = deepLink;
|
this.lastDeeplink = deepLink;
|
||||||
|
if (typeof setImmediate !== 'undefined') {
|
||||||
|
// we only want to trigger deeplinks after the plugin had a chance to render
|
||||||
|
setImmediate(() => {
|
||||||
this.events.emit('deeplink', deepLink);
|
this.events.emit('deeplink', deepLink);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.events.emit('deeplink', deepLink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ interface BasePluginResult {
|
|||||||
/**
|
/**
|
||||||
* Emulate triggering a deeplink
|
* Emulate triggering a deeplink
|
||||||
*/
|
*/
|
||||||
triggerDeepLink(deeplink: unknown): void;
|
triggerDeepLink(deeplink: unknown): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grab all the persistable state, but will ignore any onExport handler
|
* Grab all the persistable state, but will ignore any onExport handler
|
||||||
@@ -386,8 +386,13 @@ function createBasePluginResult(
|
|||||||
exportStateAsync: () =>
|
exportStateAsync: () =>
|
||||||
pluginInstance.exportState(createStubIdler(), () => {}),
|
pluginInstance.exportState(createStubIdler(), () => {}),
|
||||||
exportState: () => pluginInstance.exportStateSync(),
|
exportState: () => pluginInstance.exportStateSync(),
|
||||||
triggerDeepLink: (deepLink: unknown) => {
|
triggerDeepLink: async (deepLink: unknown) => {
|
||||||
pluginInstance.triggerDeepLink(deepLink);
|
pluginInstance.triggerDeepLink(deepLink);
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// this ensures the test won't continue until the setImmediate used by
|
||||||
|
// the deeplink handling event is handled
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
destroy: () => pluginInstance.destroy(),
|
destroy: () => pluginInstance.destroy(),
|
||||||
triggerMenuEntry: (action: string) => {
|
triggerMenuEntry: (action: string) => {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const DataFormatter = {
|
|||||||
return (
|
return (
|
||||||
value.toTimeString().split(' ')[0] +
|
value.toTimeString().split(' ')[0] +
|
||||||
'.' +
|
'.' +
|
||||||
pad('' + value.getMilliseconds(), 3)
|
pad('' + value.getMilliseconds(), 3, '0')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (value instanceof Map) {
|
if (value instanceof Map) {
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ interface DataTableProps<T = any> {
|
|||||||
// multiselect?: true
|
// multiselect?: true
|
||||||
tableManagerRef?: RefObject<DataTableManager<T> | undefined>; // Actually we want a MutableRefObject, but that is not what React.createRef() returns, and we don't want to put the burden on the plugin dev to cast it...
|
tableManagerRef?: RefObject<DataTableManager<T> | undefined>; // Actually we want a MutableRefObject, but that is not what React.createRef() returns, and we don't want to put the burden on the plugin dev to cast it...
|
||||||
_testHeight?: number; // exposed for unit testing only
|
_testHeight?: number; // exposed for unit testing only
|
||||||
|
onCopyRows?(records: T[]): string;
|
||||||
|
onContextMenu?: (selection: undefined | T) => React.ReactElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DataTableColumn<T = any> = {
|
export type DataTableColumn<T = any> = {
|
||||||
@@ -94,11 +96,13 @@ export interface RenderContext<T = any> {
|
|||||||
export function DataTable<T extends object>(
|
export function DataTable<T extends object>(
|
||||||
props: DataTableProps<T>,
|
props: DataTableProps<T>,
|
||||||
): React.ReactElement {
|
): React.ReactElement {
|
||||||
const {dataSource, onRowStyle, onSelect} = props;
|
const {dataSource, onRowStyle, onSelect, onCopyRows, onContextMenu} = props;
|
||||||
useAssertStableRef(dataSource, 'dataSource');
|
useAssertStableRef(dataSource, 'dataSource');
|
||||||
useAssertStableRef(onRowStyle, 'onRowStyle');
|
useAssertStableRef(onRowStyle, 'onRowStyle');
|
||||||
useAssertStableRef(props.onSelect, 'onRowSelect');
|
useAssertStableRef(props.onSelect, 'onRowSelect');
|
||||||
useAssertStableRef(props.columns, 'columns');
|
useAssertStableRef(props.columns, 'columns');
|
||||||
|
useAssertStableRef(onCopyRows, 'onCopyRows');
|
||||||
|
useAssertStableRef(onContextMenu, 'onContextMenu');
|
||||||
useAssertStableRef(props._testHeight, '_testHeight');
|
useAssertStableRef(props._testHeight, '_testHeight');
|
||||||
|
|
||||||
// lint disabled for conditional inclusion of a hook (_testHeight is asserted to be stable)
|
// lint disabled for conditional inclusion of a hook (_testHeight is asserted to be stable)
|
||||||
@@ -357,8 +361,18 @@ export function DataTable<T extends object>(
|
|||||||
selection,
|
selection,
|
||||||
tableState.columns,
|
tableState.columns,
|
||||||
visibleColumns,
|
visibleColumns,
|
||||||
|
onCopyRows,
|
||||||
|
onContextMenu,
|
||||||
),
|
),
|
||||||
[dataSource, dispatch, selection, tableState.columns, visibleColumns],
|
[
|
||||||
|
dataSource,
|
||||||
|
dispatch,
|
||||||
|
selection,
|
||||||
|
tableState.columns,
|
||||||
|
visibleColumns,
|
||||||
|
onCopyRows,
|
||||||
|
onContextMenu,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(function initialSetup() {
|
useEffect(function initialSetup() {
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ type DataManagerActions<T> =
|
|||||||
addToSelection?: boolean;
|
addToSelection?: boolean;
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
| Action<
|
||||||
|
'selectItemById',
|
||||||
|
{
|
||||||
|
id: string | number;
|
||||||
|
addToSelection?: boolean;
|
||||||
|
}
|
||||||
|
>
|
||||||
| Action<
|
| Action<
|
||||||
'addRangeToSelection',
|
'addRangeToSelection',
|
||||||
{
|
{
|
||||||
@@ -161,6 +168,17 @@ export const dataTableManagerReducer = produce<
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'selectItemById': {
|
||||||
|
const {id, addToSelection} = action;
|
||||||
|
// TODO: fix that this doesn't jumpt selection if items are shifted! sorting is swapped etc
|
||||||
|
const idx = config.dataSource.getIndexOfKey(id);
|
||||||
|
if (idx !== -1) {
|
||||||
|
draft.selection = castDraft(
|
||||||
|
computeSetSelection(draft.selection, idx, addToSelection),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'addRangeToSelection': {
|
case 'addRangeToSelection': {
|
||||||
const {start, end, allowUnselect} = action;
|
const {start, end, allowUnselect} = action;
|
||||||
draft.selection = castDraft(
|
draft.selection = castDraft(
|
||||||
@@ -241,6 +259,7 @@ export type DataTableManager<T> = {
|
|||||||
end: number,
|
end: number,
|
||||||
allowUnselect?: boolean,
|
allowUnselect?: boolean,
|
||||||
): void;
|
): void;
|
||||||
|
selectItemById(id: string | number, addToSelection?: boolean): void;
|
||||||
clearSelection(): void;
|
clearSelection(): void;
|
||||||
getSelectedItem(): T | undefined;
|
getSelectedItem(): T | undefined;
|
||||||
getSelectedItems(): readonly T[];
|
getSelectedItems(): readonly T[];
|
||||||
@@ -261,6 +280,9 @@ export function createDataTableManager<T>(
|
|||||||
selectItem(index: number, addToSelection = false) {
|
selectItem(index: number, addToSelection = false) {
|
||||||
dispatch({type: 'selectItem', nextIndex: index, addToSelection});
|
dispatch({type: 'selectItem', nextIndex: index, addToSelection});
|
||||||
},
|
},
|
||||||
|
selectItemById(id, addToSelection = false) {
|
||||||
|
dispatch({type: 'selectItemById', id, addToSelection});
|
||||||
|
},
|
||||||
addRangeToSelection(start, end, allowUnselect = false) {
|
addRangeToSelection(start, end, allowUnselect = false) {
|
||||||
dispatch({type: 'addRangeToSelection', start, end, allowUnselect});
|
dispatch({type: 'addRangeToSelection', start, end, allowUnselect});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {CopyOutlined, FilterOutlined} from '@ant-design/icons';
|
|||||||
import {Checkbox, Menu} from 'antd';
|
import {Checkbox, Menu} from 'antd';
|
||||||
import {
|
import {
|
||||||
DataTableDispatch,
|
DataTableDispatch,
|
||||||
|
getSelectedItem,
|
||||||
getSelectedItems,
|
getSelectedItems,
|
||||||
Selection,
|
Selection,
|
||||||
} from './DataTableManager';
|
} from './DataTableManager';
|
||||||
@@ -21,12 +22,18 @@ import {DataSource} from '../../state/DataSource';
|
|||||||
|
|
||||||
const {Item, SubMenu} = Menu;
|
const {Item, SubMenu} = Menu;
|
||||||
|
|
||||||
|
function defaultOnCopyRows<T>(items: T[]) {
|
||||||
|
return JSON.stringify(items.length > 1 ? items : items[0], null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
export function tableContextMenuFactory<T>(
|
export function tableContextMenuFactory<T>(
|
||||||
datasource: DataSource<T>,
|
datasource: DataSource<T>,
|
||||||
dispatch: DataTableDispatch<T>,
|
dispatch: DataTableDispatch<T>,
|
||||||
selection: Selection,
|
selection: Selection,
|
||||||
columns: DataTableColumn<T>[],
|
columns: DataTableColumn<T>[],
|
||||||
visibleColumns: DataTableColumn<T>[],
|
visibleColumns: DataTableColumn<T>[],
|
||||||
|
onCopyRows: (rows: T[]) => string = defaultOnCopyRows,
|
||||||
|
onContextMenu?: (selection: undefined | T) => React.ReactElement,
|
||||||
) {
|
) {
|
||||||
const lib = tryGetFlipperLibImplementation();
|
const lib = tryGetFlipperLibImplementation();
|
||||||
if (!lib) {
|
if (!lib) {
|
||||||
@@ -40,6 +47,9 @@ export function tableContextMenuFactory<T>(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
|
{onContextMenu
|
||||||
|
? onContextMenu(getSelectedItem(datasource, selection))
|
||||||
|
: null}
|
||||||
<SubMenu
|
<SubMenu
|
||||||
title="Filter on same"
|
title="Filter on same"
|
||||||
icon={<FilterOutlined />}
|
icon={<FilterOutlined />}
|
||||||
@@ -81,9 +91,7 @@ export function tableContextMenuFactory<T>(
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const items = getSelectedItems(datasource, selection);
|
const items = getSelectedItems(datasource, selection);
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
lib.writeTextToClipboard(
|
lib.writeTextToClipboard(onCopyRows(items));
|
||||||
JSON.stringify(items.length > 1 ? items : items[0], null, 2),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
Copy row(s)
|
Copy row(s)
|
||||||
@@ -94,9 +102,7 @@ export function tableContextMenuFactory<T>(
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const items = getSelectedItems(datasource, selection);
|
const items = getSelectedItems(datasource, selection);
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
lib.createPaste(
|
lib.createPaste(onCopyRows(items));
|
||||||
JSON.stringify(items.length > 1 ? items : items[0], null, 2),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
Create paste
|
Create paste
|
||||||
|
|||||||
@@ -111,7 +111,11 @@ const TableHeadContainer = styled.div({
|
|||||||
borderBottom: `1px solid ${theme.dividerColor}`,
|
borderBottom: `1px solid ${theme.dividerColor}`,
|
||||||
backgroundColor: theme.backgroundWash,
|
backgroundColor: theme.backgroundWash,
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
borderLeft: `4px solid ${theme.backgroundWash}`, // space for selection, see TableRow
|
borderLeft: `4px solid ${theme.backgroundWash}`, // space for selection, see TableRow
|
||||||
|
// hardcoded value to correct for the scrollbar in the main container.
|
||||||
|
// ideally we should measure this instead.
|
||||||
|
paddingRight: 15,
|
||||||
});
|
});
|
||||||
TableHeadContainer.displayName = 'TableHead:TableHeadContainer';
|
TableHeadContainer.displayName = 'TableHead:TableHeadContainer';
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ const TableBodyRowContainer = styled.div<TableBodyRowContainerProps>(
|
|||||||
borderLeft: props.highlighted
|
borderLeft: props.highlighted
|
||||||
? `4px solid ${theme.primaryColor}`
|
? `4px solid ${theme.primaryColor}`
|
||||||
: `4px solid transparent`,
|
: `4px solid transparent`,
|
||||||
|
borderBottom: `1px solid ${theme.dividerColor}`,
|
||||||
paddingTop: 1,
|
paddingTop: 1,
|
||||||
minHeight: DEFAULT_ROW_HEIGHT,
|
minHeight: DEFAULT_ROW_HEIGHT,
|
||||||
lineHeight: `${DEFAULT_ROW_HEIGHT - 2}px`,
|
lineHeight: `${DEFAULT_ROW_HEIGHT - 2}px`,
|
||||||
@@ -74,7 +75,6 @@ const TableBodyColumnContainer = styled.div<{
|
|||||||
flexGrow: props.width === undefined ? 1 : 0,
|
flexGrow: props.width === undefined ? 1 : 0,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
padding: `0 ${theme.space.small}px`,
|
padding: `0 ${theme.space.small}px`,
|
||||||
borderBottom: `1px solid ${theme.dividerColor}`,
|
|
||||||
verticalAlign: 'top',
|
verticalAlign: 'top',
|
||||||
// pre-wrap preserves explicit newlines and whitespace, and wraps as well when needed
|
// pre-wrap preserves explicit newlines and whitespace, and wraps as well when needed
|
||||||
whiteSpace: props.multiline ? 'pre-wrap' : 'nowrap',
|
whiteSpace: props.multiline ? 'pre-wrap' : 'nowrap',
|
||||||
|
|||||||
@@ -55,15 +55,15 @@ test('update and append', async () => {
|
|||||||
expect(elem.length).toBe(1);
|
expect(elem.length).toBe(1);
|
||||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||||
<div
|
<div
|
||||||
class="css-w3o588-TableBodyRowContainer e1luu51r1"
|
class="css-1k3kr6b-TableBodyRowContainer e1luu51r1"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-1xxqqu6-TableBodyColumnContainer e1luu51r0"
|
class="css-744e08-TableBodyColumnContainer e1luu51r0"
|
||||||
>
|
>
|
||||||
test DataTable
|
test DataTable
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="css-1xxqqu6-TableBodyColumnContainer e1luu51r0"
|
class="css-744e08-TableBodyColumnContainer e1luu51r0"
|
||||||
>
|
>
|
||||||
true
|
true
|
||||||
</div>
|
</div>
|
||||||
@@ -112,15 +112,15 @@ test('column visibility', async () => {
|
|||||||
expect(elem.length).toBe(1);
|
expect(elem.length).toBe(1);
|
||||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||||
<div
|
<div
|
||||||
class="css-w3o588-TableBodyRowContainer e1luu51r1"
|
class="css-1k3kr6b-TableBodyRowContainer e1luu51r1"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-1xxqqu6-TableBodyColumnContainer e1luu51r0"
|
class="css-744e08-TableBodyColumnContainer e1luu51r0"
|
||||||
>
|
>
|
||||||
test DataTable
|
test DataTable
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="css-1xxqqu6-TableBodyColumnContainer e1luu51r0"
|
class="css-744e08-TableBodyColumnContainer e1luu51r0"
|
||||||
>
|
>
|
||||||
true
|
true
|
||||||
</div>
|
</div>
|
||||||
@@ -137,10 +137,10 @@ test('column visibility', async () => {
|
|||||||
expect(elem.length).toBe(1);
|
expect(elem.length).toBe(1);
|
||||||
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
expect(elem[0].parentElement).toMatchInlineSnapshot(`
|
||||||
<div
|
<div
|
||||||
class="css-w3o588-TableBodyRowContainer e1luu51r1"
|
class="css-1k3kr6b-TableBodyRowContainer e1luu51r1"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="css-1xxqqu6-TableBodyColumnContainer e1luu51r0"
|
class="css-744e08-TableBodyColumnContainer e1luu51r0"
|
||||||
>
|
>
|
||||||
test DataTable
|
test DataTable
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user