Catching early DOM events in Playwright

Yesterday, I wrote about how to test custom events in Playwright.
In building out the tests for Kelp’s web components, I ran into an interesting challenge on the ready events I emit when the component is first instantiated.
Today, I wanted to explain the problem, and how I fixed it. Let’s dig in!
The challenge Kelp uses an HTML Web Component approach for most of it’s components, but there are a few exceptions where that doesn’t make sense.


This content originally appeared on Go Make Things and was authored by Go Make Things

Yesterday, I wrote about how to test custom events in Playwright.

In building out the tests for Kelp’s web components, I ran into an interesting challenge on the ready events I emit when the component is first instantiated.

Today, I wanted to explain the problem, and how I fixed it. Let’s dig in!

The challenge

Kelp uses an HTML Web Component approach for most of it’s components, but there are a few exceptions where that doesn’t make sense.

For example, the <kelp-toc> component generates a table of contents from the headings on the page. There’s no meaningful fallback state for that, so it starts out as an empty HTML element.

<kelp-toc></kelp-toc>

Typically in Playwright, you…

  1. Use one of the page.locator() methods to get your element.
  2. Wait for it to be found/loaded.
  3. Wait for your event to run.
const component = page.locator('kelp-toc');
const readyEvent = await component.evaluate((element) => {
		return new Promise((resolve) => {
			return element.addEventListener('kelp-toc-ready', () => {
				return resolve(true);
			});
		})
	});
await expect(readyEvent).toBeTruthy();

That works great for HTML Web Components, but fails on step 2 for JS-rendered ones like <kelp-toc>.

Timing issues

Step 2—wait for it to be found/loaded—doesn’t run until the element has a visible bounding rectangle.

Because custom elements are treated like a <span>, and <kelp-toc> is empty by default, it has a height and width of 0. To Playwright, it’s not loaded yet.

By the time Playwright recognizes it—after the content has been rendered—the event has already fired, and the event listener/promise never resolves. The test fails.

There’s a simple fix!

One of the things I love about Playwright is that it tests real HTML files.

I’m using it for component testing rather than end-to-end, so each test spec has a corresponding HTML file with the markup hard-coded into it. I like this a lot better than having to dynamically inject HTML with JS for testing!

|-- /tests
|   |-- /toc
|       |-- index.html
|       |-- toc.spec.js

In the test HTML, I add an event listener for the ready event before the web component JavaScript is loaded.

When the event fires, I log ready to the console. This is actually an import part of the test!

<script>
	// Ensures we can test the ready event
	document.addEventListener('kelp-toc-ready', (event) => {
		console.log('ready');
	});
</script>

<script type="module" src="../../js/components/kelp-toc.js"></script>

Over in my test file, I…

  1. Define an isReady variable as false.
  2. Use the Playwright page.on('console') method to listen for console events. If the console text is ready, set isReady to true.
  3. Navigate to the test index.html file
  4. Check if isReady is true.
test('component instantiates', async ({ page }) => {
	let isReady = false;
	page.on('console', msg => {
		if (msg.text() !== 'ready') return;
		isReady = true;
	});
	await page.goto('/tests/toc');
	expect(isReady).toEqual(true);
});

Is it silly? Yes! Does it work? Also yes!

This wouldn’t be a great solution in an end-to-end test, where you’d be logging this stuff in the actual app. But for unit/component testing, it works great!

Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.


This content originally appeared on Go Make Things and was authored by Go Make Things


Print Share Comment Cite Upload Translate Updates
APA

Go Make Things | Sciencx (2025-07-03T14:30:00+00:00) Catching early DOM events in Playwright. Retrieved from https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/

MLA
" » Catching early DOM events in Playwright." Go Make Things | Sciencx - Thursday July 3, 2025, https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/
HARVARD
Go Make Things | Sciencx Thursday July 3, 2025 » Catching early DOM events in Playwright., viewed ,<https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/>
VANCOUVER
Go Make Things | Sciencx - » Catching early DOM events in Playwright. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/
CHICAGO
" » Catching early DOM events in Playwright." Go Make Things | Sciencx - Accessed . https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/
IEEE
" » Catching early DOM events in Playwright." Go Make Things | Sciencx [Online]. Available: https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/. [Accessed: ]
rf:citation
» Catching early DOM events in Playwright | Go Make Things | Sciencx | https://www.scien.cx/2025/07/03/catching-early-dom-events-in-playwright/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.