UNPKG

@zendesk/laika

Version:

Test, mock, intercept and modify Apollo Client's operations — in both browser and unit tests!

117 lines (116 loc) 4.55 kB
import type { DocumentNode } from 'graphql'; import type { FetchResult, Observable, Operation, TypedDocumentNode } from '@apollo/client/core'; import type { Laika } from './laika'; interface SubscriptionObserver<T> { closed: boolean; next?: (value: T) => void; error?: (errorValue: any) => void; complete?: () => void; } /** @ignore */ export type { FetchResult, Operation } from '@apollo/client/core'; /** @ignore */ export type Variables = Operation['variables']; /** @ignore */ export type NoInfer<T> = [T][T extends T ? 0 : never]; /** @ignore */ export type OperationDocument<TData = unknown, TVariables = Variables> = DocumentNode | TypedDocumentNode<TData, TVariables>; /** @ignore */ export type InferResultData<TDocument> = TDocument extends TypedDocumentNode<infer TData, any> ? TData : unknown; /** @ignore */ export type FetchResultSubscriptionObserver = SubscriptionObserver<FetchResult>; /** @ignore */ export type NextLink = (operation: Operation) => Observable<FetchResult>; /** @ignore */ export interface Subscription { closed?: boolean; unsubscribe: () => void; } export type OnSubscribeCallback = (options: { operation: Operation; observer: FetchResultSubscriptionObserver; removeCallback: () => void; }) => (() => void) | void; export type OperationObserverCallback = (operation: Operation, observer: FetchResultSubscriptionObserver) => void; export interface Result<TData = unknown> { result?: FetchResult<TData>; error?: Error; /** Delay the mocked emission by this many milliseconds. */ delay?: number; } export type ResultFn<TData = unknown> = (operation: Operation) => Result<TData> | PromiseLike<Result<TData>>; export type ResultOrFn<TData = unknown> = Result<TData> | ResultFn<TData>; export interface SubscribeMeta { operation: Operation; observer: FetchResultSubscriptionObserver; forward: NextLink; enablePassthrough: PassthroughEnableFn; disablePassthrough: PassthroughDisableFn; } export type InterceptorFn = (operation: Operation, forward: NextLink) => Observable<FetchResult>; export type ManInTheMiddleFn = (options: SubscribeMeta) => Observable<FetchResult>; export type PassthroughDisableFn = () => boolean; export type PassthroughEnableFn = (mitm?: ManInTheMiddleFn) => boolean; export type OnSubscribe = (options: SubscribeMeta) => () => void; export type MatcherFn = (operation: Operation) => boolean; export interface Behavior { matcher: MatcherFn; onSubscribe: OnSubscribe; } export interface MatcherObject { operationName?: string; clientName?: string; feature?: string; variables?: Variables; operation?: OperationDocument; } /** * Leave undefined if you want to intercept every operation. Otherwise provide * either a {@link MatcherFn | matcher function} or a {@link MatcherObject | matcher object} * with properties like `clientName` and/or a partial set of `variables` * that have to match for a given operation to be intercepted. */ export type Matcher = MatcherFn | MatcherObject; export type RecordingElement = RecordingMarker | RecordingPoint; export type RecordingElementWithFixtureMeta = RecordingMarker | RecordingPointWithFixtureMeta; export type RecordingElementWithFixtureData = RecordingMarker | RecordingPointWithFixtureData; export interface RecordingPoint { clientName: string; timeDelta: number; operationName: string | null | undefined; feature?: string; variables: Variables; type: 'push' | 'response:mutation' | 'response:query'; result: FetchResult; action: string; } export type Replacements = { key: string; value: unknown; }[]; export interface RecordingPointWithFixtureMeta extends RecordingPoint { fixtureFnName: string; reuseFixture?: string; valueAsStringToVariableName?: Map<string, string>; replacedVariables?: Map<string, Replacements>; stringifiedResult?: string; } export interface RecordingPointWithFixtureData extends RecordingPointWithFixtureMeta { fixtureFnString?: string; fixtureFnName: string; fixtureCallString: string; } export interface RecordingMarker { type: 'marker'; timeDelta: number; action: string; } export type EventFilterFn = (event: RecordingElement) => boolean; export interface CreateLaikaLinkOptions { clientName: string; globalPropertyName?: string; startLoggingImmediately?: boolean; onLaikaReady?: (laika: Laika) => void; } /** @ignore */ export type ArgsType<T extends (...args: any) => any> = T extends (...args: infer R) => any ? R : any;