This is an automated email from the ASF dual-hosted git repository. sadpandajoe pushed a commit to branch test/dashboard-tabs-reveal-query in repository https://gitbox.apache.org/repos/asf/superset.git
commit 1ff35a26c891f530fff8a4dc5098b8ac94f5e6a5 Author: Joe Li <[email protected]> AuthorDate: Fri Sep 25 15:58:46 2026 -0700 test(dashboard): cover tab switching visibility and hidden chart updates Adds regression coverage for dashboard tabs: - Switching tabs selects the clicked tab, exposes only its panel, and renders its content as visible - A chart hidden in an inactive tab skips prop updates and adopts them once revealed Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../components/gridComponents/Chart/Chart.test.tsx | 16 +++++++ .../components/gridComponents/Tabs/Tabs.test.tsx | 52 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.test.tsx index a8870bcc30c..afc8d505404 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.test.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart/Chart.test.tsx @@ -892,3 +892,19 @@ test('Existing expand/collapse behavior continues to work', () => { restore(); } }); + +test('a hidden chart does not adopt a prop update, and adopts it once revealed', () => { + const { rerender } = setup({ isComponentVisible: false, isInView: false }); + expect(capturedChartContainerProps.isInView).toBe(false); + + // The parent passes an updated prop while the chart is still hidden: the + // memoized export bails out, so the prop update never reaches + // ChartContainer while the tab is hidden. Store-driven updates (such as a + // query trigger read via useSelector) are not gated by this memo. + rerender(<Chart {...props} isComponentVisible={false} isInView />); + expect(capturedChartContainerProps.isInView).toBe(false); + + // Revealing the tab lets the chart re-render and adopt the pending update. + rerender(<Chart {...props} isComponentVisible isInView />); + expect(capturedChartContainerProps.isInView).toBe(true); +}); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs/Tabs.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs/Tabs.test.tsx index 0d31b9b3514..c3270b46e8a 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tabs/Tabs.test.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs/Tabs.test.tsx @@ -265,6 +265,58 @@ test('Switching tabs', async () => { expect(props.onChangeTab).toHaveBeenCalled(); }); +test('Switching tabs shows the newly selected tab content and hides the previous one', async () => { + const props = createProps(); + render(<Tabs {...props} />, { + useRedux: true, + useDnd: true, + }); + const [firstTabId, , thirdTabId] = props.component.children; + + // The first tab starts selected and its panel is the only one exposed + // to the accessibility tree. + let tabs = screen.getAllByRole('tab'); + expect(tabs[0]).toHaveAttribute('aria-selected', 'true'); + expect(tabs[2]).toHaveAttribute('aria-selected', 'false'); + expect(screen.getByRole('tabpanel').id).toContain(firstTabId); + + await userEvent.click(tabs[2]); + + // After switching, the clicked tab is selected and its content panel + // becomes the only one exposed to the accessibility tree... + tabs = screen.getAllByRole('tab'); + expect(tabs[2]).toHaveAttribute('aria-selected', 'true'); + expect(tabs[0]).toHaveAttribute('aria-selected', 'false'); + expect(screen.getByRole('tabpanel').id).toContain(thirdTabId); + + // ...while the previously active tab's panel is hidden from it. + const firstPanel = screen + .getAllByRole('tabpanel', { hidden: true }) + .find(panel => panel.id.includes(firstTabId)); + expect(firstPanel).toHaveAttribute('aria-hidden', 'true'); + + // The selected tab's content is the one rendered as visible, which is what + // lets its charts pick up updates once revealed. + const lastContentPropsFor = (tabId: string) => + (DashboardComponent as unknown as jest.Mock).mock.calls + .map( + call => + call[0] as { + id: string; + renderType: string; + isComponentVisible?: boolean; + }, + ) + .filter( + componentProps => + componentProps.renderType === RENDER_TAB_CONTENT && + componentProps.id === tabId, + ) + .at(-1); + expect(lastContentPropsFor(thirdTabId)?.isComponentVisible).toBe(true); + expect(lastContentPropsFor(firstTabId)?.isComponentVisible).not.toBe(true); +}); + test.each([false, true])( 'A childless TABS component does not register an active tab (editMode=%s)', editMode => {
