dify/sdks/nodejs-client/tests/http.integration.test.ts
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

138 lines
4.0 KiB
TypeScript

import type { AddressInfo } from 'node:net'
import { createServer } from 'node:http'
import { Readable } from 'node:stream'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { HttpClient } from '../src/http/client'
const readBody = async (stream: NodeJS.ReadableStream): Promise<Buffer> => {
const chunks: Buffer[] = []
for await (const chunk of stream) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
}
return Buffer.concat(chunks)
}
describe('HttpClient integration', () => {
const requests: Array<{
url: string
method: string
headers: Record<string, string | string[] | undefined>
body: Buffer
}> = []
const server = createServer((req, res) => {
void (async () => {
const body = await readBody(req)
requests.push({
url: req.url ?? '',
method: req.method ?? '',
headers: req.headers,
body,
})
if (req.url?.startsWith('/json')) {
res.writeHead(200, { 'content-type': 'application/json', 'x-request-id': 'req-json' })
res.end(JSON.stringify({ ok: true }))
return
}
if (req.url === '/stream') {
res.writeHead(200, { 'content-type': 'text/event-stream' })
res.end('data: {"answer":"hello"}\n\ndata: {"delta":" world"}\n\n')
return
}
if (req.url === '/bytes') {
res.writeHead(200, { 'content-type': 'application/octet-stream' })
res.end(Buffer.from([1, 2, 3, 4]))
return
}
if (req.url === '/upload-stream') {
res.writeHead(200, { 'content-type': 'application/json' })
res.end(JSON.stringify({ received: body.toString('utf8') }))
return
}
res.writeHead(404, { 'content-type': 'application/json' })
res.end(JSON.stringify({ message: 'not found' }))
})()
})
let client: HttpClient
beforeAll(async () => {
await new Promise<void>((resolve) => {
server.listen(0, '127.0.0.1', () => resolve())
})
const address = server.address() as AddressInfo
client = new HttpClient({
apiKey: 'test-key',
baseUrl: `http://127.0.0.1:${address.port}`,
maxRetries: 0,
retryDelay: 0,
})
})
afterAll(async () => {
await new Promise<void>((resolve, reject) => {
server.close((error) => {
if (error) {
reject(error)
return
}
resolve()
})
})
})
it('uses real fetch for query serialization and json bodies', async () => {
const response = await client.request({
method: 'POST',
path: '/json',
query: { tag_ids: ['a', 'b'], limit: 2 },
data: { user: 'u' },
})
expect(response.requestId).toBe('req-json')
expect(response.data).toEqual({ ok: true })
expect(requests.at(-1)).toMatchObject({
url: '/json?tag_ids=a&tag_ids=b&limit=2',
method: 'POST',
})
expect(requests.at(-1)?.headers.authorization).toBe('Bearer test-key')
expect(requests.at(-1)?.headers['content-type']).toBe('application/json')
expect(requests.at(-1)?.body.toString('utf8')).toBe(JSON.stringify({ user: 'u' }))
})
it('supports streaming request bodies with duplex fetch', async () => {
const response = await client.request<{ received: string }>({
method: 'POST',
path: '/upload-stream',
data: Readable.from(['hello ', 'world']),
})
expect(response.data).toEqual({ received: 'hello world' })
expect(requests.at(-1)?.body.toString('utf8')).toBe('hello world')
})
it('parses real sse responses into text', async () => {
const stream = await client.requestStream({
method: 'GET',
path: '/stream',
})
await expect(stream.toText()).resolves.toBe('hello world')
})
it('parses real byte responses into buffers', async () => {
const response = await client.request<Buffer, 'bytes'>({
method: 'GET',
path: '/bytes',
responseType: 'bytes',
})
expect(Array.from(response.data.values())).toEqual([1, 2, 3, 4])
})
})