diff --git a/src/client.ts b/src/client.ts index 36097db4..488492f8 100644 --- a/src/client.ts +++ b/src/client.ts @@ -15,6 +15,7 @@ import { FetchLike, HttpRequestLike, ExtractDocumentType, + RequestInitLike, } from "./types"; import { ForbiddenError } from "./ForbiddenError"; import { NotFoundError } from "./NotFoundError"; @@ -164,18 +165,33 @@ export type ClientConfig = { * Node.js, this function must be provided. */ fetch?: FetchLike; + + /** + * Options provided to the client's `fetch()` on all network requests. These + * options will be merged with internally required options. They can also be + * overriden on a per-query basis using the query's `fetchOptions` parameter. + */ + fetchOptions?: RequestInitLike; }; /** - * Parameters for any client method that use `fetch()`. Only a subset of - * `fetch()` parameters are exposed. + * Parameters for any client method that use `fetch()`. */ type FetchParams = { + /** + * Options provided to the client's `fetch()` on all network requests. These + * options will be merged with internally required options. They can also be + * overriden on a per-query basis using the query's `fetchOptions` parameter. + */ + fetchOptions?: RequestInitLike; + /** * An `AbortSignal` provided by an `AbortController`. This allows the network * request to be cancelled if necessary. * * {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal} + * + * @deprecated Move the `signal` parameter into `fetchOptions.signal`. */ signal?: AbortSignalLike; }; @@ -341,6 +357,8 @@ export class Client< */ fetchFn: FetchLike; + fetchOptions?: RequestInitLike; + /** * Default parameters that will be sent with each query. These parameters can * be overridden on each query if needed. @@ -404,6 +422,7 @@ export class Client< this.accessToken = options.accessToken; this.routes = options.routes; this.brokenRoute = options.brokenRoute; + this.fetchOptions = options.fetchOptions; this.defaultParams = options.defaultParams; if (options.ref) { @@ -1269,12 +1288,15 @@ export class Client< */ async buildQueryURL({ signal, + fetchOptions, ...params }: Partial & FetchParams = {}): Promise { - const ref = params.ref || (await this.getResolvedRefString()); + const ref = + params.ref || (await this.getResolvedRefString({ signal, fetchOptions })); const integrationFieldsRef = params.integrationFieldsRef || - (await this.getCachedRepository({ signal })).integrationFieldsRef || + (await this.getCachedRepository({ signal, fetchOptions })) + .integrationFieldsRef || undefined; return buildQueryURL(this.endpoint, { @@ -1338,9 +1360,10 @@ export class Client< if (documentID != null && previewToken != null) { const document = await this.getByID(documentID, { - signal: args.signal, ref: previewToken, lang: "*", + signal: args.signal, + fetchOptions: args.fetchOptions, }); const url = prismicH.asLink(document, args.linkResolver); @@ -1688,7 +1711,16 @@ export class Client< // : {}; const res = await this.fetchFn(url, { - signal: params.signal, + ...this.fetchOptions, + ...params.fetchOptions, + headers: { + ...this.fetchOptions?.headers, + ...params.fetchOptions?.headers, + }, + signal: + params.fetchOptions?.signal || + params.signal || + this.fetchOptions?.signal, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/types.ts b/src/types.ts index 126cb0dd..4b0cd5d9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -72,16 +72,23 @@ export type FetchLike = ( export type AbortSignalLike = any; /** - * The minimum required properties from RequestInit. + * A subset of RequestInit properties to configure a `fetch()` request. */ -export interface RequestInitLike { +// Only options relevant to the client are included. Extending from the full +// RequestInit would cause issues, such as accepting Header objects. +// +// An interface is used to allow other libraries to augment the type with +// environment-specific types. +export interface RequestInitLike extends Pick { + /** + * An object literal to set the `fetch()` request's headers. + */ headers?: Record; /** - * An object that allows you to abort a `fetch()` request if needed via an - * `AbortController` object + * An AbortSignal to set the `fetch()` request's signal. * - * {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal} + * See: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal */ // NOTE: `AbortSignalLike` is `any`! It is left as `AbortSignalLike` // for backwards compatibility (the type is exported) and to signal to diff --git a/test/__testutils__/testAbortableMethod.ts b/test/__testutils__/testAbortableMethod.ts index a7ec97d8..6b040ee9 100644 --- a/test/__testutils__/testAbortableMethod.ts +++ b/test/__testutils__/testAbortableMethod.ts @@ -1,21 +1,21 @@ -import { it, expect } from "vitest"; +import { expect, it } from "vitest"; -import { mockPrismicRestAPIV2 } from "./mockPrismicRestAPIV2"; import { createTestClient } from "./createClient"; +import { mockPrismicRestAPIV2 } from "./mockPrismicRestAPIV2"; import * as prismic from "../../src"; type TestAbortableMethodArgs = { run: ( client: prismic.Client, - signal: prismic.AbortSignalLike, + params?: Parameters[0], ) => Promise; }; export const testAbortableMethod = ( description: string, args: TestAbortableMethodArgs, -) => { +): void => { it.concurrent(description, async (ctx) => { const controller = new AbortController(); controller.abort(); @@ -25,7 +25,31 @@ export const testAbortableMethod = ( const client = createTestClient(); await expect(async () => { - await args.run(client, controller.signal); + await args.run(client, { + fetchOptions: { + signal: controller.signal, + }, + }); }).rejects.toThrow(/aborted/i); }); + + // TODO: Remove once the `signal` parameter is removed in favor of + // `fetchOptions.signal`. + it.concurrent( + `${description} (using deprecated \`signal\` param)`, + async (ctx) => { + const controller = new AbortController(); + controller.abort(); + + mockPrismicRestAPIV2({ ctx }); + + const client = createTestClient(); + + await expect(async () => { + await args.run(client, { + signal: controller.signal, + }); + }).rejects.toThrow(/aborted/i); + }, + ); }; diff --git a/test/__testutils__/testFetchOptions.ts b/test/__testutils__/testFetchOptions.ts new file mode 100644 index 00000000..b864d826 --- /dev/null +++ b/test/__testutils__/testFetchOptions.ts @@ -0,0 +1,98 @@ +import * as prismic from "../../src"; +import { createTestClient } from "./createClient"; +import { mockPrismicRestAPIV2 } from "./mockPrismicRestAPIV2"; +import fetch from "node-fetch"; +import { expect, it, vi } from "vitest"; + +type TestFetchOptionsArgs = { + run: ( + client: prismic.Client, + params?: Parameters[0], + ) => Promise; +}; + +export const testFetchOptions = ( + description: string, + args: TestFetchOptionsArgs, +): void => { + it.concurrent(`${description} (on client)`, async (ctx) => { + const abortController = new AbortController(); + + const fetchSpy = vi.fn(fetch); + const fetchOptions: prismic.RequestInitLike = { + cache: "no-store", + headers: { + foo: "bar", + }, + signal: abortController.signal, + }; + + const repositoryResponse = ctx.mock.api.repository(); + const masterRef = ctx.mock.api.ref({ isMasterRef: true }); + const releaseRef = ctx.mock.api.ref({ isMasterRef: false }); + releaseRef.id = "id"; // Referenced in ref-related tests. + releaseRef.label = "label"; // Referenced in ref-related tests. + repositoryResponse.refs = [masterRef, releaseRef]; + + mockPrismicRestAPIV2({ + ctx, + repositoryResponse, + queryResponse: ctx.mock.api.query({ + documents: [ctx.mock.value.document()], + }), + }); + + const client = createTestClient({ + clientConfig: { + fetch: fetchSpy, + fetchOptions, + }, + }); + + await args.run(client); + + for (const [input, init] of fetchSpy.mock.calls) { + expect(init, input.toString()).toStrictEqual(fetchOptions); + } + }); + + it.concurrent(`${description} (on method)`, async (ctx) => { + const abortController = new AbortController(); + + const fetchSpy = vi.fn(fetch); + const fetchOptions: prismic.RequestInitLike = { + cache: "no-store", + headers: { + foo: "bar", + }, + signal: abortController.signal, + }; + + const repositoryResponse = ctx.mock.api.repository(); + const masterRef = ctx.mock.api.ref({ isMasterRef: true }); + const releaseRef = ctx.mock.api.ref({ isMasterRef: false }); + releaseRef.id = "id"; // Referenced in ref-related tests. + releaseRef.label = "label"; // Referenced in ref-related tests. + repositoryResponse.refs = [masterRef, releaseRef]; + + mockPrismicRestAPIV2({ + ctx, + repositoryResponse, + queryResponse: ctx.mock.api.query({ + documents: [ctx.mock.value.document()], + }), + }); + + const client = createTestClient({ + clientConfig: { + fetch: fetchSpy, + }, + }); + + await args.run(client, { fetchOptions }); + + for (const [input, init] of fetchSpy.mock.calls) { + expect(init, input.toString()).toStrictEqual(fetchOptions); + } + }); +}; diff --git a/test/client-dangerouslyGetAll.test.ts b/test/client-dangerouslyGetAll.test.ts index 057d2dcb..e520bdc4 100644 --- a/test/client-dangerouslyGetAll.test.ts +++ b/test/client-dangerouslyGetAll.test.ts @@ -7,6 +7,7 @@ import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { GET_ALL_QUERY_DELAY } from "../src/client"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; /** * Tolerance in number of milliseconds for the duration of a simulated network @@ -178,6 +179,10 @@ it("does not throttle single page queries", async (ctx) => { ).toBe(true); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.dangerouslyGetAll(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.dangerouslyGetAll({ signal }), + run: (client, params) => client.dangerouslyGetAll(params), }); diff --git a/test/client-get.test.ts b/test/client-get.test.ts index a618cff4..096dd2bc 100644 --- a/test/client-get.test.ts +++ b/test/client-get.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("resolves a query", { run: (client) => client.get(), @@ -52,6 +53,10 @@ testGetMethod("merges params and default params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.get(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.get({ signal }), + run: (client, params) => client.get(params), }); diff --git a/test/client-getAllByEveryTag.test.ts b/test/client-getAllByEveryTag.test.ts index a26f5d98..6b156738 100644 --- a/test/client-getAllByEveryTag.test.ts +++ b/test/client-getAllByEveryTag.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by every tag from paginated response", { run: (client) => client.getAllByEveryTag(["foo", "bar"]), @@ -23,6 +24,10 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getAllByEveryTag(["foo", "bar"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getAllByEveryTag(["foo", "bar"], { signal }), + run: (client, params) => client.getAllByEveryTag(["foo", "bar"], params), }); diff --git a/test/client-getAllByIDs.test.ts b/test/client-getAllByIDs.test.ts index ff1559a0..5399e457 100644 --- a/test/client-getAllByIDs.test.ts +++ b/test/client-getAllByIDs.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by IDs from paginated response", { run: (client) => client.getAllByIDs(["id1", "id2"]), @@ -23,6 +24,10 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getAllByIDs(["id1", "id2"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getAllByIDs(["id1", "id2"], { signal }), + run: (client, params) => client.getAllByIDs(["id1", "id2"], params), }); diff --git a/test/client-getAllBySomeTags.test.ts b/test/client-getAllBySomeTags.test.ts index 0fba0525..b5677928 100644 --- a/test/client-getAllBySomeTags.test.ts +++ b/test/client-getAllBySomeTags.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by some tags from paginated response", { run: (client) => client.getAllBySomeTags(["foo", "bar"]), @@ -23,6 +24,10 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getAllBySomeTags(["foo", "bar"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getAllBySomeTags(["foo", "bar"], { signal }), + run: (client, params) => client.getAllBySomeTags(["foo", "bar"], params), }); diff --git a/test/client-getAllByTag.test.ts b/test/client-getAllByTag.test.ts index cf4ff21a..3cff2313 100644 --- a/test/client-getAllByTag.test.ts +++ b/test/client-getAllByTag.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by tag from paginated response", { run: (client) => client.getAllByTag("tag"), @@ -23,6 +24,10 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getAllByTag("tag", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getAllByTag("tag", { signal }), + run: (client, params) => client.getAllByTag("tag", params), }); diff --git a/test/client-getAllByType.test.ts b/test/client-getAllByType.test.ts index 97effc08..8587b819 100644 --- a/test/client-getAllByType.test.ts +++ b/test/client-getAllByType.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by type from paginated response", { run: (client) => client.getAllByType("type"), @@ -23,6 +24,10 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getAllByType("tag", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getAllByType("tag", { signal }), + run: (client, params) => client.getAllByType("tag", params), }); diff --git a/test/client-getAllByUIDs.test.ts b/test/client-getAllByUIDs.test.ts index a9e748cd..1f940037 100644 --- a/test/client-getAllByUIDs.test.ts +++ b/test/client-getAllByUIDs.test.ts @@ -1,5 +1,6 @@ import { testGetAllMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetAllMethod("returns all documents by UIDs from paginated response", { run: (client) => client.getAllByUIDs("type", ["uid1", "uid2"]), @@ -29,7 +30,12 @@ testGetAllMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => + client.getAllByUIDs("type", ["uid1", "uid2"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => - client.getAllByUIDs("type", ["uid1", "uid2"], { signal }), + run: (client, params) => + client.getAllByUIDs("type", ["uid1", "uid2"], params), }); diff --git a/test/client-getByEveryTag.test.ts b/test/client-getByEveryTag.test.ts index 8cafbea2..4d39421f 100644 --- a/test/client-getByEveryTag.test.ts +++ b/test/client-getByEveryTag.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by tag", { run: (client) => client.getByEveryTag(["foo", "bar"]), @@ -23,6 +24,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByEveryTag(["foo", "bar"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByEveryTag(["foo", "bar"], { signal }), + run: (client, params) => client.getByEveryTag(["foo", "bar"], params), }); diff --git a/test/client-getByID.test.ts b/test/client-getByID.test.ts index 21177e99..2752413e 100644 --- a/test/client-getByID.test.ts +++ b/test/client-getByID.test.ts @@ -1,5 +1,6 @@ import { testGetFirstMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetFirstMethod("queries for document by ID", { run: (client) => client.getByID("id"), @@ -23,6 +24,10 @@ testGetFirstMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByID("id", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByID("id", { signal }), + run: (client, params) => client.getByID("id", params), }); diff --git a/test/client-getByIDs.test.ts b/test/client-getByIDs.test.ts index 3abbeb92..d15db2de 100644 --- a/test/client-getByIDs.test.ts +++ b/test/client-getByIDs.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by IDs", { run: (client) => client.getByIDs(["id1", "id2"]), @@ -23,6 +24,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByIDs(["id1", "id2"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByIDs(["id1", "id2"], { signal }), + run: (client, params) => client.getByIDs(["id1", "id2"], params), }); diff --git a/test/client-getBySomeTags.test.ts b/test/client-getBySomeTags.test.ts index 5fb369c1..d812e51a 100644 --- a/test/client-getBySomeTags.test.ts +++ b/test/client-getBySomeTags.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by some tags", { run: (client) => client.getBySomeTags(["foo", "bar"]), @@ -23,6 +24,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getBySomeTags(["foo", "bar"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getBySomeTags(["foo", "bar"], { signal }), + run: (client, params) => client.getBySomeTags(["foo", "bar"], params), }); diff --git a/test/client-getByTag.test.ts b/test/client-getByTag.test.ts index ab6d5102..5d040c59 100644 --- a/test/client-getByTag.test.ts +++ b/test/client-getByTag.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by tag", { run: (client) => client.getByTag("tag"), @@ -23,6 +24,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByTag("tag", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByTag("tag", { signal }), + run: (client, params) => client.getByTag("tag", params), }); diff --git a/test/client-getByType.test.ts b/test/client-getByType.test.ts index 8a213d3e..a3ae96c1 100644 --- a/test/client-getByType.test.ts +++ b/test/client-getByType.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by type", { run: (client) => client.getByType("type"), @@ -23,6 +24,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByType("type", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByType("type", { signal }), + run: (client, params) => client.getByType("type", params), }); diff --git a/test/client-getByUID.test.ts b/test/client-getByUID.test.ts index 55fe3601..11f326a1 100644 --- a/test/client-getByUID.test.ts +++ b/test/client-getByUID.test.ts @@ -1,5 +1,6 @@ import { testGetFirstMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetFirstMethod("queries for document by UID", { run: (client) => client.getByUID("type", "uid"), @@ -23,6 +24,10 @@ testGetFirstMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByUID("type", "uid", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getByUID("type", "uid", { signal }), + run: (client, params) => client.getByUID("type", "uid", params), }); diff --git a/test/client-getByUIDs.test.ts b/test/client-getByUIDs.test.ts index aa74cba0..0184d6e8 100644 --- a/test/client-getByUIDs.test.ts +++ b/test/client-getByUIDs.test.ts @@ -1,5 +1,6 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetMethod("queries for documents by UIDs", { run: (client) => client.getByUIDs("type", ["uid1", "uid2"]), @@ -29,7 +30,10 @@ testGetMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getByUIDs("type", ["uid1", "uid2"], params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => - client.getByUIDs("type", ["uid1", "uid2"], { signal }), + run: (client, params) => client.getByUIDs("type", ["uid1", "uid2"], params), }); diff --git a/test/client-getFirst.test.ts b/test/client-getFirst.test.ts index 7c0ab319..dc407ca3 100644 --- a/test/client-getFirst.test.ts +++ b/test/client-getFirst.test.ts @@ -8,6 +8,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetFirstMethod("returns the first document from a response", { run: (client) => client.getFirst(), @@ -92,6 +93,10 @@ it("throws if no documents were returned", async (ctx) => { ); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getFirst(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getFirst({ signal }), + run: (client, params) => client.getFirst(params), }); diff --git a/test/client-getMasterRef.test.ts b/test/client-getMasterRef.test.ts index 20903ac8..ba8583f6 100644 --- a/test/client-getMasterRef.test.ts +++ b/test/client-getMasterRef.test.ts @@ -3,6 +3,7 @@ import { it, expect } from "vitest"; import { createTestClient } from "./__testutils__/createClient"; import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns the master ref", async (ctx) => { const masterRef = ctx.mock.api.ref({ isMasterRef: true }); @@ -21,6 +22,10 @@ it("returns the master ref", async (ctx) => { expect(res).toStrictEqual(masterRef); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getMasterRef(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getMasterRef({ signal }), + run: (client, params) => client.getMasterRef(params), }); diff --git a/test/client-getRefByID.test.ts b/test/client-getRefByID.test.ts index 9be400c2..6569baef 100644 --- a/test/client-getRefByID.test.ts +++ b/test/client-getRefByID.test.ts @@ -5,6 +5,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns a ref by ID", async (ctx) => { const ref1 = ctx.mock.api.ref({ isMasterRef: true }); @@ -37,6 +38,10 @@ it("throws if ref could not be found", async (ctx) => { ); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getRefByID("id", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getRefByID("id", { signal }), + run: (client, params) => client.getRefByID("id", params), }); diff --git a/test/client-getRefByLabel.test.ts b/test/client-getRefByLabel.test.ts index 2b468c3d..19a5629f 100644 --- a/test/client-getRefByLabel.test.ts +++ b/test/client-getRefByLabel.test.ts @@ -5,6 +5,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns a ref by label", async (ctx) => { const ref1 = ctx.mock.api.ref({ isMasterRef: true }); @@ -37,6 +38,10 @@ it("throws if ref could not be found", async (ctx) => { ); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getRefByLabel("label", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getRefByLabel("label", { signal }), + run: (client, params) => client.getRefByLabel("label", params), }); diff --git a/test/client-getRefs.test.ts b/test/client-getRefs.test.ts index 7744de40..d147d047 100644 --- a/test/client-getRefs.test.ts +++ b/test/client-getRefs.test.ts @@ -3,6 +3,7 @@ import { it, expect } from "vitest"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns all refs", async (ctx) => { const repositoryResponse = ctx.mock.api.repository(); @@ -17,6 +18,10 @@ it("returns all refs", async (ctx) => { expect(res).toStrictEqual(repositoryResponse.refs); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getRefs(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getRefs({ signal }), + run: (client, params) => client.getRefs(params), }); diff --git a/test/client-getReleaseById.test.ts b/test/client-getReleaseById.test.ts index ae27c992..15dfbb49 100644 --- a/test/client-getReleaseById.test.ts +++ b/test/client-getReleaseById.test.ts @@ -5,6 +5,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns a Release by ID", async (ctx) => { const ref1 = ctx.mock.api.ref({ isMasterRef: true }); @@ -35,6 +36,10 @@ it("throws if Release could not be found", async (ctx) => { ).rejects.toThrowError(prismic.PrismicError); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getReleaseByID("id", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getReleaseByID("id", { signal }), + run: (client, params) => client.getReleaseByID("id", params), }); diff --git a/test/client-getReleaseByLabel.test.ts b/test/client-getReleaseByLabel.test.ts index 982f52f0..28525d9b 100644 --- a/test/client-getReleaseByLabel.test.ts +++ b/test/client-getReleaseByLabel.test.ts @@ -5,6 +5,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns a Release by label", async (ctx) => { const ref1 = ctx.mock.api.ref({ isMasterRef: true }); @@ -35,6 +36,10 @@ it("throws if Release could not be found", async (ctx) => { ).rejects.toThrowError(prismic.PrismicError); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getReleaseByLabel("label", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getReleaseByLabel("label", { signal }), + run: (client, params) => client.getReleaseByLabel("label", params), }); diff --git a/test/client-getReleases.test.ts b/test/client-getReleases.test.ts index aec49e41..48da974f 100644 --- a/test/client-getReleases.test.ts +++ b/test/client-getReleases.test.ts @@ -3,6 +3,7 @@ import { it, expect } from "vitest"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns all Releases", async (ctx) => { const repositoryResponse = ctx.mock.api.repository(); @@ -19,6 +20,10 @@ it("returns all Releases", async (ctx) => { ); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getReleases(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getReleases({ signal }), + run: (client, params) => client.getReleases(params), }); diff --git a/test/client-getRepository.test.ts b/test/client-getRepository.test.ts index 6c0060fc..1d72f1a5 100644 --- a/test/client-getRepository.test.ts +++ b/test/client-getRepository.test.ts @@ -5,6 +5,7 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns repository metadata", async (ctx) => { const repositoryResponse = ctx.mock.api.repository(); @@ -38,6 +39,10 @@ it("includes access token if configured", async (ctx) => { expect(res).toStrictEqual(repositoryResponse); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getRepository(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getRepository({ signal }), + run: (client, params) => client.getRepository(params), }); diff --git a/test/client-getSingle.test.ts b/test/client-getSingle.test.ts index 0f378dc8..c4d6a6d5 100644 --- a/test/client-getSingle.test.ts +++ b/test/client-getSingle.test.ts @@ -1,5 +1,6 @@ import { testGetFirstMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; testGetFirstMethod("queries for singleton document", { run: (client) => client.getSingle("type"), @@ -23,6 +24,10 @@ testGetFirstMethod("includes params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getSingle("type", params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getSingle("type", { signal }), + run: (client, params) => client.getSingle("type", params), }); diff --git a/test/client-getTags.test.ts b/test/client-getTags.test.ts index 93469bdf..5be77bd2 100644 --- a/test/client-getTags.test.ts +++ b/test/client-getTags.test.ts @@ -4,6 +4,7 @@ import * as msw from "msw"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; it("returns all tags", async (ctx) => { const repositoryResponse = ctx.mock.api.repository(); @@ -79,6 +80,10 @@ it("sends access token if form endpoint is used", async (ctx) => { expect(res).toStrictEqual(tagsResponse); }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.getTags(params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.getTags({ signal }), + run: (client, params) => client.getTags(params), }); diff --git a/test/client-graphQLFetch.test.ts b/test/client-graphQLFetch.test.ts index c5b3c267..dd255d98 100644 --- a/test/client-graphQLFetch.test.ts +++ b/test/client-graphQLFetch.test.ts @@ -5,7 +5,6 @@ import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { createTestClient } from "./__testutils__/createClient"; import { getMasterRef } from "./__testutils__/getMasterRef"; import { createAuthorizationHeader } from "./__testutils__/createAuthorizationHeader"; -import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import { createRepositoryName } from "./__testutils__/createRepositoryName"; it("resolves a query", async (ctx) => { @@ -203,9 +202,19 @@ it("includes a ref URL parameter to cache-bust", async (ctx) => { expect(json).toStrictEqual(graphqlResponse); }); -testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => - client.graphQLFetch("https://foo.cdn.prismic.io/graphql", { - signal, - }), +// `graphQLFetch()` uses a different function signature from query methods, so +// we cannot use the generalized `testAbortableMethod()` test util. +it("is abortable with an AbortController", async (ctx) => { + const controller = new AbortController(); + controller.abort(); + + mockPrismicRestAPIV2({ ctx }); + + const client = createTestClient(); + + await expect(async () => { + await client.graphQLFetch("https://foo.cdn.prismic.io/graphql", { + signal: controller.signal, + }); + }).rejects.toThrow(/aborted/i); }); diff --git a/test/client-query.test.ts b/test/client-query.test.ts index ad12c257..1d68e861 100644 --- a/test/client-query.test.ts +++ b/test/client-query.test.ts @@ -2,6 +2,7 @@ import { testGetMethod } from "./__testutils__/testAnyGetMethod"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; import * as prismic from "../src"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; const predicate = prismic.predicate.at("document.type", "page"); const q = `[${predicate}]`; @@ -63,6 +64,10 @@ testGetMethod("merges params and default params if provided", { }, }); +testFetchOptions("supports fetch options", { + run: (client, params) => client.query(predicate, params), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => client.query(predicate, { signal }), + run: (client, params) => client.query(predicate, params), }); diff --git a/test/client-resolvePreviewUrl.test.ts b/test/client-resolvePreviewUrl.test.ts index abbc04a1..e8fa29c5 100644 --- a/test/client-resolvePreviewUrl.test.ts +++ b/test/client-resolvePreviewUrl.test.ts @@ -5,6 +5,7 @@ import * as prismicM from "@prismicio/mock"; import { createTestClient } from "./__testutils__/createClient"; import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"; import { testAbortableMethod } from "./__testutils__/testAbortableMethod"; +import { testFetchOptions } from "./__testutils__/testFetchOptions"; const previewToken = "previewToken"; @@ -220,10 +221,20 @@ it("returns defaultURL if resolved URL is not a string", async (ctx) => { expect(res).toBe(defaultURL); }); +testFetchOptions("supports fetch options", { + run: (client, params) => + client.resolvePreviewURL({ + ...params, + defaultURL: "defaultURL", + documentID: "foo", + previewToken, + }), +}); + testAbortableMethod("is abortable with an AbortController", { - run: (client, signal) => + run: (client, params) => client.resolvePreviewURL({ - signal, + ...params, defaultURL: "defaultURL", documentID: "foo", previewToken,