Components Ready
Use readiness checks when your logic depends on upgraded custom elements. This prevents race conditions in tests and app code that run immediately after mount.
When to Wait for Readiness
- - Before reading internals that only exist after component upgrade.
- - Before dispatching synthetic events in automated tests.
- - Before measuring layout that depends on rendered shadow content.
- - Before taking visual snapshots or asserting focus behavior.
Readiness Helper
Create one helper in your test or app utilities and use it consistently where asynchronous upgrade timing matters.
const DEFAULT_TAGS = [
'diwa-button',
'diwa-input-text',
'diwa-select',
'diwa-toast',
] as const;
export async function waitForDiwaComponents(
root: ParentNode = document,
tags: readonly string[] = DEFAULT_TAGS,
): Promise<void> {
const presentTags = tags.filter((tag) => root.querySelector(tag));
await Promise.all(
presentTags.map(async (tag) => {
await customElements.whenDefined(tag);
const nodes = Array.from(root.querySelectorAll<HTMLElement>(tag));
await Promise.all(nodes.map((node) => node.componentOnReady?.() ?? Promise.resolve()));
}),
);
}Test Caveats (jsdom and Browser)
- - jsdom does not fully emulate browser rendering and focus behavior for every custom-element scenario.
- - Use browser-based tests (Playwright/Cypress) for keyboard flow, focus ring visibility, and motion checks.
- - Use unit tests for static rendering and event contract shape; keep interaction-critical assertions in real browsers.
import { waitForDiwaComponents } from './waitForDiwaComponents';
it('opens flyout after trigger click', async () => {
render(<App />);
await waitForDiwaComponents();
await user.click(screen.getByRole('button', { name: /open menu/i }));
expect(screen.getByRole('dialog')).toBeVisible();
});