Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsWait for an application-owned readiness signal, not merely for the Konva container to appear. Konva shapes are painted into canvas pixels, so Playwright can confirm that a DOM wrapper is visible without proving that the requested scene has been drawn. Set a marker such as data-render-state="ready" only after React state, required images or fonts, and any application-controlled drawing work are complete; then wait for that marker and capture the locator.
The reliable synchronization pattern
A robust test has four phases: navigate, trigger the scene change, wait for the app’s readiness contract, and take the screenshot.
await page.goto('/editor');
await page.getByRole('button', { name: 'Render preview' }).click();
await page.waitForFunction(() =>
document.querySelector('[data-testid="preview"]')?.getAttribute('data-render-state') === 'ready'
);
await page.locator('[data-testid="preview"]').screenshot({ path: 'preview.png' });
The marker is illustrative. Your application must set it only after the requested Konva scene is applied and its dependencies are ready. data-testid belongs to an application-owned DOM wrapper; it is not a selector for a Konva shape.
Playwright’s page.waitForFunction() polls a predicate in the page and uses requestAnimationFrame polling by default. See the Page API. A locator assertion can express the same contract:
#1 Best Overall
await expect(page.locator('[data-testid="preview"]'))
.toHaveAttribute('data-render-state', 'ready');
Use a real browser for appearance checks. Konva’s testing guidance explains that questions such as whether a shape has the right color require real pixels, not just DOM assertions: Konva’s React testing guide.
Why a visible Stage is not enough
React-Konva renders a canvas-backed Stage. Individual rectangles, text nodes, and images are not ordinary DOM elements that Playwright can query. A Stage wrapper may be present while React is still committing state, an image is still loading, or a custom drawing source has not updated.
locator.screenshot() performs actionability checks and scrolls the target into view before capturing its visible bounds (Locator API). Those checks answer “can I capture this DOM target?” They do not answer “does this canvas contain the intended frame?”
Likewise, a screenshot that is merely stable can be wrong. Playwright’s toHaveScreenshot() waits for two consecutive screenshots to match before comparing with the expectation (LocatorAssertions API), but a blank or stale canvas can also be stable. Pair pixel stability with a semantic readiness signal.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Design an application-owned readiness contract
Expose state on a wrapper
Put a marker on a normal DOM element surrounding the Stage. Typical states are idle, loading, ready, and error. Include a generation or scene identifier when several renders can be requested quickly.
Rank #2
function Preview({ scene }) {
const [renderState, setRenderState] = useState('loading');
const [generation, setGeneration] = useState(0);
useEffect(() => {
let cancelled = false;
setRenderState('loading');
const nextGeneration = generation + 1;
setGeneration(nextGeneration);
(async () => {
try {
await scene.assetsReady; // images, fonts, or other app data
if (cancelled) return;
// Update Konva/React scene here. If drawing is custom, finish it here.
setRenderState('ready');
} catch {
if (!cancelled) setRenderState('error');
}
})();
return () => { cancelled = true; };
}, [scene]);
return (
<div
data-testid="preview"
data-render-state={renderState}
data-render-generation={generation}
>
<Stage width={800} height={600}>{/* layers and shapes */}</Stage>
</div>
);
}
In production code, keep the generation in a ref or derive it from the scene request so that overlapping effects cannot mark an older request ready after a newer one. The important property is ownership: the application, not a guessed delay, declares when the requested scene is complete.
Wait for assets that affect pixels
Images introduce an asynchronous boundary. The official React-Konva image example loads an image with use-image before passing it to an Image node (Konva image example). Include image completion—and any font, data, or texture work your scene needs—in the readiness contract. Do not mark ready merely because an Image component has mounted.
Account for custom drawing sources
Konva’s automatic redraw behavior applies to normal Konva attribute changes. Since Konva 8, attribute changes mark a layer dirty and schedule a redraw on the next animation frame in the standard auto-draw configuration (Konva automatic redraws). Calling draw() or batchDraw() after every ordinary state change is therefore usually redundant.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallManual work is still relevant when pixels come from a mutable source canvas or video frame, when drawing occurs outside Konva’s awareness, or when Konva.autoDrawEnabled is disabled. Check the installed Konva version and your configuration. If you make such changes, complete that work before setting the readiness marker.
Playwright test examples
Wait with a page predicate and capture
import { test, expect } from '@playwright/test';
test('captures the rendered preview', async ({ page }) => {
await page.goto('/editor');
await page.getByRole('button', { name: 'Render preview' }).click();
await page.waitForFunction(() => {
const el = document.querySelector('[data-testid="preview"]');
return el?.getAttribute('data-render-state') === 'ready';
});
const preview = page.locator('[data-testid="preview"]');
await preview.screenshot({ path: 'test-results/preview.png' });
});
Give the wait a timeout appropriate to your app and surface a useful error rather than silently capturing a failed render:
await page.waitForFunction(
() => document.querySelector('[data-testid="preview"]')?.getAttribute('data-render-state') === 'ready',
{ timeout: 15_000 }
);
Use screenshot assertions for visual regression
await expect(page.locator('[data-testid="preview"]'))
.toHaveScreenshot('preview.png', { animations: 'disabled' });
The animations: 'disabled' option controls CSS animations, CSS transitions, and Web Animations. It does not stop a Konva animation loop. If Konva nodes animate, pause the animation or set a deterministic frame in application code before exposing ready.
Read pixels when the test needs a direct signal
For a pixel-level diagnostic, use the real browser and the layer context. Konva’s guide demonstrates pixel readback while accounting for the layer’s pixel ratio (testing react-konva components). This can verify a known coordinate or color, but it should complement—not replace—the app readiness contract.
What each waiting approach actually proves
| Approach | What it proves | What it cannot prove |
|---|---|---|
| DOM visibility or locator actionability | The wrapper is attached, visible, and capturable. | That Konva pixels show the requested scene. |
Fixed waitForTimeout() |
Only that an arbitrary interval elapsed. | Readiness on slow runs, and it wastes time on fast runs. |
| Application readiness marker | Your app’s declared state, including assets and scene generation. | Correctness if the marker is set too early or the scene logic is wrong. |
toHaveScreenshot() stabilization |
Two successive captures are visually identical before comparison. | Semantic correctness; blank and stale canvases can be stable. |
| Pixel readback | The browser produced expected pixels at selected coordinates. | Unexamined regions or the meaning of those pixels without app context. |
Why fixed delays and frame waits fail
A fixed waitForTimeout(1000) can be too short when a network image or data request is slow and unnecessarily long when the scene is ready immediately. A one-frame delay is valid only when the application’s contract is specifically “the next browser frame”; it cannot stand in for asynchronous assets, effects, or a server response. Wait for the event that makes this scene ready.
Animated scenes and deterministic captures
Decide whether the screenshot represents a static state or a particular animation frame. For a static baseline, stop the Konva animation loop, set a known timestamp or frame index, then mark the generation ready. For an intentionally animated capture, define the frame in the test and wait for that application signal. Playwright’s CSS animation controls do not govern Konva’s JavaScript animation loop.
Troubleshooting timeouts and mismatches
The readiness wait times out
- Inspect the wrapper’s
data-render-stateand any error message in a trace or debug log. - Verify that the scene’s image, font, and data promises resolve and that rejected promises set
errorinstead of leavingloadingforever. - Check that a newer scene request has not cancelled the effect for the request under test.
- Use a longer timeout only after fixing the contract; do not convert timeout into an unconditional screenshot.
The screenshot is blank or stale
- Ensure the marker is set after the state update that creates the Konva nodes and after required assets load.
- Look for mutable canvases, video frames, disabled auto-draw, or custom drawing outside Konva’s normal change tracking.
- Confirm the test waits for the correct generation when users can trigger multiple renders.
Pixels differ between runs
- Freeze Konva animation and control time-dependent data.
- Use stable viewport, device scale, fonts, timezone, and locale settings.
- Use
toHaveScreenshot()for repeatability, but retain the semantic readiness check.
The target is clipped
locator.screenshot() captures the target’s visible bounds after scrolling it into view. Make the wrapper dimensions explicit and choose a full-page or element capture intentionally; clipping is a geometry issue, not proof of render completion.
Rank #4
Performance, reliability, and cost considerations
Event-based readiness avoids sleeping through every test and reduces false failures caused by variable load times. Keep the marker local to the scene under test so unrelated page work does not delay capture. A generation value makes retries diagnosable and prevents stale asynchronous work from winning a race.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use screenshot assertions only where visual evidence is needed; they require image comparison and can be slower than a focused state assertion. When debugging, record the readiness state, generation, asset status, and browser configuration alongside the screenshot. There is no universal Konva await renderComplete() API; the correct signal depends on your React effects, assets, custom drawing sources, and animation policy.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. For a URL that can render independently, one GET request returns PNG, JPEG, WebP, or PDF. Its capture pipeline accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and whether the request was billed.
See the ScreenshotNeo API documentation for parameters such as full-page capture, element selectors, device and viewport settings, retina scale, custom CSS or JavaScript, waits for selectors, delays or network idle, request blocking, headers, cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture, usage data, and PDF options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is on every plan. These captures do not replace an in-app readiness contract for a live Konva editor, but they can remove browser orchestration when the page itself is the only target.
Create a free ScreenshotNeo account to use the 1,000 monthly screenshots without a card.
FAQ
Can I wait for a Konva shape with a CSS or DOM selector?
No. Shapes are canvas output rather than individual DOM nodes. Select an application-owned wrapper or expose a readiness marker and verify appearance with browser pixels.
Should I call layer.draw() before every screenshot?
Usually not with Konva 8 or newer and normal automatic redraw enabled. It can matter for drawing changes outside Konva’s tracking or when auto-draw is disabled.
Is one successful screenshot enough to prove rendering?
No. A screenshot can be stable while blank or stale. Combine a meaningful application signal with the visual assertion or pixel check required by the test.
Frequently Asked Questions
What should the readiness marker contain?
Use an application-owned state such as data-render-state="ready", and include a scene generation when renders can overlap.
Does Playwright’s default screenshot wait detect image loading inside Konva?
No. Actionability and visibility checks target the DOM wrapper. Your readiness contract must include all images and other assets that affect canvas pixels.
The Bottom Line
Make the app declare when the requested Konva scene is ready, wait for that state in Playwright, then capture or compare real browser pixels. Delays and screenshot stability alone cannot establish semantic render completion.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Recommended Free Tools

