mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
fix(sqllab): invalid dump sql shown after closing tab (#27295)
(cherry picked from commit 8d245704ef
)
This commit is contained in:
parent
8103f22fa3
commit
e881675f58
@ -17,6 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import * as uiCore from '@superset-ui/core';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
|
||||
import fetchMock from 'fetch-mock';
|
||||
@ -31,7 +32,7 @@ import {
|
||||
import SqlEditorLeftBar from 'src/SqlLab/components/SqlEditorLeftBar';
|
||||
import ResultSet from 'src/SqlLab/components/ResultSet';
|
||||
import { api } from 'src/hooks/apiResources/queryApi';
|
||||
import { getExtensionsRegistry } from '@superset-ui/core';
|
||||
import { getExtensionsRegistry, FeatureFlag } from '@superset-ui/core';
|
||||
import setupExtensions from 'src/setup/setupExtensions';
|
||||
import type { Action, Middleware, Store } from 'redux';
|
||||
import SqlEditor, { Props } from '.';
|
||||
@ -63,6 +64,7 @@ fetchMock.get('glob:*/api/v1/database/*/function_names/', {
|
||||
});
|
||||
fetchMock.get('glob:*/api/v1/database/*', { result: [] });
|
||||
fetchMock.get('glob:*/api/v1/database/*/tables/*', { options: [] });
|
||||
fetchMock.get('glob:*/tabstateview/*', defaultQueryEditor);
|
||||
fetchMock.post('glob:*/sqllab/execute/*', { result: [] });
|
||||
|
||||
let store: Store;
|
||||
@ -291,4 +293,43 @@ describe('SqlEditor', () => {
|
||||
await findByText('sqleditor.extension.form extension component'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('with SqllabBackendPersistence enabled', () => {
|
||||
let isFeatureEnabledMock: jest.MockInstance<
|
||||
boolean,
|
||||
[feature: FeatureFlag]
|
||||
>;
|
||||
beforeEach(() => {
|
||||
isFeatureEnabledMock = jest
|
||||
.spyOn(uiCore, 'isFeatureEnabled')
|
||||
.mockImplementation(
|
||||
featureFlag =>
|
||||
featureFlag === uiCore.FeatureFlag.SqllabBackendPersistence,
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
isFeatureEnabledMock.mockClear();
|
||||
});
|
||||
|
||||
it('should render loading state when its Editor is not loaded', async () => {
|
||||
const switchTabApi = `glob:*/tabstateview/${defaultQueryEditor.id}/activate`;
|
||||
fetchMock.post(switchTabApi, {});
|
||||
const { getByTestId } = setup(
|
||||
{
|
||||
...mockedProps,
|
||||
queryEditor: {
|
||||
...mockedProps.queryEditor,
|
||||
loaded: false,
|
||||
},
|
||||
},
|
||||
store,
|
||||
);
|
||||
const indicator = getByTestId('sqlEditor-loading');
|
||||
expect(indicator).toBeInTheDocument();
|
||||
await waitFor(() =>
|
||||
expect(fetchMock.calls('glob:*/tabstateview/*').length).toBe(1),
|
||||
);
|
||||
expect(fetchMock.calls(switchTabApi).length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -54,7 +54,7 @@ import Mousetrap from 'mousetrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Timer from 'src/components/Timer';
|
||||
import ResizableSidebar from 'src/components/ResizableSidebar';
|
||||
import { AntdDropdown, AntdSwitch } from 'src/components';
|
||||
import { AntdDropdown, AntdSwitch, Skeleton } from 'src/components';
|
||||
import { Input } from 'src/components/Input';
|
||||
import { Menu } from 'src/components/Menu';
|
||||
import Icons from 'src/components/Icons';
|
||||
@ -77,6 +77,7 @@ import {
|
||||
setActiveSouthPaneTab,
|
||||
updateSavedQuery,
|
||||
formatQuery,
|
||||
switchQueryEditor,
|
||||
} from 'src/SqlLab/actions/sqlLab';
|
||||
import {
|
||||
STATE_TYPE_MAP,
|
||||
@ -494,6 +495,16 @@ const SqlEditor: React.FC<Props> = ({
|
||||
}
|
||||
});
|
||||
|
||||
const shouldLoadQueryEditor =
|
||||
isFeatureEnabled(FeatureFlag.SqllabBackendPersistence) &&
|
||||
!queryEditor.loaded;
|
||||
|
||||
const loadQueryEditor = useEffectEvent(() => {
|
||||
if (shouldLoadQueryEditor) {
|
||||
dispatch(switchQueryEditor(queryEditor, displayLimit));
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// We need to measure the height of the sql editor post render to figure the height of
|
||||
// the south pane so it gets rendered properly
|
||||
@ -503,6 +514,7 @@ const SqlEditor: React.FC<Props> = ({
|
||||
WINDOW_RESIZE_THROTTLE_MS,
|
||||
);
|
||||
if (isActive) {
|
||||
loadQueryEditor();
|
||||
window.addEventListener('resize', handleWindowResizeWithThrottle);
|
||||
window.addEventListener('beforeunload', onBeforeUnload);
|
||||
}
|
||||
@ -512,7 +524,7 @@ const SqlEditor: React.FC<Props> = ({
|
||||
window.removeEventListener('beforeunload', onBeforeUnload);
|
||||
};
|
||||
// TODO: Remove useEffectEvent deps once https://github.com/facebook/react/pull/25881 is released
|
||||
}, [onBeforeUnload, isActive]);
|
||||
}, [onBeforeUnload, loadQueryEditor, isActive]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!database || isEmpty(database)) {
|
||||
@ -847,7 +859,17 @@ const SqlEditor: React.FC<Props> = ({
|
||||
)}
|
||||
</ResizableSidebar>
|
||||
</CSSTransition>
|
||||
{showEmptyState ? (
|
||||
{shouldLoadQueryEditor ? (
|
||||
<div
|
||||
data-test="sqlEditor-loading"
|
||||
css={css`
|
||||
flex: 1;
|
||||
padding: ${theme.gridUnit * 4}px;
|
||||
`}
|
||||
>
|
||||
<Skeleton active />
|
||||
</div>
|
||||
) : showEmptyState ? (
|
||||
<EmptyStateBig
|
||||
image="vector.svg"
|
||||
title={t('Select a database to write a query')}
|
||||
|
@ -57,7 +57,7 @@ export default function getInitialState({
|
||||
version: LatestQueryEditorVersion,
|
||||
loaded: true,
|
||||
name: t('Untitled query'),
|
||||
sql: 'SELECT *\nFROM\nWHERE',
|
||||
sql: '',
|
||||
latestQueryId: null,
|
||||
autorun: false,
|
||||
dbId: common.conf.SQLLAB_DEFAULT_DBID,
|
||||
|
@ -152,7 +152,10 @@ export default function sqlLabReducer(state = {}, action) {
|
||||
|
||||
newState = {
|
||||
...newState,
|
||||
tabHistory,
|
||||
tabHistory:
|
||||
tabHistory.length === 0 && newState.queryEditors.length > 0
|
||||
? newState.queryEditors.slice(-1).map(qe => qe.id)
|
||||
: tabHistory,
|
||||
tables,
|
||||
queries,
|
||||
unsavedQueryEditor: {
|
||||
|
@ -75,6 +75,25 @@ describe('sqlLabReducer', () => {
|
||||
initialState.queryEditors.length,
|
||||
);
|
||||
});
|
||||
it('should select the latest query editor when tabHistory is empty', () => {
|
||||
const currentQE = newState.queryEditors[0];
|
||||
newState = {
|
||||
...initialState,
|
||||
tabHistory: [initialState.queryEditors[0]],
|
||||
};
|
||||
const action = {
|
||||
type: actions.REMOVE_QUERY_EDITOR,
|
||||
queryEditor: currentQE,
|
||||
};
|
||||
newState = sqlLabReducer(newState, action);
|
||||
expect(newState.queryEditors).toHaveLength(
|
||||
initialState.queryEditors.length - 1,
|
||||
);
|
||||
expect(newState.queryEditors.map(qe => qe.id)).not.toContainEqual(
|
||||
currentQE.id,
|
||||
);
|
||||
expect(newState.tabHistory).toEqual([initialState.queryEditors[2].id]);
|
||||
});
|
||||
it('should remove a query editor including unsaved changes', () => {
|
||||
expect(newState.queryEditors).toHaveLength(
|
||||
initialState.queryEditors.length + 1,
|
||||
|
Loading…
Reference in New Issue
Block a user