@hyperfrontend/testing/fs

fs

Temporary directories that delete themselves, and fixture trees written into them from data the spec declares.

Usage

useTempDir registers the node:test hooks that give every test in the suite a fresh directory and delete it afterwards. The handle it returns always points at the current test's directory, so capture it once in the describe body:

import { describe, expect, it } from '@hyperfrontend/testing'
import { useTempDir } from '@hyperfrontend/testing/fs'
import { loadConfig } from './load-config'

describe('loadConfig', () => {
  const dir = useTempDir({
    tree: {
      'package.json': { name: 'app' },
      'src/index.ts': 'export const ready = true\n',
    },
  })

  it('reads a config file beside the manifest', () => {
    dir.write('hf.config.json', { strict: true })
    expect(loadConfig(dir.path)).toEqual({ strict: true })
  })
})

Pass scope: 'all' to share one directory across the suite instead. For a directory a single test owns, createTempDir creates it straight away and leaves removal to the caller: a matching after hook at module or suite scope, or a finally inside the one test that owns it. writeTree and writeFile write into any directory you already have.

File content

A FileTree maps relative paths to content. Parent directories are created as needed.

ValueWritten as
A stringThe text, unchanged
A Uint8ArrayThe bytes, unchanged
Any other valuePretty-printed JSON followed by a newline

Design

Fixtures held as data in the spec, rather than checked in as files, never look like a real manifest or lockfile to a dependency scanner, and the spec states every file it depends on.

The directory's path is reported with symbolic links resolved. On macOS the system temporary directory is a symbolic link, and on Windows it can be an 8.3 short name, so an unresolved path would differ from what process.cwd() or a resolved real path report inside the code under test. Writes refuse a path that is absolute or climbs out of the directory, since anything written there would survive the cleanup. Removal retries while Windows still holds a handle open inside the directory.

API Reference§

ƒ Functions

§function

createTempDir(options: TempDirOptions): TempDir

Creates a temporary directory now, for the caller to remove.
Use it at module or suite scope with a matching after, or inside a single test with a finally that removes it. For a directory every test in a suite gets, useTempDir registers the hooks itself.
Parameters
NameTypeDescription
§options
TempDirOptionsName prefix, parent and initial files.(default: {})
Returns
TempDir
The directory and its file operations.
Example

A directory one test owns

it('reads the manifest', () => {
  const dir = createTempDir({ tree: { 'package.json': { name: 'app' } } })
  try {
    expect(readManifest(dir.path).name).toBe('app')
  } finally {
    dir.remove()
  }
})
§function

useTempDir(options: UseTempDirOptions): TempDir

Gives every test in the enclosing suite a temporary directory, created before and deleted after, by registering the node:test hooks that do it.
Call it in a describe body or at the top of a spec file. The returned handle reads the directory current at the time of each call, so it can be captured once and used from any test or hook. Reading it outside a test throws, since no directory exists then.
Parameters
NameTypeDescription
§options
UseTempDirOptionsName prefix, parent, initial files, and whether tests share one directory.(default: {})
Returns
TempDir
A handle to the current directory and its file operations.
Example

A fresh directory for every test

describe('loadConfig', () => {
  const dir = useTempDir({ tree: { 'package.json': {} } })

  it('finds a config file beside the manifest', () => {
    dir.write('hf.config.json', { strict: true })
    expect(loadConfig(dir.path)).toEqual({ strict: true })
  })
})
§function

writeFile(root: string, relativePath: string, content: FileContent): string

Writes one file under a root, creating its parent directories.
Parameters
NameTypeDescription
§root
stringThe directory to write under.
§relativePath
stringWhere the file goes, relative to the root.
§content
FileContentWhat the file holds.
Returns
string
The absolute path of the written file.
Example

Writing a manifest as JSON

writeFile(root, 'packages/app/package.json', { name: 'app' })
// => '<root>/packages/app/package.json', holding '{\n  "name": "app"\n}\n'
§function

writeTree(root: string, tree: FileTree): void

Writes a tree of files under a root, creating every directory the paths name.
Fixtures held as data in a spec, rather than checked in as files, never look like a real manifest or lockfile to a dependency scanner, and a spec states exactly the files it depends on. Every path must stay inside the root.
Parameters
NameTypeDescription
§root
stringThe directory to write under. It is created when missing.
§tree
FileTreeThe files to write.
Example

Laying out a small workspace

writeTree(root, {
  'package.json': { name: 'workspace', workspaces: ['packages/*'] },
  'packages/app/package.json': { name: 'app' },
  'packages/app/src/index.ts': 'export const ready = true\n',
})

◈ Interfaces

§interface

UseTempDirOptions

When useTempDir creates and removes its directory.
Properties
§prefix?:stringStart of the directory's name, before the random suffix. Defaults to hf-test-.
§parent?:stringDirectory to create it in. Defaults to the system temporary directory.
§tree?:FileTreeFiles written into it as soon as it is created.
§scope?:"each" | "all"each gives every test a fresh directory; all shares one across the suite. Defaults to each.

◆ Types

§type

FileContent

What a file in a tree holds: text as written, bytes as given, or any other value as pretty-printed JSON with a trailing newline.
type FileContent = string | Uint8Array | object
§type

FileTree

Files to write, keyed by path relative to the directory they are written into. A key may name nested directories with /, which are created as needed.
type FileTree = Record<string, FileContent>
§type

TempDir

A temporary directory and the file operations a spec runs against it, every path relative to the directory.
§type

TempDirOptions

Where a temporary directory is created and what it starts with.