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


##########
tests/integration_tests/reports/api_tests.py:
##########
@@ -1527,6 +1527,177 @@ def test_update_report_schedule(self):
         assert updated_model.chart_id == report_schedule_data["chart"]
         assert updated_model.database_id == report_schedule_data["database"]
 
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_clear_recipients(self):
+        """
+        ReportSchedule API: clear recipients on empty list
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        assert len(report_schedule.recipients) == 2
+
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [],
+        }
+
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 200
+        db.session.expire(report_schedule)
+        assert report_schedule.recipients == []
+
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_empty_email_target(self):
+        """
+        ReportSchedule API: Test update with empty email target returns 400
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [
+                {
+                    "type": ReportRecipientType.EMAIL,
+                    "recipient_config_json": {"target": ""},
+                }
+            ],
+        }
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 400
+
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_invalid_email(self):
+        """
+        ReportSchedule API: Test update with invalid email returns 400
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [
+                {
+                    "type": ReportRecipientType.EMAIL,
+                    "recipient_config_json": {"target": "notanemail"},
+                }
+            ],
+        }
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 400
+
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_invalid_cc_email(self):
+        """
+        ReportSchedule API: Test update with invalid ccTarget
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [
+                {
+                    "type": ReportRecipientType.EMAIL,
+                    "recipient_config_json": {
+                        "target": "[email protected]",
+                        "ccTarget": "bademail",
+                    },
+                }
+            ],
+        }
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 400
+
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_invalid_bcc_email(self):
+        """
+        ReportSchedule API: Test update with invalid bccTarget
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [
+                {
+                    "type": ReportRecipientType.EMAIL,
+                    "recipient_config_json": {
+                        "target": "[email protected]",
+                        "bccTarget": "bademail",
+                    },
+                }
+            ],
+        }
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 400
+
+    @pytest.mark.usefixtures("create_report_schedules")
+    def test_update_report_schedule_slack_empty_target_allowed(self):
+        """
+        ReportSchedule API: Test that Slack recipients skip email validation
+        """
+        report_schedule = (
+            db.session.query(ReportSchedule)
+            .filter(ReportSchedule.name == "name2")
+            .one_or_none()
+        )
+        self.login(ADMIN_USERNAME)
+        report_schedule_data = {
+            "recipients": [
+                {
+                    "type": ReportRecipientType.SLACK,
+                    "recipient_config_json": {"target": ""},
+                }
+            ],
+        }
+        uri = f"api/v1/report/{report_schedule.id}"
+        rv = self.put_assert_metric(uri, report_schedule_data, "put")
+        assert rv.status_code == 200

Review Comment:
   **Suggestion:** This test currently enforces that an empty Slack `target` is 
accepted, but downstream Slack delivery code requires at least one channel and 
raises runtime notification errors when recipients are empty. The API should 
reject this invalid configuration during update, so the assertion should expect 
a validation failure instead of success. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Scheduled Slack reports fail during `reports.execute` task.
   - ⚠️ Report state flips to ERROR after send attempt.
   - ⚠️ Invalid Slack recipients persist via PUT API.
   ```
   </details>
   
   ```suggestion
           rv = self.put_assert_metric(uri, report_schedule_data, "put")
           assert rv.status_code == 400
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Call `PUT /api/v1/report/{id}` with recipient payload
   `{"type":"Slack","recipient_config_json":{"target":""}}`; request is handled 
by
   `ReportScheduleRestApi.put()` at `superset/reports/api.py:394-95`.
   
   2. The payload passes schema validation because
   `ReportRecipientSchema.validate_email_recipients()` returns early for 
non-email recipients
   (`superset/reports/schemas.py:146-148`), and update persists recipients in
   `ReportScheduleDAO.update()` (`superset/daos/report.py:190-202`).
   
   3. This behavior is explicitly exercised by the new integration test
   `test_update_report_schedule_slack_empty_target_allowed` in
   `tests/integration_tests/reports/api_tests.py:1652-1672`, which expects 
`200`.
   
   4. When the schedule later executes through Celery
   (`superset/tasks/scheduler.py:116-134`), notification send path
   (`superset/commands/report/execute.py:671-699`) processes Slack recipients; 
for Slack v2
   path, empty `target` becomes no channels and raises 
`NotificationParamException` in
   `superset/reports/notifications/slackv2.py:91-93`, causing execution errors.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** tests/integration_tests/reports/api_tests.py
   **Line:** 1671:1672
   **Comment:**
        *Logic Error: This test currently enforces that an empty Slack `target` 
is accepted, but downstream Slack delivery code requires at least one channel 
and raises runtime notification errors when recipients are empty. The API 
should reject this invalid configuration during update, so the assertion should 
expect a validation failure instead of success.
   
   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>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38711&comment_hash=8f7d09acf0956edde1961ea1d5e88ccdf618346f591a48240771b1f44f8ae697&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F38711&comment_hash=8f7d09acf0956edde1961ea1d5e88ccdf618346f591a48240771b1f44f8ae697&reaction=dislike'>👎</a>



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