Azure Test Recorder is a comprehensive testing utility library that provides HTTP request recording and playback capabilities specifically designed for the Azure SDK for JavaScript ecosystem. It enables developers to write efficient test suites by recording live HTTP interactions during initial test runs and then replaying those interactions in subsequent test executions, eliminating the need for actual network calls and ensuring fast, deterministic test execution.
npm install @azure-tools/test-recorderimport {
Recorder,
isLiveMode,
isPlaybackMode,
isRecordMode,
assertEnvironmentVariable,
setEnvironmentVariables,
delay,
env,
relativeRecordingsPath,
testPollingOptions
} from "@azure-tools/test-recorder";For CommonJS:
const {
Recorder,
isLiveMode,
isPlaybackMode,
isRecordMode,
assertEnvironmentVariable,
setEnvironmentVariables,
delay,
env,
relativeRecordingsPath,
testPollingOptions
} = require("@azure-tools/test-recorder");import { Recorder, assertEnvironmentVariable } from "@azure-tools/test-recorder";
// Setup recorder with test context
const recorder = new Recorder(testContext);
// Start recording with environment setup
await recorder.start({
envSetupForPlayback: {
"AZURE_CLIENT_ID": "fake-client-id",
"AZURE_TENANT_ID": "fake-tenant-id"
}
});
// Configure Azure SDK clients to use recorder
const client = new ServiceClient(connectionString, recorder.configureClientOptions({}));
// Add sanitizers to clean sensitive data
await recorder.addSanitizers({
generalSanitizers: [
{ target: "secret-value", value: "sanitized" }
]
});
// Stop recording after tests
await recorder.stop();Azure Test Recorder is built around several key components:
Central recording functionality for managing test recording sessions, including session lifecycle, client configuration, and variable storage.
class Recorder {
constructor(testContext?: TestInfo);
async start(options: RecorderStartOptions): Promise<void>;
async stop(): Promise<void>;
configureClientOptions<T, U>(options: T & { additionalPolicies?: U[] }): T & { additionalPolicies?: U[] };
variable(name: string, value: string): string;
variable(name: string): string;
}
interface RecorderStartOptions {
envSetupForPlayback: Record<string, string>;
sanitizerOptions?: SanitizerOptions;
tlsValidationCert?: string;
removeCentralSanitizers?: string[];
}Comprehensive sanitization system for cleaning sensitive data from recordings, with support for multiple sanitizer types and flexible matching strategies.
interface SanitizerOptions {
generalSanitizers?: FindReplaceSanitizer[];
bodySanitizers?: FindReplaceSanitizer[];
headerSanitizers?: HeaderSanitizer[];
uriSanitizers?: FindReplaceSanitizer[];
connectionStringSanitizers?: ConnectionStringSanitizer[];
bodyKeySanitizers?: BodyKeySanitizer[];
continuationSanitizers?: ContinuationSanitizer[];
removeHeaderSanitizer?: RemoveHeaderSanitizer;
oAuthResponseSanitizer?: boolean;
uriSubscriptionIdSanitizer?: { value: string };
resetSanitizer?: boolean;
}
type FindReplaceSanitizer = RegexSanitizer | StringSanitizer;Runtime detection and environment management utilities for different test execution modes, with support for environment variable handling and mode-specific behavior.
function isLiveMode(): boolean;
function isPlaybackMode(): boolean;
function isRecordMode(): boolean;
function assertEnvironmentVariable(variable: string): string;
function setEnvironmentVariables(variables: { [key: string]: string }): void;Flexible request matching strategies for controlling how recorded requests are matched during playback, with support for custom matching logic.
interface CustomMatcherOptions {
compareBodies?: boolean;
excludedHeaders?: string[];
ignoreQueryOrdering?: boolean;
}Native integration with modern test frameworks, particularly Vitest, with support for test context extraction and session management.
type TestInfo = VitestTestContext;
interface VitestTestContext {
task: VitestTask;
}
function isVitestTestContext(test: unknown): test is VitestTestContext;Advanced functionality for modifying HTTP requests and responses during recording and playback, enabling custom data transformations and request standardization.
type Transform =
| TransformType<"ApiVersionTransform">
| TransformType<"ClientIdTransform">
| TransformType<"StorageRequestIdTransform">
| TransformType<"HeaderTransform", HeaderTransformParams>;
interface HeaderTransformParams {
key: string;
value: string;
}Utilities for managing recording file paths and relative path calculations.
function relativeRecordingsPath(): string;interface VitestTask extends VitestTaskBase {
name: string;
suite?: VitestSuite;
}
interface VitestSuite extends VitestTaskBase {
name: string;
}
interface VitestTaskBase {
name: string;
suite?: VitestSuite;
}
type RecordingState = "started" | "stopped";
type ProxyToolSanitizers =
| "GeneralRegexSanitizer" | "GeneralStringSanitizer" | "RemoveHeaderSanitizer"
| "BodyKeySanitizer" | "BodyRegexSanitizer" | "BodyStringSanitizer"
| "ContinuationSanitizer" | "HeaderRegexSanitizer" | "HeaderStringSanitizer"
| "OAuthResponseSanitizer" | "UriRegexSanitizer" | "UriStringSanitizer"
| "UriSubscriptionIdSanitizer" | "Reset";
interface BodyKeySanitizer {
/** Optional regex pattern for value replacement */
regex?: string;
/** The replacement value */
value?: string;
/** The capture group to operate upon for regex replacements */
groupForReplace?: string;
/** The JSONPath selector for targeting specific JSON keys */
jsonPath: string;
}
interface ContinuationSanitizer {
/** The header key to target for sanitization */
key: string;
/** Optional HTTP method to restrict sanitization to */
method?: string;
/** Whether to reset after the first occurrence */
resetAfterFirst: boolean;
}
type TransformType<TType extends string, TParams = undefined> = {
type: TType;
applyCondition?: ApplyCondition;
} & (TParams extends undefined ? unknown : { params: TParams });
interface ApplyCondition {
uriRegex: string;
}