codeant-ai-for-open-source[bot] commented on code in PR #37012:
URL: https://github.com/apache/superset/pull/37012#discussion_r2676247302


##########
superset-frontend/src/dashboard/reducers/nativeFilters.test.ts:
##########
@@ -160,3 +160,28 @@ test('SET_NATIVE_FILTERS_CONFIG_COMPLETE treats empty 
arrays as valid scope prop
   expect(result.filters.filter1.chartsInScope).toEqual([]);
   expect(result.filters.filter1.tabsInScope).toEqual([]);
 });
+
+test('SET_NATIVE_FILTERS_CONFIG_COMPLETE removes filters that are not in the 
response', () => {
+  const initialState = {
+    filters: {
+      filter1: createMockFilter('filter1', [1, 2], ['tab1']),
+      filter2: createMockFilter('filter2', [3, 4], ['tab2']),
+      filter3: createMockFilter('filter3', [5, 6], ['tab3']),
+    },
+  };
+
+  // Only filter1 and filter3 are in the response (filter2 was deleted)
+  const action = {
+    type: SET_NATIVE_FILTERS_CONFIG_COMPLETE as typeof 
SET_NATIVE_FILTERS_CONFIG_COMPLETE,
+    filterChanges: [
+      createMockFilter('filter1', [1, 2], ['tab1']),
+      createMockFilter('filter3', [5, 6], ['tab3']),
+    ],
+  };
+
+  const result = nativeFilterReducer(initialState, action);
+
+  expect(result.filters.filter1).toBeDefined();
+  expect(result.filters.filter2).toBeUndefined();

Review Comment:
   **Suggestion:** The test uses 
`expect(result.filters.filter2).toBeUndefined()` to assert that a filter was 
removed, but this passes even if the `filter2` property still exists on the 
object with the explicit value `undefined` (which would not indicate an actual 
deletion). Replace this assertion with a check that the property does not exist 
on the `filters` object (e.g., 
`expect(result.filters).not.toHaveProperty('filter2')`) so the test fails if 
the reducer left a key present but set to `undefined`. [logic error]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
     expect(result.filters).not.toHaveProperty('filter2');
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   The current assertion passes whether the key was deleted or left present 
with an undefined value.
   Using not.toHaveProperty('filter2') makes the test stricter and correctly 
verifies the reducer removed the key.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/dashboard/reducers/nativeFilters.test.ts
   **Line:** 185:185
   **Comment:**
        *Logic Error: The test uses 
`expect(result.filters.filter2).toBeUndefined()` to assert that a filter was 
removed, but this passes even if the `filter2` property still exists on the 
object with the explicit value `undefined` (which would not indicate an actual 
deletion). Replace this assertion with a check that the property does not exist 
on the `filters` object (e.g., 
`expect(result.filters).not.toHaveProperty('filter2')`) so the test fails if 
the reducer left a key present but set to `undefined`.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx:
##########
@@ -254,6 +254,14 @@ const FilterControls: FC<FilterControlsProps> = ({
           />
         )}
 
+        {!showCollapsePanel && filtersOutOfScope.length > 0 && (

Review Comment:
   **Suggestion:** Logic/UX inconsistency: when `showCollapsePanel` is false 
the new branch renders the out-of-scope collapsible regardless of whether the 
filters section is visible/collapsed (`hideHeader` / `sectionsOpen.filters`). 
Previously, when `showCollapsePanel` was true the component respected 
`(hideHeader || sectionsOpen.filters)`. Restore the same visibility condition 
so the out-of-scope panel doesn't appear while the user has collapsed the 
filters section. [logic error]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
           {!showCollapsePanel && (hideHeader || sectionsOpen.filters) && 
filtersOutOfScope.length > 0 && (
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   Correct and actionable. The earlier branch (when showCollapsePanel is true) 
included the visibility guard (hideHeader || sectionsOpen.filters); the newly 
added branch omits it, causing the out-of-scope panel to render even when the 
filters section is collapsed — a clear UX inconsistency. Adding (hideHeader || 
sectionsOpen.filters) to this condition restores consistent behavior without 
further changes.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx
   **Line:** 257:257
   **Comment:**
        *Logic Error: Logic/UX inconsistency: when `showCollapsePanel` is false 
the new branch renders the out-of-scope collapsible regardless of whether the 
filters section is visible/collapsed (`hideHeader` / `sectionsOpen.filters`). 
Previously, when `showCollapsePanel` was true the component respected 
`(hideHeader || sectionsOpen.filters)`. Restore the same visibility condition 
so the out-of-scope panel doesn't appear while the user has collapsed the 
filters section.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/reducers/nativeFilters.test.ts:
##########
@@ -160,3 +160,28 @@ test('SET_NATIVE_FILTERS_CONFIG_COMPLETE treats empty 
arrays as valid scope prop
   expect(result.filters.filter1.chartsInScope).toEqual([]);
   expect(result.filters.filter1.tabsInScope).toEqual([]);
 });
+
+test('SET_NATIVE_FILTERS_CONFIG_COMPLETE removes filters that are not in the 
response', () => {
+  const initialState = {
+    filters: {
+      filter1: createMockFilter('filter1', [1, 2], ['tab1']),
+      filter2: createMockFilter('filter2', [3, 4], ['tab2']),
+      filter3: createMockFilter('filter3', [5, 6], ['tab3']),
+    },
+  };
+
+  // Only filter1 and filter3 are in the response (filter2 was deleted)
+  const action = {
+    type: SET_NATIVE_FILTERS_CONFIG_COMPLETE as typeof 
SET_NATIVE_FILTERS_CONFIG_COMPLETE,
+    filterChanges: [
+      createMockFilter('filter1', [1, 2], ['tab1']),
+      createMockFilter('filter3', [5, 6], ['tab3']),
+    ],
+  };
+
+  const result = nativeFilterReducer(initialState, action);
+

Review Comment:
   **Suggestion:** The test doesn't check that the reducer is not mutating the 
original `initialState`; a reducer that mutates its input can still make this 
test pass. After calling the reducer, assert that 
`initialState.filters.filter2` is still defined to catch accidental in-place 
mutation. [possible bug]
   
   **Severity Level:** Critical 🚨
   ```suggestion
     expect(initialState.filters.filter2).toBeDefined();
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   Verifying initialState.filters.filter2 is still defined after the reducer 
call catches accidental in-place mutation of the input state, which reducers 
must avoid.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/dashboard/reducers/nativeFilters.test.ts
   **Line:** 183:183
   **Comment:**
        *Possible Bug: The test doesn't check that the reducer is not mutating 
the original `initialState`; a reducer that mutates its input can still make 
this test pass. After calling the reducer, assert that 
`initialState.filters.filter2` is still defined to catch accidental in-place 
mutation.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/components/nativeFilters/state.ts:
##########
@@ -144,20 +144,38 @@ export function useSelectFiltersInScope(filters: (Filter 
| Divider)[]) {
     let filtersInScope: (Filter | Divider)[] = [];
     const filtersOutOfScope: (Filter | Divider)[] = [];
 
-    // we check native filters scopes only on dashboards with tabs
-    if (!dashboardHasTabs) {
-      filtersInScope = filters;
-    } else {
-      filters.forEach(filter => {
+    filters.forEach(filter => {
+      // Dividers are always in scope
+      if (isFilterDivider(filter)) {
+        filtersInScope.push(filter);
+        return;
+      }
+
+      // If dashboard has tabs, check scope based on visibility
+      if (dashboardHasTabs) {
         const filterInScope = isFilterInScope(filter);
-
         if (filterInScope) {
           filtersInScope.push(filter);
         } else {
           filtersOutOfScope.push(filter);
         }
-      });
-    }
+      } else {
+        // If no tabs, check if filter has any charts in scope
+        // Only mark as out of scope if chartsInScope is explicitly defined 
AND empty
+        const hasExplicitChartsInScope = Array.isArray(filter.chartsInScope);
+        const hasChartsInScope =
+          hasExplicitChartsInScope && filter.chartsInScope!.length > 0;

Review Comment:
   **Suggestion:** Unsafe non-null assertion: the code uses 
`filter.chartsInScope!.length` after checking 
`Array.isArray(filter.chartsInScope)`, but using a non-null assertion is 
unnecessary and brittle; replace with a safe length check that does not rely on 
`!` (use nullish coalescing) to avoid runtime errors if `chartsInScope` were 
unexpectedly null-ish. [type error]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
             hasExplicitChartsInScope && (filter.chartsInScope ?? []).length > 
0;
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   The non-null assertion (`!`) is unnecessary and slightly brittle; using a 
nullish coalescing fallback like `(filter.chartsInScope ?? []).length` is safer 
and clearer. This is a small, safe local improvement that doesn't change 
behavior but avoids relying on the assertion.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/dashboard/components/nativeFilters/state.ts
   **Line:** 167:167
   **Comment:**
        *Type Error: Unsafe non-null assertion: the code uses 
`filter.chartsInScope!.length` after checking 
`Array.isArray(filter.chartsInScope)`, but using a non-null assertion is 
unnecessary and brittle; replace with a safe length check that does not rely on 
`!` (use nullish coalescing) to avoid runtime errors if `chartsInScope` were 
unexpectedly null-ish.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/reducers/nativeFilters.ts:
##########
@@ -67,12 +67,13 @@ function handleFilterChangesComplete(
   state: ExtendedNativeFiltersState,
   filters: Filter[],
 ) {
-  const modifiedFilters = { ...state.filters };
+  const modifiedFilters: Record<string, Filter | Divider> = {};
+  // Build fresh filter list from server response to ensure deleted filters 
are removed
   filters.forEach(filter => {
     if (filter.chartsInScope != null && filter.tabsInScope != null) {
       modifiedFilters[filter.id] = filter;
     } else {
-      const existingFilter = modifiedFilters[filter.id];
+      const existingFilter = state.filters[filter.id];

Review Comment:
   **Suggestion:** Possible runtime exception when `state.filters` is 
undefined: the code accesses `state.filters[filter.id]` directly which will 
throw if `state.filters` is null/undefined (for example after a HYDRATE where 
`nativeFilters.filters` might be undefined). Use a safe access with a default 
empty object so the lookup won't throw. [null pointer]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
         const existingFilter = (state.filters ?? {})[filter.id];
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   The current code will throw if `state.filters` is undefined (e.g. after a 
HYDRATE action that sets filters to undefined). Using a safe fallback when 
reading avoids a potential TypeError at runtime. The proposed change is small, 
low-risk, and directly fixes a verifiable issue.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/dashboard/reducers/nativeFilters.ts
   **Line:** 76:76
   **Comment:**
        *Null Pointer: Possible runtime exception when `state.filters` is 
undefined: the code accesses `state.filters[filter.id]` directly which will 
throw if `state.filters` is null/undefined (for example after a HYDRATE where 
`nativeFilters.filters` might be undefined). Use a safe access with a default 
empty object so the lookup won't throw.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



-- 
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]

Reply via email to