mirror of
https://github.com/apache/superset.git
synced 2024-09-16 10:39:55 -04:00
feat: add tableselector to dataset creation page (#21075)
Co-authored-by: Lyndsi Kay Williams <55605634+lyndsiWilliams@users.noreply.github.com>
This commit is contained in:
parent
ce3d38d2e7
commit
8c2719b11c
@ -105,13 +105,13 @@ interface TableSelectorProps {
|
||||
tableSelectMode?: 'single' | 'multiple';
|
||||
}
|
||||
|
||||
interface TableOption {
|
||||
export interface TableOption {
|
||||
label: JSX.Element;
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const TableOption = ({ table }: { table: Table }) => {
|
||||
export const TableOption = ({ table }: { table: Table }) => {
|
||||
const { label, type, extra } = table;
|
||||
return (
|
||||
<TableLabel title={label}>
|
||||
|
@ -22,7 +22,7 @@ import AddDataset from 'src/views/CRUD/data/dataset/AddDataset';
|
||||
|
||||
describe('AddDataset', () => {
|
||||
it('renders a blank state AddDataset', () => {
|
||||
render(<AddDataset />);
|
||||
render(<AddDataset />, { useRedux: true });
|
||||
|
||||
const blankeStateImgs = screen.getAllByRole('img', { name: /empty/i });
|
||||
|
||||
@ -30,13 +30,9 @@ describe('AddDataset', () => {
|
||||
expect(screen.getByText(/header/i)).toBeVisible();
|
||||
// Left panel
|
||||
expect(blankeStateImgs[0]).toBeVisible();
|
||||
expect(screen.getByText(/no database tables found/i)).toBeVisible();
|
||||
// Database panel
|
||||
expect(blankeStateImgs[1]).toBeVisible();
|
||||
expect(screen.getByText(/select dataset source/i)).toBeVisible();
|
||||
// Footer
|
||||
expect(screen.getByText(/footer/i)).toBeVisible();
|
||||
|
||||
expect(blankeStateImgs.length).toBe(2);
|
||||
expect(blankeStateImgs.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
@ -17,15 +17,211 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import { SupersetClient } from '@superset-ui/core';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { render, screen, waitFor } from 'spec/helpers/testing-library';
|
||||
import LeftPanel from 'src/views/CRUD/data/dataset/AddDataset/LeftPanel';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
describe('LeftPanel', () => {
|
||||
it('renders a blank state LeftPanel', () => {
|
||||
render(<LeftPanel />);
|
||||
const mockFun = jest.fn();
|
||||
|
||||
expect(screen.getByRole('img', { name: /empty/i })).toBeVisible();
|
||||
expect(screen.getByText(/no database tables found/i)).toBeVisible();
|
||||
expect(screen.getByText(/try selecting a different schema/i)).toBeVisible();
|
||||
const SupersetClientGet = jest.spyOn(SupersetClient, 'get');
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
SupersetClientGet.mockImplementation(
|
||||
async ({ endpoint }: { endpoint: string }) => {
|
||||
if (endpoint.includes('schemas')) {
|
||||
return {
|
||||
json: { result: ['information_schema', 'public'] },
|
||||
} as any;
|
||||
}
|
||||
return {
|
||||
json: {
|
||||
count: 2,
|
||||
description_columns: {},
|
||||
ids: [1, 2],
|
||||
label_columns: {
|
||||
allow_file_upload: 'Allow Csv Upload',
|
||||
allow_ctas: 'Allow Ctas',
|
||||
allow_cvas: 'Allow Cvas',
|
||||
allow_dml: 'Allow Dml',
|
||||
allow_multi_schema_metadata_fetch:
|
||||
'Allow Multi Schema Metadata Fetch',
|
||||
allow_run_async: 'Allow Run Async',
|
||||
allows_cost_estimate: 'Allows Cost Estimate',
|
||||
allows_subquery: 'Allows Subquery',
|
||||
allows_virtual_table_explore: 'Allows Virtual Table Explore',
|
||||
disable_data_preview: 'Disables SQL Lab Data Preview',
|
||||
backend: 'Backend',
|
||||
changed_on: 'Changed On',
|
||||
changed_on_delta_humanized: 'Changed On Delta Humanized',
|
||||
'created_by.first_name': 'Created By First Name',
|
||||
'created_by.last_name': 'Created By Last Name',
|
||||
database_name: 'Database Name',
|
||||
explore_database_id: 'Explore Database Id',
|
||||
expose_in_sqllab: 'Expose In Sqllab',
|
||||
force_ctas_schema: 'Force Ctas Schema',
|
||||
id: 'Id',
|
||||
},
|
||||
list_columns: [
|
||||
'allow_file_upload',
|
||||
'allow_ctas',
|
||||
'allow_cvas',
|
||||
'allow_dml',
|
||||
'allow_multi_schema_metadata_fetch',
|
||||
'allow_run_async',
|
||||
'allows_cost_estimate',
|
||||
'allows_subquery',
|
||||
'allows_virtual_table_explore',
|
||||
'disable_data_preview',
|
||||
'backend',
|
||||
'changed_on',
|
||||
'changed_on_delta_humanized',
|
||||
'created_by.first_name',
|
||||
'created_by.last_name',
|
||||
'database_name',
|
||||
'explore_database_id',
|
||||
'expose_in_sqllab',
|
||||
'force_ctas_schema',
|
||||
'id',
|
||||
],
|
||||
list_title: 'List Database',
|
||||
order_columns: [
|
||||
'allow_file_upload',
|
||||
'allow_dml',
|
||||
'allow_run_async',
|
||||
'changed_on',
|
||||
'changed_on_delta_humanized',
|
||||
'created_by.first_name',
|
||||
'database_name',
|
||||
'expose_in_sqllab',
|
||||
],
|
||||
result: [
|
||||
{
|
||||
allow_file_upload: false,
|
||||
allow_ctas: false,
|
||||
allow_cvas: false,
|
||||
allow_dml: false,
|
||||
allow_multi_schema_metadata_fetch: false,
|
||||
allow_run_async: false,
|
||||
allows_cost_estimate: null,
|
||||
allows_subquery: true,
|
||||
allows_virtual_table_explore: true,
|
||||
disable_data_preview: false,
|
||||
backend: 'postgresql',
|
||||
changed_on: '2021-03-09T19:02:07.141095',
|
||||
changed_on_delta_humanized: 'a day ago',
|
||||
created_by: null,
|
||||
database_name: 'test-postgres',
|
||||
explore_database_id: 1,
|
||||
expose_in_sqllab: true,
|
||||
force_ctas_schema: null,
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
allow_csv_upload: false,
|
||||
allow_ctas: false,
|
||||
allow_cvas: false,
|
||||
allow_dml: false,
|
||||
allow_multi_schema_metadata_fetch: false,
|
||||
allow_run_async: false,
|
||||
allows_cost_estimate: null,
|
||||
allows_subquery: true,
|
||||
allows_virtual_table_explore: true,
|
||||
disable_data_preview: false,
|
||||
backend: 'mysql',
|
||||
changed_on: '2021-03-09T19:02:07.141095',
|
||||
changed_on_delta_humanized: 'a day ago',
|
||||
created_by: null,
|
||||
database_name: 'test-mysql',
|
||||
explore_database_id: 1,
|
||||
expose_in_sqllab: true,
|
||||
force_ctas_schema: null,
|
||||
id: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
} as any;
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const getTableMockFunction = async () =>
|
||||
({
|
||||
json: {
|
||||
options: [
|
||||
{ label: 'table_a', value: 'table_a' },
|
||||
{ label: 'table_b', value: 'table_b' },
|
||||
{ label: 'table_c', value: 'table_c' },
|
||||
{ label: 'table_d', value: 'table_d' },
|
||||
],
|
||||
},
|
||||
} as any);
|
||||
|
||||
it('should render', () => {
|
||||
const { container } = render(<LeftPanel setDataset={mockFun} />, {
|
||||
useRedux: true,
|
||||
});
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render tableselector and databaselector container and selects', () => {
|
||||
render(<LeftPanel setDataset={mockFun} />, { useRedux: true });
|
||||
|
||||
expect(screen.getByText(/select database & schema/i)).toBeVisible();
|
||||
|
||||
const databaseSelect = screen.getByRole('combobox', {
|
||||
name: 'Select database or type database name',
|
||||
});
|
||||
const schemaSelect = screen.getByRole('combobox', {
|
||||
name: 'Select schema or type schema name',
|
||||
});
|
||||
expect(databaseSelect).toBeInTheDocument();
|
||||
expect(schemaSelect).toBeInTheDocument();
|
||||
});
|
||||
it('does not render blank state if there is nothing selected', () => {
|
||||
render(<LeftPanel setDataset={mockFun} />, { useRedux: true });
|
||||
const emptyState = screen.queryByRole('img', { name: /empty/i });
|
||||
expect(emptyState).not.toBeInTheDocument();
|
||||
});
|
||||
it('renders list of options when user clicks on schema', async () => {
|
||||
render(<LeftPanel setDataset={mockFun} schema="schema_a" dbId={1} />, {
|
||||
useRedux: true,
|
||||
});
|
||||
|
||||
const databaseSelect = screen.getByRole('combobox', {
|
||||
name: 'Select database or type database name',
|
||||
});
|
||||
userEvent.click(databaseSelect);
|
||||
expect(await screen.findByText('test-postgres')).toBeInTheDocument();
|
||||
|
||||
act(() => {
|
||||
userEvent.click(screen.getAllByText('test-postgres')[0]);
|
||||
});
|
||||
const tableSelect = screen.getByRole('combobox', {
|
||||
name: /select schema or type schema name/i,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(tableSelect).toBeEnabled();
|
||||
});
|
||||
|
||||
userEvent.click(tableSelect);
|
||||
expect(
|
||||
await screen.findByRole('option', { name: 'information_schema' }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByRole('option', { name: 'public' }),
|
||||
).toBeInTheDocument();
|
||||
|
||||
SupersetClientGet.mockImplementation(getTableMockFunction);
|
||||
act(() => {
|
||||
userEvent.click(screen.getAllByText('public')[1]);
|
||||
});
|
||||
|
||||
// Todo: (Phillip) finish testing for showing list of options once table is implemented
|
||||
// expect(screen.getByTestId('options-list')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -16,18 +16,250 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { t } from '@superset-ui/core';
|
||||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
useMemo,
|
||||
SetStateAction,
|
||||
Dispatch,
|
||||
} from 'react';
|
||||
import { SupersetClient, t, styled, FAST_DEBOUNCE } from '@superset-ui/core';
|
||||
import { Input } from 'src/components/Input';
|
||||
import { Form } from 'src/components/Form';
|
||||
import Icons from 'src/components/Icons';
|
||||
import { TableOption } from 'src/components/TableSelector';
|
||||
import RefreshLabel from 'src/components/RefreshLabel';
|
||||
import { Table } from 'src/hooks/apiResources';
|
||||
import Loading from 'src/components/Loading';
|
||||
import DatabaseSelector from 'src/components/DatabaseSelector';
|
||||
import { debounce } from 'lodash';
|
||||
import { EmptyStateMedium } from 'src/components/EmptyState';
|
||||
import { useToasts } from 'src/components/MessageToasts/withToasts';
|
||||
import { DatasetActionType, DatasetObject } from '../types';
|
||||
|
||||
interface LeftPanelProps {
|
||||
setDataset: Dispatch<SetStateAction<object>>;
|
||||
schema?: string | undefined | null;
|
||||
dbId?: number;
|
||||
}
|
||||
|
||||
const SearchIcon = styled(Icons.Search)`
|
||||
color: ${({ theme }) => theme.colors.grayscale.light1};
|
||||
`;
|
||||
|
||||
const LeftPanelStyle = styled.div`
|
||||
${({ theme }) => `
|
||||
max-width: ${theme.gridUnit * 87.5}px;
|
||||
padding: ${theme.gridUnit * 4}px;
|
||||
height: 100%;
|
||||
background-color: ${theme.colors.grayscale.light5};
|
||||
position: relative;
|
||||
.emptystate {
|
||||
height: auto;
|
||||
margin-top: ${theme.gridUnit * 17.5}px;
|
||||
}
|
||||
.refresh {
|
||||
position: absolute;
|
||||
top: ${theme.gridUnit * 43.25}px;
|
||||
left: ${theme.gridUnit * 16.75}px;
|
||||
span[role="button"]{
|
||||
font-size: ${theme.gridUnit * 4.25}px;
|
||||
}
|
||||
}
|
||||
.section-title {
|
||||
margin-top: ${theme.gridUnit * 5.5}px;
|
||||
margin-bottom: ${theme.gridUnit * 11}px;
|
||||
font-weight: ${theme.typography.weights.bold};
|
||||
}
|
||||
.table-title {
|
||||
margin-top: ${theme.gridUnit * 11}px;
|
||||
margin-bottom: ${theme.gridUnit * 6}px;
|
||||
font-weight: ${theme.typography.weights.bold};
|
||||
}
|
||||
.options-list {
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: ${theme.gridUnit * 97.5}px;
|
||||
left: ${theme.gridUnit * 3.25}px;
|
||||
right: 0;
|
||||
.options {
|
||||
padding: ${theme.gridUnit * 1.75}px;
|
||||
border-radius: ${theme.borderRadius}px;
|
||||
}
|
||||
}
|
||||
form > span[aria-label="refresh"] {
|
||||
position: absolute;
|
||||
top: ${theme.gridUnit * 73}px;
|
||||
left: ${theme.gridUnit * 42.75}px;
|
||||
font-size: ${theme.gridUnit * 4.25}px;
|
||||
}
|
||||
.table-form {
|
||||
margin-bottom: ${theme.gridUnit * 8}px;
|
||||
}
|
||||
.loading-container {
|
||||
position: absolute;
|
||||
top: 359px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
img {
|
||||
width: ${theme.gridUnit * 20}px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
p {
|
||||
color: ${theme.colors.grayscale.light1}
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
export default function LeftPanel({
|
||||
setDataset,
|
||||
schema,
|
||||
dbId,
|
||||
}: LeftPanelProps) {
|
||||
const [tableOptions, setTableOptions] = useState<Array<TableOption>>([]);
|
||||
const [resetTables, setResetTables] = useState(false);
|
||||
const [loadTables, setLoadTables] = useState(false);
|
||||
const [searchVal, setSearchVal] = useState('');
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
|
||||
const { addDangerToast } = useToasts();
|
||||
|
||||
const setDatabase = (db: Partial<DatasetObject>) => {
|
||||
setDataset({ type: DatasetActionType.selectDatabase, payload: db });
|
||||
setResetTables(true);
|
||||
};
|
||||
|
||||
const getTablesList = (url: string) => {
|
||||
SupersetClient.get({ url })
|
||||
.then(({ json }) => {
|
||||
const options: TableOption[] = json.options.map((table: Table) => {
|
||||
const option: TableOption = {
|
||||
value: table.value,
|
||||
label: <TableOption table={table} />,
|
||||
text: table.label,
|
||||
};
|
||||
|
||||
return option;
|
||||
});
|
||||
|
||||
setTableOptions(options);
|
||||
setLoadTables(false);
|
||||
setResetTables(false);
|
||||
setRefresh(false);
|
||||
})
|
||||
.catch(e => {
|
||||
console.log('error', e);
|
||||
});
|
||||
};
|
||||
|
||||
const setSchema = (schema: string) => {
|
||||
if (schema) {
|
||||
setDataset({
|
||||
type: DatasetActionType.selectSchema,
|
||||
payload: { name: 'schema', value: schema },
|
||||
});
|
||||
setLoadTables(true);
|
||||
}
|
||||
setResetTables(true);
|
||||
};
|
||||
|
||||
const encodedSchema = schema ? encodeURIComponent(schema) : undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (loadTables) {
|
||||
const endpoint = encodeURI(
|
||||
`/superset/tables/${dbId}/${encodedSchema}/undefined/${refresh}/`,
|
||||
);
|
||||
getTablesList(endpoint);
|
||||
}
|
||||
}, [loadTables]);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetTables) {
|
||||
setTableOptions([]);
|
||||
setResetTables(false);
|
||||
}
|
||||
}, [resetTables]);
|
||||
|
||||
const search = useMemo(
|
||||
() =>
|
||||
debounce((value: string) => {
|
||||
const encodeTableName =
|
||||
value === '' ? undefined : encodeURIComponent(value);
|
||||
const endpoint = encodeURI(
|
||||
`/superset/tables/${dbId}/${encodedSchema}/${encodeTableName}/`,
|
||||
);
|
||||
getTablesList(endpoint);
|
||||
}, FAST_DEBOUNCE),
|
||||
[dbId, encodedSchema],
|
||||
);
|
||||
|
||||
const Loader = (inline: string) => (
|
||||
<div className="loading-container">
|
||||
<Loading position="inline" />
|
||||
<p>{inline} </p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function LeftPanel() {
|
||||
return (
|
||||
<>
|
||||
<EmptyStateMedium
|
||||
image="empty-table.svg"
|
||||
title={t('No database tables found')}
|
||||
description={t('Try selecting a different schema')}
|
||||
<LeftPanelStyle>
|
||||
<p className="section-title db-schema">Select database & schema</p>
|
||||
<DatabaseSelector
|
||||
handleError={addDangerToast}
|
||||
onDbChange={setDatabase}
|
||||
onSchemaChange={setSchema}
|
||||
/>
|
||||
</>
|
||||
{loadTables && !refresh && Loader('Table loading')}
|
||||
|
||||
{schema && !loadTables && !tableOptions.length && !searchVal && (
|
||||
<div className="emptystate">
|
||||
<EmptyStateMedium
|
||||
image="empty-table.svg"
|
||||
title={t('No database tables found')}
|
||||
description={t('Try selecting a different schema')}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{schema && (tableOptions.length > 0 || searchVal.length > 0) && (
|
||||
<>
|
||||
<Form>
|
||||
<p className="table-title">Select database table</p>
|
||||
<RefreshLabel
|
||||
onClick={() => {
|
||||
setLoadTables(true);
|
||||
setRefresh(true);
|
||||
}}
|
||||
tooltipContent={t('Refresh table list')}
|
||||
/>
|
||||
{refresh && Loader('Refresh tables')}
|
||||
{!refresh && (
|
||||
<Input
|
||||
value={searchVal}
|
||||
prefix={<SearchIcon iconSize="l" />}
|
||||
onChange={evt => {
|
||||
search(evt.target.value);
|
||||
setSearchVal(evt.target.value);
|
||||
}}
|
||||
className="table-form"
|
||||
placeholder={t('Search tables')}
|
||||
/>
|
||||
)}
|
||||
</Form>
|
||||
<div className="options-list" data-test="options-list">
|
||||
{!refresh &&
|
||||
tableOptions.map((o, i) => (
|
||||
<div className="options" key={i}>
|
||||
{o.label}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</LeftPanelStyle>
|
||||
);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import React, { useReducer, Reducer } from 'react';
|
||||
import Header from './Header';
|
||||
import DatasetPanel from './DatasetPanel';
|
||||
import LeftPanel from './LeftPanel';
|
||||
@ -24,13 +24,18 @@ import Footer from './Footer';
|
||||
import { DatasetActionType, DatasetObject, DSReducerActionType } from './types';
|
||||
import DatasetLayout from '../DatasetLayout';
|
||||
|
||||
type Schema = {
|
||||
schema: string;
|
||||
};
|
||||
|
||||
export function datasetReducer(
|
||||
state: Partial<DatasetObject> | null,
|
||||
state: DatasetObject | null,
|
||||
action: DSReducerActionType,
|
||||
): Partial<DatasetObject> | null {
|
||||
): Partial<DatasetObject> | Schema | null {
|
||||
const trimmedState = {
|
||||
...(state || {}),
|
||||
};
|
||||
|
||||
switch (action.type) {
|
||||
case DatasetActionType.selectDatabase:
|
||||
return {
|
||||
@ -42,7 +47,7 @@ export function datasetReducer(
|
||||
case DatasetActionType.selectSchema:
|
||||
return {
|
||||
...trimmedState,
|
||||
...action.payload,
|
||||
[action.payload.name]: action.payload.value,
|
||||
table_name: null,
|
||||
};
|
||||
case DatasetActionType.selectTable:
|
||||
@ -61,16 +66,22 @@ export function datasetReducer(
|
||||
}
|
||||
|
||||
export default function AddDataset() {
|
||||
// this is commented out for now, but can be commented in as the component
|
||||
// is built up. Uncomment the useReducer in imports too
|
||||
// const [dataset, setDataset] = useReducer<
|
||||
// Reducer<Partial<DatasetObject> | null, DSReducerActionType>
|
||||
// >(datasetReducer, null);
|
||||
const [dataset, setDataset] = useReducer<
|
||||
Reducer<Partial<DatasetObject> | null, DSReducerActionType>
|
||||
>(datasetReducer, null);
|
||||
|
||||
const LeftPanelComponent = () => (
|
||||
<LeftPanel
|
||||
setDataset={setDataset}
|
||||
schema={dataset?.schema}
|
||||
dbId={dataset?.id}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<DatasetLayout
|
||||
header={Header()}
|
||||
leftPanel={LeftPanel()}
|
||||
leftPanel={LeftPanelComponent()}
|
||||
datasetPanel={DatasetPanel()}
|
||||
footer={Footer()}
|
||||
/>
|
||||
|
@ -24,11 +24,9 @@ export enum DatasetActionType {
|
||||
}
|
||||
|
||||
export interface DatasetObject {
|
||||
database: {
|
||||
id: string;
|
||||
database_name: string;
|
||||
};
|
||||
owners: number[];
|
||||
id: number;
|
||||
database_name?: string;
|
||||
owners?: number[];
|
||||
schema?: string | null;
|
||||
dataset_name: string;
|
||||
table_name?: string | null;
|
||||
@ -39,15 +37,16 @@ interface DatasetReducerPayloadType {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export type Schema = {
|
||||
schema?: string | null | undefined;
|
||||
};
|
||||
|
||||
export type DSReducerActionType =
|
||||
| {
|
||||
type:
|
||||
| DatasetActionType.selectDatabase
|
||||
| DatasetActionType.selectSchema
|
||||
| DatasetActionType.selectTable;
|
||||
type: DatasetActionType.selectDatabase | DatasetActionType.selectTable;
|
||||
payload: Partial<DatasetObject>;
|
||||
}
|
||||
| {
|
||||
type: DatasetActionType.changeDataset;
|
||||
type: DatasetActionType.changeDataset | DatasetActionType.selectSchema;
|
||||
payload: DatasetReducerPayloadType;
|
||||
};
|
||||
|
@ -40,10 +40,12 @@ describe('DatasetLayout', () => {
|
||||
});
|
||||
|
||||
it('renders a LeftPanel when passed in', () => {
|
||||
render(<DatasetLayout leftPanel={LeftPanel()} />);
|
||||
render(
|
||||
<DatasetLayout leftPanel={<LeftPanel setDataset={() => null} />} />,
|
||||
{ useRedux: true },
|
||||
);
|
||||
|
||||
expect(screen.getByRole('img', { name: /empty/i })).toBeVisible();
|
||||
expect(screen.getByText(/no database tables found/i)).toBeVisible();
|
||||
expect(LeftPanel).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders a DatasetPanel when passed in', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user