Files
Kamran Ahmed 75edd1b4bc Restructure as a Turborepo monorepo
packages/driver is the library (still published as driver.js, with
repository.directory set); playground and docs move to apps/. One root
pnpm workspace and lockfile replace the three standalone projects, with
turbo orchestrating build/test/lint:package (apps depend on the library
build; local + CI caching via .turbo).

Apps keep importing the library from source for HMR — the aliases now
point at ../../packages/driver/src and each app gains a workspace:*
dependency so the task graph knows the edge. The dev-server fs scope
widens to the repo root accordingly.

Releases run from packages/driver (root `pnpm release` delegates). The
changelog still lives in the docs app, so the release scripts reach it
via ../../../apps/docs and the after:bump hook stages it explicitly —
release-it no longer sits above both directories.

The merged workspace settings keep sharp unbuilt on purpose (prebuilt
binaries; building from source needs node-gyp and fails) — the docs app
had this right and the playground setting was the accident. postcss and
postcss-scss were unreferenced devDependencies and are dropped; prettier
moves to the root as the only shared tool.
2026-07-16 19:45:23 +01:00

56 lines
2.1 KiB
TypeScript

import { afterEach, beforeEach } from "vitest";
import { driver, type DriveStep, type Driver } from "../src/driver";
type DriverConfig = Parameters<typeof driver>[0];
// A small, stable DOM that the tests highlight against.
export const DEMO_HTML = `
<header class="page-header"><h1>Title</h1></header>
<p id="intro">Intro paragraph</p>
<button id="card-1" type="button">Card One</button>
<ul class="feature-list"><li>One</li></ul>
`;
export const SAMPLE_STEPS: DriveStep[] = [
{ element: "#intro", popover: { title: "Step 1", description: "First" } },
{ element: "#card-1", popover: { title: "Step 2", description: "Second" } },
{ element: ".feature-list", popover: { title: "Step 3", description: "Third" } },
];
let active: Driver | undefined;
export function createDriver(config?: DriverConfig): Driver {
active = driver(config);
return active;
}
// Resets the DOM before each test and tears the driver down after, so the
// library's module-level state never leaks between tests. Call once per file.
export function useDriverHarness(): void {
beforeEach(() => {
document.body.innerHTML = DEMO_HTML;
});
afterEach(() => {
active?.destroy();
active = undefined;
document.body.innerHTML = "";
});
}
// Waits a single animation frame — needed for hooks that fire in the rAF loop.
export function nextFrame(): Promise<void> {
return new Promise(resolve => requestAnimationFrame(() => resolve()));
}
export const popoverEl = () => document.querySelector(".driver-popover");
export const popoverTitle = () => document.querySelector(".driver-popover-title")?.textContent?.trim();
export const popoverDescription = () => document.querySelector(".driver-popover-description")?.textContent?.trim();
export const progressText = () => document.querySelector(".driver-popover-progress-text")?.textContent?.trim();
export const navButton = (which: "next" | "prev" | "close") =>
document.querySelector<HTMLButtonElement>(`.driver-popover-${which}-btn`);
export function pressKey(key: string): void {
window.dispatchEvent(new KeyboardEvent("keyup", { key }));
}