diff --git a/docs/adapters/custom.md b/docs/adapters/custom.md index ed36f27e..89e8cf1f 100644 --- a/docs/adapters/custom.md +++ b/docs/adapters/custom.md @@ -41,12 +41,12 @@ class CustomAdapter extends Adapter { /* Do something when the adapter is disconnected from */ } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { /* Do something when the adapter is connect to */ } /* optional */ - async respondToRequest(pollyRequest) { + async onRespond(pollyRequest) { const { statusCode, body, headers } = pollyRequest.response; /* Deliver the response to the user */ } @@ -57,12 +57,12 @@ The `Adapter` class provides the `handleRequest()` method which can be called from `onConnect`. It accepts request parameters and returns a PollyRequest object with a `response` property. -The `passthroughRequest` method takes a PollyRequest object, makes a real HTTP +The `onFetchResponse` method takes a PollyRequest object, makes a real HTTP request and returns the response as a `{ statusCode, headers, body }` object, where `body` is a string. -The `respondToRequest()` method makes sure that the response has been delivered -to the user. `pollyjs.flush()` will wait for all `respondToRequests()` calls to +The `onRespond()` method makes sure that the response has been delivered +to the user. `pollyjs.flush()` will wait for all `onResponds()` calls to finish. You can omit the implementation of this method if no asynchronous delivery is required. @@ -103,7 +103,7 @@ class FetchAdapter extends Adapter { window.fetch = this.originalFetch; } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { const response = await this.originalFetch([ pollyRequest.url, { diff --git a/docs/persisters/custom.md b/docs/persisters/custom.md index a0a1e767..5ce0e414 100644 --- a/docs/persisters/custom.md +++ b/docs/persisters/custom.md @@ -33,11 +33,11 @@ class CustomPersister extends Persister { return 'custom'; } - findRecording() {} + onFindRecording() {} - saveRecording() {} + onSaveRecording() {} - deleteRecording() {} + onDeleteRecording() {} } ``` diff --git a/packages/@pollyjs/adapter-fetch/src/index.js b/packages/@pollyjs/adapter-fetch/src/index.js index 9ce0cbd2..a58225a6 100644 --- a/packages/@pollyjs/adapter-fetch/src/index.js +++ b/packages/@pollyjs/adapter-fetch/src/index.js @@ -16,12 +16,6 @@ export default class FetchAdapter extends Adapter { return 'fetch'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { context: global @@ -153,7 +147,7 @@ export default class FetchAdapter extends Adapter { } } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { const { context } = this.options; const { options } = pollyRequest.requestArguments; @@ -195,7 +189,7 @@ export default class FetchAdapter extends Adapter { }; } - respondToRequest(pollyRequest, error) { + onRespond(pollyRequest, error) { const { context: { Response } } = this.options; diff --git a/packages/@pollyjs/adapter-node-http/src/index.js b/packages/@pollyjs/adapter-node-http/src/index.js index 11a874ae..b4466627 100644 --- a/packages/@pollyjs/adapter-node-http/src/index.js +++ b/packages/@pollyjs/adapter-node-http/src/index.js @@ -29,12 +29,6 @@ export default class HttpAdapter extends Adapter { return 'node-http'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - onConnect() { this.assert( 'Running concurrent node-http adapters is unsupported, stop any running Polly instances.', @@ -187,7 +181,7 @@ export default class HttpAdapter extends Adapter { } } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { const { parsedArguments } = pollyRequest.requestArguments; const { method, headers, body } = pollyRequest; const { options } = parsedArguments; @@ -230,7 +224,7 @@ export default class HttpAdapter extends Adapter { }; } - async respondToRequest(pollyRequest, error) { + async onRespond(pollyRequest, error) { const { req, respond } = pollyRequest.requestArguments; const { statusCode, body, headers, encoding } = pollyRequest.response; diff --git a/packages/@pollyjs/adapter-node-http/tests/jest/integration/fetch-test.js b/packages/@pollyjs/adapter-node-http/tests/jest/integration/fetch-test.js index 8357c7cf..00e42902 100644 --- a/packages/@pollyjs/adapter-node-http/tests/jest/integration/fetch-test.js +++ b/packages/@pollyjs/adapter-node-http/tests/jest/integration/fetch-test.js @@ -21,14 +21,14 @@ describe('Integration | Jest | Fetch', function () { expect((await fetch('http://localhost:4000/api/db/foo')).status).toBe(404); await persister.persist(); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); expect(har).toBeDefined(); expect(har.log.entries.length).toBe(1); expect(har.log.entries[0].request.url.includes('/api/db/foo')).toBe(true); expect(har.log.entries[0].response.status).toBe(404); - await persister.delete(recordingId); - expect(persister.find(recordingId)).resolves.toBeNull(); + await persister.deleteRecording(recordingId); + expect(persister.findRecording(recordingId)).resolves.toBeNull(); }); }); diff --git a/packages/@pollyjs/adapter-node-http/tests/jest/integration/xhr-test.js b/packages/@pollyjs/adapter-node-http/tests/jest/integration/xhr-test.js index adf70a11..2838983c 100644 --- a/packages/@pollyjs/adapter-node-http/tests/jest/integration/xhr-test.js +++ b/packages/@pollyjs/adapter-node-http/tests/jest/integration/xhr-test.js @@ -33,14 +33,14 @@ describe('Integration | Jest | XHR', function () { expect((await request('/api/db/foo')).status).toBe(404); await persister.persist(); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); expect(har).toBeDefined(); expect(har.log.entries.length).toBe(1); expect(har.log.entries[0].request.url.includes('/api/db/foo')).toBe(true); expect(har.log.entries[0].response.status).toBe(404); - await persister.delete(recordingId); - expect(persister.find(recordingId)).resolves.toBeNull(); + await persister.deleteRecording(recordingId); + expect(persister.findRecording(recordingId)).resolves.toBeNull(); }); }); diff --git a/packages/@pollyjs/adapter-puppeteer/src/index.js b/packages/@pollyjs/adapter-puppeteer/src/index.js index 7a904e8d..b7655016 100644 --- a/packages/@pollyjs/adapter-puppeteer/src/index.js +++ b/packages/@pollyjs/adapter-puppeteer/src/index.js @@ -10,12 +10,6 @@ export default class PuppeteerAdapter extends Adapter { return 'puppeteer'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { page: null, @@ -160,7 +154,7 @@ export default class PuppeteerAdapter extends Adapter { this._requestsMapping.pollyRequests.set(request, pollyRequest); } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { const { page } = this.options; const { id, order, url, method, headers, body } = pollyRequest; const requestId = `${this.polly.recordingId}:${id}:${order}`; @@ -199,7 +193,7 @@ export default class PuppeteerAdapter extends Adapter { } } - async respondToRequest(pollyRequest, error) { + async onRespond(pollyRequest, error) { const { request } = pollyRequest.requestArguments; const { response } = pollyRequest; diff --git a/packages/@pollyjs/adapter-xhr/src/index.js b/packages/@pollyjs/adapter-xhr/src/index.js index 59581891..894d9749 100644 --- a/packages/@pollyjs/adapter-xhr/src/index.js +++ b/packages/@pollyjs/adapter-xhr/src/index.js @@ -18,12 +18,6 @@ export default class XHRAdapter extends Adapter { return 'xhr'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { context: global @@ -78,7 +72,7 @@ export default class XHRAdapter extends Adapter { } } - async passthroughRequest(pollyRequest) { + async onFetchResponse(pollyRequest) { const { xhr: fakeXhr } = pollyRequest.requestArguments; const xhr = new this.NativeXMLHttpRequest(); @@ -143,7 +137,7 @@ export default class XHRAdapter extends Adapter { }; } - respondToRequest(pollyRequest, error) { + onRespond(pollyRequest, error) { const { xhr } = pollyRequest.requestArguments; if (pollyRequest[ABORT_HANDLER]) { diff --git a/packages/@pollyjs/adapter/src/index.js b/packages/@pollyjs/adapter/src/index.js index 44379e2b..7360290c 100644 --- a/packages/@pollyjs/adapter/src/index.js +++ b/packages/@pollyjs/adapter/src/index.js @@ -54,6 +54,10 @@ export default class Adapter { } } + onConnect() { + this.assert('Must implement the `onConnect` hook.'); + } + disconnect() { if (this.isConnected) { this.onDisconnect(); @@ -65,6 +69,10 @@ export default class Adapter { } } + onDisconnect() { + this.assert('Must implement the `onDisconnect` hook.'); + } + timeout(pollyRequest, { time }) { const { timing } = pollyRequest.config; @@ -144,6 +152,15 @@ export default class Adapter { return this.onPassthrough(pollyRequest); } + /** + * @param {PollyRequest} pollyRequest + */ + async onPassthrough(pollyRequest) { + const response = await this.onFetchResponse(pollyRequest); + + await pollyRequest.respond(response); + } + async intercept(pollyRequest, interceptor) { pollyRequest.action = ACTIONS.INTERCEPT; await pollyRequest._intercept(interceptor); @@ -153,6 +170,14 @@ export default class Adapter { } } + /** + * @param {PollyRequest} pollyRequest + * @param {PollyResponse} pollyResponse + */ + async onIntercept(pollyRequest, pollyResponse) { + await pollyRequest.respond(pollyResponse); + } + async record(pollyRequest) { pollyRequest.action = ACTIONS.RECORD; @@ -166,6 +191,17 @@ export default class Adapter { return this.onRecord(pollyRequest); } + /** + * @param {PollyRequest} pollyRequest + */ + async onRecord(pollyRequest) { + await this.onPassthrough(pollyRequest); + + if (!pollyRequest.aborted) { + await this.persister.recordRequest(pollyRequest); + } + } + async replay(pollyRequest) { const { config } = pollyRequest; const recordingEntry = await this.persister.findEntry(pollyRequest); @@ -228,51 +264,6 @@ export default class Adapter { ); } - assert(message, ...args) { - assert( - `[${this.constructor.type}:${this.constructor.id}] ${message}`, - ...args - ); - } - - onConnect() { - this.assert('Must implement the `onConnect` hook.'); - } - - onDisconnect() { - this.assert('Must implement the `onDisconnect` hook.'); - } - - /** - * @param {PollyRequest} pollyRequest - * @returns {Object({ statusCode: number, headers: Object, body: string })} - */ - async passthroughRequest(/* pollyRequest */) { - this.assert('Must implement the `passthroughRequest` hook.'); - } - - /** - * Make sure the response from a Polly request is delivered to the - * user through the adapter interface. - * - * Calling `pollyjs.flush()` will await this method. - * - * @param {PollyRequest} pollyRequest - * @param {Error} [error] - */ - async respondToRequest(/* pollyRequest, error */) {} - - /** - * @param {PollyRequest} pollyRequest - */ - async onRecord(pollyRequest) { - await this.onPassthrough(pollyRequest); - - if (!pollyRequest.aborted) { - await this.persister.recordRequest(pollyRequest); - } - } - /** * @param {PollyRequest} pollyRequest * @param {Object} normalizedResponse The normalized response generated from the recording entry @@ -282,22 +273,17 @@ export default class Adapter { await pollyRequest.respond(normalizedResponse); } - /** - * @param {PollyRequest} pollyRequest - * @param {PollyResponse} pollyResponse - */ - async onIntercept(pollyRequest, pollyResponse) { - await pollyRequest.respond(pollyResponse); + assert(message, ...args) { + assert( + `[${this.constructor.type}:${this.constructor.id}] ${message}`, + ...args + ); } /** * @param {PollyRequest} pollyRequest */ - async onPassthrough(pollyRequest) { - const response = await this.passthroughRequest(pollyRequest); - - await pollyRequest.respond(response); - } + onRequest() {} /** * @param {PollyRequest} pollyRequest @@ -311,16 +297,11 @@ export default class Adapter { } } - /** - * @param {PollyRequest} pollyRequest - */ - onRequest() {} - /** * @param {PollyRequest} pollyRequest */ async onRequestFinished(pollyRequest) { - await this.respondToRequest(pollyRequest); + await this.onRespond(pollyRequest); pollyRequest.promise.resolve(); } @@ -340,9 +321,28 @@ export default class Adapter { await pollyRequest._emit('error', error); } - await this.respondToRequest(pollyRequest, error); + await this.onRespond(pollyRequest, error); } finally { pollyRequest.promise.reject(error); } } + + /** + * Make sure the response from a Polly request is delivered to the + * user through the adapter interface. + * + * Calling `pollyjs.flush()` will await this method. + * + * @param {PollyRequest} pollyRequest + * @param {Error} [error] + */ + async onRespond(/* pollyRequest, error */) {} + + /** + * @param {PollyRequest} pollyRequest + * @returns {Object({ statusCode: number, headers: Object, body: string })} + */ + async onFetchResponse(/* pollyRequest */) { + this.assert('Must implement the `onFetchResponse` hook.'); + } } diff --git a/packages/@pollyjs/adapter/types.d.ts b/packages/@pollyjs/adapter/types.d.ts index d9e6abf2..83c90a1f 100644 --- a/packages/@pollyjs/adapter/types.d.ts +++ b/packages/@pollyjs/adapter/types.d.ts @@ -1,8 +1,8 @@ -import { Polly, Headers, Request, Interceptor } from '@pollyjs/core'; +import { Polly, Request, Interceptor, Response } from '@pollyjs/core'; export default class Adapter< TOptions extends {} = {}, - TRequestArguments = any + TRequest extends Request = Request > { static readonly id: string; static readonly type: string; @@ -15,32 +15,34 @@ export default class Adapter< onConnect: () => void; disconnect: () => void; onDisconnect: () => void; - timeout: (request: Request, options: { time: number }) => Promise; - handleRequest: (request: { - url: string; - method: string; - headers: Headers; - body: string; - requestArguments?: TRequestArguments; - }) => Promise; - passthrough: (request: Request) => Promise; - onIntercept: (request: Request, interceptor: Interceptor) => Promise; - intercept: (request: Request, interceptor: Interceptor) => Promise; - onRecord: (request: Request) => Promise; - record: (request: Request) => Promise; - onReplay: (request: Request) => Promise; - replay: (request: Request) => Promise; + private timeout: ( + request: TRequest, + options: { time: number } + ) => Promise; + handleRequest: ( + request: Pick< + TRequest, + 'url' | 'method' | 'headers' | 'body' | 'requestArguments' + > + ) => Promise; + private passthrough: (request: TRequest) => Promise; + onPassthrough: (request: TRequest) => Promise; + private intercept: ( + request: TRequest, + interceptor: Interceptor + ) => Promise; + onIntercept: (request: TRequest, interceptor: Interceptor) => Promise; + private record: (request: TRequest) => Promise; + onRecord: (request: TRequest) => Promise; + private replay: (request: TRequest) => Promise; + onReplay: (request: TRequest) => Promise; assert: (message: string, condition?: boolean) => void; - onPassthrough: (request: Request) => Promise; - passthroughRequest(pollyRequest: Request): Promise<{ - statusCode: number; - headers: Headers; - body: string; - encoding?: string; - }>; - respondToRequest: (request: Request, error?: Error) => Promise; - onIdentifyRequest: (request: Request) => Promise; - onRequest: (request: Request) => Promise; - onRequestFinished: (request: Request) => Promise; - onRequestFailed: (request: Request) => Promise; + onFetchResponse( + pollyRequest: TRequest + ): Promise>; + onRespond: (request: TRequest, error?: Error) => Promise; + onIdentifyRequest: (request: TRequest) => Promise; + onRequest: (request: TRequest) => Promise; + onRequestFinished: (request: TRequest) => Promise; + onRequestFailed: (request: TRequest) => Promise; } diff --git a/packages/@pollyjs/core/src/-private/logger.js b/packages/@pollyjs/core/src/-private/logger.js index be94e424..1f694893 100644 --- a/packages/@pollyjs/core/src/-private/logger.js +++ b/packages/@pollyjs/core/src/-private/logger.js @@ -31,19 +31,23 @@ export default class Logger { logRequest(request) { const { log } = request; + const debug = log.getLevel() <= log.levels.DEBUG; - log.debug(`Request: ${request.method} ${request.url}`, { request }); + log.info( + `Request: ${request.method} ${request.url}`, + ...(debug ? [{ request }] : []) + ); } - logRequestResponse(request) { + logRequestResponse(request, response) { const { log } = request; const debug = log.getLevel() <= log.levels.DEBUG; log.info( `Response: ${FORMATTED_ACTIONS[request.action]} ➞ ${request.method} ${ request.url - } ${request.response.statusCode} • ${request.responseTime}ms`, - ...(debug ? [{ request, response: request.response }] : []) + } ${response.statusCode} • ${request.responseTime}ms`, + ...(debug ? [{ request, response }] : []) ); } diff --git a/packages/@pollyjs/core/types.d.ts b/packages/@pollyjs/core/types.d.ts index 4b4a6535..e9cd49d8 100644 --- a/packages/@pollyjs/core/types.d.ts +++ b/packages/@pollyjs/core/types.d.ts @@ -84,7 +84,7 @@ export interface PollyConfig { } export interface HTTPBase { headers: Headers; - body: any; + body?: string; getHeader(name: string): string | string[] | null; setHeader(name: string, value?: string | string[] | null): this; @@ -99,8 +99,20 @@ export interface HTTPBase { } export type RequestEvent = 'identify'; +export type RequestArguments = { [key: string]: any }; -export interface Request extends HTTPBase { +export interface Request + extends HTTPBase { + constructor( + polly: Polly, + request: { + url: string; + method: string; + headers: Headers; + body?: string; + requestArguments: TArguments; + } + ); method: string; url: string; readonly absoluteUrl: string; @@ -112,7 +124,7 @@ export interface Request extends HTTPBase { query: { [key: string]: string | string[] }; readonly params: { [key: string]: string }; readonly log: Logger; - readonly requestArguments: any; + readonly requestArguments: TArguments; recordingName: string; recordingId: string; responseTime?: number | undefined; @@ -123,6 +135,7 @@ export interface Request extends HTTPBase { action: ACTION | null; aborted: boolean; promise: Promise; + response?: Response; configure(config: Partial): void; overrideRecordingName(recordingName: string): void; on(event: RequestEvent, listener: RequestEventListener): this; @@ -240,7 +253,7 @@ export class PollyLogger { connect: () => void; disconnect: () => void; logRequest: (request: Request) => void; - logRequestResponse: (request: Request) => void; + logRequestResponse: (request: Request, response: Response) => void; logRequestError: (request: Request, error: Error) => void; } export type PollyEvent = 'create' | 'stop' | 'register'; diff --git a/packages/@pollyjs/persister-fs/src/index.js b/packages/@pollyjs/persister-fs/src/index.js index 03392ae8..0285fc78 100644 --- a/packages/@pollyjs/persister-fs/src/index.js +++ b/packages/@pollyjs/persister-fs/src/index.js @@ -13,23 +13,17 @@ export default class FSPersister extends Persister { return 'fs'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { recordingsDir: Defaults.recordingsDir }; } - findRecording(recordingId) { + onFindRecording(recordingId) { return this.api.getRecording(recordingId).body || null; } - saveRecording(recordingId, data) { + onSaveRecording(recordingId, data) { /* Pass the data through the base persister's stringify method so the output will be consistent with the rest of the persisters. @@ -37,7 +31,7 @@ export default class FSPersister extends Persister { this.api.saveRecording(recordingId, parse(this.stringify(data))); } - deleteRecording(recordingId) { + onDeleteRecording(recordingId) { this.api.deleteRecording(recordingId); } } diff --git a/packages/@pollyjs/persister-fs/tests/unit/persister-test.js b/packages/@pollyjs/persister-fs/tests/unit/persister-test.js index a55aa99f..3b8691ba 100644 --- a/packages/@pollyjs/persister-fs/tests/unit/persister-test.js +++ b/packages/@pollyjs/persister-fs/tests/unit/persister-test.js @@ -48,7 +48,7 @@ describe('Unit | FS Persister', function () { } }); - expect(persister.findRecording('FS-Persister')).to.deep.equal({}); + expect(persister.onFindRecording('FS-Persister')).to.deep.equal({}); }); }); @@ -63,25 +63,25 @@ describe('Unit | FS Persister', function () { }); }); - it('saveRecording', function () { - expect(this.persister.findRecording('FS-Persister')).to.deep.equal({}); + it('onSaveRecording', function () { + expect(this.persister.onFindRecording('FS-Persister')).to.deep.equal({}); - this.persister.saveRecording('FS-Persister', { foo: 'bar' }); - expect(this.persister.findRecording('FS-Persister')).to.deep.equal({ + this.persister.onSaveRecording('FS-Persister', { foo: 'bar' }); + expect(this.persister.onFindRecording('FS-Persister')).to.deep.equal({ foo: 'bar' }); }); - it('findRecording', function () { - expect(this.persister.findRecording('FS-Persister')).to.deep.equal({}); - expect(this.persister.findRecording('Does-Not-Exist')).to.be.null; + it('onFindRecording', function () { + expect(this.persister.onFindRecording('FS-Persister')).to.deep.equal({}); + expect(this.persister.onFindRecording('Does-Not-Exist')).to.be.null; }); - it('deleteRecording', function () { - expect(this.persister.findRecording('FS-Persister')).to.not.be.null; + it('onDeleteRecording', function () { + expect(this.persister.onFindRecording('FS-Persister')).to.not.be.null; - this.persister.deleteRecording('FS-Persister'); - expect(this.persister.findRecording('Does-Not-Exist')).to.be.null; + this.persister.onDeleteRecording('FS-Persister'); + expect(this.persister.onFindRecording('Does-Not-Exist')).to.be.null; }); }); }); diff --git a/packages/@pollyjs/persister-in-memory/src/index.js b/packages/@pollyjs/persister-in-memory/src/index.js index fad46f6f..56506276 100644 --- a/packages/@pollyjs/persister-in-memory/src/index.js +++ b/packages/@pollyjs/persister-in-memory/src/index.js @@ -7,21 +7,15 @@ export default class InMemoryPersister extends Persister { return 'in-memory-persister'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - - findRecording(recordingId) { + onFindRecording(recordingId) { return store.get(recordingId) || null; } - saveRecording(recordingId, data) { + onSaveRecording(recordingId, data) { store.set(recordingId, data); } - deleteRecording(recordingId) { + onDeleteRecording(recordingId) { store.delete(recordingId); } } diff --git a/packages/@pollyjs/persister-local-storage/src/index.js b/packages/@pollyjs/persister-local-storage/src/index.js index 39808d18..ac1b6fca 100644 --- a/packages/@pollyjs/persister-local-storage/src/index.js +++ b/packages/@pollyjs/persister-local-storage/src/index.js @@ -7,12 +7,6 @@ export default class LocalStoragePersister extends Persister { return 'local-storage'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { key: 'pollyjs', @@ -41,18 +35,18 @@ export default class LocalStoragePersister extends Persister { this.localStorage.setItem(this.options.key, this.stringify(db)); } - findRecording(recordingId) { + onFindRecording(recordingId) { return this.db[recordingId] || null; } - saveRecording(recordingId, data) { + onSaveRecording(recordingId, data) { const { db } = this; db[recordingId] = data; this.db = db; } - deleteRecording(recordingId) { + onDeleteRecording(recordingId) { const { db } = this; delete db[recordingId]; diff --git a/packages/@pollyjs/persister-rest/src/index.js b/packages/@pollyjs/persister-rest/src/index.js index dbbcc8c2..533d9a21 100644 --- a/packages/@pollyjs/persister-rest/src/index.js +++ b/packages/@pollyjs/persister-rest/src/index.js @@ -8,12 +8,6 @@ export default class RestPersister extends Persister { return 'rest'; } - static get name() { - // NOTE: deprecated in 4.1.0 but proxying since it's possible "core" is behind - // and therefore still referencing `name`. Remove in 5.0.0 - return this.id; - } - get defaultOptions() { return { host: 'http://localhost:3000', @@ -27,7 +21,7 @@ export default class RestPersister extends Persister { return ajax(buildUrl(host, apiNamespace, url), ...args); } - async findRecording(recordingId) { + async onFindRecording(recordingId) { const response = await this.ajax(`/${encodeURIComponent(recordingId)}`, { Accept: 'application/json; charset=utf-8' }); @@ -35,7 +29,7 @@ export default class RestPersister extends Persister { return this._normalize(response); } - async saveRecording(recordingId, data) { + async onSaveRecording(recordingId, data) { await this.ajax(`/${encodeURIComponent(recordingId)}`, { method: 'POST', body: this.stringify(data), @@ -46,7 +40,7 @@ export default class RestPersister extends Persister { }); } - async deleteRecording(recordingId) { + async onDeleteRecording(recordingId) { await this.ajax(`/${encodeURIComponent(recordingId)}`, { method: 'DELETE' }); diff --git a/packages/@pollyjs/persister/README.md b/packages/@pollyjs/persister/README.md index f01f39f1..8d07ce00 100644 --- a/packages/@pollyjs/persister/README.md +++ b/packages/@pollyjs/persister/README.md @@ -40,11 +40,11 @@ class CustomPersister extends Persister { return 'custom'; } - findRecording() {} + onFindRecording() {} - saveRecording() {} + onSaveRecording() {} - deleteRecording() {} + onDeleteRecording() {} } ``` diff --git a/packages/@pollyjs/persister/src/index.js b/packages/@pollyjs/persister/src/index.js index b5e44d7b..ba4b0077 100644 --- a/packages/@pollyjs/persister/src/index.js +++ b/packages/@pollyjs/persister/src/index.js @@ -56,7 +56,7 @@ export default class Persister { for (const [recordingId, { name, requests }] of this.pending) { const entries = []; - const recording = await this.find(recordingId); + const recording = await this.findRecording(recordingId); let har; if (!recording) { @@ -93,7 +93,7 @@ export default class Persister { this._removeUnusedEntries(recordingId, har); } - promises.push(this.save(recordingId, har)); + promises.push(this.saveRecording(recordingId, har)); } await Promise.all(promises); @@ -119,12 +119,12 @@ export default class Persister { this.pending.get(recordingId).requests.push(pollyRequest); } - async find(recordingId) { + async findRecording(recordingId) { const { _cache: cache } = this; if (!cache.has(recordingId)) { - const findRecording = async () => { - const recording = await this.findRecording(recordingId); + const onFindRecording = async () => { + const recording = await this.onFindRecording(recordingId); if (recording) { this.assert( @@ -140,26 +140,38 @@ export default class Persister { } }; - cache.set(recordingId, findRecording()); + cache.set(recordingId, onFindRecording()); } return cache.get(recordingId); } - async save(recordingId, har) { - await this.saveRecording(...arguments); + onFindRecording() { + this.assert('Must implement the `onFindRecording` hook.'); + } + + async saveRecording(recordingId, har) { + await this.onSaveRecording(...arguments); this._cache.delete(recordingId); this.polly.logger.log.debug('Recording saved.', { recordingId, har }); } - async delete(recordingId) { - await this.deleteRecording(...arguments); + onSaveRecording() { + this.assert('Must implement the `onSaveRecording` hook.'); + } + + async deleteRecording(recordingId) { + await this.onDeleteRecording(...arguments); this._cache.delete(recordingId); } + onDeleteRecording() { + this.assert('Must implement the `onDeleteRecording` hook.'); + } + async findEntry(pollyRequest) { const { id, order, recordingId } = pollyRequest; - const recording = await this.find(recordingId); + const recording = await this.findRecording(recordingId); return ( (recording && @@ -199,16 +211,4 @@ export default class Persister { requests.find((r) => entry._id === r.id && entry._order === r.order) ); } - - findRecording() { - this.assert('Must implement the `findRecording` hook.'); - } - - saveRecording() { - this.assert('Must implement the `saveRecording` hook.'); - } - - deleteRecording() { - this.assert('Must implement the `deleteRecording` hook.'); - } } diff --git a/packages/@pollyjs/persister/tests/unit/persister-test.js b/packages/@pollyjs/persister/tests/unit/persister-test.js index f602f807..7009f03e 100644 --- a/packages/@pollyjs/persister/tests/unit/persister-test.js +++ b/packages/@pollyjs/persister/tests/unit/persister-test.js @@ -25,19 +25,19 @@ describe('Unit | Persister', function () { return 'CustomPersister'; } - async findRecording() { + async onFindRecording() { callCounts.find++; await timeout(1); return recording; } - async saveRecording() { + async onSaveRecording() { callCounts.save++; await timeout(1); } - async deleteRecording() { + async onDeleteRecording() { callCounts.delete++; await timeout(1); } @@ -52,18 +52,18 @@ describe('Unit | Persister', function () { it('should handle concurrent find requests', async function () { await Promise.all([ - this.persister.find('test'), - this.persister.find('test'), - this.persister.find('test') + this.persister.findRecording('test'), + this.persister.findRecording('test'), + this.persister.findRecording('test') ]); expect(callCounts.find).to.equal(1); }); it('caches', async function () { - await this.persister.find('test'); - await this.persister.find('test'); - await this.persister.find('test'); + await this.persister.findRecording('test'); + await this.persister.findRecording('test'); + await this.persister.findRecording('test'); expect(callCounts.find).to.equal(1); }); @@ -71,32 +71,32 @@ describe('Unit | Persister', function () { it('does not cache falsy values', async function () { recording = null; - await this.persister.find('test'); + await this.persister.findRecording('test'); await Promise.all([ - this.persister.find('test'), - this.persister.find('test'), - this.persister.find('test') + this.persister.findRecording('test'), + this.persister.findRecording('test'), + this.persister.findRecording('test') ]); - await this.persister.find('test'); + await this.persister.findRecording('test'); expect(callCounts.find).to.equal(3); }); it('busts the cache after a save', async function () { - await this.persister.find('test'); - await this.persister.save('test'); - await this.persister.find('test'); - await this.persister.find('test'); + await this.persister.findRecording('test'); + await this.persister.saveRecording('test'); + await this.persister.findRecording('test'); + await this.persister.findRecording('test'); expect(callCounts.save).to.equal(1); expect(callCounts.find).to.equal(2); }); it('busts the cache after a delete', async function () { - await this.persister.find('test'); - await this.persister.delete('test'); - await this.persister.find('test'); - await this.persister.find('test'); + await this.persister.findRecording('test'); + await this.persister.deleteRecording('test'); + await this.persister.findRecording('test'); + await this.persister.findRecording('test'); expect(callCounts.delete).to.equal(1); expect(callCounts.find).to.equal(2); diff --git a/packages/@pollyjs/persister/types.d.ts b/packages/@pollyjs/persister/types.d.ts index 154b3d1d..a8de3aaa 100644 --- a/packages/@pollyjs/persister/types.d.ts +++ b/packages/@pollyjs/persister/types.d.ts @@ -78,13 +78,13 @@ export default class Persister { hasPending: boolean; persist: () => Promise; recordRequest: (request: Request) => void; - find: (recordingId: string) => Promise; - save: (recordingId: string, har: Har) => Promise; - delete: (recordingId: string) => Promise; + private findRecording: (recordingId: string) => Promise; + onFindRecording: (recordingId: string) => Promise; + private saveRecording: (recordingId: string, har: Har) => Promise; + onSaveRecording: (recordingId: string, har: Har) => Promise; + private deleteRecording: (recordingId: string) => Promise; + onDeleteRecording: (recordingId: string) => Promise; findEntry: (request: Request) => Promise; stringify: (value: any) => string; assert: (message: string, condition?: boolean) => void; - findRecording: (recordingId: string) => Promise; - saveRecording: (recordingId: string, har: Har) => Promise; - deleteRecording: (recordingId: string) => Promise; } diff --git a/tests/helpers/setup-persister.js b/tests/helpers/setup-persister.js index 36505356..44516fcf 100644 --- a/tests/helpers/setup-persister.js +++ b/tests/helpers/setup-persister.js @@ -7,7 +7,7 @@ setupPersister.beforeEach = function () {}; setupPersister.afterEach = function () { afterEach(async function () { - await this.polly.persister.delete(this.polly.recordingId); + await this.polly.persister.deleteRecording(this.polly.recordingId); }); }; diff --git a/tests/integration/adapter-tests.js b/tests/integration/adapter-tests.js index 3b3caed5..50ef5a67 100644 --- a/tests/integration/adapter-tests.js +++ b/tests/integration/adapter-tests.js @@ -93,9 +93,9 @@ export default function adapterTests() { server.get(this.recordUrl()).passthrough(); - expect(await persister.find(recordingId)).to.be.null; + expect(await persister.findRecording(recordingId)).to.be.null; expect((await this.fetchRecord()).status).to.equal(404); - expect(await persister.find(recordingId)).to.be.null; + expect(await persister.findRecording(recordingId)).to.be.null; }); it('should be able to intercept when in passthrough mode', async function () { @@ -142,9 +142,9 @@ export default function adapterTests() { expect(req.action).to.equal(ACTIONS.PASSTHROUGH); }); - expect(await persister.find(recordingId)).to.be.null; + expect(await persister.findRecording(recordingId)).to.be.null; expect((await this.fetchRecord()).status).to.equal(404); - expect(await persister.find(recordingId)).to.be.null; + expect(await persister.findRecording(recordingId)).to.be.null; expect(responseCalled).to.be.true; }); @@ -178,7 +178,7 @@ export default function adapterTests() { this.polly = new Polly(recordingName, config); this.polly.replay(); - const har = await this.polly.persister.find(recordingId); + const har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(1); @@ -306,7 +306,7 @@ export default function adapterTests() { this.polly.record(); await this.relativeFetch(url); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(1); @@ -319,7 +319,7 @@ export default function adapterTests() { this.polly.replay(); await this.relativeFetch(url); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(1); @@ -339,7 +339,7 @@ export default function adapterTests() { }); afterEach(async function () { - await this.polly.persister.delete(this.polly.recordingId); + await this.polly.persister.deleteRecording(this.polly.recordingId); }); it('warns and plays back on expired recording if expiryStrategy is "warn"', async function () { diff --git a/tests/integration/persister-tests.js b/tests/integration/persister-tests.js index 0f367a15..ef87246b 100644 --- a/tests/integration/persister-tests.js +++ b/tests/integration/persister-tests.js @@ -9,7 +9,8 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - expect(await validate.har(await persister.find(recordingId))).to.be.true; + expect(await validate.har(await persister.findRecording(recordingId))).to.be + .true; await this.fetchRecord({ method: 'POST', @@ -19,7 +20,8 @@ export default function persisterTests() { await persister.persist(); - expect(await validate.har(await persister.find(recordingId))).to.be.true; + expect(await validate.har(await persister.findRecording(recordingId))).to.be + .true; }); it('should have the correct metadata', async function () { @@ -29,7 +31,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); const { _recordingName, creator, entries } = har.log; const entry = entries[0]; @@ -56,7 +58,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(1)); await persister.persist(); - let har = await persister.find(recordingId); + let har = await persister.findRecording(recordingId); expect(har.log.entries).to.have.lengthOf(1); @@ -71,7 +73,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(2)); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); expect(har.log.entries).to.have.lengthOf(3); expect( @@ -120,7 +122,7 @@ export default function persisterTests() { expect(recordingId).to.include('Override'); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); expect(await validate.har(har)).to.be.true; expect(har.log.entries).to.have.lengthOf(1); @@ -149,7 +151,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); const { headers } = har.log.entries[0].response; expect(await validate.har(har)).to.be.true; @@ -185,7 +187,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - const har = await persister.find(recordingId); + const har = await persister.findRecording(recordingId); const { content, redirectURL } = har.log.entries[0].response; expect(await validate.har(har)).to.be.true; @@ -204,7 +206,7 @@ export default function persisterTests() { } catch (e) { error = e; } finally { - const savedRecording = await this.polly.persister.find( + const savedRecording = await this.polly.persister.findRecording( this.polly.recordingId ); @@ -223,7 +225,9 @@ export default function persisterTests() { await this.fetchRecord(); await this.polly.stop(); - const har = await this.polly.persister.find(this.polly.recordingId); + const har = await this.polly.persister.findRecording( + this.polly.recordingId + ); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(1); @@ -238,7 +242,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(2)); await this.polly.persister.persist(); - let har = await this.polly.persister.find(recordingId); + let har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(2); @@ -257,7 +261,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(3)); // -> New recording await this.polly.persister.persist(); - har = await this.polly.persister.find(recordingId); + har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(2); @@ -279,7 +283,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(2)); await this.polly.persister.persist(); - let har = await this.polly.persister.find(recordingId); + let har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(2); @@ -296,7 +300,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(2)); await this.polly.persister.persist(); - har = await this.polly.persister.find(recordingId); + har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(4); @@ -321,7 +325,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(2)); await this.polly.persister.persist(); - let har = await this.polly.persister.find(recordingId); + let har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(2); @@ -337,7 +341,7 @@ export default function persisterTests() { await this.fetch(orderedRecordUrl(4)); await this.polly.persister.persist(); - har = await this.polly.persister.find(recordingId); + har = await this.polly.persister.findRecording(recordingId); expect(har).to.be.an('object'); expect(har.log.entries).to.have.lengthOf(4); @@ -361,7 +365,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); content = har.log.entries[0].response.content; expect(await validate.har(har)).to.be.true; @@ -376,7 +380,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); content = har.log.entries[1].response.content; expect(await validate.har(har)).to.be.true; @@ -391,7 +395,7 @@ export default function persisterTests() { await this.fetchRecord(); await persister.persist(); - har = await persister.find(recordingId); + har = await persister.findRecording(recordingId); content = har.log.entries[2].response.content; expect(await validate.har(har)).to.be.true;