sadpandajoe commented on code in PR #45051:
URL: https://github.com/apache/superset/pull/45051#discussion_r4211524721
##########
superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx:
##########
@@ -671,7 +670,6 @@ const FilterControls: FC<FilterControlsProps> = ({
}
: undefined
}
- forceRender={hasRequiredFirst}
ref={popoverRef}
Review Comment:
Dropping `forceRender` here looks like it reintroduces the infinite
dashboard load that #24542 fixed. A "select first filter value by default"
filter scoped only to an inactive tab lives solely in the closed "More"
popover; its `InPortal` mounts with `inView={false}` and `FilterValue` never
passes its `inViewFirstTime` gate until an `OutPortal` renders, so no default
is selected. `useNativeFilters` waits on every required-first filter, including
out-of-scope ones, so the dashboard stays loading until someone opens the
popover. `forceRenderOutOfScope` can't help since its enclosing popover is
never mounted. How do required-first filters that overflow get initialized
without this, and could initialization be decoupled from popover visibility
instead?
##########
superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.overflow.test.tsx:
##########
@@ -565,3 +570,114 @@ test('focusing a filter that has not overflowed does not
open the dropdown', asy
expect(mockDropdownOpen).not.toHaveBeenCalled();
});
+
+test('initializes horizontal bar with items when native filters are
configured', async () => {
+ const filters = [
+ createSelectNativeFilter('NATIVE_FILTER-1', 'country'),
+ createSelectNativeFilter('NATIVE_FILTER-2', 'city'),
+ ];
+ renderHorizontal(filters, buildDataMaskSelected(filters));
+ await waitFor(() => expect(latestProps()).toBeTruthy());
+ expect(latestProps().items).toHaveLength(2);
+});
+
+test('renders native filters with requiredFirst and default values in the
horizontal row', async () => {
+ const filters = [
+ {
+ ...createSelectNativeFilter('NATIVE_FILTER-1', 'account'),
+ requiredFirst: true,
+ },
+ createSelectNativeFilter('NATIVE_FILTER-2', 'region'),
+ ];
+ const dataMask = buildDataMaskSelected(filters, ['NATIVE_FILTER-1']);
+ renderHorizontal(filters, dataMask);
+
+ await waitFor(() => expect(latestProps()).toBeTruthy());
+ expect(latestProps().items).toHaveLength(2);
+ expect(latestProps().items.map(i => i.id)).toEqual([
+ 'NATIVE_FILTER-1',
+ 'NATIVE_FILTER-2',
+ ]);
+});
+
+test('maintains filter item order in horizontal bar', async () => {
+ const filters = [
+ createSelectNativeFilter('NATIVE_FILTER-1', 'alpha'),
+ createSelectNativeFilter('NATIVE_FILTER-2', 'beta'),
+ createSelectNativeFilter('NATIVE_FILTER-3', 'gamma'),
+ ];
+ renderHorizontal(filters, buildDataMaskSelected(filters));
+
+ await waitFor(() => expect(latestProps()).toBeTruthy());
+ expect(latestProps().items.map(i => i.id)).toEqual([
+ 'NATIVE_FILTER-1',
+ 'NATIVE_FILTER-2',
+ 'NATIVE_FILTER-3',
+ ]);
+});
+
+test('provides correct filter count when filters include requiredFirst', async
() => {
+ const filters = [
+ {
+ ...createSelectNativeFilter('NATIVE_FILTER-1', 'account'),
+ requiredFirst: true,
+ },
+ createSelectNativeFilter('NATIVE_FILTER-2', 'country'),
+ createSelectNativeFilter('NATIVE_FILTER-3', 'status'),
+ ];
+ renderHorizontal(filters, buildDataMaskSelected(filters));
+
+ await waitFor(() => expect(latestProps()).toBeTruthy());
+ expect(latestProps().items).toHaveLength(3);
+});
+
+// Regression test group for issue #45050:
+// Prevents DropdownContainer closed popover from stealing OutPortal nodes
+// into hidden DOM when requiredFirst native filters and table cross-filters
coexist.
+test('does not pass forceRender to DropdownContainer even when a filter has
requiredFirst (regression test for #45050)', async () => {
+ const filters = [
+ {
+ ...createSelectNativeFilter('NATIVE_FILTER-1', 'account'),
+ requiredFirst: true,
+ },
+ createSelectNativeFilter('NATIVE_FILTER-2', 'flow'),
+ ];
+
+ renderHorizontal(filters, buildDataMaskSelected(filters));
+
+ await waitFor(() => expect(latestProps()).toBeTruthy());
Review Comment:
This only checks prop wiring on a mocked `DropdownContainer` (no hidden
Popover, no reverse portals, no measurement), so it can pass while the filters
still vanish after a cross-filter. It also renders the dropdown content
unconditionally on a tabless dashboard, so it can't catch a required-first
filter that never initializes. Could one test keep the real `DropdownContainer`
and portals, add a cross-filter chip with the popover closed, and assert the
native controls stay reachable (in the row or via "More")?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]