You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2025/08/03 08:41:23 UTC
(superset) 04/05: fix: cache warmup unable to login (#9597, #18933)
This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch pr-34525
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 6d281650d4e162e814231d06b0fd22ea09c8c5c5
Author: Evan Rusackas <ev...@rusackas.com>
AuthorDate: Sat Aug 2 23:49:05 2025 -0700
fix: cache warmup unable to login (#9597, #18933)
This fixes the cache warmup feature by:
- Using WebDriverProxy to perform warmups instead of simple URL fetching
- Caching dashboards instead of individual slices
- Using security_manager.find_user to find user credentials
- Refining WebDriverProxy for multiple operations with persistent driver instance
Originally by @ensky from PR #20387
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <no...@anthropic.com>
Co-Authored-By: ensky <en...@users.noreply.github.com>
---
docs/docs/configuration/cache.mdx | 24 ++++
superset/config.py | 3 +
superset/tasks/cache.py | 169 ++++++++--------------------
superset/utils/screenshots.py | 12 +-
superset/utils/webdriver.py | 88 ++++++++++-----
tests/integration_tests/strategy_tests.py | 42 ++-----
tests/integration_tests/thumbnails_tests.py | 18 +--
7 files changed, 165 insertions(+), 191 deletions(-)
diff --git a/docs/docs/configuration/cache.mdx b/docs/docs/configuration/cache.mdx
index ccd4daba6d..0f31aed840 100644
--- a/docs/docs/configuration/cache.mdx
+++ b/docs/docs/configuration/cache.mdx
@@ -80,6 +80,30 @@ instead requires a cachelib object.
See [Async Queries via Celery](/docs/configuration/async-queries-celery) for details.
+## Celery beat
+
+Superset has a Celery task that will periodically warm up the cache based on different strategies.
+To use it, add the following to the `CELERYBEAT_SCHEDULE` section in `config.py`:
+
+```python
+SUPERSET_CACHE_WARMUP_USER = "user_with_permission_to_dashboards"
+
+CELERYBEAT_SCHEDULE = {
+ 'cache-warmup-hourly': {
+ 'task': 'cache-warmup',
+ 'schedule': crontab(minute=0, hour='*'), # hourly
+ 'kwargs': {
+ 'strategy_name': 'top_n_dashboards',
+ 'top_n': 5,
+ 'since': '7 days ago',
+ },
+ },
+}
+```
+
+This will cache all the charts in the top 5 most popular dashboards every hour. For other
+strategies, check the `superset/tasks/cache.py` file.
+
## Caching Thumbnails
This is an optional feature that can be turned on by activating its [feature flag](/docs/configuration/configuring-superset#feature-flags) on config:
diff --git a/superset/config.py b/superset/config.py
index d42aadbba3..c996b81bcc 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -837,6 +837,9 @@ THUMBNAIL_CACHE_CONFIG: CacheConfig = {
}
THUMBNAIL_ERROR_CACHE_TTL = int(timedelta(days=1).total_seconds())
+# Cache warmup user
+SUPERSET_CACHE_WARMUP_USER = "admin"
+
# Time before selenium times out after trying to locate an element on the page and wait
# for that element to load for a screenshot.
SCREENSHOT_LOCATE_WAIT = int(timedelta(seconds=10).total_seconds())
diff --git a/superset/tasks/cache.py b/superset/tasks/cache.py
index 1c8012ff83..3bb29de868 100644
--- a/superset/tasks/cache.py
+++ b/superset/tasks/cache.py
@@ -18,10 +18,8 @@ from __future__ import annotations
import logging
from typing import Any, Optional, TypedDict, Union
-from urllib import request
from urllib.error import URLError
-from celery.beat import SchedulingError
from celery.utils.log import get_task_logger
from flask import current_app
from sqlalchemy import and_, func
@@ -30,14 +28,9 @@ from superset import db, security_manager
from superset.extensions import celery_app
from superset.models.core import Log
from superset.models.dashboard import Dashboard
-from superset.models.slice import Slice
from superset.tags.models import Tag, TaggedObject
-from superset.tasks.exceptions import ExecutorNotFoundError, InvalidExecutorError
-from superset.tasks.utils import fetch_csrf_token, get_executor
-from superset.utils import json
from superset.utils.date_parser import parse_human_datetime
-from superset.utils.machine_auth import MachineAuthProvider
-from superset.utils.urls import get_url_path, is_secure_url
+from superset.utils.webdriver import WebDriverSelenium
logger = get_task_logger(__name__)
logger.setLevel(logging.INFO)
@@ -53,29 +46,26 @@ class CacheWarmupTask(TypedDict):
username: str | None
-def get_task(chart: Slice, dashboard: Optional[Dashboard] = None) -> CacheWarmupTask:
- """Return task for warming up a given chart/table cache."""
- executors = current_app.config["CACHE_WARMUP_EXECUTORS"]
- payload: CacheWarmupPayload = {"chart_id": chart.id}
- if dashboard:
- payload["dashboard_id"] = dashboard.id
-
- username: str | None
- try:
- executor = get_executor(executors, chart)
- username = executor[1]
- except (ExecutorNotFoundError, InvalidExecutorError):
- username = None
-
- return {"payload": payload, "username": username}
+def get_dash_url(dashboard: Dashboard) -> str:
+ """Return external URL for warming up a given dashboard cache."""
+ with current_app.test_request_context():
+ baseurl = (
+ # when running this as an async task, drop the request context with
+ # app.test_request_context()
+ current_app.config.get("WEBDRIVER_BASEURL")
+ or "{SUPERSET_WEBSERVER_PROTOCOL}://"
+ "{SUPERSET_WEBSERVER_ADDRESS}:"
+ "{SUPERSET_WEBSERVER_PORT}".format(**current_app.config)
+ )
+ return f"{baseurl}{dashboard.url}"
class Strategy: # pylint: disable=too-few-public-methods
"""
A cache warm up strategy.
- Each strategy defines a `get_tasks` method that returns a list of tasks to
- send to the `/api/v1/chart/warm_up_cache` endpoint.
+ Each strategy defines a `get_urls` method that returns a list of dashboard URLs to
+ warm up using WebDriver.
Strategies can be configured in `superset/config.py`:
@@ -96,15 +86,16 @@ class Strategy: # pylint: disable=too-few-public-methods
def __init__(self) -> None:
pass
- def get_tasks(self) -> list[CacheWarmupTask]:
- raise NotImplementedError("Subclasses must implement get_tasks!")
+ def get_urls(self) -> list[str]:
+ raise NotImplementedError("Subclasses must implement get_urls!")
class DummyStrategy(Strategy): # pylint: disable=too-few-public-methods
"""
- Warm up all charts.
+ Warm up all published dashboards.
- This is a dummy strategy that will fetch all charts. Can be configured by:
+ This is a dummy strategy that will fetch all published dashboards.
+ Can be configured by:
beat_schedule = {
'cache-warmup-hourly': {
@@ -118,8 +109,12 @@ class DummyStrategy(Strategy): # pylint: disable=too-few-public-methods
name = "dummy"
- def get_tasks(self) -> list[CacheWarmupTask]:
- return [get_task(chart) for chart in db.session.query(Slice).all()]
+ def get_urls(self) -> list[str]:
+ dashboards = (
+ db.session.query(Dashboard).filter(Dashboard.published.is_(True)).all()
+ )
+
+ return [get_dash_url(dashboard) for dashboard in dashboards if dashboard.slices]
class TopNDashboardsStrategy(Strategy): # pylint: disable=too-few-public-methods
@@ -147,7 +142,7 @@ class TopNDashboardsStrategy(Strategy): # pylint: disable=too-few-public-method
self.top_n = top_n
self.since = parse_human_datetime(since) if since else None
- def get_tasks(self) -> list[CacheWarmupTask]:
+ def get_urls(self) -> list[str]:
records = (
db.session.query(Log.dashboard_id, func.count(Log.dashboard_id))
.filter(and_(Log.dashboard_id.isnot(None), Log.dttm >= self.since))
@@ -161,11 +156,7 @@ class TopNDashboardsStrategy(Strategy): # pylint: disable=too-few-public-method
db.session.query(Dashboard).filter(Dashboard.id.in_(dash_ids)).all()
)
- return [
- get_task(chart, dashboard)
- for dashboard in dashboards
- for chart in dashboard.slices
- ]
+ return [get_dash_url(dashboard) for dashboard in dashboards]
class DashboardTagsStrategy(Strategy): # pylint: disable=too-few-public-methods
@@ -190,8 +181,8 @@ class DashboardTagsStrategy(Strategy): # pylint: disable=too-few-public-methods
super().__init__()
self.tags = tags or []
- def get_tasks(self) -> list[CacheWarmupTask]:
- tasks = []
+ def get_urls(self) -> list[str]:
+ urls = []
tags = db.session.query(Tag).filter(Tag.name.in_(self.tags)).all()
tag_ids = [tag.id for tag in tags]
@@ -211,73 +202,14 @@ class DashboardTagsStrategy(Strategy): # pylint: disable=too-few-public-methods
Dashboard.id.in_(dash_ids)
)
for dashboard in tagged_dashboards:
- for chart in dashboard.slices:
- tasks.append(get_task(chart))
-
- # add charts that are tagged
- tagged_objects = (
- db.session.query(TaggedObject)
- .filter(
- and_(
- TaggedObject.object_type == "chart",
- TaggedObject.tag_id.in_(tag_ids),
- )
- )
- .all()
- )
- chart_ids = [tagged_object.object_id for tagged_object in tagged_objects]
- tagged_charts = db.session.query(Slice).filter(Slice.id.in_(chart_ids))
- for chart in tagged_charts:
- tasks.append(get_task(chart))
+ urls.append(get_dash_url(dashboard))
- return tasks
+ return urls
strategies = [DummyStrategy, TopNDashboardsStrategy, DashboardTagsStrategy]
-@celery_app.task(name="fetch_url")
-def fetch_url(data: str, headers: dict[str, str]) -> dict[str, str]:
- """
- Celery job to fetch url
- """
- result = {}
- try:
- url = get_url_path("ChartRestApi.warm_up_cache")
-
- if is_secure_url(url):
- logger.info("URL '%s' is secure. Adding Referer header.", url)
- headers.update({"Referer": url})
-
- # Fetch CSRF token for API request
- headers.update(fetch_csrf_token(headers))
-
- logger.info("Fetching %s with payload %s", url, data)
- req = request.Request( # noqa: S310
- url, data=bytes(data, "utf-8"), headers=headers, method="PUT"
- )
- response = request.urlopen( # pylint: disable=consider-using-with # noqa: S310
- req, timeout=600
- )
- logger.info(
- "Fetched %s with payload %s, status code: %s", url, data, response.code
- )
- if response.code == 200:
- result = {"success": data, "response": response.read().decode("utf-8")}
- else:
- result = {"error": data, "status_code": response.code}
- logger.error(
- "Error fetching %s with payload %s, status code: %s",
- url,
- data,
- response.code,
- )
- except URLError as err:
- logger.exception("Error warming up cache!")
- result = {"error": data, "exception": str(err)}
- return result
-
-
@celery_app.task(name="cache-warmup")
def cache_warmup(
strategy_name: str, *args: Any, **kwargs: Any
@@ -285,7 +217,7 @@ def cache_warmup(
"""
Warm up cache.
- This task periodically hits charts to warm up the cache.
+ This task periodically hits dashboards to warm up the cache.
"""
logger.info("Loading strategy")
@@ -307,25 +239,20 @@ def cache_warmup(
logger.exception(message)
return message
- results: dict[str, list[str]] = {"scheduled": [], "errors": []}
- for task in strategy.get_tasks():
- username = task["username"]
- payload = json.dumps(task["payload"])
- if username:
- try:
- user = security_manager.get_user_by_username(username)
- cookies = MachineAuthProvider.get_auth_cookies(user)
- headers = {
- "Cookie": f"session={cookies.get('session', '')}",
- "Content-Type": "application/json",
- }
- logger.info("Scheduling %s", payload)
- fetch_url.delay(payload, headers)
- results["scheduled"].append(payload)
- except SchedulingError:
- logger.exception("Error scheduling fetch_url for payload: %s", payload)
- results["errors"].append(payload)
- else:
- logger.warn("Executor not found for %s", payload)
+ results: dict[str, list[str]] = {"success": [], "errors": []}
+
+ user = security_manager.find_user(
+ username=current_app.config["SUPERSET_CACHE_WARMUP_USER"]
+ )
+ wd = WebDriverSelenium(current_app.config["WEBDRIVER_TYPE"], user=user)
+
+ for url in strategy.get_urls():
+ try:
+ logger.info("Fetching %s", url)
+ wd.get_screenshot(url, "grid-container")
+ results["success"].append(url)
+ except URLError:
+ logger.exception("Error warming up cache!")
+ results["errors"].append(url)
return results
diff --git a/superset/utils/screenshots.py b/superset/utils/screenshots.py
index 23493471b8..cbfedfa3e3 100644
--- a/superset/utils/screenshots.py
+++ b/superset/utils/screenshots.py
@@ -32,8 +32,8 @@ from superset.utils.urls import modify_url_query
from superset.utils.webdriver import (
ChartStandaloneMode,
DashboardStandaloneMode,
- WebDriver,
WebDriverPlaywright,
+ WebDriverProxy,
WebDriverSelenium,
WindowSize,
)
@@ -165,17 +165,19 @@ class BaseScreenshot:
self.url = url
self.screenshot = None
- def driver(self, window_size: WindowSize | None = None) -> WebDriver:
+ def driver(
+ self, window_size: WindowSize | None = None, user: User | None = None
+ ) -> WebDriverProxy:
window_size = window_size or self.window_size
if feature_flag_manager.is_feature_enabled("PLAYWRIGHT_REPORTS_AND_THUMBNAILS"):
return WebDriverPlaywright(self.driver_type, window_size)
- return WebDriverSelenium(self.driver_type, window_size)
+ return WebDriverSelenium(self.driver_type, window_size, user)
def get_screenshot(
self, user: User, window_size: WindowSize | None = None
) -> bytes | None:
- driver = self.driver(window_size)
- self.screenshot = driver.get_screenshot(self.url, self.element, user)
+ driver = self.driver(window_size, user)
+ self.screenshot = driver.get_screenshot(self.url, self.element)
return self.screenshot
def get_cache_key(
diff --git a/superset/utils/webdriver.py b/superset/utils/webdriver.py
index 6570e550f4..d423260282 100644
--- a/superset/utils/webdriver.py
+++ b/superset/utils/webdriver.py
@@ -79,7 +79,9 @@ class WebDriverProxy(ABC):
self._screenshot_load_wait = app.config["SCREENSHOT_LOAD_WAIT"]
@abstractmethod
- def get_screenshot(self, url: str, element_name: str, user: User) -> bytes | None:
+ def get_screenshot(
+ self, url: str, element_name: str, user: User | None = None
+ ) -> bytes | None:
"""
Run webdriver and return a screenshot
"""
@@ -137,7 +139,7 @@ class WebDriverPlaywright(WebDriverProxy):
return error_messages
def get_screenshot( # pylint: disable=too-many-locals, too-many-statements # noqa: C901
- self, url: str, element_name: str, user: User
+ self, url: str, element_name: str, user: User | None = None
) -> bytes | None:
with sync_playwright() as playwright:
browser_args = app.config["WEBDRIVER_OPTION_ARGS"]
@@ -154,7 +156,8 @@ class WebDriverPlaywright(WebDriverProxy):
context.set_default_timeout(
app.config["SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT"]
)
- self.auth(user, context)
+ if user:
+ self.auth(user, context)
page = context.new_page()
try:
page.goto(
@@ -220,7 +223,7 @@ class WebDriverPlaywright(WebDriverProxy):
logger.debug(
"Taking a PNG screenshot of url %s as user %s",
url,
- user.username,
+ user.username if user else "None",
)
if app.config["SCREENSHOT_REPLACE_UNEXPECTED_ERRORS"]:
unexpected_errors = WebDriverPlaywright.find_unexpected_errors(page)
@@ -243,7 +246,30 @@ class WebDriverPlaywright(WebDriverProxy):
class WebDriverSelenium(WebDriverProxy):
- def create(self) -> WebDriver:
+ def __init__(
+ self,
+ driver_type: str,
+ window: WindowSize | None = None,
+ user: User | None = None,
+ ):
+ super().__init__(driver_type, window)
+ self._user = user
+ self._driver = None
+
+ def __del__(self) -> None:
+ self._destroy()
+
+ @property
+ def driver(self) -> WebDriver:
+ if not self._driver:
+ self._driver = self._create()
+ assert self._driver # for mypy
+ self._driver.set_window_size(*self._window)
+ if self._user:
+ self._auth(self._user)
+ return self._driver
+
+ def _create(self) -> WebDriver:
pixel_density = app.config["WEBDRIVER_WINDOW"].get("pixel_density", 1)
if self._driver_type == "firefox":
driver_class: type[WebDriver] = firefox.webdriver.WebDriver
@@ -305,26 +331,32 @@ class WebDriverSelenium(WebDriverProxy):
logger.debug("Init selenium driver")
return driver_class(**kwargs)
- def auth(self, user: User) -> WebDriver:
- driver = self.create()
+ def _auth(self, user: User) -> WebDriver:
return machine_auth_provider_factory.instance.authenticate_webdriver(
- driver, user
+ self.driver, user
)
- @staticmethod
- def destroy(driver: WebDriver, tries: int = 2) -> None:
+ def _destroy(self) -> None:
"""Destroy a driver"""
+ if not self._driver:
+ return
+
# This is some very flaky code in selenium. Hence the retries
# and catch-all exceptions
try:
- retry_call(driver.close, max_tries=tries)
+ retry_call(
+ self._driver.close,
+ max_tries=app.config["SCREENSHOT_SELENIUM_RETRIES"],
+ )
except Exception: # pylint: disable=broad-except # noqa: S110
pass
try:
- driver.quit()
+ self._driver.quit()
except Exception: # pylint: disable=broad-except # noqa: S110
pass
+ self._driver = None
+
@staticmethod
def find_unexpected_errors(driver: WebDriver) -> list[str]:
error_messages = []
@@ -381,10 +413,14 @@ class WebDriverSelenium(WebDriverProxy):
return error_messages
- def get_screenshot(self, url: str, element_name: str, user: User) -> bytes | None: # noqa: C901
- driver = self.auth(user)
- driver.set_window_size(*self._window)
- driver.get(url)
+ def get_screenshot( # noqa: C901
+ self, url: str, element_name: str, user: User | None = None
+ ) -> bytes | None:
+ if user and not self._user:
+ self._user = user
+ if self._driver:
+ self._auth(user)
+ self.driver.get(url)
img: bytes | None = None
selenium_headstart = app.config["SCREENSHOT_SELENIUM_HEADSTART"]
logger.debug("Sleeping for %i seconds", selenium_headstart)
@@ -396,9 +432,9 @@ class WebDriverSelenium(WebDriverProxy):
logger.debug(
"Wait for the presence of %s at url: %s", element_name, url
)
- element = WebDriverWait(driver, self._screenshot_locate_wait).until(
- EC.presence_of_element_located((By.CLASS_NAME, element_name))
- )
+ element = WebDriverWait(
+ self.driver, self._screenshot_locate_wait
+ ).until(EC.presence_of_element_located((By.CLASS_NAME, element_name)))
except TimeoutException:
logger.exception("Selenium timed out requesting url %s", url)
raise
@@ -406,7 +442,7 @@ class WebDriverSelenium(WebDriverProxy):
try:
# chart containers didn't render
logger.debug("Wait for chart containers to draw at url: %s", url)
- WebDriverWait(driver, self._screenshot_locate_wait).until(
+ WebDriverWait(self.driver, self._screenshot_locate_wait).until(
EC.visibility_of_all_elements_located(
(By.CLASS_NAME, "chart-container")
)
@@ -415,7 +451,7 @@ class WebDriverSelenium(WebDriverProxy):
logger.info("Timeout Exception caught")
# Fallback to allow a screenshot of an empty dashboard
try:
- WebDriverWait(driver, 0).until(
+ WebDriverWait(self.driver, 0).until(
EC.visibility_of_all_elements_located(
(By.CLASS_NAME, "grid-container")
)
@@ -432,7 +468,7 @@ class WebDriverSelenium(WebDriverProxy):
logger.debug(
"Wait for loading element of charts to be gone at url: %s", url
)
- WebDriverWait(driver, self._screenshot_load_wait).until_not(
+ WebDriverWait(self.driver, self._screenshot_load_wait).until_not(
EC.presence_of_all_elements_located((By.CLASS_NAME, "loading"))
)
except TimeoutException:
@@ -447,11 +483,13 @@ class WebDriverSelenium(WebDriverProxy):
logger.debug(
"Taking a PNG screenshot of url %s as user %s",
url,
- user.username,
+ user.username if user else "None",
)
if app.config["SCREENSHOT_REPLACE_UNEXPECTED_ERRORS"]:
- unexpected_errors = WebDriverSelenium.find_unexpected_errors(driver)
+ unexpected_errors = WebDriverSelenium.find_unexpected_errors(
+ self.driver
+ )
if unexpected_errors:
logger.warning(
"%i errors found in the screenshot. URL: %s. Errors are: %s",
@@ -478,6 +516,4 @@ class WebDriverSelenium(WebDriverProxy):
"Encountered an unexpected error when requesting url %s", url
)
raise
- finally:
- self.destroy(driver, app.config["SCREENSHOT_SELENIUM_RETRIES"])
return img
diff --git a/tests/integration_tests/strategy_tests.py b/tests/integration_tests/strategy_tests.py
index 6dc99f501f..75ae84917a 100644
--- a/tests/integration_tests/strategy_tests.py
+++ b/tests/integration_tests/strategy_tests.py
@@ -82,15 +82,9 @@ class TestCacheWarmUp(SupersetTestCase):
self.client.get(f"/superset/dashboard/{dash.id}/")
strategy = TopNDashboardsStrategy(1)
- result = strategy.get_tasks()
- expected = [
- {
- "payload": {"chart_id": chart.id, "dashboard_id": dash.id},
- "username": "admin",
- }
- for chart in dash.slices
- ]
- assert len(result) == len(expected)
+ result = sorted(strategy.get_urls())
+ expected = sorted([f"http://localhost{dash.url}"])
+ assert result == expected
def reset_tag(self, tag):
"""Remove associated object from tag, used to reset tests"""
@@ -108,39 +102,27 @@ class TestCacheWarmUp(SupersetTestCase):
self.reset_tag(tag1)
strategy = DashboardTagsStrategy(["tag1"])
- assert strategy.get_tasks() == []
+ result = sorted(strategy.get_urls())
+ expected = []
+ assert result == expected
# tag dashboard 'births' with `tag1`
tag1 = get_tag("tag1", db.session, TagType.custom)
dash = self.get_dash_by_slug("births")
- tag1_payloads = [{"chart_id": chart.id} for chart in dash.slices]
+ tag1_urls = [f"http://localhost{dash.url}"]
tagged_object = TaggedObject(
tag_id=tag1.id, object_id=dash.id, object_type=ObjectType.dashboard
)
db.session.add(tagged_object)
db.session.commit()
- assert len(strategy.get_tasks()) == len(tag1_payloads)
+ result = sorted(strategy.get_urls())
+ assert result == tag1_urls
strategy = DashboardTagsStrategy(["tag2"])
tag2 = get_tag("tag2", db.session, TagType.custom)
self.reset_tag(tag2)
- assert strategy.get_tasks() == []
-
- # tag first slice
- dash = self.get_dash_by_slug("unicode-test")
- chart = dash.slices[0]
- tag2_payloads = [{"chart_id": chart.id}]
- object_id = chart.id
- tagged_object = TaggedObject(
- tag_id=tag2.id, object_id=object_id, object_type=ObjectType.chart
- )
- db.session.add(tagged_object)
- db.session.commit()
-
- assert len(strategy.get_tasks()) == len(tag2_payloads)
-
- strategy = DashboardTagsStrategy(["tag1", "tag2"])
-
- assert len(strategy.get_tasks()) == len(tag1_payloads + tag2_payloads)
+ result = sorted(strategy.get_urls())
+ expected = []
+ assert result == expected
diff --git a/tests/integration_tests/thumbnails_tests.py b/tests/integration_tests/thumbnails_tests.py
index 8949474250..a537f60d60 100644
--- a/tests/integration_tests/thumbnails_tests.py
+++ b/tests/integration_tests/thumbnails_tests.py
@@ -147,32 +147,32 @@ class TestWebDriverSelenium(SupersetTestCase):
def test_screenshot_selenium_headstart(
self, mock_sleep, mock_webdriver, mock_webdriver_wait
):
- webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(ADMIN_USERNAME)
+ webdriver = WebDriverSelenium("firefox", user=user)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
app.config["SCREENSHOT_SELENIUM_HEADSTART"] = 5
- webdriver.get_screenshot(url, "chart-container", user=user)
+ webdriver.get_screenshot(url, "chart-container")
assert mock_sleep.call_args_list[0] == call(5)
@patch("superset.utils.webdriver.WebDriverWait")
@patch("superset.utils.webdriver.firefox")
def test_screenshot_selenium_locate_wait(self, mock_webdriver, mock_webdriver_wait):
app.config["SCREENSHOT_LOCATE_WAIT"] = 15
- webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(ADMIN_USERNAME)
+ webdriver = WebDriverSelenium("firefox", user=user)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
- webdriver.get_screenshot(url, "chart-container", user=user)
+ webdriver.get_screenshot(url, "chart-container")
assert mock_webdriver_wait.call_args_list[0] == call(ANY, 15)
@patch("superset.utils.webdriver.WebDriverWait")
@patch("superset.utils.webdriver.firefox")
def test_screenshot_selenium_load_wait(self, mock_webdriver, mock_webdriver_wait):
app.config["SCREENSHOT_LOAD_WAIT"] = 15
- webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(ADMIN_USERNAME)
+ webdriver = WebDriverSelenium("firefox", user=user)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
- webdriver.get_screenshot(url, "chart-container", user=user)
- assert mock_webdriver_wait.call_args_list[2] == call(ANY, 15)
+ webdriver.get_screenshot(url, "chart-container")
+ assert mock_webdriver_wait.call_args_list[1] == call(ANY, 15)
@patch("superset.utils.webdriver.WebDriverWait")
@patch("superset.utils.webdriver.firefox")
@@ -180,11 +180,11 @@ class TestWebDriverSelenium(SupersetTestCase):
def test_screenshot_selenium_animation_wait(
self, mock_sleep, mock_webdriver, mock_webdriver_wait
):
- webdriver = WebDriverSelenium("firefox")
user = security_manager.get_user_by_username(ADMIN_USERNAME)
+ webdriver = WebDriverSelenium("firefox", user=user)
url = get_url_path("Superset.slice", slice_id=1, standalone="true")
app.config["SCREENSHOT_SELENIUM_ANIMATION_WAIT"] = 4
- webdriver.get_screenshot(url, "chart-container", user=user)
+ webdriver.get_screenshot(url, "chart-container")
assert mock_sleep.call_args_list[1] == call(4)