Copilot commented on code in PR #38591:
URL: https://github.com/apache/superset/pull/38591#discussion_r2922527167


##########
tests/unit_tests/commands/report/execute_test.py:
##########
@@ -343,6 +360,123 @@ def test_get_dashboard_urls_with_exporting_dashboard_only(
     assert expected_url == result[0]
 
 
+@patch("superset.commands.report.execute.CreateDashboardPermalinkCommand")
+@with_feature_flags(ALERT_REPORT_TABS=True)
+def test_get_dashboard_urls_with_filters_and_tabs(
+    mock_permalink_cls,
+    mocker: MockerFixture,
+    app,
+) -> None:
+    mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule)
+    mock_report_schedule.chart = False
+    mock_report_schedule.chart_id = None
+    mock_report_schedule.dashboard_id = 123
+    mock_report_schedule.type = "report_type"
+    mock_report_schedule.report_format = "report_format"
+    mock_report_schedule.owners = [1, 2]
+    mock_report_schedule.recipients = []
+    native_filter_rison = "(NATIVE_FILTER-1:(filterType:filter_select))"
+    mock_report_schedule.extra = {
+        "dashboard": {
+            "anchor": json.dumps(["TAB-1", "TAB-2"]),
+            "dataMask": {"NATIVE_FILTER-1": {"filterState": {"value": 
["Sales"]}}},
+            "activeTabs": ["TAB-1", "TAB-2"],
+            "urlParams": None,
+            "nativeFilters": [  # type: ignore[typeddict-unknown-key]
+                {
+                    "nativeFilterId": "NATIVE_FILTER-1",
+                    "filterType": "filter_select",
+                    "columnName": "department",
+                    "filterValues": ["Sales"],
+                }
+            ],
+        }
+    }
+    mock_report_schedule.get_native_filters_params.return_value = 
native_filter_rison  # type: ignore[attr-defined]
+    mock_permalink_cls.return_value.run.side_effect = ["key1", "key2"]
+
+    class_instance: BaseReportState = BaseReportState(
+        mock_report_schedule, "January 1, 2021", "execution_id_example"
+    )
+    class_instance._report_schedule = mock_report_schedule
+
+    result: list[str] = class_instance.get_dashboard_urls()
+
+    import urllib.parse
+
+    base_url = app.config.get("WEBDRIVER_BASEURL", "http://0.0.0.0:8080/";)
+    assert result == [
+        urllib.parse.urljoin(base_url, "superset/dashboard/p/key1/"),
+        urllib.parse.urljoin(base_url, "superset/dashboard/p/key2/"),
+    ]
+    mock_report_schedule.get_native_filters_params.assert_called_once()  # 
type: ignore[attr-defined]
+    assert mock_permalink_cls.call_count == 2
+    for call in mock_permalink_cls.call_args_list:
+        state = call.kwargs["state"]
+        assert state["urlParams"] == [["native_filters", native_filter_rison]]
+    assert mock_permalink_cls.call_args_list[0].kwargs["state"]["anchor"] == 
"TAB-1"
+    assert mock_permalink_cls.call_args_list[1].kwargs["state"]["anchor"] == 
"TAB-2"
+
+
+@patch("superset.commands.report.execute.CreateDashboardPermalinkCommand")
+@with_feature_flags(ALERT_REPORT_TABS=True)
+def test_get_dashboard_urls_with_filters_no_tabs(
+    mock_permalink_cls,
+    mocker: MockerFixture,
+    app,
+) -> None:
+    mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule)
+    mock_report_schedule.chart = False
+    mock_report_schedule.chart_id = None
+    mock_report_schedule.dashboard_id = 123
+    mock_report_schedule.type = "report_type"
+    mock_report_schedule.report_format = "report_format"
+    mock_report_schedule.owners = [1, 2]
+    mock_report_schedule.recipients = []
+    native_filter_rison = "(NATIVE_FILTER-1:(filterType:filter_select))"
+    mock_report_schedule.extra = {
+        "dashboard": {
+            "anchor": "",
+            "dataMask": {"NATIVE_FILTER-1": {"filterState": {"value": 
["Sales"]}}},
+            "activeTabs": None,
+            "urlParams": None,
+            "nativeFilters": [  # type: ignore[typeddict-unknown-key]
+                {
+                    "nativeFilterId": "NATIVE_FILTER-1",
+                    "filterType": "filter_select",
+                    "columnName": "department",
+                    "filterValues": ["Sales"],
+                }
+            ],
+        }
+    }
+    mock_report_schedule.get_native_filters_params.return_value = 
native_filter_rison  # type: ignore[attr-defined]
+    mock_permalink_cls.return_value.run.return_value = "key1"
+
+    class_instance: BaseReportState = BaseReportState(
+        mock_report_schedule, "January 1, 2021", "execution_id_example"
+    )
+    class_instance._report_schedule = mock_report_schedule
+
+    result: list[str] = class_instance.get_dashboard_urls()
+
+    import urllib.parse
+
+    base_url = app.config.get("WEBDRIVER_BASEURL", "http://0.0.0.0:8080/";)
+    assert result == [
+        urllib.parse.urljoin(base_url, "superset/dashboard/p/key1/"),
+    ]
+    mock_report_schedule.get_native_filters_params.assert_called_once()  # 
type: ignore[attr-defined]
+    assert mock_permalink_cls.call_count == 1
+    state = mock_permalink_cls.call_args_list[0].kwargs["state"]
+    # BUG: {urlParams: [...], **dashboard_state} lets 
dashboard_state["urlParams"]
+    # overwrite the native_filters param. The tabs path (_get_tabs_urls) does 
not
+    # have this issue because it builds the dict without **dashboard_state.
+    assert (
+        state["urlParams"] is None
+    )  # should be [["native_filters", native_filter_rison]]

Review Comment:
   This test is asserting the current buggy behavior where 
`dashboard_state["urlParams"]` overwrites the injected `native_filters` URL 
param (because the state dict is built as `{ "urlParams": ..., 
**dashboard_state }`). That means dashboard native filters are silently dropped 
whenever `dashboard_state.urlParams` is present (even `None`). Prefer asserting 
the correct behavior (native_filters preserved) and fix 
`BaseReportState.get_dashboard_urls()` to merge state without letting 
`dashboard_state.urlParams` override the computed value (eg merge in the 
opposite order or explicitly set/append `urlParams`).
   ```suggestion
       # Ensure that dashboard_state["urlParams"] does not overwrite the 
injected
       # native_filters param. The tabs path (_get_tabs_urls) already builds 
the dict
       # correctly, so get_dashboard_urls() should behave the same way.
       assert state["urlParams"] == [["native_filters", native_filter_rison]]
   ```



##########
superset-frontend/src/pages/AlertReportList/index.tsx:
##########
@@ -242,9 +242,13 @@ function AlertList({
           }),
         );
 
-        updateResource(update_id, { active: checked }, false, false)
-          .then()
-          .catch(() => setResourceCollection(original));
+        updateResource(update_id, { active: checked }, false, false).then(
+          response => {
+            if (!response) {
+              setResourceCollection(original);
+            }
+          },
+        );

Review Comment:
   PR description states this is a test-only change, but this hunk modifies 
production UI behavior (the rollback logic after `updateResource`). Please 
update the PR description to reflect the presence of production changes, or 
split the production change into a separate PR so reviewers can assess it 
independently.



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