Skip to content

API Reference ​

Complete reference documentation for all TWD functions, methods, and types.

Quick Navigation ​

SectionDescription
Initializationtwd() Vite plugin (recommended) and initTWD() (manual)
Test Functionsdescribe, it, beforeEach, it.only, it.skip, afterEach
TWD Commandstwd.get(), twd.visit(), twd.matchLayout(), twd.mockRequest(), etc.
AssertionsAll available assertions and their usage

Import Reference ​

ts
// Test structure
import { describe, it, beforeEach, afterEach } from "twd-js/runner";

// Commands, user events, queries and assertions
import { 
  twd, 
  userEvent,
  screenDom,
  screenDomGlobal,
  expect
} from "twd-js";

// Vite Plugin (Recommended - works with all Vite-based frameworks)
import { twd } from "twd-js/vite-plugin";

// Bundled Setup (manual API; the plugin uses this internally)
import { initTWD } from "twd-js/bundled";

// UI Component (for React apps using standard setup)
import { TWDSidebar } from "twd-js";

// Production-build Vite plugin (cleanup)
import { removeMockServiceWorker } from "twd-js/vite-plugin";

// CI Integration (for test execution)
import { executeTests, reportResults } from "twd-js/runner-ci";

// twd() plugin options:
//   testFilePattern?: string          // Glob for discovering test files (default: '/**/*.twd.test.ts')
//   open?: boolean                    // Whether the sidebar is open by default (default: true)
//   position?: "left" | "right"       // Sidebar position (default: "left")
//   search?: boolean                  // Show search input to filter tests (default: false)
//   serviceWorker?: boolean           // Enable request mocking (default: true)
//   serviceWorkerUrl?: string         // Custom service worker path (default: '/mock-sw.js')
//   theme?: Partial<TWDTheme>         // Custom theme

// TWDSidebar props (for standard setup):
//   open?: boolean        // Whether the sidebar is open by default (default: true)
//   position?: "left" | "right" // Sidebar position (default: "left")
//   search?: boolean      // Show search input to filter tests (default: false)

Initialization ​

TWD provides two ways to initialize the in-browser sidebar and discover tests:

  1. twd() Vite plugin (recommended) — declarative, lives in vite.config.ts, no entry-file changes.
  2. initTWD() manual API — for non-Vite projects (Angular, Webpack/CRA) or when you need direct control.

twd(options?) — Vite plugin ​

The recommended setup for any Vite-based project (React, Vue, Solid.js, Astro, etc.). Auto-injects test discovery and sidebar mounting in vite dev. No-op in production builds.

Syntax ​

ts
import { twd } from "twd-js/vite-plugin";

twd(options?: TwdPluginOptions): VitePlugin

TwdPluginOptions ​

ts
interface TwdPluginOptions {
  testFilePattern?: string;     // Glob pattern for discovering test files (default: '/**/*.twd.test.ts')
  open?: boolean;               // Whether the sidebar is open by default (default: true)
  position?: "left" | "right";  // Sidebar position (default: "left")
  search?: boolean;             // Show search input to filter tests (default: false)
  serviceWorker?: boolean;      // Enable request mocking (default: true)
  serviceWorkerUrl?: string;    // Custom service worker path (default: '/mock-sw.js')
  theme?: Partial<TWDTheme>;    // Custom theme — see /theming
  rootSelector?: string;        // Override the app root for screenDom queries
}

Examples ​

ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; // or vue, solid
import { twd } from 'twd-js/vite-plugin';

// Minimal — all defaults
export default defineConfig({
  plugins: [react(), twd()],
});

// Custom sidebar configuration
export default defineConfig({
  plugins: [react(), twd({ open: false, position: 'right' })],
});

// Different test file pattern
export default defineConfig({
  plugins: [react(), twd({ testFilePattern: '/**/*.spec.{ts,tsx}' })],
});

// Disable request mocking
export default defineConfig({
  plugins: [react(), twd({ serviceWorker: false })],
});

Notes ​

  • The plugin uses apply: 'serve', so it's a no-op in vite build. Production bundles never include TWD code.
  • Full-reload on test-file edits is handled automatically.
  • Internally the plugin imports from twd-js/bundled and calls initTWD for you. Same runtime, less boilerplate.

initTWD(files, options?) — manual API ​

The lower-level API. Use this for non-Vite projects (Angular, Webpack/CRA) or when you need conditional initialization the plugin doesn't expose.

Syntax ​

ts
import { initTWD } from "twd-js/bundled";

initTWD(files: TestModule, options?: InitTWDOptions): void

Parameters ​

  • files (TestModule) - Object mapping test file paths to async import functions (typically from import.meta.glob() in Vite, or built manually in non-Vite environments)
  • options (InitTWDOptions, optional) - Configuration options (same shape as TwdPluginOptions above, minus testFilePattern since you supply files directly)

InitTWDOptions ​

ts
interface InitTWDOptions {
  open?: boolean;              // Whether the sidebar is open by default (default: true)
  position?: "left" | "right";  // Sidebar position (default: "left")
  search?: boolean;             // Show search input to filter tests (default: false)
  serviceWorker?: boolean;      // Enable request mocking (default: true)
  serviceWorkerUrl?: string;    // Custom service worker path (default: '/mock-sw.js')
  theme?: Partial<TWDTheme>;    // Custom theme
  rootSelector?: string;        // Override the app root for screenDom queries
}

Returns ​

void

Examples ​

ts
// Minimal setup - uses all defaults
const tests = import.meta.glob("./**/*.twd.test.ts");
initTWD(tests);

// Custom sidebar configuration
initTWD(tests, { open: false, position: 'right' });

// Enable search filter for tests
initTWD(tests, { search: true });

// Disable request mocking
initTWD(tests, { serviceWorker: false });

// Custom service worker path
initTWD(tests, { serviceWorkerUrl: '/custom-path/mock-sw.js' });

// All options together
initTWD(tests, { 
  open: true, 
  position: 'right',
  serviceWorker: true,
  serviceWorkerUrl: '/my-mock-sw.js'
});

Framework Examples (manual init) ​

Angular (no Vite — manual init required):

ts
// TWD_ENABLED comes from the `define` option in angular.json — see the Angular
// section in Framework Setup. Do not use isDevMode(): it is a function call, so
// esbuild keeps the branch and ships ~580 K of unused chunks in production.
declare const TWD_ENABLED: boolean | undefined;

if (typeof TWD_ENABLED !== 'undefined' && TWD_ENABLED) {
  const { initTWD } = await import('twd-js/bundled');
  const tests = {
    './tests/example.twd.test.ts': () => import('./tests/example.twd.test'),
  };
  initTWD(tests);
}

Webpack / CRA (manual init):

ts
if (process.env.NODE_ENV === "development") {
  const context = require.context("./", true, /\.twd\.test\.ts$/);
  const tests = {};
  context.keys().forEach((key) => {
    tests[key] = async () => Promise.resolve(context(key));
  });
  const { initTWD } = await import('twd-js/bundled');
  initTWD(tests);
}

For Vite-based React/Vue/Solid examples, prefer the twd() plugin shown above.

Notes ​

  • The bundled setup automatically handles React dependencies internally
  • Request mocking is initialized automatically by default (serviceWorker: true)
  • Works with all supported frameworks (React, Vue, Angular, Solid.js)
  • Test files are excluded from production builds when the guard folds to a constant at build time: import.meta.env.DEV (Vite), process.env.NODE_ENV (Webpack), or a defined TWD_ENABLED (Angular). A guard the bundler can only evaluate at runtime — such as Angular's isDevMode() — keeps the branch and its lazy chunks in the output

Type Definitions ​

Element API ​

ts
interface TWDElemAPI {
  el: Element; // The raw DOM element
  should: ShouldFn; // Assertion function
}

Assertion Types ​

ts
type AssertionName = 
  | "have.text"
  | "contain.text" 
  | "be.empty"
  | "have.attr"
  | "have.value"
  | "be.disabled"
  | "be.enabled"
  | "be.checked"
  | "be.selected"
  | "be.focused"
  | "be.visible"
  | "be.hidden"
  | "have.class";

type AnyAssertion = AssertionName | `not.${AssertionName}`;

Mock Request Types ​

ts
interface Options {
  method: string;
  url: string | RegExp;
  response: unknown;
  status?: number;
  responseHeaders?: Record<string, string>;
  urlRegex?: boolean;
  delay?: number;
}

interface Rule {
  method: string;
  url: string | RegExp;
  response: unknown;
  alias: string;
  executed?: boolean;
  request?: unknown;
  status?: number;
  responseHeaders?: Record<string, string>;
  urlRegex?: boolean;
  delay?: number;
  hitCount?: number;
}

Core Concepts ​

Test Structure ​

TWD follows familiar testing patterns:

ts
describe("Test Suite", () => {
  beforeEach(() => {
    // Setup before each test
  });

  it("should do something", async () => {
    // Test implementation
  });

  it.only("focused test", async () => {
    // Only this test runs
  });

  it.skip("skipped test", async () => {
    // This test is skipped
  });
});

Element Selection and Interaction ​

ts
// TWD native selectors
const element = await twd.get("selector");
const elements = await twd.getAll("selector");

// Testing Library queries (also available)
// screenDom - for regular content (excludes sidebar)
const button = await screenDom.findByRole("button", { name: /submit/i });
const input = await screenDom.findByLabelText("Email:");

// screenDomGlobal - for portal-rendered elements (modals, dialogs)
// ⚠️ Use specific queries to avoid matching sidebar elements
const modal = await screenDomGlobal.findByRole("dialog", { name: "Confirm" });

// Make assertions
element.should("assertion", ...args); // For twd.get() elements
twd.should(button, "be.visible"); // For screenDom elements

// User interactions
const user = userEvent.setup();
await user.click(element.el);
await user.type(input, "text");

API Mocking ​

ts
// Mock requests
await twd.mockRequest("alias", {
  method: "GET",
  url: "/api/endpoint",
  response: { data: "value" }
});

// Wait for requests
const rule = await twd.waitForRequest("alias");
const rules = await twd.waitForRequests(["alias1", "alias2"]);

// Clean up
twd.clearRequestMockRules();

Best Practices ​

  1. Use data attributes for reliable element selection
  2. Clean up mocks after each test
  3. Wait appropriately for async operations
  4. Be specific with assertions
  5. Test user workflows rather than implementation details

Browser Compatibility ​

TWD works in all modern browsers that support:

  • ES2020+ features
  • Service Workers (for API mocking)
  • DOM APIs
  • Async/await

Supported Browsers ​

  • Chrome 80+
  • Firefox 72+
  • Safari 13.1+
  • Edge 80+

Performance Considerations ​

  • Element queries use document.querySelector internally
  • Service Worker mocking adds minimal overhead
  • Tests run in the main thread (no web workers)
  • Tests are not included in the bundle, so they are not included in the bundle size.

Debugging ​

Browser DevTools ​

  • Use browser DevTools to inspect elements
  • Check Network tab for mocked requests
  • Console logs show TWD operations
  • Check sidebar for logs and mock rules

Common Debug Patterns ​

ts
// Log element details
const element = await twd.get("selector");
console.log("Element:", element.el);
console.log("Text content:", element.el.textContent);

// Log mock rules
console.log("Active mocks:", twd.getRequestMockRules());

// Add debug waits
await twd.wait(1000); // Pause to inspect state

Migration Guide ​

From Other Testing Libraries ​

From Cypress ​

ts
// Cypress
cy.get('[data-testid="button"]').click();
cy.get('[data-testid="message"]').should('contain', 'Success');

// TWD
const button = await twd.get('[data-testid="button"]');
await userEvent.click(button.el);
const message = await twd.get('[data-testid="message"]');
message.should('contain.text', 'Success');

From Testing Library ​

TWD now supports Testing Library queries directly! You can use the same screenDom and screenDomGlobal APIs:

ts
// Testing Library
const button = screen.getByTestId('button');
fireEvent.click(button);
expect(screen.getByTestId('message')).toHaveTextContent('Success');

// TWD - Same API!
import { screenDom, screenDomGlobal, userEvent, twd } from 'twd-js';

// screenDom - for regular content (excludes sidebar)
const button = await screenDom.findByTestId('button');
await userEvent.click(button);
const message = await screenDom.findByTestId('message');
twd.should(message, 'contain.text', 'Success');

// screenDomGlobal - for portal-rendered elements (modals, dialogs)
// ⚠️ Use specific queries to avoid matching sidebar elements
const modal = await screenDomGlobal.findByRole('dialog', { name: 'Confirm' });

// Or use TWD's native selectors
const button = await twd.get('[data-testid="button"]');
await userEvent.click(button.el);
const message = await twd.get('[data-testid="message"]');
message.should('contain.text', 'Success');

Vite Plugin ​

removeMockServiceWorker() ​

Vite plugin that removes the mock service worker file from production builds. This ensures your production bundle doesn't include testing infrastructure.

Syntax ​

ts
import { removeMockServiceWorker } from "twd-js/vite-plugin";

Usage ​

ts
// vite.config.ts
import { defineConfig } from 'vite';
import { removeMockServiceWorker } from 'twd-js/vite-plugin';

export default defineConfig({
  plugins: [
    // ... other plugins
    removeMockServiceWorker()
  ]
});

What it does ​

  • Build-time cleanup: Automatically removes mock-sw.js from the dist folder
  • Production-safe: Only runs during build (apply: 'build')
  • Zero configuration: Works out of the box with standard Vite setups
  • Logging: Provides feedback about file removal

Example Output ​

bash
# During build
🧹 Removed mock-sw.js from build

# If no mock file found
🧹 No mock-sw.js found in build

CI Integration ​

reportResults(handlers, testStatus) ​

Formats and displays test results in a readable format with colored output.

Syntax ​

ts
reportResults(handlers: Handler[], testStatus: TestResult[]): void

Parameters ​

  • handlers (Handler[]) - Test handlers from executeTests()
  • testStatus (TestResult[]) - Test results from executeTests()

Usage ​

ts
import { executeTests, reportResults } from "twd-js/runner-ci";

// Complete CI workflow
const { handlers, testStatus } = await executeTests();
reportResults(handlers, testStatus);

// Exit with appropriate code
const hasFailures = testStatus.some(t => t.status === 'fail');
process.exit(hasFailures ? 1 : 0);

Example Output ​

bash
User Authentication
  ✓ should login with valid credentials
  ✓ should logout successfully
  ✗ should handle invalid credentials
    - Error: Expected element to contain text "Invalid credentials"

Shopping Cart
  ✓ should add items to cart
  ○ should remove items from cart (skipped)

Output Format ​

  • ✓ Green checkmark for passed tests
  • ✗ Red X for failed tests
  • ○ Yellow circle for skipped tests
  • Error details shown below failed tests
  • Hierarchical structure matches your test organization

Contributing ​

Released under the MIT License.