This is an automated email from the ASF dual-hosted git repository. sadpandajoe pushed a commit to branch test-viz-control-gaps in repository https://gitbox.apache.org/repos/asf/superset.git
commit 09baf1cc71eba3aa52a44633e865ea79eecce869 Author: Joe Li <[email protected]> AuthorDate: Wed Sep 30 17:25:28 2026 -0700 test(explore): cover color scheme selection, BigNumber subheader/trendline, and WorldMap bubbles Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../src/BigNumber/BigNumberViz.test.tsx | 57 ++++++++++++++++ .../BigNumberWithTrendline/transformProps.test.ts | 72 ++++++++++++++++++++ .../plugin-chart-world-map/test/WorldMap.test.ts | 14 ++++ .../ColorSchemeControl/ColorSchemeControl.test.tsx | 76 ++++++++++++++++++++++ 4 files changed, 219 insertions(+) diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx index db8d4e50f9d..659c6b24c66 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberViz.test.tsx @@ -17,6 +17,7 @@ * under the License. */ +import { ComponentProps } from 'react'; import { DTTM_ALIAS, getNumberFormatter, @@ -246,3 +247,59 @@ describe('BigNumberViz trendline context menu', () => { expect(onContextMenu).not.toHaveBeenCalled(); }); }); + +describe('BigNumberViz trendline and subheader rendering', () => { + beforeEach(() => { + mockedEchart.mockClear(); + }); + + const renderViz = ( + props: Partial<ComponentProps<typeof BigNumberVis>> = {}, + ) => + render( + <BigNumberVis + width={200} + height={100} + bigNumber={42} + headerFormatter={getNumberFormatter()} + headerFontSize={0.3} + subheaderFontSize={0.125} + subtitleFontSize={0.125} + subtitle="" + refs={{}} + trendLineData={[ + [1577836800000, 10], + [1577923200000, 20], + ]} + echartOptions={{ series: [] }} + {...props} + />, + ); + + test('renders the trendline chart when showTrendLine is true', () => { + renderViz({ showTrendLine: true }); + + expect(mockedEchart).toHaveBeenCalled(); + }); + + test('does not render the trendline chart when showTrendLine is false', () => { + const { container } = renderViz({ showTrendLine: false }); + + expect(mockedEchart).not.toHaveBeenCalled(); + expect(container.querySelector('.no-trendline')).toBeInTheDocument(); + }); + + test('renders the subheader when one is provided', () => { + const { container } = renderViz({ subheader: '10.0% WoW' }); + + expect(container.querySelector('.subheader-line')).toHaveTextContent( + '10.0% WoW', + ); + }); + + test('does not render a subheader when none is provided', () => { + const { container } = renderViz({ subheader: '' }); + + expect(container.querySelector('.subheader-line')).not.toBeInTheDocument(); + }); +}); diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts index 6a9752d57b9..225f9eef833 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.test.ts @@ -305,4 +305,76 @@ describe('BigNumberWithTrendline transformProps', () => { ); expect(result.mainColor).toBeUndefined(); }); + + const twoPointQueriesData = [ + { + data: [ + { __timestamp: 2, value: 110 }, + { __timestamp: 1, value: 100 }, + ] as unknown as BigNumberDatum[], + colnames: ['__timestamp', 'value'], + coltypes: ['TEMPORAL', 'NUMERIC'], + }, + ]; + + const buildChartProps = (formData: Record<string, unknown>) => + ({ + width: 500, + height: 400, + queriesData: twoPointQueriesData, + formData, + rawFormData: baseRawFormData, + hooks: baseHooks, + datasource: baseDatasource, + theme: { colors: { grayscale: { light5: '#eee' } } }, + }) as unknown as BigNumberWithTrendlineChartProps; + + test('should not produce a percent-change subheader when compareLag is absent', () => { + const result = transformProps( + buildChartProps({ ...baseFormData, compareLag: undefined }), + ); + + expect(result.subheader).toBe(''); + }); + + test('should not produce a percent-change subheader when compareLag is null', () => { + const result = transformProps( + buildChartProps({ ...baseFormData, compareLag: null }), + ); + + expect(result.subheader).toBe(''); + }); + + test('should keep the configured subheader when compareLag is absent', () => { + const result = transformProps( + buildChartProps({ + ...baseFormData, + compareLag: undefined, + subheader: 'custom subheader', + }), + ); + + expect(result.subheader).toBe('custom subheader'); + }); + + test('should not produce trendline data or echart options when showTrendLine is false', () => { + const result = transformProps( + buildChartProps({ ...baseFormData, showTrendLine: false }), + ); + + expect(result.trendLineData).toBeUndefined(); + expect(result.echartOptions).toEqual({}); + }); + + test('should produce chronologically ordered trendline data and echart options when showTrendLine is true', () => { + const result = transformProps( + buildChartProps({ ...baseFormData, showTrendLine: true }), + ); + + expect(result.trendLineData).toEqual([ + [1, 100], + [2, 110], + ]); + expect(result.echartOptions).toHaveProperty('series'); + }); }); diff --git a/superset-frontend/plugins/plugin-chart-world-map/test/WorldMap.test.ts b/superset-frontend/plugins/plugin-chart-world-map/test/WorldMap.test.ts index 96c30a1a4a9..d53740827f8 100644 --- a/superset-frontend/plugins/plugin-chart-world-map/test/WorldMap.test.ts +++ b/superset-frontend/plugins/plugin-chart-world-map/test/WorldMap.test.ts @@ -420,3 +420,17 @@ test('popupTemplate handles null/undefined country data gracefully', () => { expect(tooltipHtml).toBeFalsy(); }); + +test('draws bubbles for the processed data when showBubbles is true', () => { + WorldMap(container, { ...baseProps, showBubbles: true }); + + expect(mockBubbles).toHaveBeenCalledTimes(1); + const bubbleData = mockBubbles.mock.calls[0][0] as { name: string }[]; + expect(bubbleData.map(d => d.name)).toEqual(['United States', 'Canada']); +}); + +test('does not draw bubbles when showBubbles is false', () => { + WorldMap(container, { ...baseProps, showBubbles: false }); + + expect(mockBubbles).not.toHaveBeenCalled(); +}); diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx index e9d4e482904..bd419d03191 100644 --- a/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl/ColorSchemeControl.test.tsx @@ -21,6 +21,7 @@ import { CategoricalModernSunset, CategoricalScheme, ColorSchemeGroup, + SequentialScheme, getCategoricalSchemeRegistry, } from '@superset-ui/core'; import { @@ -28,6 +29,7 @@ import { screen, userEvent, waitFor, + within, } from 'spec/helpers/testing-library'; import ColorSchemeControl, { ColorSchemes } from '.'; @@ -337,3 +339,77 @@ test('should NOT show tooltip for search results (original Cypress contract)', a expect(tooltipContent).toBeFalsy(); }); }); + +test('searching for a color scheme and selecting it calls onChange with the scheme id', async () => { + getCategoricalSchemeRegistry().registerValue(lyftColors.id, lyftColors); + const onChange = jest.fn(); + setup({ onChange }); + + const selectInput = screen.getByLabelText('Select color scheme', { + selector: 'input', + }); + await userEvent.click(selectInput); + await userEvent.type(selectInput, 'lyftColors'); + await userEvent.click(await screen.findByTestId('lyftColors')); + + await waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); + expect(onChange).toHaveBeenCalledWith('lyftColors'); +}); + +test('searching by label matches a scheme and filters out non-matching schemes', async () => { + [...CategoricalD3, lyftColors].forEach(scheme => + getCategoricalSchemeRegistry().registerValue(scheme.id, scheme), + ); + setup(); + + const selectInput = screen.getByLabelText('Select color scheme', { + selector: 'input', + }); + await userEvent.click(selectInput); + await userEvent.type(selectInput, 'Lyft'); + + expect(await screen.findByTestId('lyftColors')).toBeInTheDocument(); + await waitFor(() => + expect(screen.queryByText('D3 Category 10')).not.toBeInTheDocument(), + ); +}); + +test('isLinear: searching a sequential scheme and selecting it calls onChange with the scheme id', async () => { + const sequentialSchemes = [ + new SequentialScheme({ + id: 'testBlues', + label: 'Test Blues', + colors: ['#eff3ff', '#6baed6', '#08519c'], + }), + new SequentialScheme({ + id: 'testGreens', + label: 'Test Greens', + colors: ['#edf8e9', '#74c476', '#006d2c'], + }), + ]; + const onChange = jest.fn(); + setup({ + isLinear: true, + value: 'testBlues', + choices: sequentialSchemes.map(s => [s.id, s.label]), + schemes: Object.fromEntries( + sequentialSchemes.map(s => [s.id, s]), + ) as ColorSchemes, + onChange, + }); + + const selectInput = screen.getByLabelText('Select color scheme', { + selector: 'input', + }); + await userEvent.click(selectInput); + await userEvent.type(selectInput, 'Greens'); + + const option = await screen.findByTestId('testGreens'); + // Sequential schemes are interpolated to 10 swatches, not their 3 raw colors + expect(within(option).getAllByTestId('color')).toHaveLength(10); + + await userEvent.click(option); + + await waitFor(() => expect(onChange).toHaveBeenCalledTimes(1)); + expect(onChange).toHaveBeenCalledWith('testGreens'); +});
