blob: 1e600cf41b743616a68c5047f208dc5c74e5789c [file] [log] [blame]
/**
* 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.
*/
// eslint-disable-next-line import/no-extraneous-dependencies
import fetchMock from 'fetch-mock';
import { render } from 'spec/helpers/testing-library';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { configureStore } from '@reduxjs/toolkit';
import { QueryParamProvider } from 'use-query-params';
import ChartList from 'src/pages/ChartList';
import handleResourceExport from 'src/utils/export';
export const mockHandleResourceExport =
handleResourceExport as jest.MockedFunction<typeof handleResourceExport>;
export const mockCharts = [
{
id: 0,
url: '/superset/slice/0/',
viz_type: 'table',
slice_name: 'Test Chart 0',
// ✅ Basic case - has some data
owners: [{ first_name: 'Test', last_name: 'User', id: 1 }],
dashboards: [{ dashboard_title: 'Test Dashboard', id: 1 }],
tags: [{ name: 'basic', type: 1, id: 1 }],
datasource_name_text: 'public.test_dataset',
datasource_url: '/superset/explore/table/1/',
datasource_id: 1,
changed_by_name: 'user',
changed_by: {
first_name: 'Test',
last_name: 'User',
id: 1,
},
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '1 day ago',
last_saved_at: new Date().toISOString(),
created_by: 'user',
description: 'Test chart description',
thumbnail_url: '/api/v1/chart/0/thumbnail/',
certified_by: null,
certification_details: null,
},
{
id: 1,
url: '/superset/slice/1/',
viz_type: 'bar',
slice_name: 'Test Chart 1',
// ✅ FULL DATA CASE - everything populated for comprehensive testing
owners: [
{ first_name: 'Admin', last_name: 'User', id: 2 },
{ first_name: 'Data', last_name: 'Analyst', id: 3 },
],
dashboards: [
{ dashboard_title: 'Sales Dashboard', id: 2 },
{ dashboard_title: 'Analytics Dashboard', id: 3 },
{ dashboard_title: 'Executive Dashboard', id: 4 },
],
tags: [
{ name: 'production', type: 1, id: 2 },
{ name: 'sales', type: 1, id: 3 },
{ name: 'analytics', type: 1, id: 4 },
],
datasource_name_text: 'sales_data',
datasource_url: '/superset/explore/table/2/',
datasource_id: 2,
changed_by_name: 'admin',
changed_by: {
first_name: 'Admin',
last_name: 'User',
id: 2,
},
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '2 days ago',
last_saved_at: new Date().toISOString(),
created_by: 'admin',
description: 'Comprehensive sales analytics chart',
thumbnail_url: '/api/v1/chart/1/thumbnail/',
certified_by: 'Data Team',
certification_details: 'Approved for production use',
},
{
id: 2,
url: '/superset/slice/2/',
viz_type: 'line',
slice_name: 'Test Chart 2',
// ✅ EDGE CASE - no owners, no dataset, no dashboards, no tags
owners: [],
dashboards: [],
tags: [],
datasource_name_text: null,
datasource_url: null,
datasource_id: null,
changed_by_name: 'system',
changed_by: {
first_name: 'System',
last_name: 'User',
id: 999,
},
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '3 days ago',
last_saved_at: new Date().toISOString(),
created_by: 'system',
description: null,
thumbnail_url: '/api/v1/chart/2/thumbnail/',
certified_by: null,
certification_details: null,
},
{
id: 3,
url: '/superset/slice/3/',
viz_type: 'area',
slice_name: 'Test Chart 3',
// ✅ TRUNCATION TEST - Exactly at limits (4 owners, 20 dashboards)
owners: [
{ first_name: 'Admin', last_name: 'User', id: 2 },
{ first_name: 'Data', last_name: 'Analyst', id: 3 },
{ first_name: 'Limit', last_name: 'User', id: 40 },
{ first_name: 'Test', last_name: 'User', id: 43 },
],
dashboards: Array.from({ length: 20 }, (_, i) => ({
dashboard_title: `Dashboard ${i + 1}`,
id: 200 + i,
})),
tags: [{ name: 'limit-test', type: 1, id: 10 }],
datasource_name_text: 'public.limits_dataset',
datasource_url: '/superset/explore/table/4/',
datasource_id: 4,
changed_by_name: 'limit_user',
changed_by: {
first_name: 'Limit',
last_name: 'User',
id: 40,
},
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '4 days ago',
last_saved_at: new Date().toISOString(),
created_by: 'limit_user',
description: 'Chart at exact truncation limits',
thumbnail_url: '/api/v1/chart/3/thumbnail/',
certified_by: 'QA Team',
certification_details: 'Verified for limit testing',
},
{
id: 4,
url: '/superset/slice/4/',
viz_type: 'bubble',
slice_name: 'Test Chart 4',
// ✅ TRUNCATION TEST - Just above limits (5 owners shows +1, 21 dashboards)
owners: [
{ first_name: 'Admin', last_name: 'User', id: 2 },
{ first_name: 'Data', last_name: 'Analyst', id: 3 },
{ first_name: 'Limit', last_name: 'User', id: 40 },
{ first_name: 'Test', last_name: 'User', id: 43 },
{ first_name: 'Overflow', last_name: 'User', id: 50 },
],
dashboards: Array.from({ length: 21 }, (_, i) => ({
dashboard_title: `Extra Dashboard ${i + 1}`,
id: 300 + i,
})),
tags: [{ name: 'overflow', type: 1, id: 11 }],
datasource_name_text: 'public.overflow_dataset',
datasource_url: '/superset/explore/table/5/',
datasource_id: 5,
changed_by_name: 'overflow_user',
changed_by: {
first_name: 'Overflow',
last_name: 'User',
id: 50,
},
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '5 days ago',
last_saved_at: new Date().toISOString(),
created_by: 'overflow_user',
description: 'Chart exceeding truncation limits',
thumbnail_url: '/api/v1/chart/4/thumbnail/',
certified_by: null,
certification_details: null,
},
];
// Shared store utilities
export const createMockStore = (initialState: any = {}) =>
configureStore({
reducer: {
user: (state = initialState.user || {}) => state,
common: (state = initialState.common || {}) => state,
charts: (state = initialState.charts || {}) => state,
},
preloadedState: initialState,
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
serializableCheck: false,
immutableCheck: false,
}),
});
export const createDefaultStoreState = (user: any) => ({
user,
common: {
conf: {
SUPERSET_WEBSERVER_TIMEOUT: 60000,
},
},
charts: {
chartList: mockCharts,
},
});
export const renderChartList = (user: any, props = {}, storeState = {}) => {
const defaultStoreState = createDefaultStoreState(user);
const storeStateWithUser = {
...defaultStoreState,
user,
...storeState,
};
const store = createMockStore(storeStateWithUser);
return render(
<Provider store={store}>
<MemoryRouter>
<QueryParamProvider>
<ChartList user={user} {...props} />
</QueryParamProvider>
</MemoryRouter>
</Provider>,
);
};
// API endpoint constants for reuse across tests
export const API_ENDPOINTS = {
CHARTS_INFO: 'glob:*/api/v1/chart/_info*',
CHARTS: 'glob:*/api/v1/chart/?*',
CHART_FAVORITE_STATUS: 'glob:*/api/v1/chart/favorite_status*',
CHART_VIZ_TYPES: 'glob:*/api/v1/chart/viz_types*',
CHART_THUMBNAILS: 'glob:*/api/v1/chart/*/thumbnail/*',
DATASETS: 'glob:*/api/v1/dataset/?q=*',
DASHBOARDS: 'glob:*/api/v1/dashboard/?q=*',
CHART_RELATED_OWNERS: 'glob:*/api/v1/chart/related/owners*',
CHART_RELATED_CHANGED_BY: 'glob:*/api/v1/chart/related/changed_by*',
CATCH_ALL: 'glob:*',
};
export const setupMocks = () => {
fetchMock.reset();
fetchMock.get(API_ENDPOINTS.CHARTS_INFO, {
permissions: ['can_read', 'can_write', 'can_export'],
});
fetchMock.get(API_ENDPOINTS.CHARTS, {
result: mockCharts,
chart_count: mockCharts.length,
});
fetchMock.get(API_ENDPOINTS.CHART_FAVORITE_STATUS, {
result: [],
});
fetchMock.get(API_ENDPOINTS.CHART_VIZ_TYPES, {
result: [
{ text: 'Table', value: 'table' },
{ text: 'Bar Chart', value: 'bar' },
{ text: 'Line Chart', value: 'line' },
],
count: 3,
});
fetchMock.get(API_ENDPOINTS.CHART_THUMBNAILS, {
body: new Blob(),
sendAsJson: false,
});
fetchMock.get(API_ENDPOINTS.DATASETS, {
result: [],
count: 0,
});
fetchMock.get(API_ENDPOINTS.DASHBOARDS, {
result: [],
count: 0,
});
fetchMock.get(API_ENDPOINTS.CHART_RELATED_OWNERS, {
result: [],
count: 0,
});
fetchMock.get(API_ENDPOINTS.CHART_RELATED_CHANGED_BY, {
result: [],
count: 0,
});
fetchMock.get(API_ENDPOINTS.CATCH_ALL, { result: [], count: 0 });
};