/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import { type ReactChild } from 'react'; import fetchMock from 'fetch-mock'; import { table, initialState } from 'src/SqlLab/fixtures'; import { render, waitFor, fireEvent, screen, } from 'spec/helpers/testing-library'; import TablePreview from '.'; jest.mock('src/components/FilterableTable', () => ({ __esModule: true, FilterableTable: ({ data }: { data: Record[] }) => (
{data.map((record, i) => (
{JSON.stringify(record)}
))}
), })); jest.mock( 'react-virtualized-auto-sizer', () => ({ children }: { children: (params: { height: number }) => ReactChild }) => children({ height: 500 }), ); jest.mock('@superset-ui/core/components/IconTooltip', () => ({ IconTooltip: ({ onClick, tooltip, }: { onClick: () => void; tooltip: string; }) => ( ), })); const getTableMetadataEndpoint = /\/api\/v1\/database\/\d+\/table_metadata\/(?:\?.*)?$/; const getExtraTableMetadataEndpoint = /\/api\/v1\/database\/\d+\/table_metadata\/extra\/(?:\?.*)?$/; const fetchPreviewEndpoint = 'glob:*/api/v1/sqllab/execute/'; beforeEach(() => { fetchMock.get(getTableMetadataEndpoint, table); fetchMock.get(getExtraTableMetadataEndpoint, {}); fetchMock.post(fetchPreviewEndpoint, `{ "data": 123 }`); }); afterEach(() => { fetchMock.clearHistory().removeRoutes(); }); const mockedProps = { dbId: table.dbId, catalog: table.catalog, schema: table.schema, tableName: table.name, }; test('renders columns', async () => { const { getAllByTestId, queryByText } = render( , { useRedux: true, initialState, }, ); await waitFor(() => expect(getAllByTestId('mock-record-row')).toHaveLength( table.columns.length, ), ); expect(queryByText(`Columns (${table.columns.length})`)).toBeInTheDocument(); }); test('renders indexes', async () => { const { queryByText } = render(, { useRedux: true, initialState, }); await waitFor(() => expect(fetchMock.callHistory.calls(getTableMetadataEndpoint)).toHaveLength( 1, ), ); expect(queryByText(`Indexes (${table.indexes.length})`)).toBeInTheDocument(); }); test('renders preview', async () => { const { getByText } = render(, { useRedux: true, initialState: { ...initialState, sqlLab: { ...initialState.sqlLab, databases: { [table.dbId]: { id: table.dbId, database_name: 'mysql', disable_data_preview: false, }, }, }, }, }); await waitFor(() => expect(fetchMock.callHistory.calls(getTableMetadataEndpoint)).toHaveLength( 1, ), ); expect(fetchMock.callHistory.calls(fetchPreviewEndpoint)).toHaveLength(0); fireEvent.click(getByText('Data preview')); await waitFor(() => expect(fetchMock.callHistory.calls(fetchPreviewEndpoint)).toHaveLength(1), ); }); // eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks describe('table actions', () => { test('refreshes table metadata when triggered', async () => { const { getByRole } = render(, { useRedux: true, initialState, }); await waitFor(() => expect( fetchMock.callHistory.calls(getTableMetadataEndpoint), ).toHaveLength(1), ); const refreshButton = getByRole('button', { name: 'sync' }); fireEvent.click(refreshButton); await waitFor(() => expect( fetchMock.callHistory.calls(getTableMetadataEndpoint), ).toHaveLength(2), ); }); test('shows CREATE VIEW statement', async () => { const { getByRole } = render(, { useRedux: true, initialState, }); await waitFor(() => expect( fetchMock.callHistory.calls(getTableMetadataEndpoint), ).toHaveLength(1), ); const viewButton = getByRole('button', { name: 'eye' }); fireEvent.click(viewButton); await waitFor(() => expect( screen.queryByRole('dialog', { name: 'CREATE VIEW statement' }), ).toBeInTheDocument(), ); }); });