nodepup v2.1.4
nodepup
Run component tests in a real browser.
Why does this exist?
- simulated DOM environments (like JSDOM) don't (plan) to implement every Web API
- e2e testing tools like cypress and/or playwright are too heavy handed
So this sits kind of in the middle between simulated, very fast tests and emulated but very slow tests.
Architecture
It is useful to understand what nodepup does differently under the hood so you can avoid mistakes in your tests.
With simulated DOM environments your tests run on the server and things like e.g. CSS will never be tested. Querying nodes and interacting with your components happens on the basis of a simulated environment which is fast but can only return stand-ins, which e.g. - at the time of writing - do not support form-associated custom elements.
Full e2e suites on the other hand start a headless browser and your test code also runs on the server. Your tests then execute a series of commands that are sent to that browser, meaning that getting "a grip on things" has to either be done "for you" by the library or by injecting bits of code into the browsers runtime.
Nodepup takes a different approach: it bundles your tests with esbuild and serves that bundle via a small web server. Your tests run on the client and as such you can easily listen for events, assert the DOM structure synchronously and all that stuff.
This would however normally come with the same drawback however that a simulated environment has: user interactions can only be "faked". Libraries like user-event have been created to address this issue in a best-effort manner, but they can obviously never reach the level of the e2e solutions.
For this reason nodepup enables user interactions by telling puppeteer which action to perform, thus combining the performance of a simulated environment with the capabilities of a real browser.
(Recommended) Usage
/**
* Testbed.tsx
*
* This module exposes utility functions around testing.
*
* @module
*/
import { toHtml } from "tsx-to-html";
import * as Chai from "chai";
import chaiDom from "chai-dom";
Chai.use(chaiDom);
export const expect = Chai.expect;
export const render = (element: JSX.Element) => {
// render the component to a plain HTML string.
// You could also create mountpoints for your framework of choice here
document.innerHTML = toHtml(element);
return document;
};
export * from "@testing-library/dom";
export * from "nodepup";
import { describe, it, user, expect, render } from "./Testbed.js";
describe("my component", () => {
it("should match :hover when mouse hovers", async () => {
// setup - could be abstracted on a "by component" basis
const container = render(<my-input />);
const input = getByRole(container, "textbox");
// act
const { x, y } = getCenterPoint(input);
await user.mouse.move(x, y); // user tries to alias the puppeteer functions here
// assert
expect(input).to.match(":hover");
});
});
Configuration
// nodepup.config.js
/**
* @type import("nodepup/server").NodepupConfig
*/
export default {
esbuild: {}, // changeable esbuild options
coverage: {}, // changeable monocart-coverage-reporter options
glob: "**/*.test.{ts,tsx}", // an extended glob to find your test files
bodyContent: "", // html that replaces the document body before every test run
};
CLI Usage
See npx nodepup --help
.
8 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
8 months ago
9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
9 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago