close
Skip to main content

@sys/testing@0.0.338
Built and signed on GitHub Actions

Works with
This package works with Deno, Browsers
This package works with Deno
This package works with Browsers
JSR Score100%
License
MIT
Downloads65/wk
Published2 weeks ago (0.0.338)

Tools for testing.

Testing

@sys/testing provides Deno-backed BDD tests, assertions, runtime fixtures, and browser/server test helpers.

Verify

deno task check
deno task test
deno task dry

The test suite opens a local page in Chrome or Chromium. Set CHROME_BIN when the browser is not in a standard location.

Execution

The BDD API registers native Deno tests. Deno controls scheduling, sanitizers, permissions, timeouts, diagnostics, and reporting.

Top-level options pass to Deno.test. Supported nested options pass to Deno.TestContext.step. Nested permissions and timeouts are rejected because Deno steps cannot enforce them.

Workspace tests fail on leaked asynchronous operations or resources. Teardown may finish work started in a nested step before the parent leak check. To disable a leak check for one test, name that check explicitly.

todo registers an ignored test with a visible [todo] name. Its body does not run.

Use node:test only for compatibility. Deno runs Node-compatible tests without operation, resource, or exit sanitizers.

Write a test

Use -.test.ts for a module contract and -m.<subject>.test.ts for focused behavior. Deno discovers *.test.ts; the leading hyphen keeps tests grouped with their source files.

import { describe, expect, it } from '@sys/testing';

describe('My Suite', () => {
  it('returns the expected value', () => {
    expect(123).to.eql(123);
  });
});

Use the server entry point when a test needs filesystem or browser helpers:

import { describe, expect, Fs, it, Path } from '@sys/testing/server';

Web fixtures

A Web fixture temporarily changes part of the runtime for a test, then restores its exact prior state.

@sys/testing/web provides ready-made Fetch and WebSocket fixtures and Property, the transaction primitive that owns their setup and restoration.

Property separates lifecycle mechanics from fixture behavior. Fetch, WebSocket, and future fixtures reuse one exact ownership and restoration contract instead of implementing cleanup independently.

Import Web-runtime fixtures from @sys/testing/web:

import { WebFixture } from '@sys/testing/web';

Every mock handle supports both using and .dispose(). Successful disposal restores the exact prior property descriptor. Calling it again has no effect.

WebFixture.Property.isCleanupError(error) identifies incomplete cleanup. Its rollback handle remains available after a using scope and retries only unfinished work. If the scope body also throws, JavaScript retains the cleanup error inside SuppressedError.

Dispose nested mocks in reverse creation order (LIFO). A using scope does this automatically. Do not mutate an owned property or run parallel tests that mock the same target and property.

Property

Use Property.mock to replace one or more own properties as one transaction.

const target = {};

{
  using mock = WebFixture.Property.mock([
    {
      target,
      key: 'status',
      descriptor: { configurable: true, value: 'testing' },
    },
  ]);

  Object.getOwnPropertyDescriptor(target, 'status')?.value; // "testing"
}

Object.getOwnPropertyDescriptor(target, 'status'); // undefined

A new temporary property must be configurable so it can be removed. For ordinary objects, any change that cannot be undone is rejected before a target is changed.

Setup either installs every entry or restores those already installed. Incomplete setup and disposal both retain retry authority through the cleanup error.

Exact proxy and host-object restoration requires stable, truthful property descriptors. If cleanup is rejected, correct the blocking condition and retry through rollback.

Fetch

Fetch.mock replaces globalThis.fetch. The replacement controls all Fetch behavior, including abort handling.

{
  using mock = WebFixture.Fetch.mock(async (input, init) => {
    const request = new Request(input, init);
    request.signal.throwIfAborted();
    return Response.json({ ok: true });
  });

  await fetch('https://example.test/data');
}

WebSocket

WebSocket.mock replaces globalThis.WebSocket with a small deterministic test double. It provides url, readyState, state constants, microtask-driven open and close events, and a no-op send. It does not model messages, protocols, or CloseEvent metadata.

{
  using mock = WebFixture.WebSocket.mock();
  const socket = new WebSocket('ws://example.test/socket');
}

Mock the DOM

DomMock installs a server-side DOM for a test suite. The afterAll hook restores the prior environment.

import { afterAll, beforeAll, DomMock } from '@sys/testing/server';

DomMock.init({ beforeAll, afterAll });

document.addEventListener('keydown', (event) => {
  // Handle the event.
});

const event = DomMock.Keyboard.keydownEvent('z');
DomMock.Keyboard.fire(event);

Call DomMock.unpolyfill() only when a test must restore the environment before afterAll.

Built and signed on
GitHub Actions

Report package

Please provide a reason for reporting this package. We will review your report and take appropriate action.

Please review the JSR usage policy before submitting a report.

Add Package

deno add jsr:@sys/testing

Import symbol

import * as testing from "@sys/testing";
or

Import directly with a jsr specifier

import * as testing from "jsr:@sys/testing";