-
Notifications
You must be signed in to change notification settings - Fork 13
Description
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
loadFixtureimplementation 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
asyncreturningPromise<Uint8Array> - Replace
fs.readFileSyncwithfetch(url).then(b => b.arrayBuffer()) - Remove
fsandpathimports - 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.tstests_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
loadFixturefunction (lines ~17-31) - Import
loadFixturefrom 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:browserVerify:
- ✅ 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:
?urlimports work in both environments- Node: Returns file path that
fetch()can load - Browser: Returns URL that
fetch()can load
- Node: Returns file path that
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
-
loadFixtureupdated intests_integ/__fixtures__/test-helpers.ts- Function is async returning
Promise<Uint8Array> - Uses
fetch()instead offs.readFileSync - No Node.js-specific imports (
fs,path)
- Function is async returning
- Test files updated with
awaitkeyword-
tests_integ/agent.test.ts -
tests_integ/bedrock.test.ts
-
- Browser-specific implementation removed
- Duplicate
loadFixtureremoved fromtests_integ/browser/agent.browser.test.ts - Import added from shared test helpers
- Duplicate
- 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, addawait)tests_integ/bedrock.test.ts(~4 lines changed, addawait)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.