# 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. import json from unittest.mock import patch import pytest from pytest_mock import MockerFixture from superset.commands.report.execute import BaseReportState from superset.dashboards.permalink.types import DashboardPermalinkState from superset.reports.models import ( ReportRecipientType, ReportSchedule, ReportSourceFormat, ) from superset.utils.core import HeaderDataType from tests.integration_tests.conftest import with_feature_flags def test_log_data_with_chart(mocker: MockerFixture) -> None: mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule) mock_report_schedule.chart = True mock_report_schedule.chart_id = 123 mock_report_schedule.dashboard_id = None mock_report_schedule.type = "report_type" mock_report_schedule.report_format = "report_format" mock_report_schedule.owners = [1, 2] mock_report_schedule.recipients = [] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.CHART, "notification_format": "report_format", "chart_id": 123, "dashboard_id": None, "owners": [1, 2], "slack_channels": None, } assert result == expected_result def test_log_data_with_dashboard(mocker: MockerFixture) -> 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 = [] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.DASHBOARD, "notification_format": "report_format", "chart_id": None, "dashboard_id": 123, "owners": [1, 2], "slack_channels": None, } assert result == expected_result def test_log_data_with_email_recipients(mocker: MockerFixture) -> 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 = [] mock_report_schedule.recipients = [ mocker.Mock(type=ReportRecipientType.EMAIL, recipient_config_json="email_1"), mocker.Mock(type=ReportRecipientType.EMAIL, recipient_config_json="email_2"), ] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.DASHBOARD, "notification_format": "report_format", "chart_id": None, "dashboard_id": 123, "owners": [1, 2], "slack_channels": [], } assert result == expected_result def test_log_data_with_slack_recipients(mocker: MockerFixture) -> 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 = [] mock_report_schedule.recipients = [ mocker.Mock(type=ReportRecipientType.SLACK, recipient_config_json="channel_1"), mocker.Mock(type=ReportRecipientType.SLACK, recipient_config_json="channel_2"), ] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.DASHBOARD, "notification_format": "report_format", "chart_id": None, "dashboard_id": 123, "owners": [1, 2], "slack_channels": ["channel_1", "channel_2"], } assert result == expected_result def test_log_data_no_owners(mocker: MockerFixture) -> 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 = [] mock_report_schedule.recipients = [ mocker.Mock(type=ReportRecipientType.SLACK, recipient_config_json="channel_1"), mocker.Mock(type=ReportRecipientType.SLACK, recipient_config_json="channel_2"), ] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.DASHBOARD, "notification_format": "report_format", "chart_id": None, "dashboard_id": 123, "owners": [], "slack_channels": ["channel_1", "channel_2"], } assert result == expected_result def test_log_data_with_missing_values(mocker: MockerFixture) -> None: mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule) mock_report_schedule.chart = None mock_report_schedule.chart_id = None mock_report_schedule.dashboard_id = None mock_report_schedule.type = "report_type" mock_report_schedule.report_format = "report_format" mock_report_schedule.owners = [1, 2] mock_report_schedule.recipients = [ mocker.Mock(type=ReportRecipientType.SLACK, recipient_config_json="channel_1"), mocker.Mock( type=ReportRecipientType.SLACKV2, recipient_config_json="channel_2" ), ] class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule result: HeaderDataType = class_instance._get_log_data() expected_result: HeaderDataType = { "notification_type": "report_type", "notification_source": ReportSourceFormat.DASHBOARD, "notification_format": "report_format", "chart_id": None, "dashboard_id": None, "owners": [1, 2], "slack_channels": ["channel_1", "channel_2"], } assert result == expected_result @pytest.mark.parametrize( "anchors, permalink_side_effect, expected_uris", [ # Test user select multiple tabs to export in a dashboard report ( ["mock_tab_anchor_1", "mock_tab_anchor_2"], ["url1", "url2"], [ "http://0.0.0.0:8080/superset/dashboard/p/url1/", "http://0.0.0.0:8080/superset/dashboard/p/url2/", ], ), # Test user select one tab to export in a dashboard report ( "mock_tab_anchor_1", ["url1"], ["http://0.0.0.0:8080/superset/dashboard/p/url1/"], ), ], ) @patch( "superset.commands.dashboard.permalink.create.CreateDashboardPermalinkCommand.run" ) @with_feature_flags(ALERT_REPORT_TABS=True) def test_get_dashboard_urls_with_multiple_tabs( mock_run, mocker: MockerFixture, anchors, permalink_side_effect, expected_uris ) -> 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 = [] mock_report_schedule.extra = { "dashboard": { "anchor": json.dumps(anchors) if isinstance(anchors, list) else anchors, "dataMask": None, "activeTabs": None, "urlParams": None, } } class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule mock_run.side_effect = permalink_side_effect result: list[str] = class_instance.get_dashboard_urls() assert result == expected_uris @patch( "superset.commands.dashboard.permalink.create.CreateDashboardPermalinkCommand.run" ) @with_feature_flags(ALERT_REPORT_TABS=True) def test_get_dashboard_urls_with_exporting_dashboard_only( mock_run, mocker: MockerFixture, ) -> 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 = [] mock_report_schedule.extra = { "dashboard": { "anchor": "", "dataMask": None, "activeTabs": None, "urlParams": None, } } mock_run.return_value = "url1" 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() assert "http://0.0.0.0:8080/superset/dashboard/p/url1/" == result[0] @patch( "superset.commands.dashboard.permalink.create.CreateDashboardPermalinkCommand.run" ) def test_get_tab_urls( mock_run, mocker: MockerFixture, ) -> None: mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule) mock_report_schedule.dashboard_id = 123 class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule mock_run.side_effect = ["uri1", "uri2"] tab_anchors = ["1", "2"] result: list[str] = class_instance._get_tabs_urls(tab_anchors) assert result == [ "http://0.0.0.0:8080/superset/dashboard/p/uri1/", "http://0.0.0.0:8080/superset/dashboard/p/uri2/", ] @patch( "superset.commands.dashboard.permalink.create.CreateDashboardPermalinkCommand.run" ) def test_get_tab_url( mock_run, mocker: MockerFixture, ) -> None: mock_report_schedule: ReportSchedule = mocker.Mock(spec=ReportSchedule) mock_report_schedule.dashboard_id = 123 class_instance: BaseReportState = BaseReportState( mock_report_schedule, "January 1, 2021", "execution_id_example" ) class_instance._report_schedule = mock_report_schedule mock_run.return_value = "uri" dashboard_state = DashboardPermalinkState( anchor="1", dataMask=None, activeTabs=None, urlParams=None, ) result: str = class_instance._get_tab_url(dashboard_state) assert result == "http://0.0.0.0:8080/superset/dashboard/p/uri/"