ai
Version:
AI SDK by Vercel - The AI Toolkit for TypeScript and JavaScript
186 lines (167 loc) • 5.07 kB
text/typescript
import { createTestServer } from '@ai-sdk/test-server/with-vitest';
import { UIMessageChunk } from '../ui-message-stream/ui-message-chunks';
import {
HttpChatTransport,
HttpChatTransportInitOptions,
} from './http-chat-transport';
import { UIMessage } from './ui-messages';
import { describe, it, expect } from 'vitest';
class MockHttpChatTransport extends HttpChatTransport<UIMessage> {
constructor(options: HttpChatTransportInitOptions<UIMessage> = {}) {
super(options);
}
protected processResponseStream(
stream: ReadableStream<Uint8Array<ArrayBufferLike>>,
): ReadableStream<UIMessageChunk> {
return new ReadableStream();
}
}
const server = createTestServer({
'http://localhost/api/chat': {},
});
describe('HttpChatTransport', () => {
describe('body', () => {
it('should include the body in the request by default', async () => {
server.urls['http://localhost/api/chat'].response = {
type: 'stream-chunks',
chunks: [],
};
const transport = new MockHttpChatTransport({
api: 'http://localhost/api/chat',
body: { someData: true },
});
await transport.sendMessages({
chatId: 'c123',
messageId: 'm123',
trigger: 'submit-message',
messages: [
{
id: 'm123',
role: 'user',
parts: [{ text: 'Hello, world!', type: 'text' }],
},
],
abortSignal: new AbortController().signal,
});
expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
{
"id": "c123",
"messageId": "m123",
"messages": [
{
"id": "m123",
"parts": [
{
"text": "Hello, world!",
"type": "text",
},
],
"role": "user",
},
],
"someData": true,
"trigger": "submit-message",
}
`);
});
it('should include the body in the request when a function is provided', async () => {
server.urls['http://localhost/api/chat'].response = {
type: 'stream-chunks',
chunks: [],
};
const transport = new MockHttpChatTransport({
api: 'http://localhost/api/chat',
body: () => ({ someData: true }),
});
await transport.sendMessages({
chatId: 'c123',
messageId: 'm123',
trigger: 'submit-message',
messages: [
{
id: 'm123',
role: 'user',
parts: [{ text: 'Hello, world!', type: 'text' }],
},
],
abortSignal: new AbortController().signal,
});
expect(await server.calls[0].requestBodyJson).toMatchInlineSnapshot(`
{
"id": "c123",
"messageId": "m123",
"messages": [
{
"id": "m123",
"parts": [
{
"text": "Hello, world!",
"type": "text",
},
],
"role": "user",
},
],
"someData": true,
"trigger": "submit-message",
}
`);
});
});
describe('headers', () => {
it('should include headers in the request by default', async () => {
server.urls['http://localhost/api/chat'].response = {
type: 'stream-chunks',
chunks: [],
};
const transport = new MockHttpChatTransport({
api: 'http://localhost/api/chat',
headers: { 'X-Test-Header': 'test-value' },
});
await transport.sendMessages({
chatId: 'c123',
messageId: 'm123',
trigger: 'submit-message',
messages: [
{
id: 'm123',
role: 'user',
parts: [{ text: 'Hello, world!', type: 'text' }],
},
],
abortSignal: new AbortController().signal,
});
expect(server.calls[0].requestHeaders['x-test-header']).toBe(
'test-value',
);
expect(server.calls[0].requestUserAgent).toContain('ai-sdk/');
});
it('should include headers in the request when a function is provided', async () => {
server.urls['http://localhost/api/chat'].response = {
type: 'stream-chunks',
chunks: [],
};
const transport = new MockHttpChatTransport({
api: 'http://localhost/api/chat',
headers: () => ({ 'X-Test-Header': 'test-value-fn' }),
});
await transport.sendMessages({
chatId: 'c123',
messageId: 'm123',
trigger: 'submit-message',
messages: [
{
id: 'm123',
role: 'user',
parts: [{ text: 'Hello, world!', type: 'text' }],
},
],
abortSignal: new AbortController().signal,
});
expect(server.calls[0].requestHeaders['x-test-header']).toBe(
'test-value-fn',
);
expect(server.calls[0].requestUserAgent).toContain('ai-sdk/');
});
});
});