From 79256b1da147eab59ea4c51adca8a1c7f3146d8c Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Wed, 9 Aug 2023 15:50:24 -0300 Subject: [PATCH 1/2] chore: Removes duplicated featureFlags.ts --- .../src/utils/featureFlags.ts | 10 ++++- .../test/utils/featureFlag.test.ts | 23 ++++------ superset-frontend/src/SqlLab/App.jsx | 8 +++- .../src/SqlLab/actions/sqlLab.js | 8 +++- .../src/SqlLab/actions/sqlLab.test.js | 6 +-- .../ShareSqlLabQuery.test.tsx | 6 +-- .../components/ShareSqlLabQuery/index.tsx | 9 +++- .../src/SqlLab/components/SouthPane/index.tsx | 3 +- .../src/SqlLab/components/SqlEditor/index.jsx | 2 +- .../components/TabbedSqlEditors/index.jsx | 3 +- .../TableElement/TableElement.test.tsx | 4 +- .../src/components/Chart/Chart.jsx | 2 +- .../src/components/Chart/chartAction.js | 9 +++- .../Datasource/DatasourceEditor.jsx | 2 +- .../Datasource/DatasourceEditor.test.jsx | 6 +-- .../Datasource/DatasourceModal.test.jsx | 5 +-- .../components/Datasource/DatasourceModal.tsx | 3 +- .../src/components/DynamicPlugins/index.tsx | 2 +- .../ReportModal/ReportModal.test.tsx | 6 +-- .../src/dashboard/actions/dashboardState.js | 2 +- .../dashboard/actions/dashboardState.test.js | 4 +- .../src/dashboard/actions/hydrate.js | 3 +- .../src/dashboard/actions/sliceEntities.ts | 2 +- .../DashboardBuilder.test.tsx | 42 +++++++++---------- .../DashboardBuilder/DashboardBuilder.tsx | 2 +- .../components/DashboardBuilder/state.ts | 3 +- .../HeaderActionsDropdown.test.tsx | 6 +-- .../Header/HeaderActionsDropdown/index.jsx | 10 +++-- .../src/dashboard/components/Header/index.jsx | 2 +- .../PropertiesModal/PropertiesModal.test.tsx | 3 +- .../components/PropertiesModal/index.tsx | 2 +- .../components/SliceHeaderControls/index.tsx | 2 +- .../FilterBar/FilterControls/FilterValue.tsx | 2 +- .../nativeFilters/FilterBar/Vertical.tsx | 2 +- .../FiltersConfigForm/FiltersConfigForm.tsx | 2 +- .../components/nativeFilters/utils.test.ts | 8 ++-- .../components/nativeFilters/utils.ts | 2 +- superset-frontend/src/dataMask/actions.ts | 2 +- superset-frontend/src/dataMask/reducer.ts | 2 +- .../DataTablesPane/DataTablesPane.tsx | 9 +++- .../components/DatasourcePanel/index.tsx | 2 +- .../components/ExploreChartPanel/index.jsx | 2 +- .../src/explore/components/SaveModal.tsx | 2 +- ...FilterEditPopoverSimpleTabContent.test.tsx | 4 +- .../index.tsx | 2 +- .../useExploreAdditionalActionsMenu/index.jsx | 10 ++++- superset-frontend/src/featureFlags.ts | 37 ---------------- .../src/features/alerts/AlertReportModal.tsx | 2 +- .../src/features/charts/ChartCard.tsx | 3 +- .../src/features/dashboards/DashboardCard.tsx | 3 +- .../src/features/tags/TagCard.tsx | 3 +- .../src/middleware/asyncEvent.test.ts | 4 +- .../src/middleware/asyncEvent.ts | 2 +- .../src/pages/ChartCreation/index.tsx | 2 +- .../src/pages/ChartList/ChartList.test.jsx | 6 +-- .../src/pages/ChartList/index.tsx | 2 +- .../DashboardList/DashboardList.test.jsx | 6 +-- .../src/pages/DashboardList/index.tsx | 9 +++- .../src/pages/DatabaseList/index.tsx | 2 +- .../pages/DatasetList/DatasetList.test.tsx | 4 +- .../src/pages/DatasetList/index.tsx | 2 +- .../src/pages/Home/Home.test.tsx | 4 +- superset-frontend/src/pages/Home/index.tsx | 2 +- .../SavedQueryList/SavedQueryList.test.jsx | 4 +- .../src/pages/SavedQueryList/index.tsx | 9 +++- superset-frontend/src/pages/Tags/index.tsx | 3 +- superset-frontend/src/preamble.ts | 8 +++- .../src/utils/hostNamesConfig.js | 2 +- superset-frontend/src/views/routes.test.tsx | 4 -- 69 files changed, 183 insertions(+), 191 deletions(-) delete mode 100644 superset-frontend/src/featureFlags.ts diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index 48e54d18416a8..6bc77e0e87a1a 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ +import logger from './logging'; + // We can codegen the enum definition based on a list of supported flags that we // check into source control. We're hardcoding the supported flags for now. export enum FeatureFlag { @@ -85,11 +87,17 @@ declare global { } } +export function initFeatureFlags(featureFlags?: FeatureFlagMap) { + if (!window.featureFlags) { + window.featureFlags = featureFlags || {}; + } +} + export function isFeatureEnabled(feature: FeatureFlag): boolean { try { return !!window.featureFlags[feature]; } catch (error) { - console.error(`Failed to query feature flag ${feature}`); + logger.error(`Failed to query feature flag ${feature}`); } return false; } diff --git a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts index ef6e0c3729cf9..12aefcc1026a9 100644 --- a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts @@ -16,29 +16,23 @@ * specific language governing permissions and limitations * under the License. */ -import mockConsole from 'jest-mock-console'; -import { isFeatureEnabled, FeatureFlag } from '@superset-ui/core'; +import * as uiCore from '@superset-ui/core'; it('returns false and raises console error if feature flags have not been initialized', () => { - mockConsole(); + const logging = jest.spyOn(uiCore.logging, 'error'); Object.defineProperty(window, 'featureFlags', { value: undefined, }); - - expect(isFeatureEnabled(FeatureFlag.DRILL_BY)).toEqual(false); - expect(console.error).toHaveBeenCalled(); - // @ts-expect-error - expect(console.error.mock.calls[0][0]).toEqual( - 'Failed to query feature flag DRILL_BY', - ); + expect(uiCore.isFeatureEnabled(uiCore.FeatureFlag.DRILL_BY)).toEqual(false); + expect(uiCore.logging.error).toHaveBeenCalled(); + expect(logging).toHaveBeenCalledWith('Failed to query feature flag DRILL_BY'); }); it('returns false for unset feature flag', () => { Object.defineProperty(window, 'featureFlags', { value: {}, }); - - expect(isFeatureEnabled(FeatureFlag.DRILL_BY)).toEqual(false); + expect(uiCore.isFeatureEnabled(uiCore.FeatureFlag.DRILL_BY)).toEqual(false); }); it('returns true for set feature flag', () => { @@ -47,6 +41,7 @@ it('returns true for set feature flag', () => { CLIENT_CACHE: true, }, }); - - expect(isFeatureEnabled(FeatureFlag.CLIENT_CACHE)).toEqual(true); + expect(uiCore.isFeatureEnabled(uiCore.FeatureFlag.CLIENT_CACHE)).toEqual( + true, + ); }); diff --git a/superset-frontend/src/SqlLab/App.jsx b/superset-frontend/src/SqlLab/App.jsx index deaf17726591e..8f36b7e2ab6c9 100644 --- a/superset-frontend/src/SqlLab/App.jsx +++ b/superset-frontend/src/SqlLab/App.jsx @@ -20,9 +20,13 @@ import React from 'react'; import persistState from 'redux-localstorage'; import { Provider } from 'react-redux'; import { hot } from 'react-hot-loader/root'; -import { FeatureFlag, ThemeProvider } from '@superset-ui/core'; +import { + FeatureFlag, + ThemeProvider, + initFeatureFlags, + isFeatureEnabled, +} from '@superset-ui/core'; import { GlobalStyles } from 'src/GlobalStyles'; -import { initFeatureFlags, isFeatureEnabled } from 'src/featureFlags'; import { setupStore } from 'src/views/store'; import setupExtensions from 'src/setup/setupExtensions'; import getBootstrapData from 'src/utils/getBootstrapData'; diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index 886307ad3e9c7..5d9ecdacdf6c3 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -18,10 +18,14 @@ */ import shortid from 'shortid'; import rison from 'rison'; -import { FeatureFlag, SupersetClient, t } from '@superset-ui/core'; +import { + FeatureFlag, + SupersetClient, + t, + isFeatureEnabled, +} from '@superset-ui/core'; import invert from 'lodash/invert'; import mapKeys from 'lodash/mapKeys'; -import { isFeatureEnabled } from 'src/featureFlags'; import { now } from 'src/utils/dates'; import { diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.test.js b/superset-frontend/src/SqlLab/actions/sqlLab.test.js index 2f26ec16d520a..fc94a44645c7e 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.test.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.test.js @@ -22,7 +22,7 @@ import fetchMock from 'fetch-mock'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import shortid from 'shortid'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import * as actions from 'src/SqlLab/actions/sqlLab'; import { LOG_EVENT } from 'src/logger/actions'; import { @@ -492,7 +492,7 @@ describe('async actions', () => { beforeEach(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( feature => feature === 'SQLLAB_BACKEND_PERSISTENCE', ); @@ -758,7 +758,7 @@ describe('async actions', () => { describe('with backend persistence flag off', () => { it('does not update the tab state in the backend', () => { const backendPersistenceOffMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( feature => !(feature === 'SQLLAB_BACKEND_PERSISTENCE'), ); diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx index 6e9775c3a5bae..877edb76c89fd 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx @@ -20,7 +20,7 @@ import React from 'react'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import fetchMock from 'fetch-mock'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { Provider } from 'react-redux'; import { supersetTheme, ThemeProvider } from '@superset-ui/core'; import { render, screen, act } from '@testing-library/react'; @@ -108,7 +108,7 @@ describe('ShareSqlLabQuery', () => { describe('via /kv/store', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); }); @@ -150,7 +150,7 @@ describe('ShareSqlLabQuery', () => { describe('via saved query', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => false); }); diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx index fe9990ad3f995..a123576c3e42e 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx @@ -17,14 +17,19 @@ * under the License. */ import React from 'react'; -import { FeatureFlag, styled, t, useTheme } from '@superset-ui/core'; +import { + FeatureFlag, + styled, + t, + useTheme, + isFeatureEnabled, +} from '@superset-ui/core'; import Button from 'src/components/Button'; import Icons from 'src/components/Icons'; import withToasts from 'src/components/MessageToasts/withToasts'; import CopyToClipboard from 'src/components/CopyToClipboard'; import { storeQuery } from 'src/utils/common'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; -import { isFeatureEnabled } from 'src/featureFlags'; import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor'; interface ShareSqlLabQueryProps { diff --git a/superset-frontend/src/SqlLab/components/SouthPane/index.tsx b/superset-frontend/src/SqlLab/components/SouthPane/index.tsx index 8b773986be546..c2b0cc3beb505 100644 --- a/superset-frontend/src/SqlLab/components/SouthPane/index.tsx +++ b/superset-frontend/src/SqlLab/components/SouthPane/index.tsx @@ -22,10 +22,9 @@ import shortid from 'shortid'; import Alert from 'src/components/Alert'; import Tabs from 'src/components/Tabs'; import { EmptyStateMedium } from 'src/components/EmptyState'; -import { FeatureFlag, styled, t } from '@superset-ui/core'; +import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core'; import { setActiveSouthPaneTab } from 'src/SqlLab/actions/sqlLab'; -import { isFeatureEnabled } from 'src/featureFlags'; import Label from 'src/components/Label'; import { SqlLabRootState } from 'src/SqlLab/types'; diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx index 093b90e686f55..69f9f36ee37d8 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx @@ -33,6 +33,7 @@ import Split from 'react-split'; import { css, FeatureFlag, + isFeatureEnabled, styled, t, useTheme, @@ -84,7 +85,6 @@ import { LocalStorageKeys, setItem, } from 'src/utils/localStorageHelpers'; -import { isFeatureEnabled } from 'src/featureFlags'; import { EmptyStateBig } from 'src/components/EmptyState'; import getBootstrapData from 'src/utils/getBootstrapData'; import { isEmpty } from 'lodash'; diff --git a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx index 28f2133a7546e..d914715630da4 100644 --- a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx +++ b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx @@ -23,8 +23,7 @@ import { EditableTabs } from 'src/components/Tabs'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import URI from 'urijs'; -import { FeatureFlag, styled, t } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; +import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core'; import { Tooltip } from 'src/components/Tooltip'; import { detectOS } from 'src/utils/common'; import * as Actions from 'src/SqlLab/actions/sqlLab'; diff --git a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx index 89c98cfd335e7..e25d88f5dceb9 100644 --- a/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx +++ b/superset-frontend/src/SqlLab/components/TableElement/TableElement.test.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; import fetchMock from 'fetch-mock'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { FeatureFlag } from '@superset-ui/core'; import TableElement, { Column } from 'src/SqlLab/components/TableElement'; import { table, initialState } from 'src/SqlLab/fixtures'; @@ -140,7 +140,7 @@ test('removes the table', async () => { const updateTableSchemaEndpoint = 'glob:*/tableschemaview/*'; fetchMock.delete(updateTableSchemaEndpoint, {}); const isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( featureFlag => featureFlag === FeatureFlag.SQLLAB_BACKEND_PERSISTENCE, ); diff --git a/superset-frontend/src/components/Chart/Chart.jsx b/superset-frontend/src/components/Chart/Chart.jsx index 74bde69c5c7e4..af90ae6b0a089 100644 --- a/superset-frontend/src/components/Chart/Chart.jsx +++ b/superset-frontend/src/components/Chart/Chart.jsx @@ -21,11 +21,11 @@ import React from 'react'; import { ensureIsArray, FeatureFlag, + isFeatureEnabled, logging, styled, t, } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants'; import Loading from 'src/components/Loading'; import { EmptyStateBig } from 'src/components/EmptyState'; diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index d2e8b3d3278fa..c204d58ebe32b 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -19,9 +19,14 @@ /* eslint no-undef: 'error' */ /* eslint no-param-reassign: ["error", { "props": false }] */ import moment from 'moment'; -import { FeatureFlag, isDefined, SupersetClient, t } from '@superset-ui/core'; +import { + FeatureFlag, + isDefined, + SupersetClient, + t, + isFeatureEnabled, +} from '@superset-ui/core'; import { getControlsState } from 'src/explore/store'; -import { isFeatureEnabled } from 'src/featureFlags'; import { getAnnotationJsonUrl, getExploreUrl, diff --git a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx index 3013da71d87f1..8801e2e8600f3 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx @@ -26,6 +26,7 @@ import Badge from 'src/components/Badge'; import shortid from 'shortid'; import { css, + isFeatureEnabled, getCurrencySymbol, ensureIsArray, FeatureFlag, @@ -51,7 +52,6 @@ import TextControl from 'src/explore/components/controls/TextControl'; import TextAreaControl from 'src/explore/components/controls/TextAreaControl'; import SpatialControl from 'src/explore/components/controls/SpatialControl'; import withToasts from 'src/components/MessageToasts/withToasts'; -import { isFeatureEnabled } from 'src/featureFlags'; import Icons from 'src/components/Icons'; import CurrencyControl from 'src/explore/components/controls/CurrencyControl'; import CollectionTable from './CollectionTable'; diff --git a/superset-frontend/src/components/Datasource/DatasourceEditor.test.jsx b/superset-frontend/src/components/Datasource/DatasourceEditor.test.jsx index 0cd051ace36bc..ae35ebc139c54 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditor.test.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditor.test.jsx @@ -22,7 +22,7 @@ import userEvent from '@testing-library/user-event'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; import DatasourceEditor from 'src/components/Datasource/DatasourceEditor'; import mockDatasource from 'spec/fixtures/mockDatasource'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; const props = { datasource: mockDatasource['7__table'], @@ -156,7 +156,7 @@ describe('DatasourceEditor', () => { describe('enable edit Source tab', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => false); }); @@ -194,7 +194,7 @@ describe('DatasourceEditor', () => { describe('render editor with feature flag false', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); }); diff --git a/superset-frontend/src/components/Datasource/DatasourceModal.test.jsx b/superset-frontend/src/components/Datasource/DatasourceModal.test.jsx index d5619c5527921..5bcb705b683d4 100644 --- a/superset-frontend/src/components/Datasource/DatasourceModal.test.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceModal.test.jsx @@ -29,7 +29,7 @@ import { defaultStore as store } from 'spec/helpers/testing-library'; import Modal from 'src/components/Modal'; import { DatasourceModal } from 'src/components/Datasource'; import DatasourceEditor from 'src/components/Datasource/DatasourceEditor'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import mockDatasource from 'spec/fixtures/mockDatasource'; import { api } from 'src/hooks/apiResources/queryApi'; @@ -69,7 +69,7 @@ describe('DatasourceModal', () => { let wrapper; let isFeatureEnabledMock; beforeEach(async () => { - isFeatureEnabledMock = jest.spyOn(featureFlags, 'isFeatureEnabled'); + isFeatureEnabledMock = jest.spyOn(uiCore, 'isFeatureEnabled'); fetchMock.reset(); wrapper = await mountAndWait(); }); @@ -122,7 +122,6 @@ describe('DatasourceModal', () => { }); it('renders a legacy data source btn', () => { - featureFlags.DISABLE_LEGACY_DATASOURCE_EDITOR = false; expect( wrapper.find('button[data-test="datasource-modal-legacy-edit"]'), ).toExist(); diff --git a/superset-frontend/src/components/Datasource/DatasourceModal.tsx b/superset-frontend/src/components/Datasource/DatasourceModal.tsx index c5063890cb89c..78859f4a2fe47 100644 --- a/superset-frontend/src/components/Datasource/DatasourceModal.tsx +++ b/superset-frontend/src/components/Datasource/DatasourceModal.tsx @@ -22,6 +22,7 @@ import Button from 'src/components/Button'; import { FeatureFlag, isDefined, + isFeatureEnabled, Metric, styled, SupersetClient, @@ -30,8 +31,6 @@ import { import Modal from 'src/components/Modal'; import AsyncEsmComponent from 'src/components/AsyncEsmComponent'; -import { isFeatureEnabled } from 'src/featureFlags'; - import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import withToasts from 'src/components/MessageToasts/withToasts'; import { useSelector } from 'react-redux'; diff --git a/superset-frontend/src/components/DynamicPlugins/index.tsx b/superset-frontend/src/components/DynamicPlugins/index.tsx index 87701d24622ac..9134e73fdad7a 100644 --- a/superset-frontend/src/components/DynamicPlugins/index.tsx +++ b/superset-frontend/src/components/DynamicPlugins/index.tsx @@ -20,12 +20,12 @@ import React, { useContext, useEffect, useReducer } from 'react'; import { ChartMetadata, defineSharedModules, + isFeatureEnabled, FeatureFlag, getChartMetadataRegistry, logging, makeApi, } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; import { omitBy } from 'lodash'; const metadataRegistry = getChartMetadataRegistry(); diff --git a/superset-frontend/src/components/ReportModal/ReportModal.test.tsx b/superset-frontend/src/components/ReportModal/ReportModal.test.tsx index 2755d832d79f5..63365a6baca90 100644 --- a/superset-frontend/src/components/ReportModal/ReportModal.test.tsx +++ b/superset-frontend/src/components/ReportModal/ReportModal.test.tsx @@ -21,7 +21,7 @@ import userEvent from '@testing-library/user-event'; import sinon from 'sinon'; import fetchMock from 'fetch-mock'; import { render, screen, waitFor } from 'spec/helpers/testing-library'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import * as actions from 'src/reports/actions/reports'; import { FeatureFlag } from '@superset-ui/core'; import ReportModal from '.'; @@ -54,7 +54,7 @@ const defaultProps = { describe('Email Report Modal', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( (featureFlag: FeatureFlag) => featureFlag === FeatureFlag.ALERT_REPORTS, ); @@ -118,7 +118,7 @@ describe('Email Report Modal', () => { beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); dispatch = sinon.spy(); }); diff --git a/superset-frontend/src/dashboard/actions/dashboardState.js b/superset-frontend/src/dashboard/actions/dashboardState.js index 54c5294fba4fe..dcf1020e6d0df 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.js @@ -21,6 +21,7 @@ import { ActionCreators as UndoActionCreators } from 'redux-undo'; import rison from 'rison'; import { ensureIsArray, + isFeatureEnabled, FeatureFlag, getSharedLabelColor, SupersetClient, @@ -51,7 +52,6 @@ import serializeActiveFilterValues from 'src/dashboard/util/serializeActiveFilte import serializeFilterScopes from 'src/dashboard/util/serializeFilterScopes'; import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters'; import { safeStringify } from 'src/utils/safeStringify'; -import { isFeatureEnabled } from 'src/featureFlags'; import { logEvent } from 'src/logger/actions'; import { LOG_ACTIONS_CONFIRM_OVERWRITE_DASHBOARD_METADATA } from 'src/logger/LogUtils'; import { UPDATE_COMPONENTS_PARENTS_LIST } from './dashboardLayout'; diff --git a/superset-frontend/src/dashboard/actions/dashboardState.test.js b/superset-frontend/src/dashboard/actions/dashboardState.test.js index 5fbe28cb1fc2c..1ef85f0b99ce0 100644 --- a/superset-frontend/src/dashboard/actions/dashboardState.test.js +++ b/superset-frontend/src/dashboard/actions/dashboardState.test.js @@ -27,7 +27,7 @@ import { SET_OVERRIDE_CONFIRM, } from 'src/dashboard/actions/dashboardState'; import { REMOVE_FILTER } from 'src/dashboard/actions/dashboardFilters'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { UPDATE_COMPONENTS_PARENTS_LIST } from 'src/dashboard/actions/dashboardLayout'; import { DASHBOARD_GRID_ID, @@ -145,7 +145,7 @@ describe('dashboardState actions', () => { let isFeatureEnabledMock; beforeEach(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(feature => feature === 'CONFIRM_DASHBOARD_DIFF'); }); diff --git a/superset-frontend/src/dashboard/actions/hydrate.js b/superset-frontend/src/dashboard/actions/hydrate.js index 6fd06c8f12cda..699c2041c892b 100644 --- a/superset-frontend/src/dashboard/actions/hydrate.js +++ b/superset-frontend/src/dashboard/actions/hydrate.js @@ -17,7 +17,7 @@ * under the License. */ /* eslint-disable camelcase */ -import { FeatureFlag } from '@superset-ui/core'; +import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core'; import { chart } from 'src/components/Chart/chartReducer'; import { initSliceEntities } from 'src/dashboard/reducers/sliceEntities'; import { getInitialState as getInitialNativeFilterState } from 'src/dashboard/reducers/nativeFilters'; @@ -56,7 +56,6 @@ import { TIME_RANGE } from 'src/visualizations/FilterBox/FilterBox'; import { URL_PARAMS } from 'src/constants'; import { getUrlParam } from 'src/utils/urlUtils'; import { ResourceStatus } from 'src/hooks/apiResources/apiResources'; -import { isFeatureEnabled } from '../../featureFlags'; import extractUrlParams from '../util/extractUrlParams'; import { updateColorSchema } from './dashboardInfo'; import updateComponentParentsList from '../util/updateComponentParentsList'; diff --git a/superset-frontend/src/dashboard/actions/sliceEntities.ts b/superset-frontend/src/dashboard/actions/sliceEntities.ts index a30470aad12a4..562d90657e780 100644 --- a/superset-frontend/src/dashboard/actions/sliceEntities.ts +++ b/superset-frontend/src/dashboard/actions/sliceEntities.ts @@ -19,13 +19,13 @@ import rison from 'rison'; import { DatasourceType, + isFeatureEnabled, FeatureFlag, SupersetClient, t, } from '@superset-ui/core'; import { addDangerToast } from 'src/components/MessageToasts/actions'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; -import { isFeatureEnabled } from 'src/featureFlags'; import { Dispatch } from 'redux'; import { Slice } from '../types'; diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx index 388f8ee3c181b..7c3dd23392f80 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.test.tsx @@ -16,13 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { Store } from 'redux'; import React from 'react'; import fetchMock from 'fetch-mock'; import { render } from 'spec/helpers/testing-library'; import { fireEvent, within } from '@testing-library/react'; -import { FeatureFlag } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import DashboardBuilder from 'src/dashboard/components/DashboardBuilder/DashboardBuilder'; import useStoredSidebarWidth from 'src/components/ResizableSidebar/useStoredSidebarWidth'; import { @@ -34,7 +32,7 @@ import { dashboardLayout as undoableDashboardLayout, dashboardLayoutWithTabs as undoableDashboardLayoutWithTabs, } from 'spec/fixtures/mockDashboardLayout'; -import { mockStoreWithTabs, storeWithState } from 'spec/fixtures/mockStore'; +import { storeWithState } from 'spec/fixtures/mockStore'; import mockState from 'spec/fixtures/mockState'; import { DASHBOARD_ROOT_ID } from 'src/dashboard/util/constants'; @@ -46,7 +44,6 @@ jest.mock('src/dashboard/actions/dashboardState', () => ({ setActiveTabs: jest.fn(), setDirectPathToChild: jest.fn(), })); -jest.mock('src/featureFlags'); jest.mock('src/components/ResizableSidebar/useStoredSidebarWidth'); // mock following dependant components to fix the prop warnings @@ -100,7 +97,6 @@ describe('DashboardBuilder', () => { 100, jest.fn(), ]); - (isFeatureEnabled as jest.Mock).mockImplementation(() => false); }); afterAll(() => { @@ -109,7 +105,7 @@ describe('DashboardBuilder', () => { (useStoredSidebarWidth as jest.Mock).mockReset(); }); - function setup(overrideState = {}, overrideStore?: Store) { + function setup(overrideState = {}) { return render(, { useRedux: true, store: storeWithState({ @@ -142,10 +138,9 @@ describe('DashboardBuilder', () => { }); it('should render a Sticky top-level Tabs if the dashboard has tabs', async () => { - const { findAllByTestId } = setup( - { dashboardLayout: undoableDashboardLayoutWithTabs }, - mockStoreWithTabs, - ); + const { findAllByTestId } = setup({ + dashboardLayout: undoableDashboardLayoutWithTabs, + }); const sticky = await findAllByTestId('nav-list'); expect(sticky.length).toBe(1); @@ -229,12 +224,9 @@ describe('DashboardBuilder', () => { type: 'type', arg0, })); - const { findByRole } = setup( - { - dashboardLayout: undoableDashboardLayoutWithTabs, - }, - mockStoreWithTabs, - ); + const { findByRole } = setup({ + dashboardLayout: undoableDashboardLayoutWithTabs, + }); const tabList = await findByRole('tablist'); const tabs = within(tabList).getAllByRole('tab'); expect(setDirectPathToChild).toHaveBeenCalledTimes(0); @@ -262,13 +254,17 @@ describe('DashboardBuilder', () => { }); describe('when nativeFiltersEnabled', () => { - beforeEach(() => { - (isFeatureEnabled as jest.Mock).mockImplementation( - flag => flag === FeatureFlag.DASHBOARD_NATIVE_FILTERS, - ); + let isFeatureEnabledMock: jest.MockInstance; + beforeAll(() => { + isFeatureEnabledMock = jest + .spyOn(uiCore, 'isFeatureEnabled') + .mockImplementation( + flag => flag === uiCore.FeatureFlag.DASHBOARD_NATIVE_FILTERS, + ); }); - afterEach(() => { - (isFeatureEnabled as jest.Mock).mockReset(); + + afterAll(() => { + isFeatureEnabledMock.mockRestore(); }); it('should set FilterBar width by useStoredSidebarWidth', () => { diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index 3af76c5c1cc13..a17b168374592 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -29,6 +29,7 @@ import React, { import { addAlpha, css, + isFeatureEnabled, FeatureFlag, JsonObject, styled, @@ -58,7 +59,6 @@ import { setDirectPathToChild, setEditMode, } from 'src/dashboard/actions/dashboardState'; -import { isFeatureEnabled } from 'src/featureFlags'; import { deleteTopLevelTabs, handleComponentDrop, diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts index d213d292ee465..1936e331c3db2 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/state.ts @@ -17,8 +17,7 @@ * under the License. */ import { useSelector } from 'react-redux'; -import { FeatureFlag } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; +import { isFeatureEnabled, FeatureFlag } from '@superset-ui/core'; import { useCallback, useEffect, useState } from 'react'; import { URL_PARAMS } from 'src/constants'; import { getUrlParam } from 'src/utils/urlUtils'; diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx index a89bccb4802a5..218e2e4546118 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/HeaderActionsDropdown.test.tsx @@ -25,7 +25,7 @@ import fetchMock from 'fetch-mock'; import { HeaderDropdownProps } from 'src/dashboard/components/Header/types'; import injectCustomCss from 'src/dashboard/util/injectCustomCss'; import { FeatureFlag } from '@superset-ui/core'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import HeaderActionsDropdown from '.'; let isFeatureEnabledMock: jest.MockInstance; @@ -136,7 +136,7 @@ test('should render the menu items in edit mode', async () => { describe('with native filters feature flag disabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( (featureFlag: FeatureFlag) => featureFlag !== FeatureFlag.DASHBOARD_NATIVE_FILTERS, @@ -162,7 +162,7 @@ describe('with native filters feature flag disabled', () => { describe('with native filters feature flag enabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( (featureFlag: FeatureFlag) => featureFlag === FeatureFlag.DASHBOARD_NATIVE_FILTERS, diff --git a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx index 7c375caf5b987..3f2caab72acd4 100644 --- a/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/HeaderActionsDropdown/index.jsx @@ -19,9 +19,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { isEmpty } from 'lodash'; - -import { FeatureFlag, SupersetClient, t } from '@superset-ui/core'; - +import { + isFeatureEnabled, + FeatureFlag, + SupersetClient, + t, +} from '@superset-ui/core'; import { Menu } from 'src/components/Menu'; import { URL_PARAMS } from 'src/constants'; import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems'; @@ -37,7 +40,6 @@ import getDashboardUrl from 'src/dashboard/util/getDashboardUrl'; import { getActiveFilters } from 'src/dashboard/util/activeDashboardFilters'; import { getUrlParam } from 'src/utils/urlUtils'; import { LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE } from 'src/logger/LogUtils'; -import { isFeatureEnabled } from 'src/featureFlags'; const propTypes = { addSuccessToast: PropTypes.func.isRequired, diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx index e9cf63b5a4cf7..7d96ad6b54590 100644 --- a/superset-frontend/src/dashboard/components/Header/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/index.jsx @@ -23,13 +23,13 @@ import PropTypes from 'prop-types'; import { styled, css, + isFeatureEnabled, FeatureFlag, t, getSharedLabelColor, getExtensionsRegistry, } from '@superset-ui/core'; import { Global } from '@emotion/react'; -import { isFeatureEnabled } from 'src/featureFlags'; import { LOG_ACTIONS_PERIODIC_RENDER_DASHBOARD, LOG_ACTIONS_FORCE_REFRESH_DASHBOARD, diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx index 386467e8de281..401e0dc32079b 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/PropertiesModal.test.tsx @@ -21,11 +21,10 @@ import { render, screen, waitFor } from 'spec/helpers/testing-library'; import fetchMock from 'fetch-mock'; import userEvent from '@testing-library/user-event'; import * as ColorSchemeControlWrapper from 'src/dashboard/components/ColorSchemeControlWrapper'; -import * as FF from 'src/featureFlags'; import * as SupersetCore from '@superset-ui/core'; import PropertiesModal from '.'; -const spyIsFeatureEnabled = jest.spyOn(FF, 'isFeatureEnabled'); +const spyIsFeatureEnabled = jest.spyOn(SupersetCore, 'isFeatureEnabled'); const spyColorSchemeControlWrapper = jest.spyOn( ColorSchemeControlWrapper, 'default', diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx index 2e9f54cffcaba..3bc67bc6e80ce 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx @@ -27,6 +27,7 @@ import rison from 'rison'; import { CategoricalColorNamespace, ensureIsArray, + isFeatureEnabled, FeatureFlag, getCategoricalSchemeRegistry, getSharedLabelColor, @@ -42,7 +43,6 @@ import ColorSchemeControlWrapper from 'src/dashboard/components/ColorSchemeContr import FilterScopeModal from 'src/dashboard/components/filterscope/FilterScopeModal'; import { getClientErrorObject } from 'src/utils/getClientErrorObject'; import withToasts from 'src/components/MessageToasts/withToasts'; -import { isFeatureEnabled } from 'src/featureFlags'; import TagType from 'src/types/TagType'; import { addTag, diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx index e3958755179d7..287d83692f9d2 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx @@ -33,6 +33,7 @@ import moment from 'moment'; import { Behavior, css, + isFeatureEnabled, FeatureFlag, getChartMetadataRegistry, QueryFormData, @@ -45,7 +46,6 @@ import { Menu } from 'src/components/Menu'; import { NoAnimationDropdown } from 'src/components/Dropdown'; import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems'; import downloadAsImage from 'src/utils/downloadAsImage'; -import { isFeatureEnabled } from 'src/featureFlags'; import { getSliceHeaderTooltip } from 'src/dashboard/util/getSliceHeaderTooltip'; import { Tooltip } from 'src/components/Tooltip'; import Icons from 'src/components/Icons'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx index b6005536695f7..b64f1bc8d9330 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx @@ -27,6 +27,7 @@ import { ChartDataResponseResult, Behavior, DataMask, + isFeatureEnabled, FeatureFlag, getChartMetadataRegistry, JsonObject, @@ -41,7 +42,6 @@ import { getChartDataRequest } from 'src/components/Chart/chartAction'; import Loading from 'src/components/Loading'; import BasicErrorAlert from 'src/components/ErrorMessage/BasicErrorAlert'; import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace'; -import { isFeatureEnabled } from 'src/featureFlags'; import { waitForAsyncData } from 'src/middleware/asyncEvent'; import { ClientErrorObject, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx index d9212f4058ce9..7d7f846e75372 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx @@ -31,13 +31,13 @@ import cx from 'classnames'; import { FeatureFlag, HandlerFunction, + isFeatureEnabled, isNativeFilter, styled, t, } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { AntdTabs } from 'src/components'; -import { isFeatureEnabled } from 'src/featureFlags'; import Loading from 'src/components/Loading'; import { EmptyStateSmall } from 'src/components/EmptyState'; import { getFilterBarTestId } from './utils'; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index 240c9e41b8c2c..dcfbf3d43d2ff 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -27,6 +27,7 @@ import { Behavior, ChartDataResponseResult, Column, + isFeatureEnabled, FeatureFlag, Filter, GenericDataType, @@ -71,7 +72,6 @@ import { } from 'src/dashboard/types'; import DateFilterControl from 'src/explore/components/controls/DateFilterControl'; import AdhocFilterControl from 'src/explore/components/controls/FilterControl/AdhocFilterControl'; -import { isFeatureEnabled } from 'src/featureFlags'; import { waitForAsyncData } from 'src/middleware/asyncEvent'; import { ClientErrorObject, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts index 142153c27896d..7219ae360b764 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.test.ts @@ -17,7 +17,7 @@ * under the License. */ import { Behavior, FeatureFlag } from '@superset-ui/core'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { DashboardLayout } from 'src/dashboard/types'; import { nativeFilterGate, findTabsWithChartsInScope } from './utils'; @@ -27,7 +27,7 @@ describe('nativeFilterGate', () => { describe('with all feature flags disabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => false); }); @@ -58,7 +58,7 @@ describe('nativeFilterGate', () => { describe('with only native filters feature flag enabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( (featureFlag: FeatureFlag) => featureFlag === FeatureFlag.DASHBOARD_NATIVE_FILTERS, @@ -92,7 +92,7 @@ describe('nativeFilterGate', () => { describe('with native filters and experimental feature flag enabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation((featureFlag: FeatureFlag) => [ FeatureFlag.DASHBOARD_CROSS_FILTERS, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts index 1af395a5d91c5..7086ac8512a0b 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/utils.ts @@ -23,6 +23,7 @@ import { EXTRA_FORM_DATA_APPEND_KEYS, EXTRA_FORM_DATA_OVERRIDE_KEYS, ExtraFormData, + isFeatureEnabled, FeatureFlag, Filter, getChartMetadataRegistry, @@ -30,7 +31,6 @@ import { } from '@superset-ui/core'; import { DashboardLayout } from 'src/dashboard/types'; import extractUrlParams from 'src/dashboard/util/extractUrlParams'; -import { isFeatureEnabled } from 'src/featureFlags'; import { CHART_TYPE, TAB_TYPE } from '../../util/componentTypes'; import { DASHBOARD_GRID_ID, DASHBOARD_ROOT_ID } from '../../util/constants'; import getBootstrapData from '../../../utils/getBootstrapData'; diff --git a/superset-frontend/src/dataMask/actions.ts b/superset-frontend/src/dataMask/actions.ts index 89e88ce13080a..7c41703a10bfb 100644 --- a/superset-frontend/src/dataMask/actions.ts +++ b/superset-frontend/src/dataMask/actions.ts @@ -18,11 +18,11 @@ */ import { DataMask, + isFeatureEnabled, FeatureFlag, FilterConfiguration, Filters, } from '@superset-ui/core'; -import { isFeatureEnabled } from '../featureFlags'; import { getInitialDataMask } from './reducer'; export const CLEAR_DATA_MASK_STATE = 'CLEAR_DATA_MASK_STATE'; diff --git a/superset-frontend/src/dataMask/reducer.ts b/superset-frontend/src/dataMask/reducer.ts index ae30d1be7852a..f2163a54a44a0 100644 --- a/superset-frontend/src/dataMask/reducer.ts +++ b/superset-frontend/src/dataMask/reducer.ts @@ -24,6 +24,7 @@ import { DataMask, DataMaskStateWithId, DataMaskWithId, + isFeatureEnabled, FeatureFlag, Filter, FilterConfiguration, @@ -31,7 +32,6 @@ import { } from '@superset-ui/core'; import { NATIVE_FILTER_PREFIX } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/utils'; import { HYDRATE_DASHBOARD } from 'src/dashboard/actions/hydrate'; -import { isFeatureEnabled } from 'src/featureFlags'; import { AnyDataMaskAction, CLEAR_DATA_MASK_STATE, diff --git a/superset-frontend/src/explore/components/DataTablesPane/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/DataTablesPane.tsx index 54f222c717eda..726f3ea468998 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/DataTablesPane.tsx @@ -23,10 +23,15 @@ import React, { useState, MouseEvent, } from 'react'; -import { FeatureFlag, styled, t, useTheme } from '@superset-ui/core'; +import { + isFeatureEnabled, + FeatureFlag, + styled, + t, + useTheme, +} from '@superset-ui/core'; import Icons from 'src/components/Icons'; import Tabs from 'src/components/Tabs'; -import { isFeatureEnabled } from 'src/featureFlags'; import { getItem, setItem, diff --git a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx index efedacd220bf6..1d85c8235fd6e 100644 --- a/superset-frontend/src/explore/components/DatasourcePanel/index.tsx +++ b/superset-frontend/src/explore/components/DatasourcePanel/index.tsx @@ -20,6 +20,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import { css, DatasourceType, + isFeatureEnabled, FeatureFlag, Metric, QueryFormData, @@ -37,7 +38,6 @@ import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal'; import { getDatasourceAsSaveableDataset } from 'src/utils/datasourceUtils'; import { Input } from 'src/components/Input'; import { FAST_DEBOUNCE } from 'src/constants'; -import { isFeatureEnabled } from 'src/featureFlags'; import { ExploreActions } from 'src/explore/actions/exploreActions'; import Control from 'src/explore/components/Control'; import DatasourcePanelDragOption from './DatasourcePanelDragOption'; diff --git a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx index 0dee4d076e7ea..984b389a5c9e9 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel/index.jsx @@ -23,6 +23,7 @@ import { css, DatasourceType, ensureIsArray, + isFeatureEnabled, FeatureFlag, getChartMetadataRegistry, styled, @@ -32,7 +33,6 @@ import { } from '@superset-ui/core'; import { chartPropShape } from 'src/dashboard/util/propShapes'; import ChartContainer from 'src/components/Chart/ChartContainer'; -import { isFeatureEnabled } from 'src/featureFlags'; import { getItem, setItem, diff --git a/superset-frontend/src/explore/components/SaveModal.tsx b/superset-frontend/src/explore/components/SaveModal.tsx index 3142d6b75892a..86ff27bb42e3e 100644 --- a/superset-frontend/src/explore/components/SaveModal.tsx +++ b/superset-frontend/src/explore/components/SaveModal.tsx @@ -19,7 +19,6 @@ /* eslint camelcase: 0 */ import React from 'react'; import { Dispatch } from 'redux'; -import { isFeatureEnabled } from 'src/featureFlags'; import rison from 'rison'; import { connect } from 'react-redux'; import { withRouter, RouteComponentProps } from 'react-router-dom'; @@ -27,6 +26,7 @@ import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls'; import { css, DatasourceType, + isFeatureEnabled, FeatureFlag, isDefined, styled, diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.tsx index 9ad90167b598a..d1e85a30b13b3 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.tsx +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/AdhocFilterEditPopoverSimpleTabContent.test.tsx @@ -34,7 +34,7 @@ import { import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric'; import { render, screen, act, waitFor } from '@testing-library/react'; import { supersetTheme, FeatureFlag, ThemeProvider } from '@superset-ui/core'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import userEvent from '@testing-library/user-event'; import fetchMock from 'fetch-mock'; @@ -399,7 +399,7 @@ describe('AdhocFilterEditPopoverSimpleTabContent Advanced data Type Test', () => let isFeatureEnabledMock: any; beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( (featureFlag: FeatureFlag) => featureFlag === FeatureFlag.ENABLE_ADVANCED_DATA_TYPES, diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx index 482746acf898f..8c21bf75a9e07 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx @@ -20,6 +20,7 @@ import React, { useEffect, useState } from 'react'; import FormItem from 'src/components/Form/FormItem'; import { Select } from 'src/components'; import { + isFeatureEnabled, FeatureFlag, hasGenericChartAxes, isDefined, @@ -43,7 +44,6 @@ import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilt import { Tooltip } from 'src/components/Tooltip'; import { Input } from 'src/components/Input'; import { optionLabel } from 'src/utils/common'; -import { isFeatureEnabled } from 'src/featureFlags'; import { ColumnMeta, Dataset, diff --git a/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx b/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx index 7eed888fc171f..9dd0bc0ef0844 100644 --- a/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx +++ b/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx @@ -18,7 +18,14 @@ */ import React, { useCallback, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; -import { css, FeatureFlag, styled, t, useTheme } from '@superset-ui/core'; +import { + css, + isFeatureEnabled, + FeatureFlag, + styled, + t, + useTheme, +} from '@superset-ui/core'; import Icons from 'src/components/Icons'; import { Menu } from 'src/components/Menu'; import ModalTrigger from 'src/components/ModalTrigger'; @@ -29,7 +36,6 @@ import downloadAsImage from 'src/utils/downloadAsImage'; import { getChartPermalink } from 'src/utils/urlUtils'; import copyTextToClipboard from 'src/utils/copy'; import HeaderReportDropDown from 'src/components/ReportModal/HeaderReportDropdown'; -import { isFeatureEnabled } from 'src/featureFlags'; import ViewQueryModal from '../controls/ViewQueryModal'; import EmbedCodeContent from '../EmbedCodeContent'; import DashboardsSubMenu from './DashboardsSubMenu'; diff --git a/superset-frontend/src/featureFlags.ts b/superset-frontend/src/featureFlags.ts deleted file mode 100644 index d7387f279616b..0000000000000 --- a/superset-frontend/src/featureFlags.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { FeatureFlag, FeatureFlagMap } from '@superset-ui/core'; - -export function initFeatureFlags(featureFlags?: FeatureFlagMap) { - if (!window.featureFlags) { - window.featureFlags = featureFlags || {}; - } -} - -export function isFeatureEnabled(feature: FeatureFlag) { - try { - return !!window.featureFlags[feature]; - } catch (error) { - // eslint-disable-next-line no-console - console.error(`Failed to query feature flag ${feature} (see error below)`); - // eslint-disable-next-line no-console - console.error(error); - return false; - } -} diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx b/superset-frontend/src/features/alerts/AlertReportModal.tsx index a6c039c38a932..497c4d7b7627c 100644 --- a/superset-frontend/src/features/alerts/AlertReportModal.tsx +++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx @@ -25,6 +25,7 @@ import React, { } from 'react'; import { css, + isFeatureEnabled, FeatureFlag, styled, SupersetClient, @@ -41,7 +42,6 @@ import Modal from 'src/components/Modal'; import TimezoneSelector from 'src/components/TimezoneSelector'; import { Radio } from 'src/components/Radio'; import { propertyComparator } from 'src/components/Select/utils'; -import { isFeatureEnabled } from 'src/featureFlags'; import withToasts from 'src/components/MessageToasts/withToasts'; import Owner from 'src/types/Owner'; import { AntdCheckbox, AsyncSelect, Select } from 'src/components'; diff --git a/superset-frontend/src/features/charts/ChartCard.tsx b/superset-frontend/src/features/charts/ChartCard.tsx index 1a80d34aa8b78..352f34d3590e8 100644 --- a/superset-frontend/src/features/charts/ChartCard.tsx +++ b/superset-frontend/src/features/charts/ChartCard.tsx @@ -17,9 +17,8 @@ * under the License. */ import React from 'react'; -import { FeatureFlag, t, useTheme } from '@superset-ui/core'; +import { isFeatureEnabled, FeatureFlag, t, useTheme } from '@superset-ui/core'; import { Link, useHistory } from 'react-router-dom'; -import { isFeatureEnabled } from 'src/featureFlags'; import ConfirmStatusChange from 'src/components/ConfirmStatusChange'; import Icons from 'src/components/Icons'; import Chart from 'src/types/Chart'; diff --git a/superset-frontend/src/features/dashboards/DashboardCard.tsx b/superset-frontend/src/features/dashboards/DashboardCard.tsx index 8d159395154eb..640648c9030b7 100644 --- a/superset-frontend/src/features/dashboards/DashboardCard.tsx +++ b/superset-frontend/src/features/dashboards/DashboardCard.tsx @@ -18,8 +18,7 @@ */ import React from 'react'; import { Link, useHistory } from 'react-router-dom'; -import { FeatureFlag, t, useTheme } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; +import { isFeatureEnabled, FeatureFlag, t, useTheme } from '@superset-ui/core'; import { CardStyles } from 'src/views/CRUD/utils'; import { AntdDropdown } from 'src/components'; import { Menu } from 'src/components/Menu'; diff --git a/superset-frontend/src/features/tags/TagCard.tsx b/superset-frontend/src/features/tags/TagCard.tsx index 869678545c552..f9d82f9bcec63 100644 --- a/superset-frontend/src/features/tags/TagCard.tsx +++ b/superset-frontend/src/features/tags/TagCard.tsx @@ -18,9 +18,8 @@ */ import React from 'react'; import { Link } from 'react-router-dom'; -import { FeatureFlag, t, useTheme } from '@superset-ui/core'; +import { isFeatureEnabled, FeatureFlag, t, useTheme } from '@superset-ui/core'; import { CardStyles } from 'src/views/CRUD/utils'; -import { isFeatureEnabled } from 'src/featureFlags'; import { AntdDropdown } from 'src/components'; import { Menu } from 'src/components/Menu'; import ConfirmStatusChange from 'src/components/ConfirmStatusChange'; diff --git a/superset-frontend/src/middleware/asyncEvent.test.ts b/superset-frontend/src/middleware/asyncEvent.test.ts index 60ea10f504814..c819893580a95 100644 --- a/superset-frontend/src/middleware/asyncEvent.test.ts +++ b/superset-frontend/src/middleware/asyncEvent.test.ts @@ -19,7 +19,7 @@ import fetchMock from 'fetch-mock'; import WS from 'jest-websocket-mock'; import sinon from 'sinon'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { parseErrorJson } from 'src/utils/getClientErrorObject'; import * as asyncEvent from 'src/middleware/asyncEvent'; @@ -84,7 +84,7 @@ describe('asyncEvent middleware', () => { let featureEnabledStub: any; beforeEach(async () => { - featureEnabledStub = sinon.stub(featureFlags, 'isFeatureEnabled'); + featureEnabledStub = sinon.stub(uiCore, 'isFeatureEnabled'); featureEnabledStub.withArgs('GLOBAL_ASYNC_QUERIES').returns(true); }); diff --git a/superset-frontend/src/middleware/asyncEvent.ts b/superset-frontend/src/middleware/asyncEvent.ts index 5d878cef5522d..1d5fcb66c5692 100644 --- a/superset-frontend/src/middleware/asyncEvent.ts +++ b/superset-frontend/src/middleware/asyncEvent.ts @@ -18,6 +18,7 @@ */ import { ensureIsArray, + isFeatureEnabled, FeatureFlag, makeApi, SupersetClient, @@ -25,7 +26,6 @@ import { } from '@superset-ui/core'; import { SupersetError } from 'src/components/ErrorMessage/types'; import getBootstrapData from 'src/utils/getBootstrapData'; -import { isFeatureEnabled } from '../featureFlags'; import { getClientErrorObject, parseErrorJson, diff --git a/superset-frontend/src/pages/ChartCreation/index.tsx b/superset-frontend/src/pages/ChartCreation/index.tsx index 7ff3442c9d7bc..18b8080db7aef 100644 --- a/superset-frontend/src/pages/ChartCreation/index.tsx +++ b/superset-frontend/src/pages/ChartCreation/index.tsx @@ -20,6 +20,7 @@ import React, { ReactNode } from 'react'; import rison from 'rison'; import querystring from 'query-string'; import { + isFeatureEnabled, FeatureFlag, isDefined, JsonResponse, @@ -34,7 +35,6 @@ import Button from 'src/components/Button'; import { AsyncSelect, Steps } from 'src/components'; import { Tooltip } from 'src/components/Tooltip'; import withToasts from 'src/components/MessageToasts/withToasts'; -import { isFeatureEnabled } from 'src/featureFlags'; import VizTypeGallery, { MAX_ADVISABLE_VIZ_GALLERY_WIDTH, diff --git a/superset-frontend/src/pages/ChartList/ChartList.test.jsx b/superset-frontend/src/pages/ChartList/ChartList.test.jsx index fc216e617dd95..6169c2a67e98a 100644 --- a/superset-frontend/src/pages/ChartList/ChartList.test.jsx +++ b/superset-frontend/src/pages/ChartList/ChartList.test.jsx @@ -22,7 +22,7 @@ import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; import fetchMock from 'fetch-mock'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; import { styledMount as mount } from 'spec/helpers/theming'; import { render, screen, cleanup } from 'spec/helpers/testing-library'; @@ -101,7 +101,7 @@ fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false }); describe('ChartList', () => { const isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(feature => feature === 'LISTVIEWS_DEFAULT_CARD_VIEW'); afterAll(() => { @@ -199,7 +199,7 @@ describe('RTL', () => { let isFeatureEnabledMock; beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); await renderAndWait(); }); diff --git a/superset-frontend/src/pages/ChartList/index.tsx b/superset-frontend/src/pages/ChartList/index.tsx index ef1f9374e4b16..e94dc426b1b92 100644 --- a/superset-frontend/src/pages/ChartList/index.tsx +++ b/superset-frontend/src/pages/ChartList/index.tsx @@ -18,6 +18,7 @@ */ import { ensureIsArray, + isFeatureEnabled, FeatureFlag, getChartMetadataRegistry, JsonResponse, @@ -29,7 +30,6 @@ import React, { useState, useMemo, useCallback } from 'react'; import rison from 'rison'; import { uniqBy } from 'lodash'; import moment from 'moment'; -import { isFeatureEnabled } from 'src/featureFlags'; import { createErrorHandler, createFetchRelated, diff --git a/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx b/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx index bd91faf614111..811f51afba9c8 100644 --- a/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx +++ b/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx @@ -22,7 +22,7 @@ import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import fetchMock from 'fetch-mock'; import { Provider } from 'react-redux'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; import { styledMount as mount } from 'spec/helpers/theming'; @@ -98,7 +98,7 @@ fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false }); describe('DashboardList', () => { const isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(feature => feature === 'LISTVIEWS_DEFAULT_CARD_VIEW'); afterAll(() => { @@ -217,7 +217,7 @@ describe('RTL', () => { let isFeatureEnabledMock; beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); await renderAndWait(); }); diff --git a/superset-frontend/src/pages/DashboardList/index.tsx b/superset-frontend/src/pages/DashboardList/index.tsx index 3db775e66ec82..2b6252309ddd4 100644 --- a/superset-frontend/src/pages/DashboardList/index.tsx +++ b/superset-frontend/src/pages/DashboardList/index.tsx @@ -16,11 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -import { FeatureFlag, styled, SupersetClient, t } from '@superset-ui/core'; +import { + isFeatureEnabled, + FeatureFlag, + styled, + SupersetClient, + t, +} from '@superset-ui/core'; import React, { useState, useMemo, useCallback } from 'react'; import { Link } from 'react-router-dom'; import rison from 'rison'; -import { isFeatureEnabled } from 'src/featureFlags'; import { createFetchRelated, createErrorHandler, diff --git a/superset-frontend/src/pages/DatabaseList/index.tsx b/superset-frontend/src/pages/DatabaseList/index.tsx index e2ba4ea9b0370..b2c18cecec6e5 100644 --- a/superset-frontend/src/pages/DatabaseList/index.tsx +++ b/superset-frontend/src/pages/DatabaseList/index.tsx @@ -17,6 +17,7 @@ * under the License. */ import { + isFeatureEnabled, FeatureFlag, getExtensionsRegistry, styled, @@ -30,7 +31,6 @@ import { useQueryParams, BooleanParam } from 'use-query-params'; import { LocalStorageKeys, setItem } from 'src/utils/localStorageHelpers'; import Loading from 'src/components/Loading'; -import { isFeatureEnabled } from 'src/featureFlags'; import { useListViewResource } from 'src/views/CRUD/hooks'; import { createErrorHandler, uploadUserPerms } from 'src/views/CRUD/utils'; import withToasts from 'src/components/MessageToasts/withToasts'; diff --git a/superset-frontend/src/pages/DatasetList/DatasetList.test.tsx b/superset-frontend/src/pages/DatasetList/DatasetList.test.tsx index 358a5fcfcca34..115a861bddf52 100644 --- a/superset-frontend/src/pages/DatasetList/DatasetList.test.tsx +++ b/superset-frontend/src/pages/DatasetList/DatasetList.test.tsx @@ -26,7 +26,7 @@ import { render, screen, cleanup } from 'spec/helpers/testing-library'; import { FeatureFlag } from '@superset-ui/core'; import userEvent from '@testing-library/user-event'; import { QueryParamProvider } from 'use-query-params'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import DatasetList from 'src/pages/DatasetList'; import ListView from 'src/components/ListView'; @@ -258,7 +258,7 @@ describe('RTL', () => { let isFeatureEnabledMock: jest.SpyInstance; beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); await renderAndWait(); }); diff --git a/superset-frontend/src/pages/DatasetList/index.tsx b/superset-frontend/src/pages/DatasetList/index.tsx index 43913a828029c..7633edb01617a 100644 --- a/superset-frontend/src/pages/DatasetList/index.tsx +++ b/superset-frontend/src/pages/DatasetList/index.tsx @@ -17,6 +17,7 @@ * under the License. */ import { + isFeatureEnabled, FeatureFlag, getExtensionsRegistry, styled, @@ -57,7 +58,6 @@ import FacePile from 'src/components/FacePile'; import CertifiedBadge from 'src/components/CertifiedBadge'; import InfoTooltip from 'src/components/InfoTooltip'; import ImportModelsModal from 'src/components/ImportModal/index'; -import { isFeatureEnabled } from 'src/featureFlags'; import WarningIconWithTooltip from 'src/components/WarningIconWithTooltip'; import { isUserAdmin } from 'src/dashboard/util/permissionUtils'; import { GenericLink } from 'src/components/GenericLink/GenericLink'; diff --git a/superset-frontend/src/pages/Home/Home.test.tsx b/superset-frontend/src/pages/Home/Home.test.tsx index cbf9b00272823..9f0b4e3ca1791 100644 --- a/superset-frontend/src/pages/Home/Home.test.tsx +++ b/superset-frontend/src/pages/Home/Home.test.tsx @@ -23,7 +23,7 @@ import thunk from 'redux-thunk'; import fetchMock from 'fetch-mock'; import { act } from 'react-dom/test-utils'; import configureStore from 'redux-mock-store'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import Welcome from 'src/pages/Home'; import { ReactWrapper } from 'enzyme'; import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; @@ -211,7 +211,7 @@ describe('Welcome page with toggle switch', () => { beforeAll(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockReturnValue(true); await act(async () => { wrapper = await mountAndWait(); diff --git a/superset-frontend/src/pages/Home/index.tsx b/superset-frontend/src/pages/Home/index.tsx index 00124eac7c5a6..cfeb4cd98283a 100644 --- a/superset-frontend/src/pages/Home/index.tsx +++ b/superset-frontend/src/pages/Home/index.tsx @@ -18,6 +18,7 @@ */ import React, { useEffect, useMemo, useState } from 'react'; import { + isFeatureEnabled, FeatureFlag, getExtensionsRegistry, JsonObject, @@ -45,7 +46,6 @@ import { loadingCardCount, mq, } from 'src/views/CRUD/utils'; -import { isFeatureEnabled } from 'src/featureFlags'; import { AntdSwitch } from 'src/components'; import getBootstrapData from 'src/utils/getBootstrapData'; import { TableTab } from 'src/views/CRUD/types'; diff --git a/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.jsx b/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.jsx index 5d9b35a4a30b6..3804010e26f1e 100644 --- a/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.jsx +++ b/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.jsx @@ -27,7 +27,7 @@ import { render, screen, cleanup, waitFor } from 'spec/helpers/testing-library'; import userEvent from '@testing-library/user-event'; import { QueryParamProvider } from 'use-query-params'; import { act } from 'react-dom/test-utils'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import SavedQueryList from 'src/pages/SavedQueryList'; import SubMenu from 'src/features/home/SubMenu'; import ListView from 'src/components/ListView'; @@ -261,7 +261,7 @@ describe('RTL', () => { let isFeatureEnabledMock; beforeEach(async () => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation(() => true); await renderAndWait(); }); diff --git a/superset-frontend/src/pages/SavedQueryList/index.tsx b/superset-frontend/src/pages/SavedQueryList/index.tsx index a985bd8ea8659..f0d89dba27fba 100644 --- a/superset-frontend/src/pages/SavedQueryList/index.tsx +++ b/superset-frontend/src/pages/SavedQueryList/index.tsx @@ -17,7 +17,13 @@ * under the License. */ -import { FeatureFlag, styled, SupersetClient, t } from '@superset-ui/core'; +import { + isFeatureEnabled, + FeatureFlag, + styled, + SupersetClient, + t, +} from '@superset-ui/core'; import React, { useState, useMemo, useCallback } from 'react'; import rison from 'rison'; import moment from 'moment'; @@ -46,7 +52,6 @@ import { commonMenuData } from 'src/features/home/commonMenuData'; import { SavedQueryObject } from 'src/views/CRUD/types'; import copyTextToClipboard from 'src/utils/copy'; import Tag from 'src/types/TagType'; -import { isFeatureEnabled } from 'src/featureFlags'; import ImportModelsModal from 'src/components/ImportModal/index'; import Icons from 'src/components/Icons'; import { BootstrapUser } from 'src/types/bootstrapTypes'; diff --git a/superset-frontend/src/pages/Tags/index.tsx b/superset-frontend/src/pages/Tags/index.tsx index 8087b3f4c6ab7..03a2b1da9c884 100644 --- a/superset-frontend/src/pages/Tags/index.tsx +++ b/superset-frontend/src/pages/Tags/index.tsx @@ -16,9 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { FeatureFlag, t } from '@superset-ui/core'; +import { isFeatureEnabled, FeatureFlag, t } from '@superset-ui/core'; import React, { useMemo, useCallback } from 'react'; -import { isFeatureEnabled } from 'src/featureFlags'; import { createFetchRelated, createErrorHandler, diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index d1d84b777c9a6..52fa959905931 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -20,14 +20,18 @@ import { setConfig as setHotLoaderConfig } from 'react-hot-loader'; import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; import moment from 'moment'; // eslint-disable-next-line no-restricted-imports -import { configure, makeApi, supersetTheme } from '@superset-ui/core'; +import { + configure, + makeApi, + supersetTheme, + initFeatureFlags, +} from '@superset-ui/core'; import { merge } from 'lodash'; import setupClient from './setup/setupClient'; import setupColors from './setup/setupColors'; import setupFormatters from './setup/setupFormatters'; import setupDashboardComponents from './setup/setupDashboardComponents'; import { User } from './types/bootstrapTypes'; -import { initFeatureFlags } from './featureFlags'; import getBootstrapData from './utils/getBootstrapData'; if (process.env.WEBPACK_MODE === 'development') { diff --git a/superset-frontend/src/utils/hostNamesConfig.js b/superset-frontend/src/utils/hostNamesConfig.js index dfbf9b26c9195..1d3869a8aa63b 100644 --- a/superset-frontend/src/utils/hostNamesConfig.js +++ b/superset-frontend/src/utils/hostNamesConfig.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { initFeatureFlags } from 'src/featureFlags'; +import { initFeatureFlags } from '@superset-ui/core'; import getBootstrapData from './getBootstrapData'; function getDomainsConfig() { diff --git a/superset-frontend/src/views/routes.test.tsx b/superset-frontend/src/views/routes.test.tsx index 3b01288bfdfd0..379abefb049d1 100644 --- a/superset-frontend/src/views/routes.test.tsx +++ b/superset-frontend/src/views/routes.test.tsx @@ -19,10 +19,6 @@ import React from 'react'; import { isFrontendRoute, routes } from './routes'; -jest.mock('src/featureFlags', () => ({ - ...jest.requireActual('src/featureFlags'), - isFeatureEnabled: jest.fn().mockReturnValue(true), -})); jest.mock('src/pages/Home', () => () =>
); describe('isFrontendRoute', () => { From 2391f7a24bf0e1d1516b477984dfa61ff45f466b Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Wed, 9 Aug 2023 17:40:55 -0300 Subject: [PATCH 2/2] Adds tests to featureFlags --- .../test/utils/featureFlag.test.ts | 29 +++++++++++++++++++ .../dashboard/util/permissionUtils.test.ts | 20 +++++++------ .../src/dashboard/util/permissionUtils.ts | 3 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts index 12aefcc1026a9..8c6a45ef0c479 100644 --- a/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts +++ b/superset-frontend/packages/superset-ui-core/test/utils/featureFlag.test.ts @@ -18,6 +18,35 @@ */ import * as uiCore from '@superset-ui/core'; +it('initializes feature flags', () => { + Object.defineProperty(window, 'featureFlags', { + value: undefined, + }); + uiCore.initFeatureFlags(); + expect(window.featureFlags).toEqual({}); +}); + +it('initializes feature flags with predefined values', () => { + Object.defineProperty(window, 'featureFlags', { + value: undefined, + }); + const featureFlags = { + CLIENT_CACHE: true, + DRILL_BY: false, + }; + uiCore.initFeatureFlags(featureFlags); + expect(window.featureFlags).toEqual(featureFlags); +}); + +it('does nothing if feature flags are already initialized', () => { + const featureFlags = { DRILL_BY: false }; + Object.defineProperty(window, 'featureFlags', { + value: featureFlags, + }); + uiCore.initFeatureFlags({ DRILL_BY: true }); + expect(window.featureFlags).toEqual(featureFlags); +}); + it('returns false and raises console error if feature flags have not been initialized', () => { const logging = jest.spyOn(uiCore.logging, 'error'); Object.defineProperty(window, 'featureFlags', { diff --git a/superset-frontend/src/dashboard/util/permissionUtils.test.ts b/superset-frontend/src/dashboard/util/permissionUtils.test.ts index e5e958013d6bb..b9b0e071b4ea1 100644 --- a/superset-frontend/src/dashboard/util/permissionUtils.test.ts +++ b/superset-frontend/src/dashboard/util/permissionUtils.test.ts @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { FeatureFlag } from '@superset-ui/core'; -import * as featureFlags from 'src/featureFlags'; +import * as uiCore from '@superset-ui/core'; import { UndefinedUser, UserWithPermissionsAndRoles, @@ -91,7 +90,10 @@ const dashboard: Dashboard = { roles: [], }; -let isFeatureEnabledMock: jest.MockInstance; +let isFeatureEnabledMock: jest.MockInstance< + boolean, + [feature: uiCore.FeatureFlag] +>; describe('canUserEditDashboard', () => { it('allows owners to edit', () => { @@ -160,10 +162,10 @@ test('canUserAccessSqlLab returns true for sqllab role', () => { describe('canUserSaveAsDashboard with RBAC feature flag disabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( - (featureFlag: FeatureFlag) => - featureFlag !== FeatureFlag.DASHBOARD_RBAC, + (featureFlag: uiCore.FeatureFlag) => + featureFlag !== uiCore.FeatureFlag.DASHBOARD_RBAC, ); }); @@ -188,10 +190,10 @@ describe('canUserSaveAsDashboard with RBAC feature flag disabled', () => { describe('canUserSaveAsDashboard with RBAC feature flag enabled', () => { beforeAll(() => { isFeatureEnabledMock = jest - .spyOn(featureFlags, 'isFeatureEnabled') + .spyOn(uiCore, 'isFeatureEnabled') .mockImplementation( - (featureFlag: FeatureFlag) => - featureFlag === FeatureFlag.DASHBOARD_RBAC, + (featureFlag: uiCore.FeatureFlag) => + featureFlag === uiCore.FeatureFlag.DASHBOARD_RBAC, ); }); diff --git a/superset-frontend/src/dashboard/util/permissionUtils.ts b/superset-frontend/src/dashboard/util/permissionUtils.ts index b01484a4e78e2..23744bde89cf5 100644 --- a/superset-frontend/src/dashboard/util/permissionUtils.ts +++ b/superset-frontend/src/dashboard/util/permissionUtils.ts @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { FeatureFlag } from '@superset-ui/core'; -import { isFeatureEnabled } from 'src/featureFlags'; +import { isFeatureEnabled, FeatureFlag } from '@superset-ui/core'; import { isUserWithPermissionsAndRoles, UndefinedUser,