diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx
index 9dcc37fdd188a..99551b9d41e81 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx
@@ -32,6 +32,8 @@ import {
import AceEditorWrapper from 'src/SqlLab/components/AceEditorWrapper';
import SouthPane from 'src/SqlLab/components/SouthPane';
import SqlEditor from 'src/SqlLab/components/SqlEditor';
+import { setupStore } from 'src/views/store';
+import { reducers } from 'src/SqlLab/reducers';
import QueryProvider from 'src/views/QueryProvider';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import {
@@ -40,16 +42,21 @@ import {
table,
defaultQueryEditor,
} from 'src/SqlLab/fixtures';
+import SqlEditorLeftBar from 'src/SqlLab/components/SqlEditorLeftBar';
jest.mock('src/components/AsyncAceEditor', () => ({
...jest.requireActual('src/components/AsyncAceEditor'),
- FullSQLEditor: props => (
-
{JSON.stringify(props)}
+ FullSQLEditor: ({ onChange, onBlur, value }) => (
+
),
}));
-jest.mock('src/SqlLab/components/SqlEditorLeftBar', () => () => (
-
-));
+jest.mock('src/SqlLab/components/SqlEditorLeftBar', () => jest.fn());
const MOCKED_SQL_EDITOR_HEIGHT = 500;
@@ -59,7 +66,7 @@ fetchMock.post('glob:*/sqllab/execute/*', { result: [] });
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
-const store = mockStore({
+const mockInitialState = {
...initialState,
sqlLab: {
...initialState.sqlLab,
@@ -82,7 +89,8 @@ const store = mockStore({
dbId: 'dbid1',
},
},
-});
+};
+const store = mockStore(mockInitialState);
const setup = (props = {}, store) =>
render(, {
@@ -103,6 +111,13 @@ describe('SqlEditor', () => {
displayLimit: 100,
};
+ beforeEach(() => {
+ SqlEditorLeftBar.mockClear();
+ SqlEditorLeftBar.mockImplementation(() => (
+
+ ));
+ });
+
const buildWrapper = (props = {}) =>
mount(
@@ -136,6 +151,21 @@ describe('SqlEditor', () => {
expect(await findByTestId('react-ace')).toBeInTheDocument();
});
+ it('avoids rerendering EditorLeftBar while typing', async () => {
+ const sqlLabStore = setupStore({
+ initialState: mockInitialState,
+ rootReducers: reducers,
+ });
+ const { findByTestId } = setup(mockedProps, sqlLabStore);
+ const editor = await findByTestId('react-ace');
+ const sql = 'select *';
+ const renderCount = SqlEditorLeftBar.mock.calls.length;
+ expect(SqlEditorLeftBar).toHaveBeenCalledTimes(renderCount);
+ fireEvent.change(editor, { target: { value: sql } });
+ // Verify the rendering regression
+ expect(SqlEditorLeftBar).toHaveBeenCalledTimes(renderCount);
+ });
+
it('renders sql from unsaved change', async () => {
const expectedSql = 'SELECT updated_column\nFROM updated_table\nWHERE';
const { findByTestId } = setup(
@@ -167,9 +197,8 @@ describe('SqlEditor', () => {
}),
);
- expect(await findByTestId('react-ace')).toHaveTextContent(
- JSON.stringify({ value: expectedSql }).slice(1, -1),
- );
+ const editor = await findByTestId('react-ace');
+ expect(editor).toHaveValue(expectedSql);
});
it('render a SouthPane', async () => {
diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
index 83286e588136f..d23c3099208eb 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
@@ -26,7 +26,7 @@ import React, {
useCallback,
} from 'react';
import { CSSTransition } from 'react-transition-group';
-import { useDispatch, useSelector } from 'react-redux';
+import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import Split from 'react-split';
import { css, FeatureFlag, styled, t, useTheme } from '@superset-ui/core';
@@ -230,6 +230,7 @@ const SqlEditor = ({
hideLeftBar,
};
},
+ shallowEqual,
);
const [height, setHeight] = useState(0);