mirror of
https://github.com/apache/superset.git
synced 2026-04-18 23:55:00 +00:00
fix: Invalid error tooltip if control label is function (#34698)
This commit is contained in:
committed by
GitHub
parent
f6353bd1e8
commit
47874318df
@@ -700,6 +700,7 @@ export const ControlPanelsContainer = (props: ControlPanelsContainerProps) => {
|
||||
title={props.errorMessage}
|
||||
>
|
||||
<Icons.CloseCircleOutlined
|
||||
data-test="query-error-tooltip-trigger"
|
||||
iconColor={theme.colorErrorText}
|
||||
iconSize="s"
|
||||
/>
|
||||
|
||||
@@ -299,3 +299,170 @@ test('does omit hiddenFormData when query_mode is not enabled', async () => {
|
||||
expect(formData[key]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
// Component tests for the errorMessage behavior
|
||||
test('does not show error indicator when no controls have validation errors', async () => {
|
||||
getChartControlPanelRegistry().registerValue('table', {
|
||||
controlPanelSections: [],
|
||||
});
|
||||
const customState = {
|
||||
...reduxState,
|
||||
explore: {
|
||||
...reduxState.explore,
|
||||
controls: {
|
||||
...reduxState.explore.controls,
|
||||
metric: { value: 'count', label: 'Metric' },
|
||||
groupby: { value: ['category'], label: 'Group by' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithRouter({ initialState: customState });
|
||||
|
||||
await waitFor(() => {
|
||||
const errorIndicator = screen.queryByTestId('query-error-tooltip-trigger');
|
||||
expect(errorIndicator).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test('shows error indicator when controls have validation errors', async () => {
|
||||
getChartControlPanelRegistry().registerValue('table', {
|
||||
controlPanelSections: [],
|
||||
});
|
||||
const customState = {
|
||||
...reduxState,
|
||||
explore: {
|
||||
...reduxState.explore,
|
||||
controls: {
|
||||
...reduxState.explore.controls,
|
||||
metric: {
|
||||
value: '',
|
||||
label: 'Metric',
|
||||
validationErrors: ['Metric is required'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithRouter({ initialState: customState });
|
||||
|
||||
const errorIndicator = await screen.findByTestId(
|
||||
'query-error-tooltip-trigger',
|
||||
);
|
||||
|
||||
userEvent.hover(errorIndicator);
|
||||
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
|
||||
const errorMessage = await screen.findByText(/Metric is required/);
|
||||
expect(errorMessage).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows error indicator for multiple controls with validation errors', async () => {
|
||||
getChartControlPanelRegistry().registerValue('table', {
|
||||
controlPanelSections: [],
|
||||
});
|
||||
const customState = {
|
||||
...reduxState,
|
||||
explore: {
|
||||
...reduxState.explore,
|
||||
controls: {
|
||||
...reduxState.explore.controls,
|
||||
metric: {
|
||||
value: '',
|
||||
label: 'Metric',
|
||||
validationErrors: ['Field is required'],
|
||||
},
|
||||
groupby: {
|
||||
value: [],
|
||||
label: 'Group by',
|
||||
validationErrors: ['Field is required'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithRouter({ initialState: customState });
|
||||
|
||||
const errorIndicator = await screen.findByTestId(
|
||||
'query-error-tooltip-trigger',
|
||||
);
|
||||
|
||||
userEvent.hover(errorIndicator);
|
||||
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByText(/Field is required/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows error indicator for control with multiple validation errors', async () => {
|
||||
getChartControlPanelRegistry().registerValue('table', {
|
||||
controlPanelSections: [],
|
||||
});
|
||||
const customState = {
|
||||
...reduxState,
|
||||
explore: {
|
||||
...reduxState.explore,
|
||||
controls: {
|
||||
...reduxState.explore.controls,
|
||||
metric: {
|
||||
value: '',
|
||||
label: 'Metric',
|
||||
validationErrors: ['Field is required', 'Invalid format'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithRouter({ initialState: customState });
|
||||
|
||||
const errorIndicator = await screen.findByTestId(
|
||||
'query-error-tooltip-trigger',
|
||||
);
|
||||
|
||||
userEvent.hover(errorIndicator);
|
||||
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByText(/Field is required/)).toBeInTheDocument();
|
||||
expect(await screen.findByText(/Invalid format/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('shows error indicator with function labels', async () => {
|
||||
getChartControlPanelRegistry().registerValue('table', {
|
||||
controlPanelSections: [],
|
||||
});
|
||||
// Ensure the explore state passed to the label function contains the expected property
|
||||
const customState = {
|
||||
...reduxState,
|
||||
explore: {
|
||||
...reduxState.explore,
|
||||
someState: 'test',
|
||||
controls: {
|
||||
...reduxState.explore.controls,
|
||||
metric: {
|
||||
value: '',
|
||||
label: (exploreState: { someState: string }) =>
|
||||
`Dynamic Metric (${exploreState.someState})`,
|
||||
validationErrors: ['Metric is required'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithRouter({ initialState: customState });
|
||||
|
||||
const errorIndicator = await screen.findByTestId(
|
||||
'query-error-tooltip-trigger',
|
||||
);
|
||||
|
||||
userEvent.hover(errorIndicator);
|
||||
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByText(/Metric is required/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -541,7 +541,11 @@ function ExploreViewContainer(props) {
|
||||
.map(message => {
|
||||
const matchingLabels = controlsWithErrors
|
||||
.filter(control => control.validationErrors?.includes(message))
|
||||
.map(control => control.label);
|
||||
.map(control =>
|
||||
typeof control.label === 'function'
|
||||
? control.label(props.exploreState)
|
||||
: control.label,
|
||||
);
|
||||
return [matchingLabels, message];
|
||||
})
|
||||
.map(([labels, message]) => (
|
||||
|
||||
@@ -87,17 +87,6 @@ export const useHeaderReportMenuItems = ({
|
||||
const resourceTypeReports = reportsState[resourceType] || {};
|
||||
const reportData = resourceTypeReports[resourceId];
|
||||
|
||||
// Debug logging to understand what's happening
|
||||
console.log('Report selector called:', {
|
||||
resourceId,
|
||||
resourceType,
|
||||
reportsState: Object.keys(reportsState),
|
||||
resourceTypeReports: Object.keys(resourceTypeReports),
|
||||
reportData: reportData
|
||||
? { id: reportData.id, name: reportData.name }
|
||||
: null,
|
||||
});
|
||||
|
||||
return reportData || null;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user