A high-level API to automate Chromium
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
HTTP API testing capabilities with request/response handling, authentication, context management, and comprehensive testing utilities for REST and GraphQL APIs.
Create isolated contexts for API testing with session management, authentication, and configuration.
/**
* HTTP API testing interface
*/
interface APIRequest {
/** Create new API request context */
newContext(options?: APIRequestNewContextOptions): Promise<APIRequestContext>;
/** Send GET request */
get(url: string, options?: APIRequestGetOptions): Promise<APIResponse>;
/** Send POST request */
post(url: string, options?: APIRequestPostOptions): Promise<APIResponse>;
/** Send PUT request */
put(url: string, options?: APIRequestPutOptions): Promise<APIResponse>;
/** Send PATCH request */
patch(url: string, options?: APIRequestPatchOptions): Promise<APIResponse>;
/** Send DELETE request */
delete(url: string, options?: APIRequestDeleteOptions): Promise<APIResponse>;
/** Send HEAD request */
head(url: string, options?: APIRequestHeadOptions): Promise<APIResponse>;
}
/**
* API request context with session management and authentication
*/
interface APIRequestContext {
/** Send GET request */
get(url: string, options?: APIRequestGetOptions): Promise<APIResponse>;
/** Send POST request */
post(url: string, options?: APIRequestPostOptions): Promise<APIResponse>;
/** Send PUT request */
put(url: string, options?: APIRequestPutOptions): Promise<APIResponse>;
/** Send PATCH request */
patch(url: string, options?: APIRequestPatchOptions): Promise<APIResponse>;
/** Send DELETE request */
delete(url: string, options?: APIRequestDeleteOptions): Promise<APIResponse>;
/** Send HEAD request */
head(url: string, options?: APIRequestHeadOptions): Promise<APIResponse>;
/** Send custom HTTP request */
fetch(urlOrRequest: string | APIRequest, options?: APIRequestFetchOptions): Promise<APIResponse>;
/** Get or set storage state for authentication */
storageState(options?: StorageStateOptions): Promise<StorageState>;
/** Clean up context resources */
dispose(): Promise<void>;
}Usage Examples:
// Create API context with authentication
const apiContext = await request.newContext({
baseURL: 'https://api.example.com',
extraHTTPHeaders: {
'Authorization': 'Bearer your-token-here',
'Content-Type': 'application/json'
}
});
// Simple API requests
const response = await apiContext.get('/users');
const users = await response.json();
const createResponse = await apiContext.post('/users', {
data: {
name: 'John Doe',
email: 'john@example.com'
}
});
// Context with session management
const authContext = await request.newContext();
// Login and save session
const loginResponse = await authContext.post('/auth/login', {
data: { username: 'user', password: 'pass' }
});
// Session is automatically maintained for subsequent requests
const profileResponse = await authContext.get('/profile');
// Save authentication state
const state = await authContext.storageState();Comprehensive response handling with JSON parsing, status checking, and data extraction.
/**
* API response interface with testing-focused methods
*/
interface APIResponse {
/** Get response URL */
url(): string;
/** Get HTTP status code */
status(): number;
/** Get status text */
statusText(): string;
/** Get response headers */
headers(): { [key: string]: string; };
/** Get all headers (including multiple values) */
allHeaders(): Promise<{ [key: string]: string; }>;
/** Get headers as array */
headersArray(): Promise<{ name: string; value: string; }[]>;
/** Get single header value */
headerValue(name: string): Promise<string | null>;
/** Get multiple header values */
headerValues(name: string): Promise<string[]>;
/** Parse response as JSON */
json(): Promise<any>;
/** Get response as text */
text(): Promise<string>;
/** Get response as buffer */
body(): Promise<Buffer>;
/** Check if status indicates success (200-299) */
ok(): boolean;
/** Get response sizes */
sizes(): Promise<ResponseSizes>;
}Usage Examples:
// Basic response handling
const response = await apiContext.get('/api/data');
console.log(`Status: ${response.status()}`);
console.log(`Success: ${response.ok()}`);
if (response.ok()) {
const data = await response.json();
console.log('Data:', data);
} else {
const error = await response.text();
console.log('Error:', error);
}
// Header inspection
const headers = response.headers();
const contentType = headers['content-type'];
const rateLimit = await response.headerValue('x-rate-limit-remaining');
// Response validation
const apiResponse = await apiContext.post('/api/users', {
data: { name: 'Test User', email: 'test@example.com' }
});
if (apiResponse.status() === 201) {
const createdUser = await apiResponse.json();
console.log('Created user:', createdUser);
} else {
console.log('Failed to create user:', apiResponse.statusText());
}Common authentication patterns including basic auth, bearer tokens, and session management.
Usage Examples:
// Basic Authentication
const basicAuthContext = await request.newContext({
httpCredentials: {
username: 'admin',
password: 'secret'
}
});
// Bearer Token Authentication
const tokenContext = await request.newContext({
extraHTTPHeaders: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
}
});
// API Key Authentication
const apiKeyContext = await request.newContext({
extraHTTPHeaders: {
'X-API-Key': 'your-api-key-here'
}
});
// Session-based Authentication
const sessionContext = await request.newContext();
// Login to get session cookie
await sessionContext.post('/auth/login', {
form: {
username: 'user@example.com',
password: 'password123'
}
});
// Session cookie is automatically included in subsequent requests
const userData = await sessionContext.get('/user/profile');
// OAuth2 Flow Simulation
const oauthContext = await request.newContext();
// Step 1: Get authorization code
const authResponse = await oauthContext.post('/oauth/authorize', {
form: {
client_id: 'your-client-id',
redirect_uri: 'http://localhost:3000/callback',
response_type: 'code',
scope: 'read write'
}
});
// Step 2: Exchange code for token
const tokenResponse = await oauthContext.post('/oauth/token', {
form: {
client_id: 'your-client-id',
client_secret: 'your-client-secret',
code: 'authorization-code',
grant_type: 'authorization_code'
}
});
const { access_token } = await tokenResponse.json();
// Step 3: Use token for API requests
const protectedContext = await request.newContext({
extraHTTPHeaders: {
'Authorization': `Bearer ${access_token}`
}
});Support for various request data formats including JSON, form data, and multipart uploads.
Usage Examples:
// JSON Data
const jsonResponse = await apiContext.post('/api/users', {
data: {
name: 'John Doe',
email: 'john@example.com',
settings: {
theme: 'dark',
notifications: true
}
}
});
// Form Data (application/x-www-form-urlencoded)
const formResponse = await apiContext.post('/api/login', {
form: {
username: 'user@example.com',
password: 'secretpassword',
remember_me: 'true'
}
});
// Multipart Form Data (multipart/form-data)
const multipartResponse = await apiContext.post('/api/upload', {
multipart: {
title: 'Document Title',
description: 'File description',
file: fs.readFileSync('document.pdf')
}
});
// Raw Data
const rawResponse = await apiContext.post('/api/webhook', {
data: Buffer.from('raw binary data'),
headers: {
'Content-Type': 'application/octet-stream'
}
});
// GraphQL Queries
const graphqlResponse = await apiContext.post('/graphql', {
data: {
query: `
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
title
content
}
}
}
`,
variables: {
id: '123'
}
}
});
const graphqlData = await graphqlResponse.json();Built-in utilities for common API testing scenarios including retries, timeouts, and validation.
Usage Examples:
// Request with timeout
const response = await apiContext.get('/slow-endpoint', {
timeout: 5000 // 5 seconds
});
// Request with retries (custom implementation)
async function requestWithRetry(url: string, options: any, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await apiContext.get(url, options);
if (response.ok()) return response;
if (i === maxRetries - 1) throw new Error(`Failed after ${maxRetries} retries`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // Exponential backoff
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}
// Rate limiting handling
async function handleRateLimit(response: APIResponse) {
if (response.status() === 429) {
const retryAfter = await response.headerValue('retry-after');
if (retryAfter) {
await new Promise(resolve => setTimeout(resolve, parseInt(retryAfter) * 1000));
}
}
}
// Response validation
async function validateApiResponse(response: APIResponse, expectedSchema: any) {
if (!response.ok()) {
throw new Error(`API error: ${response.status()} ${response.statusText()}`);
}
const data = await response.json();
// Validate response structure (pseudo-code)
if (!validateSchema(data, expectedSchema)) {
throw new Error('Response does not match expected schema');
}
return data;
}interface APIRequestNewContextOptions {
/** Base URL for relative requests. */
baseURL?: string;
/** Additional HTTP headers. */
extraHTTPHeaders?: { [key: string]: string; };
/** HTTP credentials. */
httpCredentials?: { username: string; password: string; };
/** Whether to ignore HTTPS errors. */
ignoreHTTPSErrors?: boolean;
/** Network proxy settings. */
proxy?: { server: string; bypass?: string; username?: string; password?: string; };
/** Storage state to populate context with. */
storageState?: string | StorageState;
/** Request timeout in milliseconds. */
timeout?: number;
/** User agent string. */
userAgent?: string;
}
interface APIRequestGetOptions {
/** Request data. */
data?: string | Buffer | Serializable;
/** Whether to throw on non-2xx/3xx status codes. */
failOnStatusCode?: boolean;
/** Form data. */
form?: { [key: string]: string | number | boolean; };
/** Request headers. */
headers?: { [key: string]: string; };
/** Whether to ignore HTTPS errors. */
ignoreHTTPSErrors?: boolean;
/** Maximum redirects to follow. */
maxRedirects?: number;
/** Maximum retries on network errors. */
maxRetries?: number;
/** Multipart form data. */
multipart?: { [key: string]: string | number | boolean; };
/** Query parameters. */
params?: { [key: string]: string | number | boolean; };
/** Request timeout. */
timeout?: number;
}
interface APIRequestPostOptions {
/** Request data. */
data?: string | Buffer | Serializable;
/** Whether to throw on non-2xx/3xx status codes. */
failOnStatusCode?: boolean;
/** Form data. */
form?: { [key: string]: string | number | boolean; };
/** Request headers. */
headers?: { [key: string]: string; };
/** Whether to ignore HTTPS errors. */
ignoreHTTPSErrors?: boolean;
/** Maximum redirects to follow. */
maxRedirects?: number;
/** Maximum retries on network errors. */
maxRetries?: number;
/** Multipart form data. */
multipart?: { [key: string]: string | number | boolean; };
/** Query parameters. */
params?: { [key: string]: string | number | boolean; };
/** Request timeout. */
timeout?: number;
}
interface APIRequestPutOptions {
/** Request data. */
data?: string | Buffer | Serializable;
/** Whether to throw on non-2xx/3xx status codes. */
failOnStatusCode?: boolean;
/** Form data. */
form?: { [key: string]: string | number | boolean; };
/** Request headers. */
headers?: { [key: string]: string; };
/** Whether to ignore HTTPS errors. */
ignoreHTTPSErrors?: boolean;
/** Maximum redirects to follow. */
maxRedirects?: number;
/** Maximum retries on network errors. */
maxRetries?: number;
/** Multipart form data. */
multipart?: { [key: string]: string | number | boolean; };
/** Query parameters. */
params?: { [key: string]: string | number | boolean; };
/** Request timeout. */
timeout?: number;
}
interface APIRequestDeleteOptions {
/** Request data. */
data?: string | Buffer | Serializable;
/** Whether to throw on non-2xx/3xx status codes. */
failOnStatusCode?: boolean;
/** Form data. */
form?: { [key: string]: string | number | boolean; };
/** Request headers. */
headers?: { [key: string]: string; };
/** Whether to ignore HTTPS errors. */
ignoreHTTPSErrors?: boolean;
/** Maximum redirects to follow. */
maxRedirects?: number;
/** Maximum retries on network errors. */
maxRetries?: number;
/** Multipart form data. */
multipart?: { [key: string]: string | number | boolean; };
/** Query parameters. */
params?: { [key: string]: string | number | boolean; };
/** Request timeout. */
timeout?: number;
}
interface StorageState {
/** Cookies to set. */
cookies: Array<{
name: string;
value: string;
domain: string;
path: string;
expires: number;
httpOnly: boolean;
secure: boolean;
sameSite: 'Strict' | 'Lax' | 'None';
}>;
/** Local storage entries to set. */
origins: Array<{
origin: string;
localStorage: Array<{
name: string;
value: string;
}>;
}>;
}
type Serializable = any;API testing can be integrated with browser automation for end-to-end testing scenarios.
Usage Examples:
// Share authentication between browser and API contexts
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
// Login through browser
await page.goto('https://example.com/login');
await page.fill('[name="email"]', 'user@example.com');
await page.fill('[name="password"]', 'password123');
await page.click('button[type="submit"]');
// Extract authentication state
const storageState = await context.storageState();
// Use authentication state for API testing
const apiContext = await request.newContext({
baseURL: 'https://api.example.com',
storageState
});
// API requests now use the same authentication as browser
const apiResponse = await apiContext.get('/user/profile');
const userData = await apiResponse.json();
// Verify UI reflects API data
await page.goto('https://example.com/profile');
const displayedName = await page.textContent('.user-name');
console.assert(displayedName === userData.name);Usage Examples:
try {
const response = await apiContext.get('/api/data');
if (!response.ok()) {
const errorBody = await response.text();
throw new Error(`API Error ${response.status()}: ${errorBody}`);
}
const data = await response.json();
return data;
} catch (error) {
if (error.message.includes('timeout')) {
console.log('Request timed out, retrying...');
// Implement retry logic
} else if (error.message.includes('ECONNREFUSED')) {
console.log('Server is not available');
} else {
console.log('API request failed:', error.message);
}
throw error;
}Install with Tessl CLI
npx tessl i tessl/npm-playwright-chromium