diff --git a/eslint.config.js b/eslint.config.js index 3d6ea0f0..23fbb902 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -46,6 +46,7 @@ export default [ window: 'readonly', document: 'readonly', navigator: 'readonly', + fetch: 'readonly', }, }, plugins: { diff --git a/tests_integ/__fixtures__/test-helpers.ts b/tests_integ/__fixtures__/test-helpers.ts index 7311bf50..87770aa9 100644 --- a/tests_integ/__fixtures__/test-helpers.ts +++ b/tests_integ/__fixtures__/test-helpers.ts @@ -1,17 +1,34 @@ -import { readFileSync } from 'node:fs' -import { join } from 'node:path' - /** * Helper to load fixture files from Vite URL imports. - * Vite ?url imports return paths like '/tests_integ/__resources__/file.png' in test environment. + * Works in both Node.js and browser environments with a unified async API. * * @param url - The URL from a Vite ?url import - * @returns The file contents as a Uint8Array + * @returns Promise resolving to the file contents as a Uint8Array + * + * @remarks + * Implementation uses environment-specific approaches: + * - **Browser**: Uses fetch() with HTTP URLs from Vite dev server + * - **Node.js**: Uses fs.readFile since Node's fetch() doesn't support file:// protocol + * + * Note: Node.js's native fetch() (v18+) explicitly does not support file:// URLs. + * This limitation is documented in the Node.js fetch implementation and returns + * "not implemented... yet..." error. The hybrid approach is necessary until Node.js + * adds file:// protocol support to fetch(). */ -export const loadFixture = (url: string): Uint8Array => { +export const loadFixture = async (url: string): Promise => { + // Browser environment: Vite serves files over HTTP during development + if (url.startsWith('http')) { + const arrayBuffer = await fetch(url).then((b) => b.arrayBuffer()) + return new Uint8Array(arrayBuffer) + } + + // Node.js environment: Use file system since fetch() doesn't support file:// protocol + const { readFile } = await import('node:fs/promises') + const { join } = await import('node:path') const relativePath = url.startsWith('/') ? url.slice(1) : url const filePath = join(process.cwd(), relativePath) - return new Uint8Array(readFileSync(filePath)) + const buffer = await readFile(filePath) + return new Uint8Array(buffer) } /** diff --git a/tests_integ/agent.test.ts b/tests_integ/agent.test.ts index b4606597..c9292b86 100644 --- a/tests_integ/agent.test.ts +++ b/tests_integ/agent.test.ts @@ -117,7 +117,7 @@ describe.each(providers)('Agent with $name', ({ name, skip, createModel }) => { }) // Create image block - const imageBytes = loadFixture(yellowPngUrl) + const imageBytes = await loadFixture(yellowPngUrl) const imageBlock = new ImageBlock({ format: 'png', source: { bytes: imageBytes }, diff --git a/tests_integ/bedrock.test.ts b/tests_integ/bedrock.test.ts index 1c91f535..66189360 100644 --- a/tests_integ/bedrock.test.ts +++ b/tests_integ/bedrock.test.ts @@ -376,7 +376,7 @@ describe.skipIf(!(await shouldRunTests()))('BedrockModel Integration Tests', () }) // PDF document - const pdfBytes = loadFixture(letterPdfUrl) + const pdfBytes = await loadFixture(letterPdfUrl) const pdfDocBlock = new DocumentBlock({ name: 'letter', format: 'pdf', diff --git a/tests_integ/browser/agent.browser.test.ts b/tests_integ/browser/agent.browser.test.ts index 675c2b5a..804158ba 100644 --- a/tests_integ/browser/agent.browser.test.ts +++ b/tests_integ/browser/agent.browser.test.ts @@ -8,30 +8,11 @@ import { httpRequest } from '@strands-agents/sdk/vended_tools/http_request' import { z } from 'zod' import { collectGenerator } from '../../src/__fixtures__/model-test-helpers.js' +import { loadFixture } from '../__fixtures__/test-helpers.js' // Import fixtures import yellowPngUrl from '../__resources__/yellow.png?url' -// Environment detection for browser vs Node.js -const isNode = typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node - -// Browser-compatible fixture loader -const loadFixture = async (url: string): Promise => { - if (isNode) { - // In Node.js, use synchronous file reading - const { readFileSync } = await import('node:fs') - const { join } = await import('node:path') - const relativePath = url.startsWith('/') ? url.slice(1) : url - const filePath = join(process.cwd(), relativePath) - return new Uint8Array(readFileSync(filePath)) - } else { - // In browser, use fetch API - const response = await globalThis.fetch(url) - const arrayBuffer = await response.arrayBuffer() - return new Uint8Array(arrayBuffer) - } -} - // Calculator tool for testing const calculatorTool = tool({ name: 'calculator', diff --git a/vitest.config.ts b/vitest.config.ts index 8028acab..4bc30454 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -31,6 +31,11 @@ const getOpenAIAPIKey: BrowserCommand<[], string | undefined> = async ({ } export default defineConfig({ + server: { + fs: { + allow: ['.'], + }, + }, test: { projects: [ {