This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch replace-jest-enzyme
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 6d45f7e48a510e54bb7df5c998fe16e690b3b8a9
Author: Evan Rusackas <[email protected]>
AuthorDate: Fri Feb 7 15:19:13 2025 -0700

    more fixes...
---
 superset-frontend/package.json                     |   2 +-
 .../Chart/DrillDetail/DrillDetailPane.test.tsx     |  68 +-
 .../DatabaseSelector/DatabaseSelector.test.tsx     | 173 +++--
 .../src/components/Select/AsyncSelect.test.tsx     |  24 +-
 .../FilterScope/FilterScope.test.tsx               |  95 ++-
 .../AnnotationLayer.test.tsx                       |   2 +-
 .../databases/DatabaseModal/index.test.tsx         | 701 ++++++++++-----------
 7 files changed, 485 insertions(+), 580 deletions(-)

diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index a3dbc78926..1d074fdaab 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -69,7 +69,7 @@
     "prune": "rm -rf 
./{packages,plugins}/*/{node_modules,lib,esm,tsconfig.tsbuildinfo,package-lock.json}
 ./.temp_cache",
     "storybook": "cross-env NODE_ENV=development BABEL_ENV=development 
storybook dev -p 6006",
     "tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=4096\" 
jest --watch",
-    "test": "cross-env NODE_ENV=test 
NODE_OPTIONS=\"--max-old-space-size=4096\" jest --max-workers=90% --silent",
+    "test": "cross-env NODE_ENV=test 
NODE_OPTIONS=\"--max-old-space-size=4096\" jest --max-workers=30% --silent",
     "type": "tsc --noEmit",
     "update-maps": "jupyter nbconvert --to notebook --execute --inplace 
'plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON 
Generator.ipynb' -Xfrozen_modules=off",
     "validate-release": "../RELEASING/validate_this_release.sh"
diff --git 
a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.test.tsx 
b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.test.tsx
index 9f6c7f6d3b..6f1a628646 100644
--- 
a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.test.tsx
+++ 
b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.test.tsx
@@ -16,26 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { cleanup } from '@testing-library/react';
 import fetchMock from 'fetch-mock';
-import type { QueryFormData } from '@superset-ui/core';
-import { SupersetClient } from '@superset-ui/core';
+import { QueryFormData, SupersetClient } from '@superset-ui/core';
 import { render, screen, waitFor } from 'spec/helpers/testing-library';
 import { getMockStoreWithNativeFilters } from 'spec/fixtures/mockStore';
 import chartQueries, { sliceId } from 'spec/fixtures/mockChartQueries';
 import { supersetGetCache } from 'src/utils/cachedSupersetGet';
 import DrillDetailPane from './DrillDetailPane';
 
-// Add cleanup after each test
-afterEach(async () => {
-  cleanup();
-  fetchMock.restore();
-  supersetGetCache.clear();
-  jest.resetAllMocks();
-  // Wait for any pending effects to complete
-  await new Promise(resolve => setTimeout(resolve, 0));
-});
-
 const chart = chartQueries[sliceId];
 const setup = (overrides: Record<string, any> = {}) => {
   const store = getMockStoreWithNativeFilters();
@@ -126,52 +114,44 @@ const fetchWithData = () => {
   });
 };
 
-// Add cleanup function
-afterEach(async () => {
+afterEach(() => {
   fetchMock.restore();
   supersetGetCache.clear();
-  // Wait for any pending effects to complete
-  await waitFor(() => {}, { timeout: 100 }).catch(() => {});
 });
 
-// Modify test cases to properly await all operations
 test('should render', async () => {
   fetchWithNoData();
   const { container } = await waitForRender();
-  await waitFor(() => {
-    expect(container).toBeInTheDocument();
-  });
+  expect(container).toBeInTheDocument();
 });
 
 test('should render loading indicator', async () => {
   fetchWithData();
   setup();
-  await waitFor(() => {
-    expect(screen.getByLabelText('Loading')).toBeInTheDocument();
-  });
+  await waitFor(() =>
+    expect(screen.getByLabelText('Loading')).toBeInTheDocument(),
+  );
 });
 
 test('should render the table with results', async () => {
   fetchWithData();
   await waitForRender();
-  await waitFor(() => {
-    expect(screen.getByRole('table')).toBeInTheDocument();
-    expect(screen.getByText('1996')).toBeInTheDocument();
-    expect(screen.getByText('11.27')).toBeInTheDocument();
-    expect(screen.getByText('1989')).toBeInTheDocument();
-    expect(screen.getByText('23.2')).toBeInTheDocument();
-    expect(screen.getByText('1999')).toBeInTheDocument();
-    expect(screen.getByText('9')).toBeInTheDocument();
-    expect(
-      screen.getByRole('columnheader', { name: 'year' }),
-    ).toBeInTheDocument();
-    expect(
-      screen.getByRole('columnheader', { name: 'na_sales' }),
-    ).toBeInTheDocument();
-    expect(
-      screen.getByRole('columnheader', { name: 'eu_sales' }),
-    ).toBeInTheDocument();
-  });
+  expect(screen.getByRole('table')).toBeInTheDocument();
+  expect(screen.getByText('1996')).toBeInTheDocument();
+  expect(screen.getByText('11.27')).toBeInTheDocument();
+  expect(screen.getByText('1989')).toBeInTheDocument();
+  expect(screen.getByText('23.2')).toBeInTheDocument();
+  expect(screen.getByText('1999')).toBeInTheDocument();
+  expect(screen.getByText('9')).toBeInTheDocument();
+  expect(
+    screen.getByRole('columnheader', { name: 'year' }),
+  ).toBeInTheDocument();
+  expect(
+    screen.getByRole('columnheader', { name: 'na_sales' }),
+  ).toBeInTheDocument();
+  expect(
+    screen.getByRole('columnheader', { name: 'eu_sales' }),
+  ).toBeInTheDocument();
 });
 
 test('should render the "No results" components', async () => {
@@ -215,7 +195,5 @@ test('should render the error', async () => {
     .spyOn(SupersetClient, 'post')
     .mockRejectedValue(new Error('Something went wrong'));
   await waitForRender();
-  await waitFor(() => {
-    expect(screen.getByText('Error: Something went 
wrong')).toBeInTheDocument();
-  });
+  expect(screen.getByText('Error: Something went wrong')).toBeInTheDocument();
 });
diff --git 
a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx 
b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
index 44c23a0756..ee17f2d801 100644
--- 
a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
+++ 
b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx
@@ -203,111 +203,98 @@ test('Should render', async () => {
   expect(await screen.findByTestId('DatabaseSelector')).toBeInTheDocument();
 });
 
-describe('DatabaseSelector', () => {
-  beforeAll(() => {
-    jest.setTimeout(30000);
-  });
-
-  afterEach(async () => {
-    fetchMock.reset();
-    act(() => {
-      store.dispatch(api.util.resetApiState());
-    });
-    await new Promise(resolve => setTimeout(resolve, 0));
-  });
-
-  test('Refresh should work', async () => {
-    const props = createProps();
-    const { unmount } = render(<DatabaseSelector {...props} />, {
-      useRedux: true,
-      store,
-    });
-
-    expect(fetchMock.calls(schemaApiRoute).length).toBe(0);
-
-    const select = screen.getByRole('combobox', {
-      name: 'Select schema or type to search schemas',
-    });
-
-    await act(async () => {
-      userEvent.click(select);
-    });
+test('Refresh should work', async () => {
+  const props = createProps();
 
-    await waitFor(
-      () => {
-        expect(fetchMock.calls(databaseApiRoute).length).toBe(1);
-        expect(fetchMock.calls(schemaApiRoute).length).toBe(1);
-        expect(props.handleError).toHaveBeenCalledTimes(0);
-        expect(props.onDbChange).toHaveBeenCalledTimes(0);
-        expect(props.onSchemaChange).toHaveBeenCalledTimes(0);
-      },
-      { timeout: 10000 },
-    );
+  render(<DatabaseSelector {...props} />, { useRedux: true, store });
 
-    // click schema reload
-    await act(async () => {
-      userEvent.click(screen.getByRole('button', { name: 'refresh' }));
-    });
+  expect(fetchMock.calls(schemaApiRoute).length).toBe(0);
 
-    await waitFor(
-      () => {
-        expect(fetchMock.calls(databaseApiRoute).length).toBe(1);
-        expect(fetchMock.calls(schemaApiRoute).length).toBe(2);
-        expect(props.handleError).toHaveBeenCalledTimes(0);
-        expect(props.onDbChange).toHaveBeenCalledTimes(0);
-        expect(props.onSchemaChange).toHaveBeenCalledTimes(0);
-      },
-      { timeout: 10000 },
-    );
+  const select = screen.getByRole('combobox', {
+    name: 'Select schema or type to search schemas',
+  });
 
-    unmount();
-  }, 15000);
+  userEvent.click(select);
 
-  test('Should fetch the search keyword when total count exceeds initial 
options', async () => {
-    fetchMock.get(
-      databaseApiRoute,
-      {
-        ...fakeDatabaseApiResult,
-        count: fakeDatabaseApiResult.result.length + 1,
-      },
-      { overwriteRoutes: true },
-    );
+  await waitFor(() => {
+    expect(fetchMock.calls(databaseApiRoute).length).toBe(1);
+    expect(fetchMock.calls(schemaApiRoute).length).toBe(1);
+    expect(props.handleError).toHaveBeenCalledTimes(0);
+    expect(props.onDbChange).toHaveBeenCalledTimes(0);
+    expect(props.onSchemaChange).toHaveBeenCalledTimes(0);
+  });
 
-    const props = createProps();
-    const { unmount } = render(<DatabaseSelector {...props} />, {
-      useRedux: true,
-      store,
-    });
+  // click schema reload
+  userEvent.click(screen.getByRole('button', { name: 'refresh' }));
 
-    const select = screen.getByRole('combobox', {
-      name: 'Select database or type to search databases',
-    });
+  await waitFor(() => {
+    expect(fetchMock.calls(databaseApiRoute).length).toBe(1);
+    expect(fetchMock.calls(schemaApiRoute).length).toBe(2);
+    expect(props.handleError).toHaveBeenCalledTimes(0);
+    expect(props.onDbChange).toHaveBeenCalledTimes(0);
+    expect(props.onSchemaChange).toHaveBeenCalledTimes(0);
+  });
+});
 
-    await waitFor(
-      () => {
-        expect(fetchMock.calls(databaseApiRoute)).toHaveLength(1);
-      },
-      { timeout: 10000 },
-    );
+test('Should database select display options', async () => {
+  const props = createProps();
+  render(<DatabaseSelector {...props} />, { useRedux: true, store });
+  const select = screen.getByRole('combobox', {
+    name: 'Select database or type to search databases',
+  });
+  expect(select).toBeInTheDocument();
+  userEvent.click(select);
+  expect(await screen.findByText('test-mysql')).toBeInTheDocument();
+});
 
-    expect(select).toBeInTheDocument();
+test('should display options in order of the api response', async () => {
+  fetchMock.get(databaseApiRoute, fakeDatabaseApiResultInReverseOrder, {
+    overwriteRoutes: true,
+  });
+  const props = createProps();
+  render(<DatabaseSelector {...props} db={undefined} />, {
+    useRedux: true,
+    store,
+  });
+  const select = screen.getByRole('combobox', {
+    name: 'Select database or type to search databases',
+  });
+  expect(select).toBeInTheDocument();
+  userEvent.click(select);
+  const options = await screen.findAllByRole('option');
 
-    await act(async () => {
-      userEvent.type(select, 'keywordtest');
-    });
+  expect(options[0]).toHaveTextContent(
+    `${fakeDatabaseApiResultInReverseOrder.result[0].id}`,
+  );
+  expect(options[1]).toHaveTextContent(
+    `${fakeDatabaseApiResultInReverseOrder.result[1].id}`,
+  );
+});
 
-    await waitFor(
-      () => {
-        expect(fetchMock.calls(databaseApiRoute)).toHaveLength(2);
-        expect(fetchMock.calls(databaseApiRoute)[1][0]).toContain(
-          'keywordtest',
-        );
-      },
-      { timeout: 10000 },
-    );
+test('Should fetch the search keyword when total count exceeds initial 
options', async () => {
+  fetchMock.get(
+    databaseApiRoute,
+    {
+      ...fakeDatabaseApiResult,
+      count: fakeDatabaseApiResult.result.length + 1,
+    },
+    { overwriteRoutes: true },
+  );
 
-    unmount();
-  }, 15000);
+  const props = createProps();
+  render(<DatabaseSelector {...props} />, { useRedux: true, store });
+  const select = screen.getByRole('combobox', {
+    name: 'Select database or type to search databases',
+  });
+  await waitFor(() =>
+    expect(fetchMock.calls(databaseApiRoute)).toHaveLength(1),
+  );
+  expect(select).toBeInTheDocument();
+  userEvent.type(select, 'keywordtest');
+  await waitFor(() =>
+    expect(fetchMock.calls(databaseApiRoute)).toHaveLength(2),
+  );
+  expect(fetchMock.calls(databaseApiRoute)[1][0]).toContain('keywordtest');
 });
 
 test('should show empty state if there are no options', async () => {
diff --git a/superset-frontend/src/components/Select/AsyncSelect.test.tsx 
b/superset-frontend/src/components/Select/AsyncSelect.test.tsx
index be46dbbe45..2e9efcbf0b 100644
--- a/superset-frontend/src/components/Select/AsyncSelect.test.tsx
+++ b/superset-frontend/src/components/Select/AsyncSelect.test.tsx
@@ -26,7 +26,6 @@ import {
 } from 'spec/helpers/testing-library';
 import userEvent from '@testing-library/user-event';
 import { AsyncSelect } from 'src/components';
-import { cleanup } from '@testing-library/react';
 
 const ARIA_LABEL = 'Test';
 const NEW_OPTION = 'Kyle';
@@ -105,13 +104,10 @@ const getSelect = () => screen.getByRole('combobox', { 
name: ARIA_LABEL });
 const getAllSelectOptions = () =>
   getElementsByClassName('.ant-select-item-option-content');
 
-const findSelectOption = async (text: string) => {
-  await waitFor(() => {
-    const virtualList = getElementByClassName('.rc-virtual-list');
-    expect(virtualList).not.toBeInTheDocument();
-  });
-  return within(getElementByClassName('.rc-virtual-list')).findByText(text);
-};
+const findSelectOption = (text: string) =>
+  waitFor(() =>
+    within(getElementByClassName('.rc-virtual-list')).getByText(text),
+  );
 
 const querySelectOption = (text: string) =>
   waitFor(() =>
@@ -149,13 +145,6 @@ const type = (text: string) => {
 
 const open = () => waitFor(() => userEvent.click(getSelect()));
 
-// Add cleanup after each test
-afterEach(async () => {
-  cleanup();
-  // Wait for any pending effects to complete
-  await new Promise(resolve => setTimeout(resolve, 0));
-});
-
 test('displays a header', async () => {
   const headerText = 'Header';
   render(<AsyncSelect {...defaultProps} header={headerText} />);
@@ -308,10 +297,7 @@ test('searches for label or value', async () => {
   render(<AsyncSelect {...defaultProps} />);
   const search = option.value;
   await type(search.toString());
-
-  const optionElement = await findSelectOption(option.label);
-  expect(optionElement).toBeInTheDocument();
-
+  expect(await findSelectOption(option.label)).toBeInTheDocument();
   const options = await findAllSelectOptions();
   expect(options.length).toBe(1);
   expect(options[0]).toHaveTextContent(option.label);
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx
index 7ada1ccaa0..c37153993e 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx
@@ -76,69 +76,46 @@ describe('FilterScope', () => {
     document.querySelectorAll('.ant-tree-switcher')[order];
 
   beforeAll(() => {
-    jest.setTimeout(30000);
+    // Reduce the global timeout
+    jest.setTimeout(10000);
   });
 
-  afterEach(async () => {
-    cleanup();
-    // Wait for any pending effects to complete
-    await new Promise(resolve => setTimeout(resolve, 0));
+  beforeEach(() => {
+    // Add this to speed up animations/transitions
+    jest.useFakeTimers();
   });
 
-  it('renders "apply to all" filter scope', async () => {
-    const { unmount } = render(<MockModal />);
-    expect(screen.queryByRole('tree')).not.toBeInTheDocument();
-    unmount();
+  afterEach(() => {
+    cleanup();
+    jest.runOnlyPendingTimers();
+    jest.useRealTimers();
   });
 
   it('select tree values with 1 excluded', async () => {
     const { unmount } = render(<MockModal />);
 
-    // Wait for the Scoping tab to be visible and click it
-    await waitFor(() => {
-      expect(screen.getByText('Scoping')).toBeInTheDocument();
-    });
-    fireEvent.click(screen.getByText('Scoping'));
+    // First, wait for and click the Scoping tab
+    const scopingTab = await screen.findByRole('tab', { name: 'Scoping' });
+    fireEvent.click(scopingTab);
 
-    // Wait for the tree to be rendered
+    // Wait for tree to be rendered after tab switch
     await waitFor(
       () => {
         expect(screen.getByRole('tree')).toBeInTheDocument();
-      },
-      { timeout: 10000 },
-    );
-
-    // Wait for tree items to be loaded
-    await waitFor(
-      () => {
         expect(
           document.querySelector('.ant-tree-treenode'),
         ).toBeInTheDocument();
       },
-      { timeout: 10000 },
-    );
-
-    // Expand the tree node and wait for children
-    await waitFor(() => {
-      fireEvent.click(getTreeSwitcher(2));
-    });
-
-    // Find and click the chart node using a more specific selector
-    const chartNode = await waitFor(
-      () =>
-        document.querySelector('[title="CHART_ID2"]') ||
-        document.querySelector(
-          '.ant-tree-node-content-wrapper:contains("CHART_ID2")',
-        ),
+      { timeout: 3000 },
     );
 
-    if (!chartNode) {
-      throw new Error('Chart node not found in tree');
-    }
+    // Continue with tree interactions
+    fireEvent.click(getTreeSwitcher(2));
 
+    const chartNode = await screen.findByText('CHART_ID2');
     fireEvent.click(chartNode);
 
-    // Verify the form value
+    // Check form values
     await waitFor(
       () =>
         expect(
@@ -147,27 +124,37 @@ describe('FilterScope', () => {
           excluded: [20],
           rootPath: ['ROOT_ID'],
         }),
-      { timeout: 10000 },
+      { timeout: 3000 },
     );
 
     unmount();
-  }, 20000);
+  }, 5000);
 
   it('select 1 value only', async () => {
     const { unmount } = render(<MockModal />);
 
-    await waitFor(() => {
-      fireEvent.click(screen.getByText('Scoping'));
-    });
+    // First, wait for and click the Scoping tab
+    const scopingTab = await screen.findByRole('tab', { name: 'Scoping' });
+    fireEvent.click(scopingTab);
+
+    // Wait for tree to be rendered
+    await waitFor(
+      () => {
+        expect(screen.getByRole('tree')).toBeInTheDocument();
+      },
+      { timeout: 3000 },
+    );
 
-    expect(screen.getByRole('tree')).toBeInTheDocument();
+    // Perform tree interactions
+    fireEvent.click(getTreeSwitcher(2));
 
-    await waitFor(() => {
-      fireEvent.click(getTreeSwitcher(2));
-      fireEvent.click(screen.getByText('CHART_ID2'));
-      fireEvent.click(screen.getByText('tab1'));
-    });
+    const chartNode = await screen.findByText('CHART_ID2');
+    fireEvent.click(chartNode);
+
+    const tabNode = await screen.findByText('tab1');
+    fireEvent.click(tabNode);
 
+    // Update expected state to include both excluded IDs
     await waitFor(
       () =>
         expect(
@@ -176,11 +163,11 @@ describe('FilterScope', () => {
           excluded: [18, 20],
           rootPath: ['ROOT_ID'],
         }),
-      { timeout: 10000 },
+      { timeout: 3000 },
     );
 
     unmount();
-  }, 15000);
+  }, 5000);
 
   it('correct init tree with values', async () => {
     const { unmount } = render(
diff --git 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
index 3f3a592ea0..1b60cd7ae6 100644
--- 
a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.test.tsx
@@ -102,7 +102,7 @@ test('renders extra checkboxes when type is time series', 
async () => {
     await screen.findByRole('button', { name: 'Show Markers' }),
   ).toBeInTheDocument();
   expect(screen.getByRole('button', { name: 'Hide Line' 
})).toBeInTheDocument();
-});
+}, 10000);
 
 test('enables apply and ok buttons', async () => {
   const { container } = render(<AnnotationLayer {...defaultProps} />);
diff --git 
a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx 
b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
index b6b3e208bd..5c109a1c4e 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
@@ -21,14 +21,7 @@
 
 import fetchMock from 'fetch-mock';
 import userEvent from '@testing-library/user-event';
-import {
-  render,
-  screen,
-  within,
-  cleanup,
-  act,
-  waitFor,
-} from 'spec/helpers/testing-library';
+import { render, screen, within, waitFor } from 'spec/helpers/testing-library';
 import { getExtensionsRegistry } from '@superset-ui/core';
 import setupExtensions from 'src/setup/setupExtensions';
 import * as hooks from 'src/views/CRUD/hooks';
@@ -37,6 +30,7 @@ import DatabaseModal, {
   dbReducer,
   DBReducerActionType,
   ActionType,
+  DatabaseModalProps,
 } from './index';
 
 jest.mock('@superset-ui/core', () => ({
@@ -64,279 +58,281 @@ const AVAILABLE_DB_ENDPOINT = 
'glob:*/api/v1/database/available*';
 const VALIDATE_PARAMS_ENDPOINT = 'glob:*/api/v1/database/validate_parameters*';
 const DATABASE_CONNECT_ENDPOINT = 'glob:*/api/v1/database/';
 
-fetchMock.post(DATABASE_CONNECT_ENDPOINT, {
-  id: 10,
-  result: {
-    configuration_method: 'sqlalchemy_form',
-    database_name: 'Other2',
-    driver: 'apsw',
-    expose_in_sqllab: true,
-    extra: '{"allows_virtual_table_explore":true}',
-    sqlalchemy_uri: 'gsheets://',
-  },
-  json: 'foo',
-});
+const databaseFixture: DatabaseObject = {
+  id: 123,
+  backend: 'postgres',
+  configuration_method: ConfigurationMethod.DynamicForm,
+  database_name: 'Postgres',
+  name: 'PostgresDB',
+  is_managed_externally: false,
+  driver: 'psycopg2',
+};
 
-fetchMock.config.overwriteRoutes = true;
-fetchMock.get(DATABASE_FETCH_ENDPOINT, {
-  result: {
-    id: 10,
-    database_name: 'my database',
-    expose_in_sqllab: false,
-    allow_ctas: false,
-    allow_cvas: false,
-    configuration_method: 'sqlalchemy_form',
-  },
-});
-fetchMock.mock(AVAILABLE_DB_ENDPOINT, {
-  databases: [
-    {
-      available_drivers: ['psycopg2'],
-      default_driver: 'psycopg2',
-      engine: 'postgresql',
-      name: 'PostgreSQL',
-      parameters: {
-        properties: {
-          database: {
-            description: 'Database name',
-            type: 'string',
-          },
-          encryption: {
-            description: 'Use an encrypted connection to the database',
-            type: 'boolean',
-          },
-          host: {
-            description: 'Hostname or IP address',
-            type: 'string',
-          },
-          password: {
-            description: 'Password',
-            nullable: true,
-            type: 'string',
-          },
-          port: {
-            description: 'Database port',
-            format: 'int32',
-            maximum: 65536,
-            minimum: 0,
-            type: 'integer',
-          },
-          query: {
-            additionalProperties: {},
-            description: 'Additional parameters',
-            type: 'object',
-          },
-          ssh: {
-            description: 'Create SSH Tunnel',
-            type: 'boolean',
-          },
-          username: {
-            description: 'Username',
-            nullable: true,
-            type: 'string',
-          },
-        },
-        required: ['database', 'host', 'port', 'username'],
-        type: 'object',
-      },
-      preferred: true,
-      sqlalchemy_uri_placeholder:
-        'postgresql://user:password@host:port/dbname[?key=value&key=value...]',
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: false,
+describe('DatabaseModal', () => {
+  beforeEach(() => {
+    fetchMock.post(DATABASE_CONNECT_ENDPOINT, {
+      id: 10,
+      result: {
+        configuration_method: 'sqlalchemy_form',
+        database_name: 'Other2',
+        driver: 'apsw',
+        expose_in_sqllab: true,
+        extra: '{"allows_virtual_table_explore":true}',
+        sqlalchemy_uri: 'gsheets://',
       },
-    },
-    {
-      available_drivers: ['rest'],
-      engine: 'presto',
-      name: 'Presto',
-      preferred: true,
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: false,
+      json: 'foo',
+    });
+
+    fetchMock.get(DATABASE_FETCH_ENDPOINT, {
+      result: {
+        id: 10,
+        database_name: 'my database',
+        expose_in_sqllab: false,
+        allow_ctas: false,
+        allow_cvas: false,
+        configuration_method: 'sqlalchemy_form',
       },
-    },
-    {
-      available_drivers: ['mysqldb'],
-      default_driver: 'mysqldb',
-      engine: 'mysql',
-      name: 'MySQL',
-      parameters: {
-        properties: {
-          database: {
-            description: 'Database name',
-            type: 'string',
-          },
-          encryption: {
-            description: 'Use an encrypted connection to the database',
-            type: 'boolean',
-          },
-          host: {
-            description: 'Hostname or IP address',
-            type: 'string',
+    });
+    fetchMock.mock(AVAILABLE_DB_ENDPOINT, {
+      databases: [
+        {
+          available_drivers: ['psycopg2'],
+          default_driver: 'psycopg2',
+          engine: 'postgresql',
+          name: 'PostgreSQL',
+          parameters: {
+            properties: {
+              database: {
+                description: 'Database name',
+                type: 'string',
+              },
+              encryption: {
+                description: 'Use an encrypted connection to the database',
+                type: 'boolean',
+              },
+              host: {
+                description: 'Hostname or IP address',
+                type: 'string',
+              },
+              password: {
+                description: 'Password',
+                nullable: true,
+                type: 'string',
+              },
+              port: {
+                description: 'Database port',
+                format: 'int32',
+                maximum: 65536,
+                minimum: 0,
+                type: 'integer',
+              },
+              query: {
+                additionalProperties: {},
+                description: 'Additional parameters',
+                type: 'object',
+              },
+              ssh: {
+                description: 'Create SSH Tunnel',
+                type: 'boolean',
+              },
+              username: {
+                description: 'Username',
+                nullable: true,
+                type: 'string',
+              },
+            },
+            required: ['database', 'host', 'port', 'username'],
+            type: 'object',
           },
-          password: {
-            description: 'Password',
-            nullable: true,
-            type: 'string',
+          preferred: true,
+          sqlalchemy_uri_placeholder:
+            
'postgresql://user:password@host:port/dbname[?key=value&key=value...]',
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: false,
           },
-          port: {
-            description: 'Database port',
-            format: 'int32',
-            maximum: 65536,
-            minimum: 0,
-            type: 'integer',
+        },
+        {
+          available_drivers: ['rest'],
+          engine: 'presto',
+          name: 'Presto',
+          preferred: true,
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: false,
           },
-          query: {
-            additionalProperties: {},
-            description: 'Additional parameters',
+        },
+        {
+          available_drivers: ['mysqldb'],
+          default_driver: 'mysqldb',
+          engine: 'mysql',
+          name: 'MySQL',
+          parameters: {
+            properties: {
+              database: {
+                description: 'Database name',
+                type: 'string',
+              },
+              encryption: {
+                description: 'Use an encrypted connection to the database',
+                type: 'boolean',
+              },
+              host: {
+                description: 'Hostname or IP address',
+                type: 'string',
+              },
+              password: {
+                description: 'Password',
+                nullable: true,
+                type: 'string',
+              },
+              port: {
+                description: 'Database port',
+                format: 'int32',
+                maximum: 65536,
+                minimum: 0,
+                type: 'integer',
+              },
+              query: {
+                additionalProperties: {},
+                description: 'Additional parameters',
+                type: 'object',
+              },
+              username: {
+                description: 'Username',
+                nullable: true,
+                type: 'string',
+              },
+            },
+            required: ['database', 'host', 'port', 'username'],
             type: 'object',
           },
-          username: {
-            description: 'Username',
-            nullable: true,
-            type: 'string',
+          preferred: true,
+          sqlalchemy_uri_placeholder:
+            'mysql://user:password@host:port/dbname[?key=value&key=value...]',
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: false,
           },
         },
-        required: ['database', 'host', 'port', 'username'],
-        type: 'object',
-      },
-      preferred: true,
-      sqlalchemy_uri_placeholder:
-        'mysql://user:password@host:port/dbname[?key=value&key=value...]',
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: false,
-      },
-    },
-    {
-      available_drivers: ['pysqlite'],
-      engine: 'sqlite',
-      name: 'SQLite',
-      preferred: true,
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: false,
-      },
-    },
-    {
-      available_drivers: ['rest'],
-      engine: 'druid',
-      name: 'Apache Druid',
-      preferred: false,
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: false,
-      },
-    },
-    {
-      available_drivers: ['bigquery'],
-      default_driver: 'bigquery',
-      engine: 'bigquery',
-      name: 'Google BigQuery',
-      parameters: {
-        properties: {
-          credentials_info: {
-            description: 'Contents of BigQuery JSON credentials.',
-            type: 'string',
-            'x-encrypted-extra': true,
-          },
-          query: {
-            type: 'object',
+        {
+          available_drivers: ['pysqlite'],
+          engine: 'sqlite',
+          name: 'SQLite',
+          preferred: true,
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: false,
           },
         },
-        type: 'object',
-      },
-      preferred: false,
-      sqlalchemy_uri_placeholder: 'bigquery://{project_id}',
-      engine_information: {
-        supports_file_upload: true,
-        disable_ssh_tunneling: true,
-      },
-    },
-    {
-      available_drivers: ['rest'],
-      default_driver: 'apsw',
-      engine: 'gsheets',
-      name: 'Google Sheets',
-      preferred: false,
-      engine_information: {
-        supports_file_upload: false,
-        disable_ssh_tunneling: true,
-      },
-    },
-    {
-      available_drivers: ['connector'],
-      default_driver: 'connector',
-      engine: 'databricks',
-      name: 'Databricks',
-      parameters: {
-        properties: {
-          access_token: {
-            type: 'string',
+        {
+          available_drivers: ['rest'],
+          engine: 'druid',
+          name: 'Apache Druid',
+          preferred: false,
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: false,
           },
-          database: {
-            type: 'string',
+        },
+        {
+          available_drivers: ['bigquery'],
+          default_driver: 'bigquery',
+          engine: 'bigquery',
+          name: 'Google BigQuery',
+          parameters: {
+            properties: {
+              credentials_info: {
+                description: 'Contents of BigQuery JSON credentials.',
+                type: 'string',
+                'x-encrypted-extra': true,
+              },
+              query: {
+                type: 'object',
+              },
+            },
+            type: 'object',
           },
-          host: {
-            type: 'string',
+          preferred: false,
+          sqlalchemy_uri_placeholder: 'bigquery://{project_id}',
+          engine_information: {
+            supports_file_upload: true,
+            disable_ssh_tunneling: true,
           },
-          http_path: {
-            type: 'string',
+        },
+        {
+          available_drivers: ['rest'],
+          default_driver: 'apsw',
+          engine: 'gsheets',
+          name: 'Google Sheets',
+          preferred: false,
+          engine_information: {
+            supports_file_upload: false,
+            disable_ssh_tunneling: true,
           },
-          port: {
-            format: 'int32',
-            type: 'integer',
+        },
+        {
+          available_drivers: ['connector'],
+          default_driver: 'connector',
+          engine: 'databricks',
+          name: 'Databricks',
+          parameters: {
+            properties: {
+              access_token: {
+                type: 'string',
+              },
+              database: {
+                type: 'string',
+              },
+              host: {
+                type: 'string',
+              },
+              http_path: {
+                type: 'string',
+              },
+              port: {
+                format: 'int32',
+                type: 'integer',
+              },
+            },
+            required: ['access_token', 'database', 'host', 'http_path', 
'port'],
+            type: 'object',
           },
+          preferred: true,
+          sqlalchemy_uri_placeholder:
+            
'databricks+connector://token:{access_token}@{host}:{port}/{database_name}',
         },
-        required: ['access_token', 'database', 'host', 'http_path', 'port'],
-        type: 'object',
-      },
-      preferred: true,
-      sqlalchemy_uri_placeholder:
-        
'databricks+connector://token:{access_token}@{host}:{port}/{database_name}',
-    },
-  ],
-});
-fetchMock.post(VALIDATE_PARAMS_ENDPOINT, {
-  message: 'OK',
-});
-
-const databaseFixture: DatabaseObject = {
-  id: 123,
-  backend: 'postgres',
-  configuration_method: ConfigurationMethod.DynamicForm,
-  database_name: 'Postgres',
-  name: 'PostgresDB',
-  is_managed_externally: false,
-  driver: 'psycopg2',
-};
-
-describe('DatabaseModal', () => {
-  const renderAndWait = async () =>
-    waitFor(() =>
-      render(<DatabaseModal {...dbProps} />, {
-        useRedux: true,
-      }),
-    );
+      ],
+    });
+    fetchMock.post(VALIDATE_PARAMS_ENDPOINT, {
+      message: 'OK',
+    });
+  });
 
-  beforeEach(async () => {
-    await renderAndWait();
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+  afterEach(() => {
+    fetchMock.restore();
   });
 
-  afterEach(cleanup);
+  const setup = (propsOverwrite: Partial<DatabaseModalProps> = {}) =>
+    render(<DatabaseModal {...dbProps} {...propsOverwrite} />, {
+      useRedux: true,
+    });
 
   describe('Visual: New database connection', () => {
-    test('renders the initial load of Step 1 correctly', () => {
+    test('renders the initial load of Step 1 correctly', async () => {
+      setup();
+
       // ---------- Components ----------
       // <TabHeader> - AntD header
-      const closeButton = screen.getByLabelText('Close');
+      const closeButton = await screen.findByLabelText('Close');
       const step1Header = screen.getByRole('heading', {
         name: /connect a database/i,
       });
       // <ModalHeader> - Connection header
-      const step1Helper = screen.getByText(/step 1 of 3/i);
+      const step1Helper = await screen.findByText(/step 1 of 3/i);
       const selectDbHeader = screen.getByRole('heading', {
         name: /select a database to connect/i,
       });
@@ -376,7 +372,8 @@ describe('DatabaseModal', () => {
         hidden: true,
       });
 
-      const footer = document.getElementsByClassName('ant-modal-footer');
+      const modal = screen.getByRole('dialog');
+      const footer = modal.querySelector('.ant-modal-footer');
       // ---------- TODO (lyndsiWilliams): Selector options, can't seem to get 
these to render properly.
 
       // renderAvailableSelector() => <Alert> - Supported databases alert
@@ -415,13 +412,15 @@ describe('DatabaseModal', () => {
         expect(component).toBeInTheDocument();
       });
       // there should be a footer but it should not have any buttons in it
-      expect(footer[0]).toBeEmptyDOMElement();
+      expect(footer).toBeEmptyDOMElement();
     });
 
     test('renders the "Basic" tab of SQL Alchemy form (step 2 of 2) 
correctly', async () => {
+      setup();
+
       // On step 1, click dbButton to access SQL Alchemy form
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -429,7 +428,7 @@ describe('DatabaseModal', () => {
 
       // ---------- Components ----------
       // <TabHeader> - AntD header
-      const closeButton = screen.getByRole('button', { name: 'Close' });
+      const closeButton = await screen.findByRole('button', { name: 'Close' });
 
       const basicHeader = screen.getByRole('heading', {
         name: /connect a database/i,
@@ -462,7 +461,7 @@ describe('DatabaseModal', () => {
       // <SSHTunnelForm> - Basic tab's SSH Tunnel Form
       const SSHTunnelingToggle = screen.getByTestId('ssh-tunnel-switch');
       userEvent.click(SSHTunnelingToggle);
-      const SSHTunnelServerAddressInput = screen.getByTestId(
+      const SSHTunnelServerAddressInput = await screen.findByTestId(
         'ssh-tunnel-server_address-input',
       );
       const SSHTunnelServerPortInput = screen.getByTestId(
@@ -527,9 +526,11 @@ describe('DatabaseModal', () => {
     });
 
     test('renders the unexpanded "Advanced" tab correctly', async () => {
+      setup();
+
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -626,18 +627,20 @@ describe('DatabaseModal', () => {
     });
 
     test('renders the "Advanced" - SQL LAB tab correctly (unexpanded)', async 
() => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
       // Click the "Advanced" tab
-      userEvent.click(screen.getByRole('tab', { name: /advanced/i }));
+      userEvent.click(await screen.findByRole('tab', { name: /advanced/i }));
       // Click the "SQL Lab" tab
       userEvent.click(
-        screen.getByRole('tab', {
+        await screen.findByRole('tab', {
           name: /right sql lab adjust how this database will interact with sql 
lab\./i,
         }),
       );
@@ -645,7 +648,7 @@ describe('DatabaseModal', () => {
 
       // ----- BEGIN STEP 2 (ADVANCED - SQL LAB)
       // <TabHeader> - AntD header
-      const closeButton = screen.getByRole('button', { name: /close/i });
+      const closeButton = await screen.findByRole('button', { name: /close/i 
});
       const advancedHeader = screen.getByRole('heading', {
         name: /connect a database/i,
       });
@@ -788,10 +791,12 @@ describe('DatabaseModal', () => {
     });
 
     test('renders the "Advanced" - PERFORMANCE tab correctly', async () => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -851,10 +856,12 @@ describe('DatabaseModal', () => {
     });
 
     test('renders the "Advanced" - SECURITY tab correctly', async () => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -935,10 +942,12 @@ describe('DatabaseModal', () => {
     });
 
     it('renders the "Advanced" - SECURITY tab correctly after selecting Allow 
file uploads', async () => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -1021,10 +1030,12 @@ describe('DatabaseModal', () => {
     });
 
     test('renders the "Advanced" - OTHER tab correctly', async () => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /sqlite/i,
         }),
       );
@@ -1040,7 +1051,7 @@ describe('DatabaseModal', () => {
 
       // ----- BEGIN STEP 2 (ADVANCED - OTHER)
       // <TabHeader> - AntD header
-      const closeButton = screen.getByRole('button', { name: /close/i });
+      const closeButton = await screen.findByRole('button', { name: /close/i 
});
       const advancedHeader = screen.getByRole('heading', {
         name: /connect a database/i,
       });
@@ -1092,10 +1103,12 @@ describe('DatabaseModal', () => {
     });
 
     test('Dynamic form', async () => {
+      setup();
+
       // ---------- Components ----------
       // On step 1, click dbButton to access step 2
       userEvent.click(
-        screen.getByRole('button', {
+        await screen.findByRole('button', {
           name: /postgresql/i,
         }),
       );
@@ -1107,9 +1120,11 @@ describe('DatabaseModal', () => {
 
   describe('Functional: Create new database', () => {
     test('directs databases to the appropriate form (dynamic vs. SQL 
Alchemy)', async () => {
+      setup();
+
       // ---------- Dynamic example (3-step form)
       // Click the PostgreSQL button to enter the dynamic form
-      const postgreSQLButton = screen.getByRole('button', {
+      const postgreSQLButton = await screen.findByRole('button', {
         name: /postgresql/i,
       });
       userEvent.click(postgreSQLButton);
@@ -1139,8 +1154,10 @@ describe('DatabaseModal', () => {
 
     describe('SQL Alchemy form flow', () => {
       test('enters step 2 of 2 when proper database is selected', async () => {
+        setup();
+
         userEvent.click(
-          screen.getByRole('button', {
+          await screen.findByRole('button', {
             name: /sqlite/i,
           }),
         );
@@ -1167,8 +1184,10 @@ describe('DatabaseModal', () => {
 
       describe('step 2 component interaction', () => {
         test('properly interacts with textboxes', async () => {
+          setup();
+
           userEvent.click(
-            screen.getByRole('button', {
+            await screen.findByRole('button', {
               name: /sqlite/i,
             }),
           );
@@ -1211,15 +1230,17 @@ describe('DatabaseModal', () => {
 
       describe('SSH Tunnel Form interaction', () => {
         test('properly interacts with SSH Tunnel form textboxes for dynamic 
form', async () => {
+          setup();
+
           userEvent.click(
-            screen.getByRole('button', {
+            await screen.findByRole('button', {
               name: /postgresql/i,
             }),
           );
           expect(await screen.findByText(/step 2 of 3/i)).toBeInTheDocument();
           const SSHTunnelingToggle = screen.getByTestId('ssh-tunnel-switch');
           userEvent.click(SSHTunnelingToggle);
-          const SSHTunnelServerAddressInput = screen.getByTestId(
+          const SSHTunnelServerAddressInput = await screen.findByTestId(
             'ssh-tunnel-server_address-input',
           );
           expect(SSHTunnelServerAddressInput).toHaveValue('');
@@ -1246,8 +1267,10 @@ describe('DatabaseModal', () => {
         });
 
         test('properly interacts with SSH Tunnel form textboxes', async () => {
+          setup();
+
           userEvent.click(
-            screen.getByRole('button', {
+            await screen.findByRole('button', {
               name: /sqlite/i,
             }),
           );
@@ -1255,7 +1278,7 @@ describe('DatabaseModal', () => {
           expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
           const SSHTunnelingToggle = screen.getByTestId('ssh-tunnel-switch');
           userEvent.click(SSHTunnelingToggle);
-          const SSHTunnelServerAddressInput = screen.getByTestId(
+          const SSHTunnelServerAddressInput = await screen.findByTestId(
             'ssh-tunnel-server_address-input',
           );
           expect(SSHTunnelServerAddressInput).toHaveValue('');
@@ -1282,8 +1305,10 @@ describe('DatabaseModal', () => {
         });
 
         test('if the SSH Tunneling toggle is not true, no inputs are 
displayed', async () => {
+          setup();
+
           userEvent.click(
-            screen.getByRole('button', {
+            await screen.findByRole('button', {
               name: /sqlite/i,
             }),
           );
@@ -1310,8 +1335,10 @@ describe('DatabaseModal', () => {
         });
 
         test('If user changes the login method, the inputs change', async () 
=> {
+          setup();
+
           userEvent.click(
-            screen.getByRole('button', {
+            await screen.findByRole('button', {
               name: /sqlite/i,
             }),
           );
@@ -1319,7 +1346,7 @@ describe('DatabaseModal', () => {
           expect(await screen.findByText(/step 2 of 2/i)).toBeInTheDocument();
           const SSHTunnelingToggle = screen.getByTestId('ssh-tunnel-switch');
           userEvent.click(SSHTunnelingToggle);
-          const SSHTunnelUsePasswordInput = screen.getByTestId(
+          const SSHTunnelUsePasswordInput = await screen.findByTestId(
             'ssh-tunnel-use_password-radio',
           );
           expect(SSHTunnelUsePasswordInput).toBeInTheDocument();
@@ -1348,6 +1375,8 @@ describe('DatabaseModal', () => {
 
     describe('Dynamic form flow', () => {
       test('enters step 2 of 3 when proper database is selected', async () => {
+        setup();
+
         expect(await screen.findByText(/step 1 of 3/i)).toBeInTheDocument();
         userEvent.click(
           screen.getByRole('button', {
@@ -1355,14 +1384,13 @@ describe('DatabaseModal', () => {
           }),
         );
         expect(await screen.findByText(/step 2 of 3/i)).toBeInTheDocument();
-
-        const step2of3text = screen.getByText(/step 2 of 3/i);
-        expect(step2of3text).toBeVisible();
       });
 
       test('enters form credentials and runs fetchResource when "Connect" is 
clicked', async () => {
+        setup();
+
         userEvent.click(
-          screen.getByRole('button', {
+          await screen.findByRole('button', {
             name: /postgresql/i,
           }),
         );
@@ -1403,9 +1431,11 @@ describe('DatabaseModal', () => {
 
     describe('Import database flow', () => {
       test('imports a file', async () => {
-        const importDbButton = screen.getByTestId(
+        setup();
+
+        const importDbButton = (await screen.findByTestId(
           'import-database-btn',
-        ) as HTMLInputElement;
+        )) as HTMLInputElement;
         importDbButton.type = 'file';
         importDbButton.files = {} as FileList;
         expect(importDbButton).toBeInTheDocument();
@@ -1423,54 +1453,25 @@ describe('DatabaseModal', () => {
   });
 
   describe('DatabaseModal w/ Deeplinking Engine', () => {
-    const renderAndWait = async () => {
-      const mounted = act(async () => {
-        render(<DatabaseModal {...dbProps} dbEngine="PostgreSQL" />, {
-          useRedux: true,
-        });
-      });
-
-      return mounted;
-    };
-
-    beforeEach(async () => {
-      await renderAndWait();
-    });
-
-    test('enters step 2 of 3 when proper database is selected', () => {
-      const step2of3text = screen.getByText(/step 2 of 3/i);
+    test('enters step 2 of 3 when proper database is selected', async () => {
+      setup({ dbEngine: 'PostgreSQL' });
+      const step2of3text = await screen.findByText(/step 2 of 3/i);
       expect(step2of3text).toBeInTheDocument();
     });
   });
 
   describe('DatabaseModal w/ GSheet Engine', () => {
-    const renderAndWait = async () => {
-      const dbProps = {
-        show: true,
-        database_name: 'my database',
-        sqlalchemy_uri: 'gsheets://',
-      };
-      const mounted = act(async () => {
-        render(<DatabaseModal {...dbProps} dbEngine="Google Sheets" />, {
-          useRedux: true,
-        });
-      });
-
-      return mounted;
-    };
-
-    beforeEach(async () => {
-      await renderAndWait();
-    });
-
-    it('enters step 2 of 2 when proper database is selected', () => {
-      const step2of2text = screen.getByText(/step 2 of 2/i);
+    it('enters step 2 of 2 when proper database is selected', async () => {
+      setup({ dbEngine: 'Google Sheets' });
+      const step2of2text = await screen.findByText(/step 2 of 2/i);
       expect(step2of2text).toBeInTheDocument();
     });
 
     it('renders the "Advanced" - SECURITY tab without Allow File Upload 
Checkbox', async () => {
+      setup({ dbEngine: 'Google Sheets' });
+
       // Click the "Advanced" tab
-      userEvent.click(screen.getByRole('tab', { name: /advanced/i }));
+      userEvent.click(await screen.findByRole('tab', { name: /advanced/i }));
       // Click the "Security" tab
       userEvent.click(
         screen.getByRole('tab', {
@@ -1509,6 +1510,8 @@ describe('DatabaseModal', () => {
     });
 
     it('if the SSH Tunneling toggle is not displayed, nothing should get 
displayed', async () => {
+      setup({ dbEngine: 'Google Sheets' });
+
       const SSHTunnelingToggle = screen.queryByTestId('ssh-tunnel-switch');
       expect(SSHTunnelingToggle).not.toBeInTheDocument();
       const SSHTunnelServerAddressInput = screen.queryByTestId(
@@ -1536,22 +1539,9 @@ describe('DatabaseModal', () => {
       useSingleViewResource: jest.fn(),
     }));
 
-    const renderAndWait = async () => {
-      const mounted = act(async () => {
-        render(<DatabaseModal {...dbProps} dbEngine="PostgreSQL" />, {
-          useRedux: true,
-        });
-      });
-
-      return mounted;
-    };
-
-    beforeEach(async () => {
-      await renderAndWait();
-    });
-
     test('Error displays when it is an object', async () => {
-      const step2of3text = screen.getByText(/step 2 of 3/i);
+      setup({ dbEngine: 'PostgreSQL' });
+      const step2of3text = await screen.findByText(/step 2 of 3/i);
       const errorSection = screen.getByText(/Database Creation Error/i);
       expect(step2of3text).toBeInTheDocument();
       expect(errorSection).toBeInTheDocument();
@@ -1581,22 +1571,10 @@ describe('DatabaseModal', () => {
       setResource: jest.fn(),
     });
 
-    const renderAndWait = async () => {
-      const mounted = act(async () => {
-        render(<DatabaseModal {...dbProps} dbEngine="PostgreSQL" />, {
-          useRedux: true,
-        });
-      });
-
-      return mounted;
-    };
-
-    beforeEach(async () => {
-      await renderAndWait();
-    });
-
     test('Error displays when it is a string', async () => {
-      const step2of3text = screen.getByText(/step 2 of 3/i);
+      setup({ dbEngine: 'PostgreSQL' });
+
+      const step2of3text = await screen.findByText(/step 2 of 3/i);
       const errorTitleMessage = screen.getByText(/Database Creation Error/i);
       const button = screen.getByText('See more');
       userEvent.click(button);
@@ -1608,7 +1586,7 @@ describe('DatabaseModal', () => {
   });
 
   describe('DatabaseModal w Extensions', () => {
-    const renderAndWait = async () => {
+    beforeAll(() => {
       const extensionsRegistry = getExtensionsRegistry();
 
       extensionsRegistry.set('ssh_tunnel.form.switch', () => (
@@ -1616,23 +1594,12 @@ describe('DatabaseModal', () => {
       ));
 
       setupExtensions();
-
-      const mounted = act(async () => {
-        render(<DatabaseModal {...dbProps} dbEngine="SQLite" />, {
-          useRedux: true,
-        });
-      });
-
-      return mounted;
-    };
-
-    beforeEach(async () => {
-      await renderAndWait();
     });
 
-    test('should render an extension component if one is supplied', () => {
+    test('should render an extension component if one is supplied', async () 
=> {
+      setup({ dbEngine: 'SQLite' });
       expect(
-        screen.getByText('ssh_tunnel.form.switch extension component'),
+        await screen.findByText('ssh_tunnel.form.switch extension component'),
       ).toBeInTheDocument();
     });
   });

Reply via email to