Skip to content

rstackjs/path-serializer

Repository files navigation

path-serializer

npm latest version

A snapshot serializer that normalizes system-specific paths into stable, readable placeholders — designed for Vitest, Jest, and Rstest.

  • Stabilize pnpm dependencies path in snapshot (including enableGlobalVirtualStore)
  • Transform win32 path to posix path
  • Replace absolute paths with placeholders (<ROOT>, <WORKSPACE>, <HOME>, <TEMP>)
  • Handle file:// protocol URLs
  • Escape EOL (\r\n -> \n)
  • Normalize ANSI color codes
// __snapshots__/index.test.ts.snap

// 😭 Without path-serializer — fragile, platform-specific, unreadable
{
  "loader" : "D:\\user\\rspack\\node_modules\\.pnpm\\css-loader@6.11.0_@rspack+core@packages+rspack_webpack@5.94.0_@swc+core@1.4.0_@swc+helpers@0._jlcdgjlw2ezzhg43ml3d627wdu\\node_modules\\css-loader\\utils.ts"
}

// 😎 With path-serializer — stable, cross-platform, clean
{
  "loader" : "<PNPM_INNER>/css-loader/utils.ts"
}

Installation

# npm
npm install path-serializer -D

# pnpm
pnpm add path-serializer -D

Usage

Basic

// vitest.setup.ts
import path from 'node:path';
import { expect } from 'vitest';
import { createSnapshotSerializer } from 'path-serializer';

expect.addSnapshotSerializer(
  createSnapshotSerializer({
    root: path.join(__dirname, '..'),
  }),
);

With Workspace (Monorepo)

expect.addSnapshotSerializer(
  createSnapshotSerializer({
    root: path.join(__dirname, '../..'),
    workspace: path.join(__dirname, '..'),
  }),
);

This replaces:

  • Workspace paths → <WORKSPACE>/...
  • Root paths → <ROOT>/...

Custom Replacements

Use replace and replacePost to add custom path matchers:

expect.addSnapshotSerializer(
  createSnapshotSerializer({
    root: path.join(__dirname, '..'),
    replace: [
      { match: /port\s\d+/, mark: 'PORT' },
      { match: '/specific/path', mark: 'CUSTOM' },
    ],
  }),
);

Hooks

Use beforeSerialize and afterSerialize for custom pre/post processing:

expect.addSnapshotSerializer(
  createSnapshotSerializer({
    root: path.join(__dirname, '..'),
    beforeSerialize: (val) => val.replace(/hash:\w{8}/g, 'hash:<HASH>'),
    afterSerialize: (val) => val.trim(),
  }),
);

Options

root

  • Type: string
  • Default: process.cwd()

Repository root path. Paths under this directory are replaced with <ROOT>.

workspace

  • Type: string
  • Default: ''

Workspace root path (for monorepos). Paths under this directory are replaced with <WORKSPACE>.

replace

  • Type: PathMatcher[]

Custom matchers applied before built-in replacements.

replacePost

  • Type: PathMatcher[]

Custom matchers applied after built-in replacements.

beforeSerialize

  • Type: (val: string) => string

Transform the raw string before any replacements.

afterSerialize

  • Type: (val: string) => string

Transform the final string after all replacements.

features

Toggle individual features (all enabled by default):

Feature Default Description
replaceWorkspace true /foo/packages/core/src<WORKSPACE>/src
replaceRoot true /foo/node_modules/.pnpm<ROOT>/node_modules/.pnpm
replaceWorkspaceWithFileProtocol true file:///foo/packages/core/src<WORKSPACE>/src
replaceRootWithFileProtocol true file:///foo/node_modules/.pnpm<ROOT>/node_modules/.pnpm
replacePnpmInner true Collapse pnpm's long .pnpm/... and global virtual store pnpm/store/.../links/... paths to <PNPM_INNER>
replaceTmpDir true os.tmpdir() paths → <TEMP>
replaceHomeDir true os.homedir() paths → <HOME>
transformWin32Path true Convert D:\\foo\\bar to /d/foo/bar
transformCLR true Normalize ANSI color escape codes
escapeDoubleQuotes true Escape " to \"
escapeEOL true Normalize \r\n to \n
addDoubleQuotes true Wrap output in double quotes

More details can be found in ./src/types.ts.

Showcases

License

MIT

About

Rstest/Vitest/Jest✅ snapshot path-serializer, e.g: `/usr/packages` -> `<ROOT>/packages`

Topics

Resources

License

Stars

Watchers

Forks

Contributors