diff --git a/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx index 4f6f909f9ce17..d5bdf2af761c7 100644 --- a/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx +++ b/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx @@ -17,9 +17,9 @@ * under the License. */ -import { mount, shallow } from 'enzyme'; import { triggerResizeObserver } from 'resize-observer-polyfill'; import { promiseTimeout, WithLegend } from '@superset-ui/core'; +import { render } from '@testing-library/react'; let renderChart = jest.fn(); let renderLegend = jest.fn(); @@ -31,18 +31,18 @@ describe('WithLegend', () => { }); it('sets className', () => { - const wrapper = shallow( + const { container } = render( , ); - expect(wrapper.hasClass('test-class')).toEqual(true); + expect(container.querySelectorAll('.test-class')).toHaveLength(1); }); it('renders when renderLegend is not set', () => { - const wrapper = mount( + const { container } = render( { // Have to delay more than debounceTime (1ms) return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(0); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(0); }, 100); }); it('renders', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders without width or height', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders legend on the left', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders legend on the right', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders legend on the top', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders legend on the bottom', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); it('renders legend with justifyContent set', () => { - const wrapper = mount( + const { container } = render( { return promiseTimeout(() => { expect(renderChart).toHaveBeenCalledTimes(1); expect(renderLegend).toHaveBeenCalledTimes(1); - expect(wrapper.render().find('div.chart')).toHaveLength(1); - expect(wrapper.render().find('div.legend')).toHaveLength(1); + expect(container.querySelectorAll('div.chart')).toHaveLength(1); + expect(container.querySelectorAll('div.legend')).toHaveLength(1); }, 100); }); }); diff --git a/superset-frontend/packages/superset-ui-core/test/chart/components/reactify.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart/components/reactify.test.tsx index db74801bac53a..1d00b372c5880 100644 --- a/superset-frontend/packages/superset-ui-core/test/chart/components/reactify.test.tsx +++ b/superset-frontend/packages/superset-ui-core/test/chart/components/reactify.test.tsx @@ -17,10 +17,11 @@ * under the License. */ +import '@testing-library/jest-dom'; import PropTypes from 'prop-types'; import { PureComponent } from 'react'; -import { mount } from 'enzyme'; import { reactify } from '@superset-ui/core'; +import { render, screen } from '@testing-library/react'; import { RenderFuncType } from '../../../src/chart/components/reactify'; describe('reactify(renderFn)', () => { @@ -78,14 +79,18 @@ describe('reactify(renderFn)', () => { it('returns a React component class', () => new Promise(done => { - const wrapper = mount(); + render(); expect(renderFn).toHaveBeenCalledTimes(1); - expect(wrapper.html()).toEqual('
abc
'); + expect(screen.getByText('abc')).toBeInTheDocument(); + expect(screen.getByText('abc').parentNode).toHaveAttribute('id', 'test'); setTimeout(() => { expect(renderFn).toHaveBeenCalledTimes(2); - expect(wrapper.html()).toEqual('
def
'); - wrapper.unmount(); + expect(screen.getByText('def')).toBeInTheDocument(); + expect(screen.getByText('def').parentNode).toHaveAttribute( + 'id', + 'test', + ); done(undefined); }, 20); })); @@ -119,8 +124,9 @@ describe('reactify(renderFn)', () => { describe('defaultProps', () => { it('has defaultProps if renderFn.defaultProps is defined', () => { expect(TheChart.defaultProps).toBe(renderFn.defaultProps); - const wrapper = mount(); - expect(wrapper.html()).toEqual('
ghi
'); + render(); + expect(screen.getByText('ghi')).toBeInTheDocument(); + expect(screen.getByText('ghi').parentNode).toHaveAttribute('id', 'test'); }); it('does not have defaultProps if renderFn.defaultProps is not defined', () => { const AnotherChart = reactify(() => {}); @@ -136,9 +142,9 @@ describe('reactify(renderFn)', () => { }); it('calls willUnmount hook when it is provided', () => new Promise(done => { - const wrapper = mount(); + const { unmount } = render(); setTimeout(() => { - wrapper.unmount(); + unmount(); expect(willUnmountCb).toHaveBeenCalledTimes(1); done(undefined); }, 20); diff --git a/superset-frontend/src/features/home/EmptyState.test.tsx b/superset-frontend/src/features/home/EmptyState.test.tsx index 0be86559dcf63..a43fac1fe8936 100644 --- a/superset-frontend/src/features/home/EmptyState.test.tsx +++ b/superset-frontend/src/features/home/EmptyState.test.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { styledMount as mount } from 'spec/helpers/theming'; import { TableTab } from 'src/views/CRUD/types'; +import { render, screen } from 'spec/helpers/testing-library'; import EmptyState, { EmptyStateProps } from './EmptyState'; import { WelcomeTable } from './types'; @@ -65,29 +65,30 @@ describe('EmptyState', () => { variants.forEach(variant => { it(`renders an ${variant.tab} ${variant.tableName} empty state`, () => { - const wrapper = mount(); - expect(wrapper).toExist(); + const { container } = render(); // Select the first description node - const textContainer = wrapper.find('.ant-empty-description').at(0); - expect(textContainer.text()).toEqual('Nothing here yet'); - expect(wrapper.find('button')).toHaveLength(1); + expect( + container.querySelector('.ant-empty-description'), + ).toHaveTextContent('Nothing here yet'); + expect(screen.getAllByRole('button')).toHaveLength(1); }); }); recents.forEach(recent => { it(`renders a ${recent.tab} ${recent.tableName} empty state`, () => { - const wrapper = mount(); - expect(wrapper).toExist(); + const { container } = render(); // Select the first description node - const textContainer = wrapper.find('.ant-empty-description').at(0); + // Check the correct text is displayed + expect( + container.querySelector('.ant-empty-description'), + ).toHaveTextContent('Nothing here yet'); // Validate the image - expect(wrapper.find('.ant-empty-image').children()).toHaveLength(1); - - // Check the correct text is displayed - expect(textContainer.text()).toContain(`Nothing here yet`); + expect( + container.querySelector('.ant-empty-image')?.children, + ).toHaveLength(1); }); }); }); diff --git a/superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.jsx b/superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.tsx similarity index 69% rename from superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.jsx rename to superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.tsx index 1318b3625ef5a..5c323714317a8 100644 --- a/superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.jsx +++ b/superset-frontend/src/pages/ExecutionLogList/ExecutionLogList.test.tsx @@ -17,24 +17,15 @@ * under the License. */ import fetchMock from 'fetch-mock'; -import { Provider } from 'react-redux'; -import configureStore from 'redux-mock-store'; -import thunk from 'redux-thunk'; -import { styledMount as mount } from 'spec/helpers/theming'; -import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; -import ListView from 'src/components/ListView'; import ExecutionLog from 'src/pages/ExecutionLogList'; - -// store needed for withToasts(ExecutionLog) -const mockStore = configureStore([thunk]); -const store = mockStore({}); +import { render, screen } from 'spec/helpers/testing-library'; const executionLogsEndpoint = 'glob:*/api/v1/report/*/log*'; const reportEndpoint = 'glob:*/api/v1/report/*'; fetchMock.delete(executionLogsEndpoint, {}); -const mockannotations = [...new Array(3)].map((_, i) => ({ +const mockAnnotations = [...new Array(3)].map((_, i) => ({ end_dttm: new Date().toISOString, error_message: `report ${i} error message`, id: i, @@ -47,7 +38,7 @@ const mockannotations = [...new Array(3)].map((_, i) => ({ fetchMock.get(executionLogsEndpoint, { ids: [2, 0, 1], - result: mockannotations, + result: mockAnnotations, count: 3, }); @@ -61,30 +52,22 @@ jest.mock('react-router-dom', () => ({ useParams: () => ({ alertId: '1' }), })); -async function mountAndWait(props) { - const mounted = mount( - - - , - ); - await waitForComponentToPaint(mounted); - - return mounted; -} - -describe('ExecutionLog', () => { - let wrapper; - - beforeAll(async () => { - wrapper = await mountAndWait(); +const renderAndWait = (props = {}) => + render(, { + useRedux: true, + useQueryParams: true, + useRouter: true, }); - it('renders', () => { - expect(wrapper.find(ExecutionLog)).toExist(); - }); +describe('ExecutionLog', () => { + beforeAll(() => renderAndWait()); - it('renders a ListView', () => { - expect(wrapper.find(ListView)).toExist(); + it('renders with a ListView', () => { + expect(screen.getByText('Back to all')).toHaveAttribute( + 'href', + '/alert/list/', + ); + expect(screen.getByTestId('execution-log-list-view')).toBeVisible(); }); it('fetches report/alert', () => {