Skip to content

Investigate vitest file imports #225

@Unshure

Description

@Unshure

Simplify Test Fixture Loading with Async fetch()

Overview

Update the loadFixture helper function to use the standard fetch() API, making it work consistently across both Node.js and browser test environments without requiring file system access or environment-specific implementations.

Current Implementation Problem

Today, test files use environment-specific implementations:

Node.js tests (tests_integ/__fixtures__/test-helpers.ts):

import { readFileSync } from 'node:fs'
import { join } from 'node:path'

export const loadFixture = (url: string): Uint8Array => {
  const relativePath = url.startsWith('/') ? url.slice(1) : url
  const filePath = join(process.cwd(), relativePath)
  return new Uint8Array(readFileSync(filePath))
}

Browser tests (tests_integ/browser/agent.browser.test.ts):

const loadFixture = async (url: string): Promise<Uint8Array> => {
  if (isNode) {
    // Node.js implementation with fs.readFileSync
  } else {
    // Browser implementation with fetch
    const response = await globalThis.fetch(url)
    const arrayBuffer = await response.arrayBuffer()
    return new Uint8Array(arrayBuffer)
  }
}

Issues:

  • Requires different implementations for Node vs browser
  • Node implementation uses fs.readFileSync (not available in browsers)
  • Browser tests have duplicate loadFixture implementation with environment detection
  • Synchronous in Node, async in browser (inconsistent API)

Desired Implementation

Based on Vite issue #12366, modern Node.js (20+) supports fetch() natively, allowing a single implementation:

Unified async helper:

export const loadFixture = async (url: string): Promise<Uint8Array> => {
  const arrayBuffer = await fetch(url).then(b => b.arrayBuffer())
  return new Uint8Array(arrayBuffer)
}

Usage:

import yellowPngUrl from './__resources__/yellow.png?url'
const imageBytes = await loadFixture(yellowPngUrl)

Implementation Requirements

1. Update loadFixture Helper

File: tests_integ/__fixtures__/test-helpers.ts

  • Make function async returning Promise<Uint8Array>
  • Replace fs.readFileSync with fetch(url).then(b => b.arrayBuffer())
  • Remove fs and path imports
  • Keep same signature: (url: string) => Promise<Uint8Array>

Before:

import { readFileSync } from 'node:fs'
import { join } from 'node:path'

export const loadFixture = (url: string): Uint8Array => {
  const relativePath = url.startsWith('/') ? url.slice(1) : url
  const filePath = join(process.cwd(), relativePath)
  return new Uint8Array(readFileSync(filePath))
}

After:

export const loadFixture = async (url: string): Promise<Uint8Array> => {
  const arrayBuffer = await fetch(url).then(b => b.arrayBuffer())
  return new Uint8Array(arrayBuffer)
}

2. Update Test Files to Use await

All test functions are already async, just need to add await when calling loadFixture:

Files to update:

  • tests_integ/agent.test.ts
  • tests_integ/bedrock.test.ts

Change:

// Before
const imageBytes = loadFixture(yellowPngUrl)

// After
const imageBytes = await loadFixture(yellowPngUrl)

3. Remove Duplicate Browser Implementation

File: tests_integ/browser/agent.browser.test.ts

  • Remove the local loadFixture function (lines ~17-31)
  • Import loadFixture from shared test helpers instead
  • Update import statement:
    import { loadFixture } from '../__fixtures__/test-helpers.js'

4. Verification

Run tests in both environments to ensure no regressions:

# Node.js integration tests
npm run test:integ

# Browser integration tests  
npm run test:integ:browser

Verify:

  • ✅ Tests pass in both Node and browser environments
  • ✅ Image/PDF data loads correctly (yellow.png, letter.pdf)
  • ✅ No performance degradation
  • ✅ Unified implementation works across environments

Technical Details

Why This Works

  • Node.js 20+: Native fetch() support (already required by project)
  • Browser: fetch() is standard Web API
  • Vite/Vitest: ?url imports work in both environments
    • Node: Returns file path that fetch() can load
    • Browser: Returns URL that fetch() can load

Benefits

✅ Single, unified implementation
✅ No environment detection needed
✅ No file system dependencies
✅ Works in Node, browser, and future environments
✅ Simpler codebase (removes ~15 lines of duplicate code)
✅ Consistent async API across all tests

Acceptance Criteria

  • loadFixture updated in tests_integ/__fixtures__/test-helpers.ts
    • Function is async returning Promise<Uint8Array>
    • Uses fetch() instead of fs.readFileSync
    • No Node.js-specific imports (fs, path)
  • Test files updated with await keyword
    • tests_integ/agent.test.ts
    • tests_integ/bedrock.test.ts
  • Browser-specific implementation removed
    • Duplicate loadFixture removed from tests_integ/browser/agent.browser.test.ts
    • Import added from shared test helpers
  • Tests pass in Node environment (npm run test:integ)
  • Tests pass in browser environment (npm run test:integ:browser)
  • Code quality checks pass (lint, format, type-check)
  • No performance regressions

Files Affected

Modified:

  • tests_integ/__fixtures__/test-helpers.ts (~5 lines changed)
  • tests_integ/agent.test.ts (~2 lines changed, add await)
  • tests_integ/bedrock.test.ts (~4 lines changed, add await)
  • tests_integ/browser/agent.browser.test.ts (~15 lines removed, 1 import added)

Total: 4 files, approximately +5/-25 lines

Additional Context

This approach is based on the Vite maintainer's recommendation in issue #12366 and leverages Node.js 20's native fetch() support, which is already a project requirement (see package.json engines field).

Previous attempts to use a custom Vite plugin encountered technical blockers. This simpler solution achieves the same goal without additional dependencies or build configuration.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions