Browse Source

test(ui): Remove act use from dashboards (#47166)

Instead of wrapping render with act or tick, use `waitFor` or `findBy`
to wait for the component to finish rendering.
Scott Cooper 1 year ago
parent
commit
a28821620b

+ 19 - 27
static/app/views/dashboards/dashboard.spec.tsx

@@ -1,5 +1,5 @@
 import {initializeOrg} from 'sentry-test/initializeOrg';
-import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
+import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
 
 import MemberListStore from 'sentry/stores/memberListStore';
 import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
@@ -253,11 +253,9 @@ describe('Dashboards > Dashboard', () => {
         ...mockDashboard,
         widgets: [newWidget, issueWidget],
       };
-      await act(async () => {
-        mount(mockDashboardWithIssueWidget, organization);
-        await tick();
-      });
-      expect(screen.getByText('Test Discover Widget')).toBeInTheDocument();
+
+      mount(mockDashboardWithIssueWidget, organization);
+      expect(await screen.findByText('Test Discover Widget')).toBeInTheDocument();
       expect(screen.getByText('Test Issue Widget')).toBeInTheDocument();
     });
 
@@ -312,24 +310,21 @@ describe('Dashboards > Dashboard', () => {
 
     it('displays the copy widget button in edit mode', async () => {
       const dashboardWithOneWidget = {...mockDashboard, widgets};
-      await act(async () => {
-        mount(dashboardWithOneWidget);
-        await tick();
-      });
 
-      expect(screen.getByLabelText('Duplicate Widget')).toBeInTheDocument();
+      mount(dashboardWithOneWidget);
+      expect(await screen.findByLabelText('Duplicate Widget')).toBeInTheDocument();
     });
 
     it('duplicates the widget', async () => {
       const dashboardWithOneWidget = {...mockDashboard, widgets};
-      await act(async () => {
-        const {rerender} = mount(dashboardWithOneWidget);
+      const {rerender} = mount(dashboardWithOneWidget);
 
-        await userEvent.click(screen.getByLabelText('Duplicate Widget'));
-        rerender();
-        await tick();
+      await userEvent.click(await screen.findByLabelText('Duplicate Widget'));
+      rerender();
+
+      await waitFor(() => {
+        expect(screen.getAllByText('Test Discover Widget')).toHaveLength(2);
       });
-      expect(screen.getAllByText('Test Discover Widget')).toHaveLength(2);
     });
 
     it('opens the widget builder when editing with the modal access flag', async function () {
@@ -344,17 +339,14 @@ describe('Dashboards > Dashboard', () => {
         widgets: [newWidget],
       };
 
-      await act(async () => {
-        mount(
-          dashboardWithOneWidget,
-          testData.organization,
-          testData.router,
-          testData.router.location
-        );
-        await tick();
+      mount(
+        dashboardWithOneWidget,
+        testData.organization,
+        testData.router,
+        testData.router.location
+      );
 
-        await userEvent.click(screen.getByLabelText('Edit Widget'));
-      });
+      await userEvent.click(await screen.findByLabelText('Edit Widget'));
 
       expect(testData.router.push).toHaveBeenCalledWith(
         expect.objectContaining({

+ 65 - 80
static/app/views/dashboards/detail.spec.jsx

@@ -560,21 +560,19 @@ describe('Dashboards > Detail', function () {
           {id: '1', title: 'Custom Errors'}
         ),
       });
-      await act(async () => {
-        render(
-          <ViewEditDashboard
-            organization={initialData.organization}
-            params={{orgId: 'org-slug', dashboardId: '1'}}
-            router={initialData.router}
-            location={initialData.router.location}
-          />,
-          {context: initialData.routerContext, organization: initialData.organization}
-        );
-        await tick();
-      });
 
-      await screen.findByText('First Widget');
-      await screen.findByText('Second Widget');
+      render(
+        <ViewEditDashboard
+          organization={initialData.organization}
+          params={{orgId: 'org-slug', dashboardId: '1'}}
+          router={initialData.router}
+          location={initialData.router.location}
+        />,
+        {context: initialData.routerContext, organization: initialData.organization}
+      );
+
+      expect(await screen.findByText('First Widget')).toBeInTheDocument();
+      expect(await screen.findByText('Second Widget')).toBeInTheDocument();
     });
 
     it('does not trigger request if layout not updated', async () => {
@@ -603,22 +601,19 @@ describe('Dashboards > Detail', function () {
           {id: '1', title: 'Custom Errors'}
         ),
       });
-      await act(async () => {
-        render(
-          <ViewEditDashboard
-            organization={initialData.organization}
-            params={{orgId: 'org-slug', dashboardId: '1'}}
-            router={initialData.router}
-            location={initialData.router.location}
-          />,
-          {context: initialData.routerContext, organization: initialData.organization}
-        );
-        await tick();
 
-        await userEvent.click(screen.getByText('Edit Dashboard'));
-        await userEvent.click(screen.getByText('Save and Finish'));
-        await tick();
-      });
+      render(
+        <ViewEditDashboard
+          organization={initialData.organization}
+          params={{orgId: 'org-slug', dashboardId: '1'}}
+          router={initialData.router}
+          location={initialData.router.location}
+        />,
+        {context: initialData.routerContext, organization: initialData.organization}
+      );
+
+      await userEvent.click(await screen.findByText('Edit Dashboard'));
+      await userEvent.click(await screen.findByText('Save and Finish'));
 
       expect(screen.getByText('Edit Dashboard')).toBeInTheDocument();
       expect(mockPut).not.toHaveBeenCalled();
@@ -651,18 +646,15 @@ describe('Dashboards > Detail', function () {
         ),
       });
 
-      await act(async () => {
-        render(
-          <ViewEditDashboard
-            organization={initialData.organization}
-            params={{orgId: 'org-slug', dashboardId: '1'}}
-            router={initialData.router}
-            location={initialData.router.location}
-          />,
-          {context: initialData.routerContext, organization: initialData.organization}
-        );
-        await tick();
-      });
+      render(
+        <ViewEditDashboard
+          organization={initialData.organization}
+          params={{orgId: 'org-slug', dashboardId: '1'}}
+          router={initialData.router}
+          location={initialData.router.location}
+        />,
+        {context: initialData.routerContext, organization: initialData.organization}
+      );
 
       await userEvent.click(await screen.findByText('Edit Dashboard'));
       const widget = screen.getByText('First Widget').closest('.react-grid-item');
@@ -697,23 +689,19 @@ describe('Dashboards > Detail', function () {
           {id: '1', title: 'Custom Errors'}
         ),
       });
-      await act(async () => {
-        render(
-          <ViewEditDashboard
-            organization={initialData.organization}
-            params={{orgId: 'org-slug', dashboardId: '1'}}
-            router={initialData.router}
-            location={initialData.router.location}
-          />,
-          {context: initialData.routerContext, organization: initialData.organization}
-        );
-        await tick();
-      });
 
-      await act(async () => {
-        await userEvent.click(await screen.findByText('Edit Dashboard'));
-        await userEvent.click(await screen.findByText('Cancel'));
-      });
+      render(
+        <ViewEditDashboard
+          organization={initialData.organization}
+          params={{orgId: 'org-slug', dashboardId: '1'}}
+          router={initialData.router}
+          location={initialData.router.location}
+        />,
+        {context: initialData.routerContext, organization: initialData.organization}
+      );
+
+      await userEvent.click(await screen.findByText('Edit Dashboard'));
+      await userEvent.click(await screen.findByText('Cancel'));
 
       expect(window.confirm).not.toHaveBeenCalled();
     });
@@ -743,26 +731,25 @@ describe('Dashboards > Detail', function () {
         body: TestStubs.Dashboard([widget], {id: '1', title: 'Custom Errors'}),
       });
 
-      await act(async () => {
-        render(
-          <ViewEditDashboard
-            organization={initialData.organization}
-            params={{orgId: 'org-slug', dashboardId: '1', widgetId: '1'}}
-            router={initialData.router}
-            location={{...initialData.router.location, pathname: '/widget/123/'}}
-          />,
-          {context: initialData.routerContext, organization: initialData.organization}
+      render(
+        <ViewEditDashboard
+          organization={initialData.organization}
+          params={{orgId: 'org-slug', dashboardId: '1', widgetId: '1'}}
+          router={initialData.router}
+          location={{...initialData.router.location, pathname: '/widget/123/'}}
+        />,
+        {context: initialData.routerContext, organization: initialData.organization}
+      );
+
+      await waitFor(() => {
+        expect(openWidgetViewerModal).toHaveBeenCalledWith(
+          expect.objectContaining({
+            organization: initialData.organization,
+            widget,
+            onClose: expect.anything(),
+          })
         );
-        await tick();
       });
-
-      expect(openWidgetViewerModal).toHaveBeenCalledWith(
-        expect.objectContaining({
-          organization: initialData.organization,
-          widget,
-          onClose: expect.anything(),
-        })
-      );
     });
 
     it('redirects user to dashboard url if widget is not found', async () => {
@@ -781,7 +768,7 @@ describe('Dashboards > Detail', function () {
         {context: initialData.routerContext, organization: initialData.organization}
       );
 
-      await screen.findByText('All Releases');
+      expect(await screen.findByText('All Releases')).toBeInTheDocument();
 
       expect(openWidgetViewerModal).not.toHaveBeenCalled();
       expect(initialData.router.replace).toHaveBeenCalledWith(
@@ -1410,12 +1397,10 @@ describe('Dashboards > Detail', function () {
 
       await userEvent.click(await screen.findByText('All Releases'));
       await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 's');
-      await act(async () => {
-        await userEvent.click(await screen.findByRole('option', {name: 'search-result'}));
-      });
+      await userEvent.click(await screen.findByRole('option', {name: 'search-result'}));
 
       // Validate that after search is cleared, search result still appears
-      expect(screen.getByText('Latest Release(s)')).toBeInTheDocument();
+      expect(await screen.findByText('Latest Release(s)')).toBeInTheDocument();
       expect(screen.getByRole('option', {name: 'search-result'})).toBeInTheDocument();
     });
   });

+ 82 - 87
static/app/views/dashboards/widgetCard/index.spec.tsx

@@ -1,6 +1,5 @@
 import {initializeOrg} from 'sentry-test/initializeOrg';
 import {
-  act,
   render,
   renderGlobalModal,
   screen,
@@ -416,71 +415,72 @@ describe('Dashboards > WidgetCard', function () {
 
   it('calls events with a limit of 20 items', async function () {
     const mock = jest.fn();
-    await act(async () => {
-      renderWithProviders(
-        <WidgetCard
-          api={api}
-          organization={organization}
-          widget={{
-            ...multipleQueryWidget,
-            displayType: DisplayType.TABLE,
-            queries: [{...multipleQueryWidget.queries[0], fields: ['count()']}],
-          }}
-          selection={selection}
-          isEditing={false}
-          onDelete={mock}
-          onEdit={() => undefined}
-          onDuplicate={() => undefined}
-          renderErrorMessage={() => undefined}
-          showContextMenu
-          widgetLimitReached={false}
-          tableItemLimit={20}
-        />
+
+    renderWithProviders(
+      <WidgetCard
+        api={api}
+        organization={organization}
+        widget={{
+          ...multipleQueryWidget,
+          displayType: DisplayType.TABLE,
+          queries: [{...multipleQueryWidget.queries[0], fields: ['count()']}],
+        }}
+        selection={selection}
+        isEditing={false}
+        onDelete={mock}
+        onEdit={() => undefined}
+        onDuplicate={() => undefined}
+        renderErrorMessage={() => undefined}
+        showContextMenu
+        widgetLimitReached={false}
+        tableItemLimit={20}
+      />
+    );
+
+    await waitFor(() => {
+      expect(eventsMock).toHaveBeenCalledWith(
+        '/organizations/org-slug/events/',
+        expect.objectContaining({
+          query: expect.objectContaining({
+            per_page: 20,
+          }),
+        })
       );
-      await tick();
     });
-    expect(eventsMock).toHaveBeenCalledWith(
-      '/organizations/org-slug/events/',
-      expect.objectContaining({
-        query: expect.objectContaining({
-          per_page: 20,
-        }),
-      })
-    );
   });
 
   it('calls events with a default limit of 5 items', async function () {
     const mock = jest.fn();
-    await act(async () => {
-      renderWithProviders(
-        <WidgetCard
-          api={api}
-          organization={organization}
-          widget={{
-            ...multipleQueryWidget,
-            displayType: DisplayType.TABLE,
-            queries: [{...multipleQueryWidget.queries[0], fields: ['count()']}],
-          }}
-          selection={selection}
-          isEditing={false}
-          onDelete={mock}
-          onEdit={() => undefined}
-          onDuplicate={() => undefined}
-          renderErrorMessage={() => undefined}
-          showContextMenu
-          widgetLimitReached={false}
-        />
+    renderWithProviders(
+      <WidgetCard
+        api={api}
+        organization={organization}
+        widget={{
+          ...multipleQueryWidget,
+          displayType: DisplayType.TABLE,
+          queries: [{...multipleQueryWidget.queries[0], fields: ['count()']}],
+        }}
+        selection={selection}
+        isEditing={false}
+        onDelete={mock}
+        onEdit={() => undefined}
+        onDuplicate={() => undefined}
+        renderErrorMessage={() => undefined}
+        showContextMenu
+        widgetLimitReached={false}
+      />
+    );
+
+    await waitFor(() => {
+      expect(eventsMock).toHaveBeenCalledWith(
+        '/organizations/org-slug/events/',
+        expect.objectContaining({
+          query: expect.objectContaining({
+            per_page: 5,
+          }),
+        })
       );
-      await tick();
     });
-    expect(eventsMock).toHaveBeenCalledWith(
-      '/organizations/org-slug/events/',
-      expect.objectContaining({
-        query: expect.objectContaining({
-          per_page: 5,
-        }),
-      })
-    );
   });
 
   it('has sticky table headers', async function () {
@@ -500,25 +500,24 @@ describe('Dashboards > WidgetCard', function () {
         },
       ],
     };
-    await act(async () => {
-      renderWithProviders(
-        <WidgetCard
-          api={api}
-          organization={organization}
-          widget={tableWidget}
-          selection={selection}
-          isEditing={false}
-          onDelete={() => undefined}
-          onEdit={() => undefined}
-          onDuplicate={() => undefined}
-          renderErrorMessage={() => undefined}
-          showContextMenu
-          widgetLimitReached={false}
-          tableItemLimit={20}
-        />
-      );
-      await tick();
-    });
+
+    renderWithProviders(
+      <WidgetCard
+        api={api}
+        organization={organization}
+        widget={tableWidget}
+        selection={selection}
+        isEditing={false}
+        onDelete={() => undefined}
+        onEdit={() => undefined}
+        onDuplicate={() => undefined}
+        renderErrorMessage={() => undefined}
+        showContextMenu
+        widgetLimitReached={false}
+        tableItemLimit={20}
+      />
+    );
+
     await waitFor(() => expect(eventsMock).toHaveBeenCalled());
 
     expect(SimpleTableChart).toHaveBeenCalledWith(
@@ -620,17 +619,13 @@ describe('Dashboards > WidgetCard', function () {
       />
     );
 
-    await waitFor(() => {
-      // Badge in the widget header
-      expect(screen.getByText('Indexed')).toBeInTheDocument();
-    });
+    // Badge in the widget header
+    expect(await screen.findByText('Indexed')).toBeInTheDocument();
 
-    await waitFor(() => {
-      expect(
-        // Alert below the widget
-        screen.getByText(/we've automatically adjusted your results/i)
-      ).toBeInTheDocument();
-    });
+    expect(
+      // Alert below the widget
+      await screen.findByText(/we've automatically adjusted your results/i)
+    ).toBeInTheDocument();
   });
 
   it('renders chart using axis and tooltip formatters from custom measurement meta', async function () {