You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2026/08/25 00:38:36 UTC
(superset) branch master updated: fix(archived-list): use the semantic-layers-aware label for the dataset type (#43465)
This is an automated email from the ASF dual-hosted git repository.
aminghadersohi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new f83fb7c0e07 fix(archived-list): use the semantic-layers-aware label for the dataset type (#43465)
f83fb7c0e07 is described below
commit f83fb7c0e07ae646f4e8bcc9bf86378b160a7f2e
Author: Mike Bridge <mi...@preset.io>
AuthorDate: Mon Aug 24 18:38:29 2026 -0600
fix(archived-list): use the semantic-layers-aware label for the dataset type (#43465)
Co-authored-by: Claude Fable 5 <no...@anthropic.com>
Co-authored-by: Amin Ghadersohi <am...@gmail.com>
---
docs/docs/using-superset/recently-archived.mdx | 3 +-
.../src/pages/ArchivedList/ArchivedList.test.tsx | 72 ++++++++++++++++++++++
superset-frontend/src/pages/ArchivedList/index.tsx | 19 +++---
3 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/docs/docs/using-superset/recently-archived.mdx b/docs/docs/using-superset/recently-archived.mdx
index 777e4efa56f..ebca8c6c416 100644
--- a/docs/docs/using-superset/recently-archived.mdx
+++ b/docs/docs/using-superset/recently-archived.mdx
@@ -26,7 +26,8 @@ page and its menu entry are hidden, and deletes are permanent as before.
## Finding archived objects
Open **Recently Archived** and pick a type — **Chart**, **Dashboard**, or
-**Dataset** — from the Type selector. The view shows one type at a time; each
+**Dataset** (shown as **Datasource** when semantic layers are enabled) — from
+the Type selector. The view shows one type at a time; each
type is read from its own list endpoint, so the same row-level access rules that
govern the normal lists apply here.
diff --git a/superset-frontend/src/pages/ArchivedList/ArchivedList.test.tsx b/superset-frontend/src/pages/ArchivedList/ArchivedList.test.tsx
index 360f682898b..849e3164b9b 100644
--- a/superset-frontend/src/pages/ArchivedList/ArchivedList.test.tsx
+++ b/superset-frontend/src/pages/ArchivedList/ArchivedList.test.tsx
@@ -25,8 +25,10 @@ import {
fireEvent,
userEvent,
waitFor,
+ within,
selectOption,
} from 'spec/helpers/testing-library';
+import { FeatureFlag, isFeatureEnabled } from '@superset-ui/core';
import { MemoryRouter } from 'react-router-dom';
import { QueryParamProvider } from 'use-query-params';
import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5';
@@ -88,6 +90,15 @@ const mockCharts = [
// list so `_info` requests resolve to it rather than the broader list glob.
// withToasts injects the toast callbacks as props; the harness renders no
// toast container, so the spy is the only way to pin what the user is told.
+// The type label for the dataset concept is flag-aware (SEMANTIC_LAYERS →
+// "Datasource"); mock the flag reader so tests can exercise both states. The
+// default (false for every flag) matches the real test environment, where no
+// bootstrap flags are set.
+jest.mock('@superset-ui/core', () => ({
+ ...jest.requireActual('@superset-ui/core'),
+ isFeatureEnabled: jest.fn(() => false),
+}));
+
const mockAddDangerToast = jest.fn();
jest.mock('src/components/MessageToasts/withToasts', () => ({
__esModule: true,
@@ -144,6 +155,13 @@ beforeEach(() => {
mockAddDangerToast.mockClear();
});
+afterEach(() => {
+ // The flag mock is shared module state; restore the environment default so a
+ // flag-flipping test that dies mid-body (e.g. by Jest timeout) cannot leak
+ // SEMANTIC_LAYERS into whichever test runs next.
+ (isFeatureEnabled as jest.Mock).mockImplementation(() => false);
+});
+
test('renders archived rows with Name and Type columns', async () => {
mockRoutes();
renderArchivedList();
@@ -573,3 +591,57 @@ test('a viewer who can read none of the types gets an empty state, not three 403
// No list fetch was ever issued.
expect(fetchMock.callHistory.calls(/chart\/\?q/)).toHaveLength(0);
});
+
+test('labels the dataset type "Datasource" when semantic layers is enabled', async () => {
+ (isFeatureEnabled as jest.Mock).mockImplementation(
+ (flag: FeatureFlag) => flag === FeatureFlag.SemanticLayers,
+ );
+ mockRoutes();
+ renderArchivedList();
+ await screen.findByText('Deleted Chart One');
+
+ userEvent.click(screen.getByRole('combobox', { name: 'Type' }));
+ expect(
+ await screen.findByRole('option', { name: 'Datasource' }),
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByRole('option', { name: 'Dataset' }),
+ ).not.toBeInTheDocument();
+
+ // Selecting the renamed option still drives the dataset resource —
+ // the underlying type value is flag-independent.
+ await selectOption('Datasource', 'Type');
+ await screen.findByText('deleted_table_one');
+ expect(
+ fetchMock.callHistory.calls(datasetListEndpoint).length,
+ ).toBeGreaterThan(0);
+ // Pin the Type COLUMN cell, not just the Select's own rendered value.
+ const datasetRow = screen.getByText('deleted_table_one').closest('tr');
+ expect(
+ within(datasetRow as HTMLElement).getByText('Datasource'),
+ ).toBeInTheDocument();
+});
+
+test('labels the dataset type "Dataset" when semantic layers is disabled', async () => {
+ mockRoutes();
+ renderArchivedList();
+ await screen.findByText('Deleted Chart One');
+
+ userEvent.click(screen.getByRole('combobox', { name: 'Type' }));
+ expect(
+ await screen.findByRole('option', { name: 'Dataset' }),
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByRole('option', { name: 'Datasource' }),
+ ).not.toBeInTheDocument();
+
+ await selectOption('Dataset', 'Type');
+ await screen.findByText('deleted_table_one');
+ expect(
+ fetchMock.callHistory.calls(datasetListEndpoint).length,
+ ).toBeGreaterThan(0);
+ const datasetRow = screen.getByText('deleted_table_one').closest('tr');
+ expect(
+ within(datasetRow as HTMLElement).getByText('Dataset'),
+ ).toBeInTheDocument();
+});
diff --git a/superset-frontend/src/pages/ArchivedList/index.tsx b/superset-frontend/src/pages/ArchivedList/index.tsx
index fffa83b83ec..c6d5f811c5d 100644
--- a/superset-frontend/src/pages/ArchivedList/index.tsx
+++ b/superset-frontend/src/pages/ArchivedList/index.tsx
@@ -37,6 +37,7 @@ import {
type ListViewFilters,
} from 'src/components';
import SubMenu from 'src/features/home/SubMenu';
+import { datasetLabel } from 'src/features/semanticLayers/label';
import withToasts from 'src/components/MessageToasts/withToasts';
import { recoveredToast } from 'src/utils/softDeleteCopy';
import { findPermission } from 'src/utils/findPermission';
@@ -82,10 +83,12 @@ const EmptyStateRow = styled.div`
`}
`;
-const TYPE_LABELS: Record<ArchivedType, string> = {
- chart: t('Chart'),
- dashboard: t('Dashboard'),
- dataset: t('Dataset'),
+// Getters, not strings: the dataset label follows the SEMANTIC_LAYERS flag
+// ("Dataset" / "Datasource"), read at render time via the shared naming module.
+const TYPE_LABELS: Record<ArchivedType, () => string> = {
+ chart: () => t('Chart'),
+ dashboard: () => t('Dashboard'),
+ dataset: datasetLabel,
};
interface ToastProps {
@@ -166,7 +169,7 @@ function ArchivedListBody({
refreshData,
} = useListViewResource<ArchivedItem>(
config.resource,
- TYPE_LABELS[type],
+ TYPE_LABELS[type](),
addDangerToast,
true,
[],
@@ -247,7 +250,7 @@ function ArchivedListBody({
name => {
const { text, options } = recoveredToast(
name,
- TYPE_LABELS[type],
+ TYPE_LABELS[type](),
item.url ?? item.explore_url,
);
addSuccessToast(text, options);
@@ -306,7 +309,7 @@ function ArchivedListBody({
id: config.nameField,
},
{
- Cell: () => TYPE_LABELS[type],
+ Cell: () => TYPE_LABELS[type](),
Header: t('Type'),
id: 'type',
disableSortBy: true,
@@ -539,7 +542,7 @@ function ArchivedList({ addDangerToast, addSuccessToast }: ToastProps) {
onChange={handleTypeChange}
options={availableTypes.map(option => ({
value: option,
- label: TYPE_LABELS[option],
+ label: TYPE_LABELS[option](),
}))}
/>
</TypeSelectRow>