GitHub user dosubot[bot] added a comment to the discussion: How can I integrate
Superset charts with PlayWright to ensure that all charts and data on the page
are fully rendered and there are no unexpected errors before taking a
screenshot?
<!-- Answer -->
This happens because Superset removes the `.loading` spinner as soon as the
data fetch finishes, but the chart's actual rendering (drawing SVG, canvas, or
DOM updates) can take a bit longer due to asynchronous UI updates and
animations. So, waiting only for `.loading` to disappear isn't always enough.
To make your Playwright automation more robust, you should:
- Wait for all `.chart-container` elements to be visible.
- Wait for all `.loading` elements to be detached.
- Then, for each chart, wait for a specific chart content element (like
`#chart-id-{chartId}`) to be visible—this element only appears when the chart
is fully rendered.
- Optionally, add a short extra wait (e.g., 1–2 seconds) for chart animations
to finish. Superset's own screenshot logic uses a configurable animation wait
for this reason.
Example C# Playwright logic:
```csharp
// Wait for all chart containers to be visible
var chartContainers = await page.QuerySelectorAllAsync(".chart-container");
foreach (var chart in chartContainers)
{
await chart.WaitForElementStateAsync(ElementState.Visible);
}
// Wait for all loading spinners to disappear
var loadingElements = await page.QuerySelectorAllAsync(".loading");
foreach (var loading in loadingElements)
{
await loading.WaitForElementStateAsync(ElementState.Detached);
}
// Wait for each chart's content to be visible (replace with actual chart IDs)
foreach (var chart in chartContainers)
{
var chartId = await chart.GetAttributeAsync("data-test-chart-id");
if (!string.IsNullOrEmpty(chartId))
{
await page.WaitForSelectorAsync($"#chart-id-{chartId}", new
PageWaitForSelectorOptions { State = WaitForSelectorState.Visible });
}
}
// Optional: wait for chart animations to finish
await page.WaitForTimeoutAsync(1000); // 1 second
```
This approach matches how Superset's own automation and Cypress tests ensure
charts are fully rendered before screenshots or assertions. You can tune the
extra wait with the `SCREENSHOT_SELENIUM_ANIMATION_WAIT` config if needed. More
details:
[Superset Playwright/Selenium screenshot
logic](https://github.com/apache/superset/blob/master/superset/utils/webdriver.py)
[Why waiting for .loading isn't
enough](https://github.com/apache/superset/blob/master/superset-frontend/cypress-base/cypress/utils/index.ts)
[ChartRenderer rendering
lifecycle](https://github.com/apache/superset/blob/master/superset-frontend/src/components/Chart/ChartRenderer.jsx)
<!-- Dosu Comment Footer -->
*To reply, just mention [@dosu](https://go.dosu.dev/dosubot).*
---
<sup>How did I do?
[Good](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=great_response)
|
[Irrelevant](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=irrelevant_answer)
|
[Incorrect](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=incorrect_sources)
|
[Verbose](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=too_verbose)
|
[Hallucination](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=hallucination)
| [Report
🐛](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=bug_report)
|
[Other](https://app.dosu.dev/response-feedback/3fb2c37a-5a6e-49c4-be9f-60e908da0ba2?feedback_type=other)</sup>
[](https://app.dosu.dev/a28d3c7e-a9d3-459e-9fb6-3a6f9ff4f357/ask?utm_source=github) [](https://cursor.com/link/prompt?text=This%20happens%20because%20Superset%20removes%20the%20%60.loading%60%20spinner%20as%20soon%20as%20the%20data%20fetch%20finishes%2C%20but%20the%20chart%27s%20actual%20rendering%20%28drawing%20SVG%2C%20canvas%2C%20or%20DOM%20updates%29%20can%20take%20a%20bit%20longer%20due%20to%20asynchronous%20UI%20updates%20and%20animations.%20So%2C%20waiting%20only%20for%20%60.loading%60%20to%20disappear%20isn%27t%20always%20enough.%0A%0ATo%20make%20your%20Playwright%20automation%20more%20robust%2C%20you%20should%3A%0A%0A-%20Wait%20for%20all%20%60.chart-container%60%20elements%20to%20be%20visible.%0A-%20Wait%20for%20all%20%60.loading%60%20elements%20to%20be%20detached.%0A-%20Then%2C%20for%20each%20chart%2C%20wait%20for%20a%20specific%20chart%20content%20element%20%28
like%20%60%23chart-id-%7BchartId%7D%60%29%20to%20be%20visible%E2%80%94this%20element%20only%20appears%20when%20the%20chart%20is%20fully%20rendered.%0A-%20Optionally%2C%20add%20a%20short%20extra%20wait%20%28e.g.%2C%201%E2%80%932%20seconds%29%20for%20chart%20animations%20to%20finish.%20Superset%27s%20own%20screenshot%20logic%20uses%20a%20configurable%20animation%20wait%20for%20this%20reason.%0A%0AExample%20C%23%20Playwright%20logic%3A%0A%0A%60%60%60csharp%0A//%20Wait%20for%20all%20chart%20containers%20to%20be%20visible%0Avar%20chartContainers%20%3D%20await%20page.QuerySelectorAllAsync%28%22.chart-container%22%29%3B%0Aforeach%20%28var%20chart%20in%20chartContainers%29%0A%7B%0A%20%20%20%20await%20chart.WaitForElementStateAsync%28ElementState.Visible%29%3B%0A%7D%0A%0A//%20Wait%20for%20all%20loading%20spinners%20to%20disappear%0Avar%20loadingElements%20%3D%20await%20page.QuerySelectorAllAsync%28%22.loading%22%29%3B%0Aforeach%20%28var%20loading%20in%20loadingElements%29%0A%7B%0A%20%20%20%2
0await%20loading.WaitForElementStateAsync%28ElementState.Detached%29%3B%0A%7D%0A%0A//%20Wait%20for%20each%20chart%27s%20content%20to%20be%20visible%20%28replace%20with%20actual%20chart%20IDs%29%0Aforeach%20%28var%20chart%20in%20chartContainers%29%0A%7B%0A%20%20%20%20var%20chartId%20%3D%20await%20chart.GetAttributeAsync%28%22data-test-chart-id%22%29%3B%0A%20%20%20%20if%20%28%21string.IsNullOrEmpty%28chartId%29%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20await%20page.WaitForSelectorAsync%28%24%22%23chart-id-%7BchartId%7D%22%2C%20new%20PageWaitForSelectorOptions%20%7B%20State%20%3D%20WaitForSelectorState.Visible%20%7D%29%3B%0A%20%20%20%20%7D%0A%7D%0A%0A//%20Optional%3A%20wait%20for%20chart%20animations%20to%20finish%0Aawait%20page.WaitForTimeoutAsync%281000%29%3B%20//%201%20second%0A%60%60%60%0A%0AThis%20approach%20matches%20how%20Superset%27s%20own%20automation%20and%20Cypress%20tests%20ensure%20charts%20are%20fully%20rendered%20before%20screenshots%20or%20assertions.%20You%20can%2
0tune%20the%20extra%20wait%20with%20the%20%60SCREENSHOT_SELENIUM_ANIMATION_WAIT%60%20config%20if%20needed.%20More%20details%3A%20%20%0A%5BSuperset%20Playwright/Selenium%20screenshot%20logic%5D%28https%3A//github.com/apache/superset/blob/master/superset/utils/webdriver.py%29%20%20%0A%5BWhy%20waiting%20for%20.loading%20isn%27t%20enough%5D%28https%3A//github.com/apache/superset/blob/master/superset-frontend/cypress-base/cypress/utils/index.ts%29%20%20%0A%5BChartRenderer%20rendering%20lifecycle%5D%28https%3A//github.com/apache/superset/blob/master/superset-frontend/src/components/Chart/ChartRenderer.jsx%29) [](https://go.dosu.dev/discord-bot) [](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/apache/superset/discussions/36845)
GitHub link:
https://github.com/apache/superset/discussions/36845#discussioncomment-15359770
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]