Aegir provides comprehensive testing utilities including enhanced Chai assertions, HTTP echo server, fixture loading, port management, path resolution, and environment detection.
Pre-configured Chai instance with useful testing plugins for comprehensive assertion capabilities.
// Import enhanced Chai
import { expect, assert, chai } from 'aegir/chai';
// Available exports
export const expect: Chai.ExpectStatic;
export const assert: Chai.AssertStatic;
export const chai: Chai.ChaiStatic;
// Included plugins (automatically configured):
export const chaiAsPromised: any; // Promise assertion support
export const chaiParentheses: any; // Parentheses syntax support
export const chaiSubset: any; // Object subset matching
export const chaiBites: any; // Binary data assertions
export const chaiString: any; // String assertion extensionsUsage Examples:
import { expect } from 'aegir/chai';
// Standard Chai assertions
expect(true).to.be.true();
expect('hello').to.be.a('string');
expect([1, 2, 3]).to.have.length(3);
// Promise assertions (chai-as-promised)
await expect(Promise.resolve('success')).to.eventually.equal('success');
await expect(Promise.reject('error')).to.be.rejected;
// String assertions (chai-string)
expect('hello world').to.startWith('hello');
expect('test@example.com').to.be.an.email();
// Object subset matching (chai-subset)
expect({ a: 1, b: 2, c: 3 }).to.containSubset({ a: 1, b: 2 });
// Binary data assertions (chai-bites)
const buffer = Buffer.from('hello');
expect(buffer).to.have.bytes([104, 101, 108, 108, 111]);HTTP server for testing HTTP requests with configurable endpoints and responses.
/**
* HTTP echo server for testing purposes
*/
export default class EchoServer {
/**
* Create echo server instance
* @param options - Server configuration options
*/
constructor(options?: {
port?: number; // Server port (default: 3000)
host?: string; // Server host (default: '127.0.0.1')
findPort?: boolean; // Auto-find available port (default: true)
});
/** Start the server */
start(): Promise<EchoServer>;
/** Stop the server */
stop(): Promise<EchoServer>;
/** Server port (available after start()) */
port: number;
/** Server host */
host: string;
/** Server started status */
started: boolean;
}Usage Examples:
import EchoServer from 'aegir/echo-server';
// Basic usage
const server = new EchoServer();
await server.start();
console.log(`Server running on http://${server.host}:${server.port}`);
// Test endpoints
const response = await fetch(`http://${server.host}:${server.port}/echo`, {
method: 'POST',
body: JSON.stringify({ test: 'data' }),
headers: { 'Content-Type': 'application/json' }
});
const echoed = await response.json();
await server.stop();Available Endpoints:
# Echo request body
POST/GET /echo
# Returns: complete request object
# Echo query parameters
GET /echo/query?key=value
# Returns: { key: "value" }
# Echo request headers
GET /echo/headers
# Returns: request headers object
# Redirect endpoint
GET /redirect?to=<url>
# Returns: 302 redirect to specified URL
# Download endpoint
GET /download?data=<string>
# Returns: binary data as downloadCross-platform fixture file loading for tests (works in Node.js and browsers).
/**
* Load fixture files for testing
* @param filePath - Path to fixture file relative to module root
* @param module - Optional module name for cross-module fixtures
* @returns File contents as Uint8Array
*/
export default function loadFixtures(filePath: string, module?: string): Uint8Array;Usage Examples:
import loadFixtures from 'aegir/fixtures';
// Load fixture from current module
const fixture = loadFixtures('test/fixtures/sample.json');
const data = JSON.parse(new TextDecoder().decode(fixture));
// Load fixture from different module (for shared test suites)
const sharedFixture = loadFixtures('test/fixtures/data.json', 'shared-test-module');
// Convert to string
const textFixture = loadFixtures('test/fixtures/text-file.txt');
const content = new TextDecoder().decode(textFixture);The loader searches for files in multiple locations:
Utility for finding available ports for test servers and development tools.
/**
* Find available port for server binding
* @param port - Preferred port number (default: 3000)
* @param host - Host address (default: '127.0.0.1')
* @returns Promise resolving to available port number
*/
export default function getPort(port?: number, host?: string): Promise<number>;Usage Examples:
import getPort from 'aegir/get-port';
// Find available port starting from 3000
const port = await getPort(3000);
console.log(`Using port: ${port}`);
// Find any available port
const anyPort = await getPort();
// Specific host
const port = await getPort(8080, '0.0.0.0');
// Use in test setup
const testPort = await getPort(9000, '127.0.0.1');
const server = createServer().listen(testPort);Cross-context path resolution utility for loading resources across different module contexts.
/**
* Resolve file paths across different module contexts
* @param filePath - File path to resolve
* @param module - Optional module context for resolution
* @returns Absolute path to the resolved file
* @throws Error if file cannot be found
*/
export default function resolve(filePath: string, module?: string): string;Usage Examples:
import resolve from 'aegir/resolve';
// Resolve file in current project
const configPath = resolve('config/test.json');
// Resolve file in specific module context
const sharedPath = resolve('templates/base.html', 'shared-templates');
// Use resolved path
import fs from 'fs';
const config = JSON.parse(fs.readFileSync(resolve('config/app.json'), 'utf8'));
// Browser version available as 'aegir/resolve' (different implementation)Resolution Strategy:
Environment detection utilities for cross-platform test code using wherearewe package.
// Re-exports all from 'wherearewe' package
export * from 'wherearewe';
// Common environment detection constants:
export const isNode: boolean; // Node.js environment
export const isBrowser: boolean; // Browser environment
export const isWebWorker: boolean; // Web Worker environment
export const isElectron: boolean; // Electron environment
export const isElectronMain: boolean; // Electron main process
export const isElectronRenderer: boolean; // Electron renderer process
export const isReactNative: boolean; // React Native environment
// ... and other environment flags from whereareweUsage Examples:
import { isNode, isBrowser, isWebWorker, isElectron } from 'aegir/env';
// Platform-specific code
if (isNode) {
// Use Node.js APIs
const fs = await import('fs');
const data = fs.readFileSync('config.json');
}
if (isBrowser) {
// Use browser APIs
const data = localStorage.getItem('config');
}
if (isWebWorker) {
// Web Worker specific code
self.addEventListener('message', handler);
}
if (isElectron) {
// Electron-specific functionality
const { ipcRenderer } = await import('electron');
}
// Test environment setup
describe('Cross-platform tests', () => {
it('should work in Node.js', function() {
if (!isNode) this.skip();
// Node.js specific test
});
it('should work in browsers', function() {
if (!isBrowser) this.skip();
// Browser specific test
});
});Combining utilities for comprehensive test setups:
import { expect } from 'aegir/chai';
import EchoServer from 'aegir/echo-server';
import loadFixtures from 'aegir/fixtures';
import getPort from 'aegir/get-port';
import { isNode, isBrowser } from 'aegir/env';
describe('HTTP Client Tests', () => {
let server;
let serverUrl;
before(async () => {
// Setup test server
const port = await getPort(9000);
server = new EchoServer({ port, findPort: false });
await server.start();
serverUrl = `http://127.0.0.1:${port}`;
});
after(async () => {
// Cleanup
if (server) {
await server.stop();
}
});
it('should echo request data', async () => {
const testData = { message: 'hello' };
const response = await fetch(`${serverUrl}/echo`, {
method: 'POST',
body: JSON.stringify(testData),
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
expect(result.body).to.deep.equal(testData);
});
it('should load fixture data', () => {
if (!isNode) return; // Node.js only test
const fixture = loadFixtures('test/fixtures/sample.json');
const data = JSON.parse(new TextDecoder().decode(fixture));
expect(data).to.be.an('object');
expect(data).to.have.property('version');
});
});