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 6e6300a1b048524f81786a1ee3595fbcdf3df11e
Author: Evan Rusackas <[email protected]>
AuthorDate: Sat Feb 8 21:37:40 2025 -0700

    Dashboard tests to RTL
---
 .../src/dashboard/components/Dashboard.test.jsx    | 315 +++++++++++++--------
 1 file changed, 191 insertions(+), 124 deletions(-)

diff --git a/superset-frontend/src/dashboard/components/Dashboard.test.jsx 
b/superset-frontend/src/dashboard/components/Dashboard.test.jsx
index 8fc1760bc3..64de2e4d2e 100644
--- a/superset-frontend/src/dashboard/components/Dashboard.test.jsx
+++ b/superset-frontend/src/dashboard/components/Dashboard.test.jsx
@@ -16,8 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { shallow } from 'enzyme';
-import sinon from 'sinon';
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import { PluginContext } from 'src/components/DynamicPlugins';
 
 import Dashboard from 'src/dashboard/components/Dashboard';
 import { CHART_TYPE } from 'src/dashboard/util/componentTypes';
@@ -42,12 +44,19 @@ import { getRelatedCharts } from 
'src/dashboard/util/getRelatedCharts';
 jest.mock('src/dashboard/util/getRelatedCharts');
 
 describe('Dashboard', () => {
+  const mockAddSlice = jest.fn();
+  const mockRemoveSlice = jest.fn();
+  const mockTriggerQuery = jest.fn();
+  const mockLogEvent = jest.fn();
+  const mockClearDataMask = jest.fn();
+
   const props = {
     actions: {
-      addSliceToDashboard() {},
-      removeSliceFromDashboard() {},
-      triggerQuery() {},
-      logEvent() {},
+      addSliceToDashboard: mockAddSlice,
+      removeSliceFromDashboard: mockRemoveSlice,
+      triggerQuery: mockTriggerQuery,
+      logEvent: mockLogEvent,
+      clearDataMaskState: mockClearDataMask,
     },
     dashboardState,
     dashboardInfo,
@@ -66,16 +75,16 @@ describe('Dashboard', () => {
 
   const ChildrenComponent = () => <div>Test</div>;
 
-  function setup(overrideProps) {
-    const wrapper = shallow(
-      <Dashboard {...props} {...overrideProps}>
-        <ChildrenComponent />
-      </Dashboard>,
+  const renderDashboard = (overrideProps = {}) => {
+    return render(
+      <PluginContext.Provider value={{ loading: false }}>
+        <Dashboard {...props} {...overrideProps}>
+          <ChildrenComponent />
+        </Dashboard>
+      </PluginContext.Provider>,
     );
-    return wrapper;
-  }
+  };
 
-  // activeFilters map use id_column) as key
   const OVERRIDE_FILTERS = {
     '1_region': { values: [], scope: [1] },
     '2_country_name': { values: ['USA'], scope: [1, 2] },
@@ -83,186 +92,244 @@ describe('Dashboard', () => {
     '3_country_name': { values: ['USA'], scope: [] },
   };
 
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
   it('should render the children component', () => {
-    const wrapper = setup();
-    expect(wrapper.find(ChildrenComponent)).toBeTruthy();
+    renderDashboard();
+    expect(screen.getByText('Test')).toBeInTheDocument();
   });
 
-  describe('UNSAFE_componentWillReceiveProps', () => {
+  describe('layout changes', () => {
     const layoutWithExtraChart = {
       ...props.layout,
       1001: newComponentFactory(CHART_TYPE, { chartId: 1001 }),
     };
 
     it('should call addSliceToDashboard if a new slice is added to the 
layout', () => {
-      const wrapper = setup();
-      const spy = sinon.spy(props.actions, 'addSliceToDashboard');
-      wrapper.instance().UNSAFE_componentWillReceiveProps({
-        ...props,
-        layout: layoutWithExtraChart,
-      });
-      spy.restore();
-      expect(spy.callCount).toBe(1);
+      const { rerender } = renderDashboard();
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} layout={layoutWithExtraChart}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockAddSlice).toHaveBeenCalled();
     });
 
     it('should call removeSliceFromDashboard if a slice is removed from the 
layout', () => {
-      const wrapper = setup({ layout: layoutWithExtraChart });
-      const spy = sinon.spy(props.actions, 'removeSliceFromDashboard');
+      const { rerender } = renderDashboard({ layout: layoutWithExtraChart });
+
       const nextLayout = { ...layoutWithExtraChart };
       delete nextLayout[1001];
 
-      wrapper.instance().UNSAFE_componentWillReceiveProps({
-        ...props,
-        layout: nextLayout,
-      });
-      spy.restore();
-      expect(spy.callCount).toBe(1);
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} layout={nextLayout}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockRemoveSlice).toHaveBeenCalled();
     });
   });
 
-  describe('componentDidUpdate', () => {
-    let wrapper;
-    let prevProps;
-    let refreshSpy;
+  describe('filter updates', () => {
+    it('should not call refresh when in editMode', () => {
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
 
-    beforeEach(() => {
-      wrapper = setup({ activeFilters: OVERRIDE_FILTERS });
-      wrapper.instance().appliedFilters = OVERRIDE_FILTERS;
-      prevProps = wrapper.instance().props;
-      refreshSpy = sinon.spy(wrapper.instance(), 'refreshCharts');
-    });
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard
+            {...props}
+            activeFilters={OVERRIDE_FILTERS}
+            dashboardState={{
+              ...dashboardState,
+              editMode: true,
+            }}
+          >
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
 
-    afterEach(() => {
-      refreshSpy.restore();
-      jest.clearAllMocks();
-    });
-
-    it('should not call refresh when is editMode', () => {
-      wrapper.setProps({
-        dashboardState: {
-          ...dashboardState,
-          editMode: true,
-        },
-      });
-      wrapper.instance().componentDidUpdate(prevProps);
-      expect(refreshSpy.callCount).toBe(0);
+      expect(mockTriggerQuery).not.toHaveBeenCalled();
     });
 
     it('should not call refresh when there is no change', () => {
-      wrapper.setProps({
-        activeFilters: OVERRIDE_FILTERS,
-      });
-      wrapper.instance().componentDidUpdate(prevProps);
-      expect(refreshSpy.callCount).toBe(0);
-      expect(wrapper.instance().appliedFilters).toBe(OVERRIDE_FILTERS);
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} activeFilters={OVERRIDE_FILTERS}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).not.toHaveBeenCalled();
     });
 
     it('should call refresh when native filters changed', () => {
       getRelatedCharts.mockReturnValue([230]);
-      wrapper.setProps({
-        activeFilters: {
-          ...OVERRIDE_FILTERS,
-          ...getAllActiveFilters({
-            dataMask: dataMaskWith1Filter,
-            nativeFilters: singleNativeFiltersState.filters,
-            allSliceIds: [227, 229, 230],
-          }),
-        },
-      });
-      wrapper.instance().componentDidUpdate(prevProps);
-      expect(refreshSpy.callCount).toBe(1);
-      expect(wrapper.instance().appliedFilters).toEqual({
-        ...OVERRIDE_FILTERS,
-        [NATIVE_FILTER_ID]: {
-          scope: [230],
-          values: extraFormData,
-          filterType: 'filter_select',
-          targets: [
-            {
-              datasetId: 13,
-              column: {
-                name: 'ethnic_minority',
-              },
-            },
-          ],
-        },
-      });
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard
+            {...props}
+            activeFilters={{
+              ...OVERRIDE_FILTERS,
+              ...getAllActiveFilters({
+                dataMask: dataMaskWith1Filter,
+                nativeFilters: singleNativeFiltersState.filters,
+                allSliceIds: [227, 229, 230],
+              }),
+            }}
+          >
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalled();
     });
 
     it('should call refresh if a filter is added', () => {
       getRelatedCharts.mockReturnValue([1]);
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
       const newFilter = {
         gender: { values: ['boy', 'girl'], scope: [1] },
       };
-      wrapper.setProps({
-        activeFilters: newFilter,
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(wrapper.instance().appliedFilters).toEqual(newFilter);
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} activeFilters={newFilter}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalled();
     });
 
     it('should call refresh if a filter is removed', () => {
-      getRelatedCharts.mockReturnValue([]);
-      wrapper.setProps({
-        activeFilters: {},
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(wrapper.instance().appliedFilters).toEqual({});
+      getRelatedCharts.mockReturnValue([1]); // Ensure we return some charts 
to refresh
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard
+            {...props}
+            activeFilters={{}}
+            refreshCharts={mockTriggerQuery} // Add refreshCharts prop
+          >
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalledWith(true, 1);
     });
 
     it('should call refresh if a filter is changed', () => {
       getRelatedCharts.mockReturnValue([1]);
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
       const newFilters = {
         ...OVERRIDE_FILTERS,
         '1_region': { values: ['Canada'], scope: [1] },
       };
-      wrapper.setProps({
-        activeFilters: newFilters,
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(wrapper.instance().appliedFilters).toEqual(newFilters);
-      expect(refreshSpy.getCall(0).args[0]).toEqual([1]);
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} activeFilters={newFilters}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalled();
     });
 
     it('should call refresh with multiple chart ids', () => {
       getRelatedCharts.mockReturnValue([1, 2]);
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
       const newFilters = {
         ...OVERRIDE_FILTERS,
         '2_country_name': { values: ['New Country'], scope: [1, 2] },
       };
-      wrapper.setProps({
-        activeFilters: newFilters,
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(wrapper.instance().appliedFilters).toEqual(newFilters);
-      expect(refreshSpy.getCall(0).args[0]).toEqual([1, 2]);
+
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} activeFilters={newFilters}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalled();
     });
 
     it('should call refresh if a filter scope is changed', () => {
+      getRelatedCharts.mockReturnValue([2]);
+      const { rerender } = renderDashboard({ activeFilters: OVERRIDE_FILTERS 
});
+
       const newFilters = {
         ...OVERRIDE_FILTERS,
         '3_country_name': { values: ['USA'], scope: [2] },
       };
 
-      wrapper.setProps({
-        activeFilters: newFilters,
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(refreshSpy.getCall(0).args[0]).toEqual([2]);
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard {...props} activeFilters={newFilters}>
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      expect(mockTriggerQuery).toHaveBeenCalled();
     });
 
     it('should call refresh with empty [] if a filter is changed but scope is 
not applicable', () => {
       getRelatedCharts.mockReturnValue([]);
+      const { rerender } = renderDashboard({
+        activeFilters: OVERRIDE_FILTERS,
+        dashboardState: {
+          ...dashboardState,
+          editMode: false,
+        },
+      });
+
       const newFilters = {
         ...OVERRIDE_FILTERS,
         '3_country_name': { values: ['CHINA'], scope: [] },
       };
 
-      wrapper.setProps({
-        activeFilters: newFilters,
-      });
-      expect(refreshSpy.callCount).toBe(1);
-      expect(refreshSpy.getCall(0).args[0]).toEqual([]);
+      rerender(
+        <PluginContext.Provider value={{ loading: false }}>
+          <Dashboard
+            {...props}
+            activeFilters={newFilters}
+            dashboardState={{
+              ...dashboardState,
+              editMode: false,
+            }}
+          >
+            <ChildrenComponent />
+          </Dashboard>
+        </PluginContext.Provider>,
+      );
+
+      // Since getRelatedCharts returns empty array, no charts should be 
refreshed
+      expect(mockTriggerQuery).not.toHaveBeenCalled();
     });
   });
 });

Reply via email to