mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
fix: pass slack recipients correctly (#29721)
(cherry picked from commit 57e8cd2ba2)
This commit is contained in:
committed by
Joe Li
parent
bca2366d5a
commit
77ade18107
222
tests/unit_tests/commands/report/execute_test.py
Normal file
222
tests/unit_tests/commands/report/execute_test.py
Normal file
@@ -0,0 +1,222 @@
|
||||
# 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 pytest_mock import MockerFixture
|
||||
|
||||
from superset.commands.report.execute import BaseReportState
|
||||
from superset.reports.models import (
|
||||
ReportRecipientType,
|
||||
ReportSchedule,
|
||||
ReportSourceFormat,
|
||||
)
|
||||
from superset.utils.core import HeaderDataType
|
||||
|
||||
|
||||
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
|
||||
@@ -41,6 +41,7 @@ def test_render_description_with_html() -> None:
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
"slack_channels": None,
|
||||
},
|
||||
)
|
||||
email_body = (
|
||||
|
||||
@@ -19,12 +19,27 @@ import uuid
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
from superset.reports.notifications.slackv2 import SlackV2Notification
|
||||
from superset.utils.core import HeaderDataType
|
||||
|
||||
|
||||
def test_get_channel_with_multi_recipients() -> None:
|
||||
@pytest.fixture
|
||||
def mock_header_data() -> HeaderDataType:
|
||||
return {
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
"slack_channels": ["some_channel"],
|
||||
}
|
||||
|
||||
|
||||
def test_get_channel_with_multi_recipients(mock_header_data) -> None:
|
||||
"""
|
||||
Test the _get_channel function to ensure it will return a string
|
||||
with recipients separated by commas without interstitial spacing
|
||||
@@ -35,14 +50,7 @@ def test_get_channel_with_multi_recipients() -> None:
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -67,7 +75,7 @@ def test_get_channel_with_multi_recipients() -> None:
|
||||
# Test if the recipient configuration JSON is valid when using a SlackV2 recipient type
|
||||
|
||||
|
||||
def test_valid_recipient_config_json_slackv2() -> None:
|
||||
def test_valid_recipient_config_json_slackv2(mock_header_data) -> None:
|
||||
"""
|
||||
Test if the recipient configuration JSON is valid when using a SlackV2 recipient type
|
||||
"""
|
||||
@@ -77,14 +85,7 @@ def test_valid_recipient_config_json_slackv2() -> None:
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -109,7 +110,7 @@ def test_valid_recipient_config_json_slackv2() -> None:
|
||||
# Ensure _get_inline_files function returns the correct tuple when content has screenshots
|
||||
|
||||
|
||||
def test_get_inline_files_with_screenshots() -> None:
|
||||
def test_get_inline_files_with_screenshots(mock_header_data) -> None:
|
||||
"""
|
||||
Test the _get_inline_files function to ensure it will return the correct tuple
|
||||
when content has screenshots
|
||||
@@ -120,14 +121,7 @@ def test_get_inline_files_with_screenshots() -> None:
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -153,7 +147,7 @@ def test_get_inline_files_with_screenshots() -> None:
|
||||
# Ensure _get_inline_files function returns None when content has no screenshots or csv
|
||||
|
||||
|
||||
def test_get_inline_files_with_no_screenshots_or_csv() -> None:
|
||||
def test_get_inline_files_with_no_screenshots_or_csv(mock_header_data) -> None:
|
||||
"""
|
||||
Test the _get_inline_files function to ensure it will return None
|
||||
when content has no screenshots or csv
|
||||
@@ -164,14 +158,7 @@ def test_get_inline_files_with_no_screenshots_or_csv() -> None:
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -201,6 +188,7 @@ def test_send_slackv2(
|
||||
slack_client_mock: MagicMock,
|
||||
logger_mock: MagicMock,
|
||||
flask_global_mock: MagicMock,
|
||||
mock_header_data,
|
||||
) -> None:
|
||||
# `superset.models.helpers`, a dependency of following imports,
|
||||
# requires app context
|
||||
@@ -212,14 +200,7 @@ def test_send_slackv2(
|
||||
slack_client_mock.return_value.chat_postMessage.return_value = {"ok": True}
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -269,6 +250,7 @@ def test_send_slack(
|
||||
slack_client_mock_util: MagicMock,
|
||||
logger_mock: MagicMock,
|
||||
flask_global_mock: MagicMock,
|
||||
mock_header_data,
|
||||
) -> None:
|
||||
# `superset.models.helpers`, a dependency of following imports,
|
||||
# requires app context
|
||||
@@ -285,14 +267,7 @@ def test_send_slack(
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
@@ -343,6 +318,7 @@ def test_send_slack_no_feature_flag(
|
||||
slack_client_mock_util: MagicMock,
|
||||
logger_mock: MagicMock,
|
||||
flask_global_mock: MagicMock,
|
||||
mock_header_data,
|
||||
) -> None:
|
||||
# `superset.models.helpers`, a dependency of following imports,
|
||||
# requires app context
|
||||
@@ -360,14 +336,7 @@ def test_send_slack_no_feature_flag(
|
||||
|
||||
content = NotificationContent(
|
||||
name="test alert",
|
||||
header_data={
|
||||
"notification_format": "PNG",
|
||||
"notification_type": "Alert",
|
||||
"owners": [1],
|
||||
"notification_source": None,
|
||||
"chart_id": None,
|
||||
"dashboard_id": None,
|
||||
},
|
||||
header_data=mock_header_data,
|
||||
embedded_data=pd.DataFrame(
|
||||
{
|
||||
"A": [1, 2, 3],
|
||||
|
||||
Reference in New Issue
Block a user