{"id":16569,"library":"vcr-test","title":"HTTP Interaction Recorder for Tests","description":"vcr-test is a testing utility that records and replays HTTP interactions, enabling fast, deterministic, and accurate tests by eliminating reliance on live external APIs. It intercepts HTTP traffic from any client (`fetch`, `axios`, `got`, etc.) using `@mswjs/interceptors` and stores request/response pairs in YAML \"cassette\" files. The current stable version is 1.4.0. It provides flexible recording modes (once, none, update, all) and extensibility for request masking, pass-through, and custom matching. Its key differentiator is its framework-agnostic nature and support for modern JavaScript features like `await using`, while also offering a callback API for older environments. While no explicit release cadence is stated, the project appears actively maintained on GitHub.","status":"active","version":"1.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/epignosisx/vcr-test","tags":["javascript","http","mocking","record","vcr","testing","typescript"],"install":[{"cmd":"npm install vcr-test","lang":"bash","label":"npm"},{"cmd":"yarn add vcr-test","lang":"bash","label":"yarn"},{"cmd":"pnpm add vcr-test","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Main class for managing HTTP recording and playback. Primarily designed for ESM usage.","wrong":"const VCR = require('vcr-test').VCR","symbol":"VCR","correct":"import { VCR } from 'vcr-test'"},{"note":"Default storage mechanism for cassettes, typically used when instantiating VCR.","wrong":"const FileStorage = require('vcr-test').FileStorage","symbol":"FileStorage","correct":"import { FileStorage } from 'vcr-test'"},{"note":"Enum for controlling VCR's recording behavior (e.g., `RecordMode.update`).","wrong":"const RecordMode = require('vcr-test').RecordMode","symbol":"RecordMode","correct":"import { RecordMode } from 'vcr-test'"},{"note":"Class for configuring how incoming requests are matched against recorded interactions. Not a default export.","wrong":"import DefaultRequestMatcher from 'vcr-test/DefaultRequestMatcher'","symbol":"DefaultRequestMatcher","correct":"import { DefaultRequestMatcher } from 'vcr-test'"}],"quickstart":{"code":"import { join } from 'node:path';\nimport { VCR, FileStorage } from 'vcr-test';\n\n// This would be your actual API client, e.g., using fetch or axios\nconst api = {\n  async myAwesomeApiCall() {\n    const response = await fetch('https://httpbin.org/post', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({ name: 'john' })\n    });\n    return response.json();\n  }\n};\n\ndescribe('some suite', () => {\n  const cassettesPath = join(process.cwd(), '__cassettes__');\n  const vcr = new VCR(new FileStorage(cassettesPath));\n\n  it('should record and replay an API call using await using', async () => {\n    // Ensure the cassette directory exists and is clean for testing\n    // For real usage, you'd manage this outside the test.\n\n    await using _cassette = await vcr.useCassette('my_test_cassette');\n    const result = await api.myAwesomeApiCall();\n\n    expect(result).toBeDefined();\n    expect(result.data).toBe('{\"name\":\"john\"}');\n    expect(result.headers['Content-Type']).toContain('application/json');\n  }, 10000); // Increase timeout for initial recording\n});\n","lang":"typescript","description":"Demonstrates recording and replaying an HTTP interaction using `VCR` and `FileStorage` with the modern `await using` syntax. It shows how to initialize VCR, wrap an API call with `useCassette`, and assert the replayed result."},"warnings":[{"fix":"For older environments, use the callback-based API: `await vcr.useCassette('cassette_name', async () => { /* test code */ });`.","message":"The `await using` syntax for cassette management requires Node.js 22+ and TypeScript 5.2+. Using `vcr-test` with older versions of Node.js or TypeScript will result in syntax errors or runtime issues if this pattern is adopted.","severity":"breaking","affected_versions":"<=1.x.x"},{"fix":"Recalculate the byte length of the modified response body and update the `content-length` header accordingly, or re-record the cassette to automatically generate correct headers.","message":"When manually editing recorded YAML cassette files, especially modifying response bodies, ensure that the `content-length` header in the `response.headers` section is updated to accurately reflect the new body's length. Mismatched `content-length` can lead to unexpected client behavior or parsing issues.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be aware of `VCR_MODE` in deployment environments. To ensure consistent behavior, explicitly unset `VCR_MODE` if you intend to use programmatic mode settings, or rely solely on the environment variable for mode control in pipelines.","message":"The `VCR_MODE` environment variable takes precedence over any programmatically set `vcr.mode` property. This can lead to unexpected recording behavior if tests are run in an environment where `VCR_MODE` is set (e.g., CI/CD) and overrides local settings.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Change the `vcr.mode` to `RecordMode.once` (default), `RecordMode.update`, or `RecordMode.all` to allow recording the cassette, or ensure the cassette exists before running the test in `none` mode.","cause":"The VCR instance's `mode` is set to `RecordMode.none` (or `VCR_MODE=none`), and the specified cassette file does not exist.","error":"Error: Cassette 'cassette_name' not found and mode is 'none'."},{"fix":"Open the YAML cassette file and ensure the `content-length` header value for the affected interaction is an integer representing the byte length of the response body, or delete the cassette and re-record it.","cause":"This error can occur if a manually edited cassette has an invalid or non-numeric value for the `content-length` header in a response.","error":"TypeError: Invalid value for 'headers': 'content-length' should be a number."}],"ecosystem":"npm"}