Flexible request matching strategies for controlling how recorded requests are matched during playback, with support for custom matching logic and various comparison options for Azure SDK testing scenarios.
Configuration interface for customizing how requests are matched during playback, providing fine-grained control over comparison behavior.
/**
* Configuration options for custom request matching during playback
*/
interface CustomMatcherOptions {
/** Whether to compare request/response bodies during matching */
compareBodies?: boolean;
/** List of header names to exclude from matching */
excludedHeaders?: string[];
/** Whether to ignore query parameter ordering when matching URLs */
ignoreQueryOrdering?: boolean;
}Usage Examples:
import { Recorder } from "@azure-tools/test-recorder";
// Basic custom matcher ignoring certain headers
const matcherOptions: CustomMatcherOptions = {
excludedHeaders: ["x-ms-client-request-id", "user-agent", "date"]
};
await recorder.setMatcher("CustomDefaultMatcher", matcherOptions);
// Matcher that compares bodies and ignores query order
const strictMatcherOptions: CustomMatcherOptions = {
compareBodies: true,
ignoreQueryOrdering: true,
excludedHeaders: ["authorization", "x-ms-date"]
};
await recorder.setMatcher("CustomDefaultMatcher", strictMatcherOptions);Methods for configuring how recorded requests are matched during playback, supporting both predefined and custom matcher strategies.
/**
* Sets a predefined matcher for request matching during playback
* @param matcher - The predefined matcher type to use
*/
async setMatcher(matcher: "HeaderlessMatcher" | "BodilessMatcher"): Promise<void>;
/**
* Sets a custom matcher with specific configuration options
* @param matcher - The custom matcher type
* @param options - Optional configuration for the custom matcher
*/
async setMatcher(matcher: "CustomDefaultMatcher", options?: CustomMatcherOptions): Promise<void>;Usage Examples:
// Use headerless matcher (ignores all headers)
await recorder.setMatcher("HeaderlessMatcher");
// Use bodiless matcher (ignores request/response bodies)
await recorder.setMatcher("BodilessMatcher");
// Use custom matcher with default settings
await recorder.setMatcher("CustomDefaultMatcher");
// Use custom matcher with specific options
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: false,
excludedHeaders: ["x-ms-client-request-id", "x-ms-date"],
ignoreQueryOrdering: true
});Built-in matcher strategies that provide common matching behaviors for different testing scenarios.
Matches requests while ignoring all HTTP headers, useful when headers contain dynamic or timestamp-based values that change between test runs.
Usage Examples:
// Good for scenarios where headers are highly dynamic
await recorder.setMatcher("HeaderlessMatcher");
// Example: Testing storage operations where headers like x-ms-date change
const blobClient = containerClient.getBlobClient("test.txt");
await blobClient.uploadData(Buffer.from("test content")); // Headers ignored during matchingMatches requests while ignoring request and response bodies, useful for testing scenarios where body content is dynamic but URLs and headers are consistent.
Usage Examples:
// Good for scenarios where request/response bodies are dynamic
await recorder.setMatcher("BodilessMatcher");
// Example: Testing operations with large or dynamic payloads
const searchClient = new SearchClient(endpoint, indexName, credential);
await searchClient.search("*"); // Body content ignored during matchingFlexible matcher that allows fine-tuned control over which aspects of requests are compared during matching.
Usage Examples:
// Typical Azure SDK scenarios - ignore volatile headers but compare bodies
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: true,
excludedHeaders: [
"x-ms-client-request-id",
"x-ms-date",
"authorization",
"user-agent"
],
ignoreQueryOrdering: true
});
// For APIs with stable headers but dynamic bodies
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: false,
excludedHeaders: ["date", "x-request-id"]
});Guidelines for choosing the appropriate matcher strategy based on your testing scenario.
// Storage blob operations with dynamic headers
await recorder.setMatcher("HeaderlessMatcher");
const blobClient = new BlobServiceClient(connectionString, recorder.configureClientOptions({}));
await blobClient.createContainer("test-container"); // x-ms-date and other headers ignored// Search operations with variable results
await recorder.setMatcher("BodilessMatcher");
const searchClient = new SearchClient(endpoint, indexName, credential, recorder.configureClientOptions({}));
await searchClient.search("query", { top: 50 }); // Response body ignored// Typical Azure service testing
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: true, // Compare request/response content
excludedHeaders: [
"x-ms-client-request-id", // Always unique
"x-ms-date", // Timestamp-based
"authorization", // May include dynamic tokens
"user-agent" // Environment-dependent
],
ignoreQueryOrdering: true // Flexible parameter ordering
});Complex matching configurations for specialized testing scenarios.
// Scenario: Testing with multiple service versions
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: false, // Bodies may differ between versions
excludedHeaders: [
"x-ms-version", // Service version may vary
"api-version" // API version differences
]
});
// Scenario: Testing with different authentication methods
await recorder.setMatcher("CustomDefaultMatcher", {
excludedHeaders: [
"authorization", // Different auth tokens
"x-ms-client-id", // Different client IDs
"x-azure-fdid" // Flight ID differences
],
ignoreQueryOrdering: true
});
// Scenario: Strict matching for critical operations
await recorder.setMatcher("CustomDefaultMatcher", {
compareBodies: true, // Must match exactly
excludedHeaders: [
"x-ms-client-request-id" // Only exclude truly random headers
],
ignoreQueryOrdering: false // Strict parameter ordering
});