codeant-ai-for-open-source[bot] commented on code in PR #41097:
URL: https://github.com/apache/superset/pull/41097#discussion_r3483212732
##########
tests/unit_tests/utils/webdriver_test.py:
##########
@@ -964,13 +964,240 @@ def evaluate_side_effect(script):
driver = WebDriverPlaywright("chrome")
result = driver.get_screenshot(
- "http://example.com", "dashboard", mock_user
+ "http://example.com", "standalone", mock_user
)
- assert result is None
- mock_element.screenshot.assert_not_called()
- mock_logger.error.assert_any_call(
- "Tiled screenshot failed at url %s; "
- "not falling back to avoid sending a blank PDF",
- "http://example.com",
+ assert result == b"fallback_screenshot"
+ mock_take_tiled.assert_called_once()
+ mock_logger.warning.assert_any_call(
+ ("Tiled screenshot failed, falling back to standard screenshot"),
+ )
+
+
+class TestWebDriverPlaywrightAnimationWaitOrder:
+ """Animation wait must run after the spinner wait, not before."""
+
+ _base_config = {
+ "WEBDRIVER_OPTION_ARGS": [],
+ "WEBDRIVER_WINDOW": {"pixel_density": 1},
+ "SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT": 30000,
+ "SCREENSHOT_PLAYWRIGHT_WAIT_EVENT": "networkidle",
+ "SCREENSHOT_SELENIUM_HEADSTART": 0,
+ "SCREENSHOT_SELENIUM_ANIMATION_WAIT": 2,
+ "SCREENSHOT_REPLACE_UNEXPECTED_ERRORS": False,
+ "SCREENSHOT_LOCATE_WAIT": 10,
+ "SCREENSHOT_LOAD_WAIT": 30,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_VISIBLE": 10,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_INVISIBLE": 10,
+ }
+
+ def _make_pw_mocks(self, mock_sync_playwright):
Review Comment:
**Suggestion:** Add explicit type hints for the parameters and return value
of this helper so new test code remains fully typed. [custom_rule]
**Severity Level:** Minor ⚠️
<details>
<summary><b>Why it matters? 🤔 </b></summary>
This is newly added Python code and it omits both parameter type hints and a
return type annotation.
The custom rule requires new Python functions/methods to be fully typed, so
this is a real violation.
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=f7073a4db9c041728668fd7bf8cbc6e7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=f7073a4db9c041728668fd7bf8cbc6e7&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** tests/unit_tests/utils/webdriver_test.py
**Line:** 994:994
**Comment:**
*Custom Rule: Add explicit type hints for the parameters and return
value of this helper so new test code remains fully typed.
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.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=6ed4d8c17d11b756811b9fb5eddd90047b107cfc89d138e2d36d6fe46c7e08e8&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=6ed4d8c17d11b756811b9fb5eddd90047b107cfc89d138e2d36d6fe46c7e08e8&reaction=dislike'>👎</a>
##########
tests/unit_tests/utils/webdriver_test.py:
##########
@@ -964,13 +964,240 @@ def evaluate_side_effect(script):
driver = WebDriverPlaywright("chrome")
result = driver.get_screenshot(
- "http://example.com", "dashboard", mock_user
+ "http://example.com", "standalone", mock_user
)
- assert result is None
- mock_element.screenshot.assert_not_called()
- mock_logger.error.assert_any_call(
- "Tiled screenshot failed at url %s; "
- "not falling back to avoid sending a blank PDF",
- "http://example.com",
+ assert result == b"fallback_screenshot"
+ mock_take_tiled.assert_called_once()
+ mock_logger.warning.assert_any_call(
+ ("Tiled screenshot failed, falling back to standard screenshot"),
+ )
+
+
+class TestWebDriverPlaywrightAnimationWaitOrder:
+ """Animation wait must run after the spinner wait, not before."""
+
+ _base_config = {
+ "WEBDRIVER_OPTION_ARGS": [],
+ "WEBDRIVER_WINDOW": {"pixel_density": 1},
+ "SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT": 30000,
+ "SCREENSHOT_PLAYWRIGHT_WAIT_EVENT": "networkidle",
+ "SCREENSHOT_SELENIUM_HEADSTART": 0,
+ "SCREENSHOT_SELENIUM_ANIMATION_WAIT": 2,
+ "SCREENSHOT_REPLACE_UNEXPECTED_ERRORS": False,
+ "SCREENSHOT_LOCATE_WAIT": 10,
+ "SCREENSHOT_LOAD_WAIT": 30,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_VISIBLE": 10,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_INVISIBLE": 10,
+ }
+
+ def _make_pw_mocks(self, mock_sync_playwright):
+ mock_playwright_instance = MagicMock()
+ mock_browser = MagicMock()
+ mock_context = MagicMock()
+ mock_page = MagicMock()
+ mock_element = MagicMock()
+
+ mock_sync_playwright.return_value.__enter__.return_value = (
+ mock_playwright_instance
+ )
+ mock_playwright_instance.chromium.launch.return_value = mock_browser
+ mock_browser.new_context.return_value = mock_context
+ mock_context.new_page.return_value = mock_page
+ mock_page.locator.return_value = mock_element
+ mock_element.screenshot.return_value = b"screenshot"
+ return mock_context, mock_page
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_after_spinner_wait_tiled_disabled(
+ self, mock_app, mock_sync_playwright
+ ):
Review Comment:
**Suggestion:** Add a return type annotation and parameter type hints to
this newly added test method to comply with the typing rule for new Python
code. [custom_rule]
**Severity Level:** Minor ⚠️
<details>
<summary><b>Why it matters? 🤔 </b></summary>
This newly added test method omits parameter annotations and a return
annotation.
Since the surrounding code is being changed, the custom typing rule applies
and this is a genuine violation.
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=2b7f072a2eec4ac88c38bd38e6a06dd5&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=2b7f072a2eec4ac88c38bd38e6a06dd5&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** tests/unit_tests/utils/webdriver_test.py
**Line:** 1014:1016
**Comment:**
*Custom Rule: Add a return type annotation and parameter type hints to
this newly added test method to comply with the typing rule for new Python code.
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.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=b8dec38244db9bfcd19cc6e9b2d2b41efe3ff5dfb430d1419d930b2897e09c82&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=b8dec38244db9bfcd19cc6e9b2d2b41efe3ff5dfb430d1419d930b2897e09c82&reaction=dislike'>👎</a>
##########
tests/unit_tests/utils/webdriver_test.py:
##########
@@ -964,13 +964,240 @@ def evaluate_side_effect(script):
driver = WebDriverPlaywright("chrome")
result = driver.get_screenshot(
- "http://example.com", "dashboard", mock_user
+ "http://example.com", "standalone", mock_user
)
- assert result is None
- mock_element.screenshot.assert_not_called()
- mock_logger.error.assert_any_call(
- "Tiled screenshot failed at url %s; "
- "not falling back to avoid sending a blank PDF",
- "http://example.com",
+ assert result == b"fallback_screenshot"
+ mock_take_tiled.assert_called_once()
+ mock_logger.warning.assert_any_call(
+ ("Tiled screenshot failed, falling back to standard screenshot"),
+ )
+
+
+class TestWebDriverPlaywrightAnimationWaitOrder:
+ """Animation wait must run after the spinner wait, not before."""
+
+ _base_config = {
+ "WEBDRIVER_OPTION_ARGS": [],
+ "WEBDRIVER_WINDOW": {"pixel_density": 1},
+ "SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT": 30000,
+ "SCREENSHOT_PLAYWRIGHT_WAIT_EVENT": "networkidle",
+ "SCREENSHOT_SELENIUM_HEADSTART": 0,
+ "SCREENSHOT_SELENIUM_ANIMATION_WAIT": 2,
+ "SCREENSHOT_REPLACE_UNEXPECTED_ERRORS": False,
+ "SCREENSHOT_LOCATE_WAIT": 10,
+ "SCREENSHOT_LOAD_WAIT": 30,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_VISIBLE": 10,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_INVISIBLE": 10,
+ }
+
+ def _make_pw_mocks(self, mock_sync_playwright):
+ mock_playwright_instance = MagicMock()
+ mock_browser = MagicMock()
+ mock_context = MagicMock()
+ mock_page = MagicMock()
+ mock_element = MagicMock()
+
+ mock_sync_playwright.return_value.__enter__.return_value = (
+ mock_playwright_instance
+ )
+ mock_playwright_instance.chromium.launch.return_value = mock_browser
+ mock_browser.new_context.return_value = mock_context
+ mock_context.new_page.return_value = mock_page
+ mock_page.locator.return_value = mock_element
+ mock_element.screenshot.return_value = b"screenshot"
+ return mock_context, mock_page
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_after_spinner_wait_tiled_disabled(
+ self, mock_app, mock_sync_playwright
+ ):
+ """Non-tiled path: animation wait runs after spinner
wait_for_function."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {**self._base_config, "SCREENSHOT_TILED_ENABLED":
False}
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+
+ call_order: list[str] = []
+
+ def record_wait_for_function(*args, **kwargs):
+ call_order.append("spinner_wait")
+
+ def record_wait_for_timeout(ms):
+ if ms == 2 * 1000:
+ call_order.append("animation_wait")
+
+ mock_page.wait_for_function.side_effect = record_wait_for_function
+ mock_page.wait_for_timeout.side_effect = record_wait_for_timeout
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "test-element", mock_user
+ )
+
+ assert "spinner_wait" in call_order
+ assert "animation_wait" in call_order
+ spinner_idx = call_order.index("spinner_wait")
+ anim_idx = call_order.index("animation_wait")
+ assert spinner_idx < anim_idx, (
+ "spinner wait must precede animation wait in non-tiled path"
+ )
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_after_spinner_wait_tiled_enabled_small_dashboard(
+ self, mock_app, mock_sync_playwright
+ ):
+ """Non-tiled path (tiled on, small dashboard): animation after
spinner."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {
+ **self._base_config,
+ "SCREENSHOT_TILED_ENABLED": True,
+ "SCREENSHOT_TILED_CHART_THRESHOLD": 20,
+ "SCREENSHOT_TILED_HEIGHT_THRESHOLD": 5000,
+ "SCREENSHOT_TILED_VIEWPORT_HEIGHT": 600,
+ }
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+
+ # Small dashboard: 3 charts, 1000px height — below both thresholds
+ mock_page.evaluate.side_effect = [3, 1000]
+
+ call_order: list[str] = []
+
+ def record_wait_for_function(*args, **kwargs):
+ call_order.append("spinner_wait")
+
+ def record_wait_for_timeout(ms):
+ if ms == 2 * 1000:
+ call_order.append("animation_wait")
+
+ mock_page.wait_for_function.side_effect = record_wait_for_function
+ mock_page.wait_for_timeout.side_effect = record_wait_for_timeout
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "test-element", mock_user
+ )
+
+ assert "spinner_wait" in call_order
+ assert "animation_wait" in call_order
+ assert call_order.index("spinner_wait") <
call_order.index("animation_wait")
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.take_tiled_screenshot")
+ @patch("superset.utils.webdriver.app")
+ def test_tiled_path_passes_animation_wait_per_tile_no_global_wait(
+ self, mock_app, mock_take_tiled, mock_sync_playwright
+ ):
Review Comment:
**Suggestion:** Add complete type annotations to this new test method
signature, including its return type. [custom_rule]
**Severity Level:** Minor ⚠️
<details>
<summary><b>Why it matters? 🤔 </b></summary>
This is new Python test code and it is not typed: the parameters are
unannotated and there is no return type.
That matches the custom rule for new or modified Python code, so the
suggestion is verified.
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=7cd9bb45eb6f4b29b1b5427cdbd77d1c&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=7cd9bb45eb6f4b29b1b5427cdbd77d1c&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** tests/unit_tests/utils/webdriver_test.py
**Line:** 1096:1098
**Comment:**
*Custom Rule: Add complete type annotations to this new test method
signature, including its return type.
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.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=653c1eac6e1fd19f4fab2a74086fb154e9a5c2b42fcc33821551732f3dc8c3e4&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=653c1eac6e1fd19f4fab2a74086fb154e9a5c2b42fcc33821551732f3dc8c3e4&reaction=dislike'>👎</a>
##########
tests/unit_tests/utils/webdriver_test.py:
##########
@@ -964,13 +964,240 @@ def evaluate_side_effect(script):
driver = WebDriverPlaywright("chrome")
result = driver.get_screenshot(
- "http://example.com", "dashboard", mock_user
+ "http://example.com", "standalone", mock_user
)
- assert result is None
- mock_element.screenshot.assert_not_called()
- mock_logger.error.assert_any_call(
- "Tiled screenshot failed at url %s; "
- "not falling back to avoid sending a blank PDF",
- "http://example.com",
+ assert result == b"fallback_screenshot"
+ mock_take_tiled.assert_called_once()
+ mock_logger.warning.assert_any_call(
+ ("Tiled screenshot failed, falling back to standard screenshot"),
+ )
+
+
+class TestWebDriverPlaywrightAnimationWaitOrder:
+ """Animation wait must run after the spinner wait, not before."""
+
+ _base_config = {
+ "WEBDRIVER_OPTION_ARGS": [],
+ "WEBDRIVER_WINDOW": {"pixel_density": 1},
+ "SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT": 30000,
+ "SCREENSHOT_PLAYWRIGHT_WAIT_EVENT": "networkidle",
+ "SCREENSHOT_SELENIUM_HEADSTART": 0,
+ "SCREENSHOT_SELENIUM_ANIMATION_WAIT": 2,
+ "SCREENSHOT_REPLACE_UNEXPECTED_ERRORS": False,
+ "SCREENSHOT_LOCATE_WAIT": 10,
+ "SCREENSHOT_LOAD_WAIT": 30,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_VISIBLE": 10,
+ "SCREENSHOT_WAIT_FOR_ERROR_MODAL_INVISIBLE": 10,
+ }
+
+ def _make_pw_mocks(self, mock_sync_playwright):
+ mock_playwright_instance = MagicMock()
+ mock_browser = MagicMock()
+ mock_context = MagicMock()
+ mock_page = MagicMock()
+ mock_element = MagicMock()
+
+ mock_sync_playwright.return_value.__enter__.return_value = (
+ mock_playwright_instance
+ )
+ mock_playwright_instance.chromium.launch.return_value = mock_browser
+ mock_browser.new_context.return_value = mock_context
+ mock_context.new_page.return_value = mock_page
+ mock_page.locator.return_value = mock_element
+ mock_element.screenshot.return_value = b"screenshot"
+ return mock_context, mock_page
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_after_spinner_wait_tiled_disabled(
+ self, mock_app, mock_sync_playwright
+ ):
+ """Non-tiled path: animation wait runs after spinner
wait_for_function."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {**self._base_config, "SCREENSHOT_TILED_ENABLED":
False}
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+
+ call_order: list[str] = []
+
+ def record_wait_for_function(*args, **kwargs):
+ call_order.append("spinner_wait")
+
+ def record_wait_for_timeout(ms):
+ if ms == 2 * 1000:
+ call_order.append("animation_wait")
+
+ mock_page.wait_for_function.side_effect = record_wait_for_function
+ mock_page.wait_for_timeout.side_effect = record_wait_for_timeout
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "test-element", mock_user
+ )
+
+ assert "spinner_wait" in call_order
+ assert "animation_wait" in call_order
+ spinner_idx = call_order.index("spinner_wait")
+ anim_idx = call_order.index("animation_wait")
+ assert spinner_idx < anim_idx, (
+ "spinner wait must precede animation wait in non-tiled path"
+ )
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_after_spinner_wait_tiled_enabled_small_dashboard(
+ self, mock_app, mock_sync_playwright
+ ):
+ """Non-tiled path (tiled on, small dashboard): animation after
spinner."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {
+ **self._base_config,
+ "SCREENSHOT_TILED_ENABLED": True,
+ "SCREENSHOT_TILED_CHART_THRESHOLD": 20,
+ "SCREENSHOT_TILED_HEIGHT_THRESHOLD": 5000,
+ "SCREENSHOT_TILED_VIEWPORT_HEIGHT": 600,
+ }
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+
+ # Small dashboard: 3 charts, 1000px height — below both thresholds
+ mock_page.evaluate.side_effect = [3, 1000]
+
+ call_order: list[str] = []
+
+ def record_wait_for_function(*args, **kwargs):
+ call_order.append("spinner_wait")
+
+ def record_wait_for_timeout(ms):
+ if ms == 2 * 1000:
+ call_order.append("animation_wait")
+
+ mock_page.wait_for_function.side_effect = record_wait_for_function
+ mock_page.wait_for_timeout.side_effect = record_wait_for_timeout
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "test-element", mock_user
+ )
+
+ assert "spinner_wait" in call_order
+ assert "animation_wait" in call_order
+ assert call_order.index("spinner_wait") <
call_order.index("animation_wait")
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.take_tiled_screenshot")
+ @patch("superset.utils.webdriver.app")
+ def test_tiled_path_passes_animation_wait_per_tile_no_global_wait(
+ self, mock_app, mock_take_tiled, mock_sync_playwright
+ ):
+ """Tiled path delegates animation_wait to take_tiled_screenshot; no
global."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {
+ **self._base_config,
+ "SCREENSHOT_TILED_ENABLED": True,
+ "SCREENSHOT_TILED_CHART_THRESHOLD": 20,
+ "SCREENSHOT_TILED_HEIGHT_THRESHOLD": 5000,
+ "SCREENSHOT_TILED_VIEWPORT_HEIGHT": 600,
+ }
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+
+ # Large dashboard: 25 charts, 6000px height
+ mock_page.evaluate.side_effect = [25, 6000]
+ mock_take_tiled.return_value = b"tiled_screenshot"
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ result = WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "standalone", mock_user
+ )
+
+ assert result == b"tiled_screenshot"
+ mock_take_tiled.assert_called_once_with(
+ mock_page,
+ "standalone",
+ 600,
+ load_wait=30,
+ animation_wait=2,
+ )
+ # The only wait_for_timeout call should be the 0ms headstart; no global
+ # animation wait should be issued (handled per-tile by
take_tiled_screenshot)
+ animation_waits = [
+ call[0][0]
+ for call in mock_page.wait_for_timeout.call_args_list
+ if call[0][0] == 2 * 1000
+ ]
+ assert animation_waits == [], (
+ "No global 2s animation wait_for_timeout should fire on the tiled
path"
+ )
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.take_tiled_screenshot")
+ @patch("superset.utils.webdriver.app")
+ def test_tiled_fallback_triggered_on_empty_bytes(
+ self, mock_app, mock_take_tiled, mock_sync_playwright
+ ):
+ """Tiled fallback fires when take_tiled_screenshot returns b"" (not
None)."""
+ mock_user = MagicMock()
+ mock_user.username = "test_user"
+ mock_app.config = {
+ **self._base_config,
+ "SCREENSHOT_TILED_ENABLED": True,
+ "SCREENSHOT_TILED_CHART_THRESHOLD": 20,
+ "SCREENSHOT_TILED_HEIGHT_THRESHOLD": 5000,
+ "SCREENSHOT_TILED_VIEWPORT_HEIGHT": 600,
+ }
+
+ mock_context, mock_page = self._make_pw_mocks(mock_sync_playwright)
+ mock_page.evaluate.side_effect = [25, 6000]
+ # Empty bytes — falsy but not None; was silently passed through before
the fix
+ mock_take_tiled.return_value = b""
+ # _get_screenshot("standalone") calls page.screenshot(full_page=True);
+ # configure that return value so we can assert the fallback was reached
+ mock_page.screenshot.return_value = b"fallback"
+
+ with patch.object(WebDriverPlaywright, "auth",
return_value=mock_context):
+ result = WebDriverPlaywright("chrome").get_screenshot(
+ "http://example.com", "standalone", mock_user
+ )
+
+ assert result == b"fallback"
+ # Tiled path was taken (take_tiled_screenshot was called)
+ mock_take_tiled.assert_called_once()
+ # Standard screenshot was called as fallback (full_page=True for
"standalone")
+ mock_page.screenshot.assert_called_with(full_page=True)
+
+ @patch("superset.utils.webdriver.PLAYWRIGHT_AVAILABLE", True)
+ @patch("superset.utils.webdriver.sync_playwright")
+ @patch("superset.utils.webdriver.app")
+ def test_animation_wait_skipped_when_zero(self, mock_app,
mock_sync_playwright):
Review Comment:
**Suggestion:** Add type hints for method parameters and an explicit `None`
return annotation on this new test method. [custom_rule]
**Severity Level:** Minor ⚠️
<details>
<summary><b>Why it matters? 🤔 </b></summary>
This newly added test method lacks parameter type hints and a return
annotation.
The custom rule explicitly requires new Python functions and classes to be
fully typed, so this is a real violation.
</details>
[](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=2e103522d2c541a18890412893458fa2&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
[](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=2e103522d2c541a18890412893458fa2&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
*(Use Cmd/Ctrl + Click for best experience)*
<details>
<summary><b>Prompt for AI Agent 🤖 </b></summary>
```mdx
This is a comment left during a code review.
**Path:** tests/unit_tests/utils/webdriver_test.py
**Line:** 1180:1180
**Comment:**
*Custom Rule: Add type hints for method parameters and an explicit
`None` return annotation on this new test method.
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.
Once fix is implemented, also check other comments on the same PR, and ask
user if the user wants to fix the rest of the comments as well. if said yes,
then fetch all the comments validate the correctness and implement a minimal fix
```
</details>
<a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=6fe2a0cf8bdd40ba15a8bbded22d774a2ddb0583e5dc01b6454630f98187165f&reaction=like'>👍</a>
| <a
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F41097&comment_hash=6fe2a0cf8bdd40ba15a8bbded22d774a2ddb0583e5dc01b6454630f98187165f&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]