Testing
Run the two suites, and point them at in-development Lit when you need to. Read Development first if you have not installed the workspace yet.
pnpm test # unit + e2epnpm run test:unit # node-only unit testspnpm run test:e2e # spawns vite dev servers + system Chrometest:unit is the fast loop: plain Node, no browser. test:e2e builds the
plugin first, then drives a real dev server with playwright-core and the system
Chrome through channel: 'chrome'. It runs one dev server and one browser per
test file, sequentially, to avoid port and file contention.
Environment variables
Section titled “Environment variables”HMR_E2E_HEADED=1watches the browser while the tests run.HMR_E2E_EXECUTABLE=/path/to/chromeuses a specific browser binary. Reach for it afternpx playwright install chromiumwhen you have no system Chrome.
By default the tests run against the published npm versions of lit,
@lit/context, @lit/task, @lit-labs/signals, and @lit-labs/virtualizer.
Writing an e2e test
Section titled “Writing an e2e test”Start from startFixture() in src/test/e2e/utils.ts. It copies the playground
into a fresh directory and serves that, so a test can edit files to trigger HMR
without touching the real playground or another test’s copy.
- Fixtures live under
.e2e-tmp/, inside the package, not the OS temp directory. Bare imports in a fixture resolve by walking up to the repo’snode_modules, and they would not find it from/tmp. UsetmpRoot(prefix)for any other throwaway directory a test needs..e2e-tmp/is gitignored. HOMEpoints at a throwaway directory while a fixture runs, because devframe keeps its global settings store under the home directory. Panel settings a test writes never reach your own. Seed them with theseedSettingsoption instead of writing to~/.vite.- Importing a bare package a fixture has never loaded can make Vite’s dep optimizer reload the page mid-test. Load the module once and wait for the network to settle before the part of the test that matters.
The plugin’s internal virtual modules use ids that start with \0lit-plugin:
(VIRTUAL_PREFIX in src/lib/transform.ts). The \0 is Rollup’s marker for “not
a file”: other plugins skip these ids, and this plugin’s own transforms skip
them too. The one public virtual module, virtual:lit-plugin/timeline, resolves
to \0virtual:lit-plugin/timeline. When a test looks for a module in Vite’s
module graph or a build chunk, match on these ids, not on a file path.
Canary runs against lit main
Section titled “Canary runs against lit main”The lit monorepo is checked out as a submodule. It is a read-only reference to the real lit source, not the compiled npm output, and an opt-in way to test this plugin against in-development lit changes.
git submodule update --init # oncepnpm build:lit-canary # installs + builds lit inside ./litLIT_CANARY=1 pnpm test # resolves lit imports from ./litWith LIT_CANARY=1, every bare lit, @lit/*, and @lit-labs/* import in the
test fixtures and the unit tests is aliased into the built submodule output. The
whole suite then runs against lit main.
The Lit canary workflow does the same every Monday and on demand from the
Actions tab. It moves the submodule to the tip of lit’s default branch first, so
a red run means something changed upstream, or in the plugin’s reading of it.