Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@leaflink/dom-testing-utils

Package Overview
Dependencies
Maintainers
4
Versions
281
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@leaflink/dom-testing-utils

Frontend DOM testing utilities

latest
npmnpm
Version
5.3.2
Version published
Maintainers
4
Created
Source

@leaflink/dom-testing-utils

Leaflink repository to manage test utilities to be shared across front-end applications.

version downloads MIT License semantic-release Commitizen friendly

Installation

Requirements: Node.js >= 24

pnpm add -D @leaflink/dom-testing-utils

Releases

Releases are fully automated using semantic-release. When changes are pushed to a release branch (main, alpha, beta, canary, next, next-major, or [0-9]+.x), the CI workflow:

  • Builds the package with pnpm build
  • Analyzes commits to determine the next version (using Conventional Commits)
  • Publishes to npm and creates a GitHub release with changelog

Commit types that trigger releases: feat, fix, perf, and revert. Other types (e.g. docs, chore) appear in changelogs but do not bump the version on their own.

For detailed commit conventions and manual release instructions, see CONTRIBUTING.md.

Dependency updates

Dependency updates are handled by self-hosted Renovate, invoked from .github/workflows/renovate.yml using a PAT (RENOVATE_PAT) issued from the leaflink-automation account. Configuration lives in .github/renovate.json5. Tracking ticket: MKPL-1055.

Schedule

  • Workflow cron wakes Renovate hourly.
  • Renovate only opens PRs between 1am–5am America/New_York, every day.
  • A new release must be ≥ 10 days old (minimumReleaseAge) before Renovate will propose it — buffer against compromised/withdrawn publishes.
  • Merging is handled by a separate workflow (see Auto-merge) that runs whenever required CI completes — independent of Renovate's schedule.

Update groups and auto-merge policy

SourceUpdate typePR shapeAuto-merge
devDependenciesanygrouped as one PR (chore(deps-dev): update dev dependencies)
dependencies / peerDependenciespatchindividual PR (chore(deps): ...)
dependencies / peerDependenciesminor / majorindividual PR (chore(deps): ...)❌ awaits review
github-actionspatch / minor / digest / pinindividual PR
github-actionsmajorindividual PR❌ awaits review
Lockfile maintenance (transitive refresh of pnpm-lock.yaml)weeklyRefresh ... (chore(deps-dev))

Renovate PR bodies all link back to MKPL-1055 via prBodyNotes.

Auto-merge

main requires quality-checks + release status checks and a CODEOWNERS review. The leaflink-automation account (whose PAT Renovate uses) is in main's bypass_pull_request_allowances, but Renovate itself won't call the merge API while the PR shows as BLOCKED in GitHub's API — even though the bypass would let it through.

To work around this, .github/workflows/renovate-merge.yml performs the merge on Renovate's behalf:

  • Renovate creates the PR. Any rule with automerge: true adds addLabels: ['automerge'], so the label is the single source of truth for "Renovate intended to auto-merge this."
  • PR Quality Checks and Release run on the PR.
  • When either completes, the Renovate Merge workflow is triggered via workflow_run. It:
    • filters to PRs authored by leaflink-automation with the automerge label,
    • asserts both required checks are present and successful,
    • calls the merge API authenticated as leaflink-automation.
  • Because the user is on the bypass list, the merge call succeeds despite BLOCKED status.

Human PRs are unaffected — they still require CODEOWNERS review.

The required-checks list in renovate-merge.yml (REQUIRED_CHECKS) is hard-coded and must stay in sync with branch protection on main.

Where to look

  • Dependency Dashboard issue (auto-created by Renovate, label dependencies) — single source of truth for what Renovate sees, what it skipped, and why.
  • Workflow runs for Renovate in the Actions tab — workflow_dispatch with logLevel: debug to debug Renovate itself.
  • Workflow runs for Renovate Merge in the Actions tab — shows which PRs were merged or skipped (with reason) when CI completed. workflow_dispatch for manual recovery.
  • config:recommended is the base preset; any unspecified behavior comes from there.

Usage

In your test files you can import utility functions.

import {
  waitForLoading,
  cleanupDropdowns,
  assertAndDismissNoty,
  cleanupNoty,
  createFixtureGenerator,
} from '@leaflink/dom-testing-utils';

it('...', () => {
  cleanupNoty();
});

Setup file

Import @leaflink/dom-testing-utils/setup-env once (for instance in your tests setup file) and you're good to go:

Note: @testing-library/jest-dom is auto-imported from @leaflink/dom-testing-utils so you don't have to.

// In your own setup-env.ts (or any other name)
import '@leaflink/dom-testing-utils/setup-env'
// DON'T import `@testing-library/jest-dom` is auto imported from dom-testing-utils

// In vite.config.ts add (if you haven't already)
setupFiles: ['tests/setup-env.js'],

// In jest.config.js add (if you haven't already)
setupFilesAfterEnv: ['<rootDir>/tests/setup-env.js']

This will be run once before each test file. See https://vitest.dev/config/#setupfiles.

Global setup

Add the following import to your test config:

// In vite.config.ts add
globalSetup: ['node_modules/@leaflink/dom-testing-utils/dist/global-setup.js'],

// In jest.config.js add
globalSetup: ['<rootDir>/node_modules/@leaflink/dom-testing-utils/dist/global-setup.js']

This will run once before everything. See https://vitest.dev/config/#globalsetup.

Utilities

cleanupNoty

Helper method to remove all noty alerts from the DOM.

Parameters: None

Returns: void

waitForLoading

Utility that waits for all loading elements to be removed from the DOM. The data-test argument defaults to ll-loading or loading-spinner if testId is not specified.

ParametersTypeDefaultSummary
testIdstringll-loading && loading-spinnerThe data test ID to target.
timeoutnumber2000How long to wait for loading elements to be removed
failIfNullbooleanfalseThrows an error if no loading elements are found

Returns: Promise<void>

Will resolve if the loaders get removed before the timeout. Otherwise, will throw an error if the loaders are still in the DOM by the end of the timeout.

Setting failIfNull to true will cause an error to be thrown if no loading spinners are initially found in the DOM.

cleanupDropdowns

Helper method to remove all floating Stash Dropdown elements from the DOM.

Parameters: None

Returns: void

assertAndDismissNoty

Helper to assert and manually dismiss a notification. This is useful in scenarios where cleanupNoty() does not work as expected, such as when validating error messages in test suites.

ParametersTypeDefaultSummary
textstringRequiredExpected notification text.

Returns: void

getByDescriptionTerm

Finds the first HTML element with the role "definition" (DD) that matches the specified text for the description term.

ParametersTypeDefaultSummary
textstring | RegExpRequiredExpected description term text or regex

Returns: HTMLElement | undefined - The first matching description detail element or undefined if no match is found.

getAllByDescriptionTerm

Queries and returns an array of HTML elements with the role "definition" (DD) that matches the specified text of a description term.

ParametersTypeDefaultSummary
textMatchstring | RegExpRequiredThe text to match within the HTML elements. It can be a string or a regular expression.

Returns: HTMLElement[] - An array of HTML description detail elements that match the given text.

getSelectedOption

Finds the first selected HTML element with the role "definition" (LI) "listitem" inside the specified select element.

ParametersTypeDefaultSummary
elementHTMLSelectElementRequiredStash Select element to be checked.
selectedClassstring'is-selected'Selected class added on selected items
optionsByRoleOptionsnullgetAllByRole() options values using ByRoleOptions type

Returns: HTMLElement | undefined - The first selected HTML listitem element or undefined if no match is found.

getSelectedOptions

Finds all the selected HTML elements with the role "definition" (LI) "listitem" inside the specified select element.

ParametersTypeDefaultSummary
elementHTMLSelectElementRequiredStash Select element to be checked.
selectedClassstring'is-selected'Selected class added on selected items
optionsByRoleOptionsnullgetAllByRole() options values using ByRoleOptions type

Returns: HTMLElement[] - An array of selected HTML listitem elements.

createFixtureGenerator

Higher order function that takes a method whose responsibility is to create a single data fixture object and returns a new generator function that allows you to create 1 or more of those fixtures. Fixture generator function that's returned supports passing optional num and overrides params.

ParametersTypeDefaultSummary
fixtureFnfunctionRequiredMethod that generates and returns a single data object.

Returns

(num?, overrides?) => Array<{[key: string]: any}> | {[key: string]: any}
// OR
(overrides?) => {[key: string]: any}

A new generator function that accepts a number & overrides where:

  • num = The number of fake data objects to generate. Defaults to 1
  • overrides = Specific attributes you want to override in each data fixture object.

When calling the returned function, you'll get an array OR object of fixture data (It will be a ** single object** if num = 1).

Examples

Quick example:

const generateInvoice = (overrides) => ({
  id: uuid(),
  balance: 15799,
  classification: 'Adult Use',
  ...overrides,
});
const generateInvoices = createFixtureGenerator(generateInvoice);

generateInvoices();
// => Single invoice object

generateInvoices(1);
// => Single invoice object

generateInvoices(1, { foo: 'bar' });
// => Single invoice object, override `foo` to equal `'bar'`

generateInvoices({ foo: 'bar' });
// => Single invoice object, override `foo` to equal `'bar'`

generateInvoices(10);
// => Array of 10 invoice objects

generateInvoices(10, { foo: 'bar' });
// => Array of 10 invoice objects, override `foo` to equal `'bar'` in each

Full example:

// tests/fixtures/products.ts
import { faker } from '@faker-js/faker';
import { createFixtureGenerator } from '@leaflink/dom-testing-utils';

export const generateProduct = (overrides = {}) => ({
  sku: git.commitSha(),
  name: faker.commerce.productName(),
  quantity: faker.random.number(100),
  cases: faker.random.number(10),
  ...overrides,
});

export default createFixtureGenerator(generateProduct);

// services/api/products.ts
import generateProducts from '@/tests/fixtures/products';

// ...
const mockProducts = generateProducts(10, { cases: 25 });
// ...

Mocking API Endpoints

In order to mock API endpoints that your tests interact with, you can get a set of mocking functions from createMockApiUtils.

import { createMockApiUtils } from '@leaflink/dom-testing-utils';
import yourServer from './server.ts';

const {
  mockGetData,
  mockGetEndpoint,
  mockPatchData,
  // etc.
} = createMockApiUtils(yourServer);

There are two flavors of mocking utility functions:

  • mock{VERB}Data - mocks response with a singular data object
  • mock{VERB}Endpoint - mocks a response endpoint with a function like msw's Response Resolver

To mock an endpoint with simple return data

mockGetData('/relative-url', myMockObj);

or you can customize the response

mockGetEndpoint('/relative-url', (req, res, ctx) => {
  if (someConditional()) {
    HttpResponse.json({ foo: 'bar' });
  } else {
    HttpResponse.json({ foo: 'baz' });
  }
});

FAQs

Package last updated on 29 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts