mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat(alert/reports): adding logic to handle downstream reports when tab is deleted from dashboard (#29333)
This commit is contained in:
219
tests/integration_tests/dashboards/update_tabs_test.py
Normal file
219
tests/integration_tests/dashboards/update_tabs_test.py
Normal file
@@ -0,0 +1,219 @@
|
||||
# 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.
|
||||
from unittest.mock import ANY, call, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from superset import db, security_manager
|
||||
from superset.commands.dashboard.update import UpdateDashboardCommand
|
||||
from superset.models.dashboard import Dashboard
|
||||
from superset.utils.json import dumps
|
||||
from tests.integration_tests.fixtures.tabbed_dashboard import (
|
||||
tabbed_dashboard, # noqa: F401
|
||||
)
|
||||
from tests.integration_tests.reports.utils import (
|
||||
cleanup_report_schedule,
|
||||
create_report_notification,
|
||||
)
|
||||
from tests.integration_tests.test_app import app
|
||||
|
||||
tab1 = "TAB-L1AA"
|
||||
tab2 = "TAB-L1AB"
|
||||
tab3 = "TAB-L1BB"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True, scope="module")
|
||||
def initial_report_cleanup():
|
||||
with app.app_context():
|
||||
cleanup_report_schedule()
|
||||
|
||||
|
||||
def remove_tabs_from_dashboard(dashboard: Dashboard, tabs: list[str]):
|
||||
data = dashboard.data.copy()
|
||||
position = data["position_json"]
|
||||
for tab in tabs:
|
||||
del position[tab]
|
||||
data["position_json"] = dumps(position)
|
||||
return data
|
||||
|
||||
|
||||
@patch("superset.commands.dashboard.update.send_email_smtp")
|
||||
@patch.dict(
|
||||
"superset.extensions.feature_flag_manager._feature_flags", ALERT_REPORT_TABS=True
|
||||
)
|
||||
def test_tab_deletion_single_report(
|
||||
send_email_smtp_mock: MagicMock,
|
||||
tabbed_dashboard: Dashboard, # noqa: F811
|
||||
login_as_admin,
|
||||
):
|
||||
tab_to_delete = tab1
|
||||
users = db.session.query(security_manager.user_model).all()
|
||||
report = create_report_notification(
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": tab_to_delete}},
|
||||
owners=[users[0]],
|
||||
)
|
||||
assert report.active is True
|
||||
UpdateDashboardCommand(
|
||||
tabbed_dashboard.id,
|
||||
remove_tabs_from_dashboard(tabbed_dashboard, [tab_to_delete]),
|
||||
).run()
|
||||
|
||||
assert report.active is False
|
||||
send_email_smtp_mock.assert_called_with(
|
||||
to=users[0].email,
|
||||
subject="[Report: report] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
)
|
||||
cleanup_report_schedule(report)
|
||||
|
||||
|
||||
@patch("superset.commands.dashboard.update.send_email_smtp")
|
||||
@patch.dict(
|
||||
"superset.extensions.feature_flag_manager._feature_flags", ALERT_REPORT_TABS=True
|
||||
)
|
||||
def test_tab_deletion_multiple_reports(
|
||||
send_email_smtp_mock: MagicMock,
|
||||
tabbed_dashboard: Dashboard, # noqa: F811
|
||||
login_as_admin,
|
||||
):
|
||||
tab_to_delete = tab1
|
||||
retained_tab = tab2
|
||||
users = db.session.query(security_manager.user_model).all()
|
||||
report1 = create_report_notification(
|
||||
name="report 1",
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": tab_to_delete}},
|
||||
owners=[users[0], users[1]],
|
||||
)
|
||||
report2 = create_report_notification(
|
||||
name="report 2",
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": tab_to_delete}},
|
||||
owners=[users[1]],
|
||||
)
|
||||
report3 = create_report_notification(
|
||||
name="report 3",
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": retained_tab}},
|
||||
owners=[users[2]],
|
||||
)
|
||||
|
||||
assert report1.active is True
|
||||
assert report2.active is True
|
||||
assert report3.active is True
|
||||
|
||||
UpdateDashboardCommand(
|
||||
tabbed_dashboard.id,
|
||||
remove_tabs_from_dashboard(tabbed_dashboard, [tab_to_delete]),
|
||||
).run()
|
||||
|
||||
assert report1.active is False
|
||||
assert report2.active is False
|
||||
assert report3.active is True
|
||||
|
||||
expected_calls = [
|
||||
call(
|
||||
to=users[0].email,
|
||||
subject="[Report: report 1] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
call(
|
||||
to=users[1].email,
|
||||
subject="[Report: report 1] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
call(
|
||||
to=users[1].email,
|
||||
subject="[Report: report 2] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
]
|
||||
|
||||
assert send_email_smtp_mock.call_count == 3
|
||||
assert send_email_smtp_mock.call_args_list == expected_calls
|
||||
|
||||
cleanup_report_schedule(report1)
|
||||
cleanup_report_schedule(report2)
|
||||
cleanup_report_schedule(report3)
|
||||
|
||||
|
||||
@patch("superset.commands.dashboard.update.send_email_smtp")
|
||||
@patch.dict(
|
||||
"superset.extensions.feature_flag_manager._feature_flags", ALERT_REPORT_TABS=True
|
||||
)
|
||||
def test_multitple_tabs_removed(
|
||||
send_email_smtp_mock: MagicMock,
|
||||
tabbed_dashboard: Dashboard, # noqa: F811
|
||||
login_as_admin,
|
||||
):
|
||||
tabs_to_delete = [tab1, tab2]
|
||||
users = db.session.query(security_manager.user_model).all()
|
||||
report1 = create_report_notification(
|
||||
name="report 1",
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": tabs_to_delete[0]}},
|
||||
owners=[users[0], users[1]],
|
||||
)
|
||||
report2 = create_report_notification(
|
||||
name="report 2",
|
||||
dashboard=tabbed_dashboard,
|
||||
extra={"dashboard": {"anchor": tabs_to_delete[1]}},
|
||||
owners=[users[2]],
|
||||
)
|
||||
|
||||
assert report1.active is True
|
||||
assert report2.active is True
|
||||
|
||||
UpdateDashboardCommand(
|
||||
tabbed_dashboard.id,
|
||||
remove_tabs_from_dashboard(tabbed_dashboard, tabs_to_delete),
|
||||
).run()
|
||||
|
||||
assert report1.active is False
|
||||
assert report2.active is False
|
||||
|
||||
expected_calls = [
|
||||
call(
|
||||
to=users[0].email,
|
||||
subject="[Report: report 1] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
call(
|
||||
to=users[1].email,
|
||||
subject="[Report: report 1] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
call(
|
||||
to=users[2].email,
|
||||
subject="[Report: report 2] Deactivated",
|
||||
html_content=ANY,
|
||||
config=ANY,
|
||||
),
|
||||
]
|
||||
|
||||
assert send_email_smtp_mock.call_count == 3
|
||||
assert send_email_smtp_mock.call_args_list == expected_calls
|
||||
|
||||
cleanup_report_schedule(report1)
|
||||
cleanup_report_schedule(report2)
|
||||
Reference in New Issue
Block a user