Compare commits

...

10 Commits

Author SHA1 Message Date
Joe Li
98f6d627ed Merge branch 'master' into fix-no-top-level-tab 2026-05-11 09:19:34 -07:00
Joe Li
ff323ba328 Merge branch 'master' into fix-no-top-level-tab 2026-05-07 10:02:44 -07:00
Joe Li
78fada7f43 Merge branch 'master' into fix-no-top-level-tab 2026-05-06 19:18:19 -07:00
Joe Li
b71c556560 fix(dashboard): derive min-height assertion from theme.sizeUnit
Use supersetTheme.sizeUnit * 4 instead of hard-coded '16px' so the
test stays in sync with the source rule and resilient to theme
token changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 10:10:19 -07:00
Joe Li
7d6513f946 Merge branch 'master' into fix-no-top-level-tab 2026-05-05 15:11:11 -07:00
Joe Li
d25c07586d Merge branch 'master' into fix-no-top-level-tab 2026-05-04 12:33:46 -07:00
Joe Li
93066ade52 fix(dashboard): assert concrete min-height value and centralize emotion-jest types
- Assert min-height is '16px' (theme.sizeUnit * 4) instead of /\S+/
  to catch zero-height regressions
- Move @emotion/jest type reference from per-file directive to
  src/types/emotion-jest.d.ts for global availability

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 12:26:09 -07:00
Joe Li
3fe59024ef fix(dashboard): use toHaveStyleRule and getByTestId in droptarget test
Replace CSSOM scan with @emotion/jest toHaveStyleRule matcher using
the target option to verify the .empty-droptarget rule on StyledHeader.
Switch from container.querySelector to getByTestId for consistency
with other tests in this file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-02 17:14:47 -07:00
Joe Li
0b442ef9ae fix(dashboard): address review feedback and fix test type errors
- Assert the actual .empty-droptarget element exists on the Droppable
  (addresses Copilot review feedback on PR #39423)
- Add @emotion/jest type reference to fix pre-existing toHaveStyleRule
  TS errors in this test file
- Prettier formatting fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 13:35:04 -07:00
Joe Li
5bb88b2b74 fix(dashboard): restore top-level tab drop target height for dashboards with content
PR #37891 moved the DashboardHeader out of the root Droppable, leaving
it with zero height when no top-level tabs exist. This made it impossible
to drag a Tabs component onto dashboards that already have content.

Add min-height to .empty-droptarget in StyledHeader, matching the pattern
used by DashboardGrid for its drop targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-30 09:49:14 -07:00
3 changed files with 66 additions and 0 deletions

View File

@@ -24,6 +24,7 @@ import {
screen,
} from 'spec/helpers/testing-library';
import { FeatureFlag } from '@superset-ui/core';
import { supersetTheme } from '@apache-superset/core/theme';
import {
OPEN_FILTER_BAR_WIDTH,
CLOSED_FILTER_BAR_WIDTH,
@@ -487,6 +488,47 @@ test('should render ParentSize wrapper with height 100% for tabs', async () => {
expect(tabPanels.length).toBeGreaterThan(0);
});
test('should apply min-height to the top-level tab drop target so tabs can be dropped on dashboards with content', () => {
(useStoredSidebarWidth as jest.Mock).mockImplementation(() => [
100,
jest.fn(),
]);
(fetchFaveStar as jest.Mock).mockReturnValue({ type: 'mock-action' });
(setActiveTab as jest.Mock).mockReturnValue({ type: 'mock-action' });
const { getByTestId } = render(<DashboardBuilder />, {
useRedux: true,
store: storeWithState({
...mockState,
dashboardLayout: undoableDashboardLayout,
dashboardState: { ...mockState.dashboardState, editMode: true },
}),
useDnd: true,
useTheme: true,
});
const headerWrapper = getByTestId('dashboard-header-wrapper');
// The Droppable inside the header should have the empty-droptarget class
// when there are no top-level tabs and edit mode is active. Without this
// class (and its associated min-height CSS rule), the drop target has zero
// height and users cannot drag tabs onto dashboards that already have
// content.
const droptarget = headerWrapper.querySelector('.empty-droptarget');
expect(droptarget).toBeInTheDocument();
// Verify the StyledHeader CSS defines a non-zero min-height for
// .empty-droptarget, derived from theme.sizeUnit * 4 to stay in sync
// with the source rule in DashboardBuilder.tsx.
expect(headerWrapper).toHaveStyleRule(
'min-height',
`${supersetTheme.sizeUnit * 4}px`,
{
target: '.empty-droptarget',
},
);
});
test('should maintain layout when switching between tabs', async () => {
(useStoredSidebarWidth as jest.Mock).mockImplementation(() => [
100,

View File

@@ -100,6 +100,10 @@ const StyledHeader = styled.div<{ filterBarWidth: number }>`
z-index: 99;
max-width: calc(100vw - ${filterBarWidth}px);
.empty-droptarget {
min-height: ${theme.sizeUnit * 4}px;
}
.empty-droptarget:before {
position: absolute;
content: '';

View File

@@ -0,0 +1,20 @@
/**
* 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.
*/
/// <reference types="@emotion/jest" />