Advertisement

← vibesdk

sdk/test/client-build.test.ts

2.4 KB Download file
import { describe, expect, it } from 'bun:test';
import { VibeClient } from '../src/client';
import type { Credentials } from '../src/types';

import { createFetchMock, streamFromString } from './fakes';

describe('VibeClient.build', () => {
	it('uses apiKey exchange then streams NDJSON start+chunks', async () => {
		const credentials: Credentials = {
			providers: { openai: { apiKey: 'sk-test' } },
		};

		const { fetchFn, calls } = createFetchMock(async ({ url, init }) => {
			if (url.endsWith('/api/auth/exchange-api-key')) {
				return new Response(
					JSON.stringify({
						success: true,
						data: {
							accessToken: 'ACCESS_TOKEN',
							expiresIn: 900,
							expiresAt: new Date(Date.now() + 900_000).toISOString(),
							apiKeyId: 'k_123',
							user: { id: 'u_1' },
						},
					}),
					{ status: 200, headers: { 'Content-Type': 'application/json' } },
				);
			}

			if (url.endsWith('/api/agent')) {
				const headers = init?.headers;
				const auth =
					headers instanceof Headers
						? headers.get('Authorization')
						: (headers as Record<string, string> | undefined)?.Authorization;
				expect(auth).toBe('Bearer ACCESS_TOKEN');

				const parsedBody = JSON.parse(String(init?.body ?? '{}')) as Record<string, unknown>;
				expect(parsedBody.query).toBe('Hello');
				expect(parsedBody.credentials).toEqual(credentials);

				const ndjson =
					JSON.stringify({ agentId: 'a1', websocketUrl: 'ws://x/ws', behaviorType: 'phasic', projectType: 'app' }) +
					'\n' +
					JSON.stringify({ chunk: 'blueprint chunk' }) +
					'\n';

				return new Response(streamFromString(ndjson), {
					status: 200,
					headers: { 'Content-Type': 'text/event-stream' },
				});
			}

			return new Response('not found', { status: 404 });
		});

		const client = new VibeClient({ baseUrl: 'http://localhost:5173', apiKey: 'API_KEY', fetchFn });

		let blueprint = '';
		const session = await client.build('Hello', {
			autoConnect: false,
			autoGenerate: false,
			credentials,
			onBlueprintChunk: (c) => {
				blueprint += c;
			},
		});

		expect(session.agentId).toBe('a1');
		expect(session.websocketUrl).toBe('ws://x/ws');
		expect(blueprint).toBe('blueprint chunk');

		// sanity: exchange then agent
		expect(calls[0]?.url.endsWith('/api/auth/exchange-api-key')).toBe(true);
		expect(calls[1]?.url.endsWith('/api/agent')).toBe(true);
	});
});