/* eslint-disable @typescript-eslint/no-use-before-define */ import nock from 'nock' import { promises as fs } from 'fs' type CassetteFile = Record type DefinitionProcessor = (defns: nock.Definition[]) => nock.Definition[] export async function startVCR(processDefns: DefinitionProcessor = defns => defns): Promise { const defns = await currentCassettes() if (!defns) { // No cassettes found - recording responses nock.recorder.rec({ output_objects: true, dont_print: true }) } else { // Cassettes found - using saved responses // set up the mocks nock.define(processDefns(defns)) } } export async function stopVCR() { const defns = nock.recorder.play() as nock.Definition[] nock.recorder.clear() if (defns.length) { await saveCassettes(defns) } nock.restore() nock.cleanAll() } // function timeString(...args: Parameters) { // const date = new Date(...args) // // the dates returned by this api appear to be iso string formatted but without the Z // return date.toISOString().replace(/Z$/, '') // } function cassettePath(): string { const state: jest.MatcherState = expect.getState() const pathParts = state.testPath.split('/') const fileName = pathParts.pop() pathParts.push('__cassettes__') pathParts.push(fileName.replace(/\..+/, '.cassette.json')) return pathParts.join('/') } async function writeCassetteFile(cassettes: CassetteFile): Promise { console.log('updating cassette file') await fs.writeFile(cassettePath(), JSON.stringify(cassettes, null, 2)) } async function saveCassettes(defns: nock.Definition[]): Promise { const cassettes: CassetteFile = await readCassetteFile() cassettes[expect.getState().currentTestName] = defns await writeCassetteFile(cassettes) } async function readCassetteFile(): Promise { try { const buffer = await fs.readFile(cassettePath()) return JSON.parse(buffer.toString()) as CassetteFile } catch { // no cassette file return {} } } async function currentCassettes(): Promise { const cassettes = await readCassetteFile() return cassettes[expect.getState().currentTestName] }