159 lines
4.8 KiB
TypeScript
159 lines
4.8 KiB
TypeScript
import { describe, test, expect, beforeEach, beforeAll, afterAll } from 'bun:test';
|
|
import { HttpClient, HttpError, ProxyManager } from '../src/index';
|
|
import type { ProxyInfo } from '../src/types';
|
|
import { MockServer } from './mock-server';
|
|
|
|
// Global mock server instance
|
|
let mockServer: MockServer;
|
|
let mockServerBaseUrl: string;
|
|
|
|
beforeAll(async () => {
|
|
// Start mock server for all tests
|
|
mockServer = new MockServer();
|
|
await mockServer.start();
|
|
mockServerBaseUrl = mockServer.getBaseUrl();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
// Stop mock server
|
|
await mockServer.stop();
|
|
});
|
|
|
|
describe('HttpClient', () => {
|
|
let client: HttpClient;
|
|
|
|
beforeEach(() => {
|
|
client = new HttpClient();
|
|
});
|
|
|
|
describe('Basic functionality', () => {
|
|
test('should create client with default config', () => {
|
|
expect(client).toBeInstanceOf(HttpClient);
|
|
});
|
|
|
|
test('should make GET request', async () => {
|
|
const response = await client.get(`${mockServerBaseUrl}/`);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.data).toHaveProperty('url');
|
|
expect(response.data).toHaveProperty('method', 'GET');
|
|
});
|
|
|
|
test('should make POST request with body', async () => {
|
|
const testData = {
|
|
title: 'Test Post',
|
|
body: 'Test body',
|
|
userId: 1,
|
|
};
|
|
|
|
const response = await client.post(`${mockServerBaseUrl}/post`, testData);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.data).toHaveProperty('data');
|
|
expect(response.data.data).toEqual(testData);
|
|
});
|
|
|
|
test('should handle custom headers', async () => {
|
|
const customHeaders = {
|
|
'X-Custom-Header': 'test-value',
|
|
'User-Agent': 'StockBot-HTTP-Client/1.0'
|
|
};
|
|
|
|
const response = await client.get(`${mockServerBaseUrl}/headers`, {
|
|
headers: customHeaders
|
|
});
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.data.headers).toHaveProperty('x-custom-header', 'test-value');
|
|
expect(response.data.headers).toHaveProperty('user-agent', 'StockBot-HTTP-Client/1.0');
|
|
});
|
|
|
|
test('should handle timeout', async () => {
|
|
const clientWithTimeout = new HttpClient({ timeout: 1 }); // 1ms timeout
|
|
|
|
await expect(
|
|
clientWithTimeout.get('https://httpbin.org/delay/1')
|
|
).rejects.toThrow();
|
|
});
|
|
});
|
|
describe('Error handling', () => {
|
|
test('should handle HTTP errors', async () => {
|
|
await expect(
|
|
client.get(`${mockServerBaseUrl}/status/404`)
|
|
).rejects.toThrow(HttpError);
|
|
});
|
|
|
|
test('should handle network errors gracefully', async () => {
|
|
await expect(
|
|
client.get('https://nonexistent-domain-that-will-fail-12345.test')
|
|
).rejects.toThrow();
|
|
});
|
|
|
|
test('should handle invalid URLs', async () => {
|
|
await expect(
|
|
client.get('not:/a:valid/url')
|
|
).rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('HTTP methods', () => {
|
|
test('should make PUT request', async () => {
|
|
const testData = { id: 1, name: 'Updated' };
|
|
const response = await client.put(`${mockServerBaseUrl}/post`, testData);
|
|
expect(response.status).toBe(200);
|
|
});
|
|
|
|
test('should make DELETE request', async () => {
|
|
const response = await client.del(`${mockServerBaseUrl}/`);
|
|
expect(response.status).toBe(200);
|
|
expect(response.data.method).toBe('DELETE');
|
|
});
|
|
|
|
test('should make PATCH request', async () => {
|
|
const testData = { name: 'Patched' };
|
|
const response = await client.patch(`${mockServerBaseUrl}/post`, testData);
|
|
expect(response.status).toBe(200);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('ProxyManager', () => {
|
|
test('should determine when to use Bun fetch', () => {
|
|
const httpProxy: ProxyInfo = {
|
|
protocol: 'http',
|
|
host: 'proxy.example.com',
|
|
port: 8080
|
|
};
|
|
|
|
const socksProxy: ProxyInfo = {
|
|
protocol: 'socks5',
|
|
host: 'proxy.example.com',
|
|
port: 1080
|
|
};
|
|
|
|
expect(ProxyManager.shouldUseBunFetch(httpProxy)).toBe(true);
|
|
expect(ProxyManager.shouldUseBunFetch(socksProxy)).toBe(false);
|
|
});
|
|
|
|
test('should create proxy URL for Bun fetch', () => {
|
|
const proxy: ProxyInfo = {
|
|
protocol: 'http',
|
|
host: 'proxy.example.com',
|
|
port: 8080,
|
|
username: 'user',
|
|
password: 'pass' };
|
|
|
|
const proxyUrl = ProxyManager.createProxyUrl(proxy);
|
|
expect(proxyUrl).toBe('http://user:pass@proxy.example.com:8080');
|
|
});
|
|
|
|
test('should create proxy URL without credentials', () => {
|
|
const proxy: ProxyInfo = {
|
|
protocol: 'https',
|
|
host: 'proxy.example.com',
|
|
port: 8080 };
|
|
|
|
const proxyUrl = ProxyManager.createProxyUrl(proxy);
|
|
expect(proxyUrl).toBe('https://proxy.example.com:8080');
|
|
});
|
|
});
|