cursery.nixDocs

Testing

Apps run in any test environment with a DOM, such as jsdom. This guide uses Vitest and DOM Testing Library.

Set up#

$ pnpm add -D vitest jsdom @testing-library/dom

Set the test environment in vite.config.js:

vite.config.js
export default defineConfig({
  // ...
  test: {
    environment: "jsdom",
  },
});

Test the app#

Import the app with ?cursery:store-path and mount it:

src/app.test.js
import { fireEvent, screen } from "@testing-library/dom";
import { mount, unmount } from "cursery";
import { expect, test } from "vitest";

// The path of the app's `default.nix`, loaded but not mounted.
import app from "./app?cursery:store-path";

test("counts clicks", () => {
  mount(document.body, app);

  // The app re-renders before `fireEvent` returns.
  fireEvent.click(screen.getByRole("button", { name: "Increment" }));
  expect(screen.getByRole("heading").textContent).toBe("Clicked 1 times");

  unmount(document.body);
});

Test Nix files#

Import the app's files with ?cursery:files, and load them. evaluate can then call any file by its path, with inputs:

src/app/plural.nix
count: noun: if count == 1 then "1 ${noun}" else "${toString count} ${noun}s"
src/plural.test.js
import { evaluate, load } from "cursery";
import { expect, test } from "vitest";

import files from "./app?cursery:files";

const app = load(files);

test("pluralizes", () => {
  expect(evaluate(`import ${app}/plural.nix 1 "click"`)).toBe("1 click");
  expect(evaluate(`import ${app}/plural.nix 2 "click"`)).toBe("2 clicks");
});

Other test runners#

Import cursery/testing/setup before the tests. It polyfills missing jsdom features.

?cursery:store-path and ?cursery:files imports need the Vite plugin. Without it, load the app's files with load, as in Pre-rendering.