Article summary
We’re using SvelteKit on my current software development project, along with Playwright for end-to-end browser testing. Some tests would intermittently fail – so I spent some time investigating.
The Issue
The problem arose on pages where text was being entered into a form. Playwright starts filling out the form as soon as the page is loaded in the browser (coming back from SSR). However, when the page is hydrated moments later, the text in the form is cleared out!
Although Playwright is able to start entering data into a form much faster than a human could, it’s not out of the question that something might get delayed, causing a human user to experience the same issue. So it seems this might be a bug but perhaps one with such a low chance of occurrence that it’s not really an issue. The only mention I’ve been able to find of this is related to automated test frameworks.
The Workaround
After some searching, I found a workaround mentioned in a GitHub issue. The first step is to use an onMount
callback that adds a class to the body
tag. This will be executed during hydration. The following code snippet can be added to the layout.svelte
file so it will be run regardless of the page that’s first loaded by the browser.
onMount(() => {
// Indicate that the SvelteKit app has started
document.body.classList.add("started");
});
We now have a way of knowing when the page has been hydrated. The next step is to wait for the started
class to be added to the body
when doing initial page navigation in the tests.
In the SvelteKit project tests, this has been done by enhancing the Playwright navigation helpers. I chose to go a different route. Instead, I added a goto
helper to my TestUtils
module:
const goto = async (page: Page, url: string, opts?: { waitForStarted?: boolean }) => {
await page.goto(url);
if (opts?.waitForStarted !== false) {
await page.waitForSelector("body.started", { timeout: 5000 });
}
};
Hydration Problem Solved
Now, when making an initial page navigation, I use TestUtils.goto('/')
, and I know that Playwright won’t start entering text into form fields until after hydration has completed. Problem solved!
Thanks a million Patric! I had been looking for the solution of such issue for a long time. I tried different approaches and they worked only partial or didn’t work at all.
This solution is so simple and elegant. It’s a brilliant!
Just hit this problem myself and your post was immensely helpful. I’m surprised more isn’t done to make this problem less of a stumbling block for SvelteKit developers. I haven’t found anything in the official docs or a built in SvelteKit that would make it easier to avoid this.
I was similarly surprised Brian – glad this was helpful!