# E2E Tests for FBI Proxy
This directory contains end-to-end tests for both the Rust and TypeScript implementations of FBI Proxy using Vitest.
## Test Structure
### Test Files
- **`proxy-core.test.ts`** - Tests core proxy functionality including:
- Rule 1: Number host to local port routing (`3000` → `localhost:3000`)
- Rule 1.2: Host--port syntax (`localhost--3000` → `localhost:3000`)
- Rule 2: Default host routing (`localhost` → `localhost:80`)
- Rule 3: Subdomain hoisting (`api.service` → `service:80`)
- HTTP methods support (GET, POST, PUT, DELETE, PATCH)
- Header preservation and processing
- Error handling for unreachable hosts
- **`domain-filtering.test.ts`** - Tests domain filtering functionality:
- Acceptance of requests matching domain filter
- Rejection of requests not matching domain filter
- Edge cases (ports, subdomains, malformed hosts)
- **`implementation-comparison.test.ts`** - Compares Rust vs TypeScript implementations:
- Core routing compatibility
- HTTP method support consistency
- Error handling consistency
- Performance characteristics
- Header handling consistency
- **`websocket.test.ts`** - Tests WebSocket functionality:
- WebSocket connection establishment through proxy
- Bidirectional message forwarding
- Multiple concurrent connections
- Error handling for failed connections
- Different host pattern support
### Helper Files
- **`helpers/proxy-client.ts`** - Test client for making HTTP requests through the proxy
- **`helpers/test-server.ts`** - Manager for creating and controlling test HTTP servers
- **`setup/global-setup.ts`** - Global test environment setup
- **`setup/global-teardown.ts`** - Global test environment cleanup
- **`types.d.ts`** - TypeScript type definitions for global test variables
## Running Tests
### Prerequisites
1. Make sure you have both Rust and Node.js/Bun installed
2. Install dependencies: `bun install`
3. Build the Rust binary: `cargo build --release`
### Test Commands
```bash
# Run all E2E tests once
bun run test:e2e
# Run E2E tests in watch mode
bun run test:e2e:watch
# Run all tests (including E2E)
bun run test
# Run tests with UI
bun run test:ui
# Run tests with coverage
bun run test:coverage
```
## Test Environment
The tests automatically:
1. **Start a Rust proxy server** on a random available port
2. **Start test HTTP servers** on ports 3000, 8080, and others as needed
3. **Start a WebSocket test server** on port 3001 for WebSocket tests
4. **Create domain-filtered proxy instances** for domain filtering tests
5. **Start TypeScript proxy server** for implementation comparison tests
All servers are automatically cleaned up after tests complete.
## Test Coverage
The tests cover:
### Core Functionality
- ✅ All host parsing rules (numeric, host--port, subdomain hoisting)
- ✅ HTTP method support (GET, POST, PUT, DELETE, PATCH)
- ✅ Header preservation and modification
- ✅ Error handling for unreachable targets
- ✅ Content handling (JSON, large bodies)
### Advanced Features
- ✅ Domain filtering (acceptance and rejection)
- ✅ WebSocket proxying and message forwarding
- ✅ Multiple concurrent connections
- ✅ Performance under load
### Implementation Compatibility
- ✅ Rust vs TypeScript routing consistency
- ✅ Error handling parity
- ✅ Header processing compatibility
- ✅ Performance characteristics comparison
## Architecture
The test suite uses:
- **Vitest** as the test runner for its speed and modern features
- **Global setup/teardown** to manage proxy and test servers
- **Helper classes** to abstract common testing patterns
- **Concurrent test execution** for faster test runs
- **Automatic port allocation** to avoid conflicts
- **Process cleanup** to ensure clean test environments
## Writing New Tests
When adding new tests:
1. Use the `ProxyTestClient` helper for HTTP requests
2. Use the `TestServerManager` for creating mock servers
3. Follow the existing pattern of beforeAll/afterAll for setup
4. Test both success and error cases
5. Consider testing both Rust and TypeScript implementations for compatibility
Example:
```typescript
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { ProxyTestClient } from "./helpers/proxy-client";
describe("My New Feature", () => {
let client: ProxyTestClient;
beforeAll(() => {
client = new ProxyTestClient();
});
it("should handle my feature", async () => {
const response = await client.makeRequest({
host: "3000",
path: "/my-feature",
});
expect(response.status).toBe(200);
});
});
```