/** * 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 React from 'react'; import configureStore from 'redux-mock-store'; import fetchMock from 'fetch-mock'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; import userEvent from '@testing-library/user-event'; import { Provider } from 'react-redux'; import '@testing-library/jest-dom/extend-expect'; import thunk from 'redux-thunk'; import SqlEditorLeftBar from 'src/SqlLab/components/SqlEditorLeftBar'; import { table, initialState, defaultQueryEditor } from 'src/SqlLab/fixtures'; const mockedProps = { tables: [table], queryEditorId: defaultQueryEditor.id, database: { id: 1, database_name: 'main', backend: 'mysql', }, height: 0, }; const middlewares = [thunk]; const mockStore = configureStore(middlewares); const store = mockStore(initialState); beforeEach(() => { fetchMock.get('glob:*/api/v1/database/?*', { result: [] }); fetchMock.get('glob:*/api/v1/database/*/schemas/?*', { count: 2, result: ['main', 'new_schema'], }); fetchMock.get('glob:*/api/v1/database/*/tables/*', { count: 1, result: [ { label: 'ab_user', value: 'ab_user', }, ], }); }); afterEach(() => { fetchMock.restore(); }); const renderAndWait = (props, store) => waitFor(() => render(, { useRedux: true, ...(store && { store }), }), ); test('is valid', () => { expect( React.isValidElement( , ), ).toBe(true); }); test('renders a TableElement', async () => { await renderAndWait(mockedProps, store); expect(await screen.findByText(/Database/i)).toBeInTheDocument(); const tableElement = screen.getAllByTestId('table-element'); expect(tableElement.length).toBeGreaterThanOrEqual(1); }); test('table should be visible when expanded is true', async () => { const { container } = await renderAndWait(mockedProps, store); const dbSelect = screen.getByRole('combobox', { name: 'Select database or type database name', }); const schemaSelect = screen.getByRole('combobox', { name: 'Select schema or type schema name', }); const dropdown = screen.getByText(/Table/i); const abUser = screen.queryAllByText(/ab_user/i); await waitFor(() => { expect(screen.getByText(/Database/i)).toBeInTheDocument(); expect(dbSelect).toBeInTheDocument(); expect(schemaSelect).toBeInTheDocument(); expect(dropdown).toBeInTheDocument(); expect(abUser).toHaveLength(2); expect( container.querySelector('.ant-collapse-content-active'), ).toBeInTheDocument(); }); }); test('should toggle the table when the header is clicked', async () => { const store = mockStore(initialState); await renderAndWait(mockedProps, store); const header = (await screen.findAllByText(/ab_user/))[1]; expect(header).toBeInTheDocument(); userEvent.click(header); await waitFor(() => { expect(store.getActions()[store.getActions().length - 1].type).toEqual( 'COLLAPSE_TABLE', ); }); }); test('When changing database the table list must be updated', async () => { const { rerender } = await renderAndWait(mockedProps, store); expect(screen.getAllByText(/main/i)[0]).toBeInTheDocument(); expect(screen.getAllByText(/ab_user/i)[0]).toBeInTheDocument(); rerender( , { useRedux: true, store: mockStore({ ...initialState, sqlLab: { ...initialState.sqlLab, unsavedQueryEditor: { id: defaultQueryEditor.id, schema: 'new_schema', }, }, }), }, ); expect(await screen.findByText(/new_db/i)).toBeInTheDocument(); expect(await screen.findByText(/new_table/i)).toBeInTheDocument(); }); test('ignore schema api when current schema is deprecated', async () => { const invalidSchemaName = 'None'; const { rerender } = await renderAndWait( mockedProps, mockStore({ ...initialState, sqlLab: { ...initialState.sqlLab, unsavedQueryEditor: { id: defaultQueryEditor.id, schema: invalidSchemaName, }, }, }), ); expect(await screen.findByText(/Database/i)).toBeInTheDocument(); expect(screen.queryByText(/None/i)).toBeInTheDocument(); expect(fetchMock.calls()).not.toContainEqual( expect.arrayContaining([ expect.stringContaining( `/tables/${mockedProps.database.id}/${invalidSchemaName}/`, ), ]), ); rerender(); // Deselect the deprecated schema selection await waitFor(() => expect(screen.queryByText(/None/i)).not.toBeInTheDocument(), ); });