From b5a72e21f73808bcca94341f5a904753a589e67b Mon Sep 17 00:00:00 2001
From: Ross Mabbett <92495987+rtexelm@users.noreply.github.com>
Date: Tue, 25 Jun 2024 17:58:26 -0400
Subject: [PATCH] refactor(Homepage): Migrate Home.test to RTL (#29353)
---
.../src/pages/Home/Home.test.tsx | 213 +++++++-----------
1 file changed, 85 insertions(+), 128 deletions(-)
diff --git a/superset-frontend/src/pages/Home/Home.test.tsx b/superset-frontend/src/pages/Home/Home.test.tsx
index 6a63483be55b8..6be4dc186ed79 100644
--- a/superset-frontend/src/pages/Home/Home.test.tsx
+++ b/superset-frontend/src/pages/Home/Home.test.tsx
@@ -16,23 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { styledMount as mount } from 'spec/helpers/theming';
-import { Provider } from 'react-redux';
-import thunk from 'redux-thunk';
import fetchMock from 'fetch-mock';
-import { act } from 'react-dom/test-utils';
-import configureStore from 'redux-mock-store';
import * as uiCore from '@superset-ui/core';
+import { render, screen, waitFor } from 'spec/helpers/testing-library';
+import userEvent from '@testing-library/user-event';
import Welcome from 'src/pages/Home';
-import { ReactWrapper } from 'enzyme';
-import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
-import { render, screen } from 'spec/helpers/testing-library';
import { getExtensionsRegistry } from '@superset-ui/core';
import setupExtensions from 'src/setup/setupExtensions';
-const mockStore = configureStore([thunk]);
-const store = mockStore({});
-
const chartsEndpoint = 'glob:*/api/v1/chart/?*';
const chartInfoEndpoint = 'glob:*/api/v1/chart/_info?*';
const chartFavoriteStatusEndpoint = 'glob:*/api/v1/chart/favorite_status?*';
@@ -113,130 +104,104 @@ const mockedProps = {
},
};
-describe('Welcome with sql role', () => {
- let wrapper: ReactWrapper;
+const mockedPropsWithoutSqlRole = {
+ ...{
+ ...mockedProps,
+ user: {
+ ...mockedProps.user,
+ roles: {},
+ },
+ },
+};
- beforeAll(async () => {
- await act(async () => {
- wrapper = mount(
-
-
- ,
- );
- });
- });
+const setupFeatureToggleMock = () =>
+ jest.spyOn(uiCore, 'isFeatureEnabled').mockReturnValue(true);
- afterAll(() => {
- fetchMock.resetHistory();
+const renderWelcome = (props = mockedProps) =>
+ waitFor(() => {
+ render(, {
+ useRedux: true,
+ useRouter: true,
+ });
});
- it('renders', () => {
- expect(wrapper).toExist();
- });
+afterEach(() => {
+ fetchMock.resetHistory();
+});
- it('renders all panels on the page on page load', () => {
- expect(wrapper.find('CollapsePanel')).toHaveLength(8);
- });
+test('With sql role - renders', async () => {
+ await renderWelcome();
+ expect(await screen.findByText('Dashboards')).toBeInTheDocument();
+});
- it('calls api methods in parallel on page load', () => {
- const chartCall = fetchMock.calls(/chart\/\?q/);
- const savedQueryCall = fetchMock.calls(/saved_query\/\?q/);
- const recentCall = fetchMock.calls(/api\/v1\/log\/recent_activity\/*/);
- const dashboardCall = fetchMock.calls(/dashboard\/\?q/);
- expect(chartCall).toHaveLength(2);
- expect(recentCall).toHaveLength(1);
- expect(savedQueryCall).toHaveLength(1);
- expect(dashboardCall).toHaveLength(2);
- });
+test('With sql role - renders all panels on the page on page load', async () => {
+ await renderWelcome();
+ const panels = await screen.findAllByText(
+ /Dashboards|Charts|Recents|Saved queries/,
+ );
+ expect(panels).toHaveLength(4);
});
-describe('Welcome without sql role', () => {
- let wrapper: ReactWrapper;
-
- beforeAll(async () => {
- await act(async () => {
- const props = {
- ...mockedProps,
- user: {
- ...mockedProps.user,
- roles: {},
- },
- };
- wrapper = mount(
-
-
- ,
- );
- });
- });
+test('With sql role - calls api methods in parallel on page load', async () => {
+ await renderWelcome();
+ expect(fetchMock.calls(chartsEndpoint)).toHaveLength(2);
+ expect(fetchMock.calls(recentActivityEndpoint)).toHaveLength(1);
+ expect(fetchMock.calls(savedQueryEndpoint)).toHaveLength(1);
+ expect(fetchMock.calls(dashboardsEndpoint)).toHaveLength(2);
+});
- afterAll(() => {
- fetchMock.resetHistory();
- fetchMock.restore();
- });
+test('Without sql role - renders', async () => {
+ /*
+ We ignore the ts error here because the type does not recognize the absence of a role entry
+ */
+ // @ts-ignore-next-line
+ await renderWelcome(mockedPropsWithoutSqlRole);
+ expect(await screen.findByText('Dashboards')).toBeInTheDocument();
+});
- it('renders', () => {
- expect(wrapper).toExist();
- });
+test('Without sql role - renders all panels on the page on page load', async () => {
+ // @ts-ignore-next-line
+ await renderWelcome(mockedPropsWithoutSqlRole);
+ const panels = await screen.findAllByText(/Dashboards|Charts|Recents/);
+ expect(panels).toHaveLength(3);
+});
- it('renders all panels on the page on page load', () => {
- expect(wrapper.find('CollapsePanel')).toHaveLength(6);
- });
+test('Without sql role - calls api methods in parallel on page load', async () => {
+ // @ts-ignore-next-line
+ await renderWelcome(mockedPropsWithoutSqlRole);
+ expect(fetchMock.calls(chartsEndpoint)).toHaveLength(2);
+ expect(fetchMock.calls(recentActivityEndpoint)).toHaveLength(1);
+ expect(fetchMock.calls(savedQueryEndpoint)).toHaveLength(0);
+ expect(fetchMock.calls(dashboardsEndpoint)).toHaveLength(2);
+});
- it('calls api methods in parallel on page load', () => {
- const chartCall = fetchMock.calls(/chart\/\?q/);
- const savedQueryCall = fetchMock.calls(/saved_query\/\?q/);
- const recentCall = fetchMock.calls(/api\/v1\/log\/recent_activity\/*/);
- const dashboardCall = fetchMock.calls(/dashboard\/\?q/);
- expect(chartCall).toHaveLength(2);
- expect(recentCall).toHaveLength(1);
- expect(savedQueryCall).toHaveLength(0);
- expect(dashboardCall).toHaveLength(2);
- });
+// Mock specific to the tests related to the toggle switch
+fetchMock.get('glob:*/api/v1/dashboard/*', {
+ result: {
+ dashboard_title: 'Dashboard 4',
+ changed_on_utc: '24 Feb 2014 10:13:14',
+ url: '/fakeUrl/dashboard/4',
+ id: '4',
+ },
});
-async function mountAndWait(props = mockedProps) {
- const wrapper = mount(
-
-
- ,
- );
- await waitForComponentToPaint(wrapper);
- return wrapper;
-}
-
-describe('Welcome page with toggle switch', () => {
- let wrapper: ReactWrapper;
- let isFeatureEnabledMock: any;
-
- beforeAll(async () => {
- isFeatureEnabledMock = jest
- .spyOn(uiCore, 'isFeatureEnabled')
- .mockReturnValue(true);
- await act(async () => {
- wrapper = await mountAndWait();
- });
- });
+test('With toggle switch - shows a toggle button when feature flag is turned on', async () => {
+ setupFeatureToggleMock();
- afterAll(() => {
- isFeatureEnabledMock.mockRestore();
- });
+ await renderWelcome();
+ expect(screen.getByRole('switch')).toBeInTheDocument();
+});
- it('shows a toggle button when feature flags is turned on', async () => {
- await waitForComponentToPaint(wrapper);
- expect(wrapper.find('Switch')).toExist();
- });
- it('does not show thumbnails when switch is off', async () => {
- act(() => {
- // @ts-ignore
- wrapper.find('button[role="switch"]').props().onClick();
- });
- await waitForComponentToPaint(wrapper);
- expect(wrapper.find('ImageLoader')).not.toExist();
- });
+test('With toggle switch - does not show thumbnails when switch is off', async () => {
+ setupFeatureToggleMock();
+
+ await renderWelcome();
+ const toggle = await screen.findByRole('switch');
+ userEvent.click(toggle);
+ expect(screen.queryByAltText('Thumbnails')).not.toBeInTheDocument();
});
-test('should render an extension component if one is supplied', () => {
+test('Should render an extension component if one is supplied', async () => {
const extensionsRegistry = getExtensionsRegistry();
extensionsRegistry.set('welcome.banner', () => (
@@ -245,29 +210,21 @@ test('should render an extension component if one is supplied', () => {
setupExtensions();
- render(
-
-
- ,
- );
+ await renderWelcome();
expect(
screen.getByText('welcome.banner extension component'),
).toBeInTheDocument();
});
-test('should render a submenu extension component if one is supplied', () => {
+test('Should render a submenu extension component if one is supplied', async () => {
const extensionsRegistry = getExtensionsRegistry();
extensionsRegistry.set('home.submenu', () => <>submenu extension>);
setupExtensions();
- render(
-
-
- ,
- );
+ await renderWelcome();
expect(screen.getByText('submenu extension')).toBeInTheDocument();
});