Cypress component tests for Lit Elements (web components)

Recently I have been using lit, a web component framework.

If you are not familiar with web components here is a quick summary:

Web Components is a suite of different technologies allowing you to create reusable custom elements - with their functionality encapsulated away from the rest of your code - and utilize them in your web apps.

MDN - https://developer.mozilla.org/en-US/docs/Web/Web_Components

Lit is a popular framework for these components with over 1 million weekly downloads. (Oct 10th 2022).

Testing Lit

For how to test Lit Elements I had been following some big notable projects,

Spectrum web components by Adobe is really mature design system that makes a lot of usage of Lit Elements. Their testing setup uses the suggested web test runner. Lit's documentation on testing suggests using that library.

Cypress has become one of the most popular test runners in the space. So I was a little surprised to not see some guidance for it on the lit documentation. I think it's an ideal candidate for Web Component testing on modern browsers, and because it recently added support for safari it has great coverage across chromium, webkit, electron and quantum (firefox) based browsers.

Testing Lit Components with Cypress

To test with lit elements you will need a project with cypress.

TL;DR

An example project: https://github.com/simonireilly/cypress-lit

The testing setup consists of writing a cy.mount command for mounting Lit Elements into the DOM.

import { getContainerEl } from "@cypress/mount-utils";
import { LitElement, render, TemplateResult } from "lit";

export const mount = (_element: LitElement, template: TemplateResult) => {
const target = getContainerEl();

render(template, target);

return cy
.wait(0, { log: false })
.then(() => {
const mountMessage = `
<
${String(_element.constructor.name)} ... />
`
;

Cypress.log({
name: "mount",
message: [mountMessage],
})
.snapshot("mounted")
.end();
})
.get("[data-cy-root]")
.children()
.first()
.shadow();
};

And this means you can write tess like this:

import { html } from "lit";
import { MyElement } from "../../src/my-element";

describe("my-element.cy.ts", () => {
it("playground", () => {
cy.mount(new MyElement(), html`<my-element></my-element>`).as("element");

cy.get("@element").contains("count").click();
});
});

And just like that, you can run a cypress test for the component. Here is a quick snapshot of me testing one.

lit element tested with cypress running electron

Wrap up

That is a quick example of how to run component tests for Lit with cypress. Hopefully it's just enough information for you to get it setup.

Since cypress components supports so many frameworks already, I don't think it will be long before an official lit component implementation lands. In the meantime, happy testing!