Skip to content

Commit 38a61b7

Browse files
authored
tests: import from entry points where possible, add @apollo/client/testing/internal entry point (#12511)
1 parent a7f5f0c commit 38a61b7

File tree

106 files changed

+925
-527
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+925
-527
lines changed
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
## API Report File for "@apollo/client"
2+
3+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
4+
5+
```ts
6+
7+
import type { ApolloClient } from '@apollo/client/core';
8+
import { ApolloLink } from '@apollo/client/core';
9+
import type { ApolloPayloadResult } from '@apollo/client/core';
10+
import { FetchResult } from '@apollo/client/core';
11+
import type { GraphQLFormattedError } from 'graphql-17-alpha2';
12+
import { GraphQLRequest } from '@apollo/client/core';
13+
import { HttpLink } from '@apollo/client/link/http';
14+
import type { InitialIncrementalExecutionResult } from 'graphql-17-alpha2';
15+
import type { MaskedDocumentNode } from '@apollo/client/masking';
16+
import type { MockedProviderProps } from '@apollo/client/testing/react';
17+
import type { MockedResponse } from '@apollo/client/testing/core';
18+
import type { Observable } from 'rxjs';
19+
import type { Queries } from '@testing-library/dom';
20+
import type { queries } from '@testing-library/dom';
21+
import * as React_2 from 'react';
22+
import type * as ReactDOMClient from 'react-dom/client';
23+
import type { RenderHookOptions } from '@testing-library/react';
24+
import type { RenderHookResult } from '@testing-library/react';
25+
import type { RenderOptions } from '@testing-library/react';
26+
import type { RenderResult } from '@testing-library/react';
27+
import { ResultFunction } from '@apollo/client/testing/core';
28+
import type { Subscribable } from 'rxjs';
29+
import type { SubsequentIncrementalExecutionResult } from 'graphql-17-alpha2';
30+
import type { TypedDocumentNode } from '@apollo/client/core';
31+
32+
// @public (undocumented)
33+
export function actAsync<T>(scope: () => T | Promise<T>): Promise<T>;
34+
35+
// @public (undocumented)
36+
export function addDelayToMocks<T extends MockedResponse<unknown>[]>(mocks: T, delay?: number, override?: boolean): {
37+
delay: number;
38+
request: GraphQLRequest<Record<string, any>>;
39+
maxUsageCount?: number;
40+
result?: FetchResult<unknown> | ResultFunction<FetchResult<unknown>, Record<string, any>> | undefined;
41+
error?: Error;
42+
variableMatcher?: ((arg: Record<string, any>) => boolean) | undefined;
43+
newData?: ResultFunction<FetchResult<unknown>, Record<string, any>> | undefined;
44+
}[];
45+
46+
// @public (undocumented)
47+
type ConsoleMethod = "log" | "info" | "warn" | "error" | "debug";
48+
49+
// @public (undocumented)
50+
export function createClientWrapper(client: ApolloClient, Wrapper?: React_2.JSXElementConstructor<{
51+
children: React_2.ReactNode;
52+
}>): React_2.JSXElementConstructor<{
53+
children: React_2.ReactNode;
54+
}>;
55+
56+
// @public (undocumented)
57+
export function createMockWrapper(renderOptions: MockedProviderProps, Wrapper?: React_2.JSXElementConstructor<{
58+
children: React_2.ReactNode;
59+
}>): React_2.JSXElementConstructor<{
60+
children: React_2.ReactNode;
61+
}>;
62+
63+
// @public (undocumented)
64+
export function enableFakeTimers(config?: FakeTimersConfig | LegacyFakeTimersConfig): Disposable;
65+
66+
// @public (undocumented)
67+
type HydrateableContainer = Parameters<(typeof ReactDOMClient)["hydrateRoot"]>[0];
68+
69+
// @public (undocumented)
70+
type HydrateableContainer_2 = Parameters<(typeof ReactDOMClient)["hydrateRoot"]>[0];
71+
72+
// @public (undocumented)
73+
interface Letter {
74+
// (undocumented)
75+
__typename: "Letter";
76+
// (undocumented)
77+
letter: string;
78+
// (undocumented)
79+
position: number;
80+
}
81+
82+
// @public (undocumented)
83+
export interface MaskedVariablesCaseData {
84+
// (undocumented)
85+
character: {
86+
__typename: "Character";
87+
id: string;
88+
} & {
89+
" $fragmentRefs"?: {
90+
MaskedVariablesCaseFragment: MaskedVariablesCaseFragment;
91+
};
92+
};
93+
}
94+
95+
// @public (undocumented)
96+
type MaskedVariablesCaseFragment = {
97+
__typename: "Character";
98+
name: string;
99+
} & {
100+
" $fragmentName"?: "MaskedVariablesCaseFragment";
101+
};
102+
103+
// @public (undocumented)
104+
export function mockDeferStream<TData = Record<string, unknown>, TExtensions = Record<string, unknown>>(): {
105+
httpLink: HttpLink;
106+
enqueueInitialChunk(chunk: InitialIncrementalExecutionResult<TData, TExtensions>): void;
107+
enqueueSubsequentChunk(chunk: SubsequentIncrementalExecutionResult<TData, TExtensions>): void;
108+
enqueueErrorChunk(errors: GraphQLFormattedError[]): void;
109+
};
110+
111+
// @public (undocumented)
112+
export function mockMultipartSubscriptionStream<TData = Record<string, unknown>, TExtensions = Record<string, unknown>>(): {
113+
httpLink: HttpLink;
114+
enqueueHeartbeat: () => void;
115+
enqueuePayloadResult(payload: ApolloPayloadResult<TData, TExtensions>["payload"], hasNext?: boolean): void;
116+
enqueueProtocolErrors(errors: ApolloPayloadResult["errors"]): void;
117+
};
118+
119+
// @public (undocumented)
120+
type ObservableEvent<T> = {
121+
type: "next";
122+
value: T;
123+
} | {
124+
type: "error";
125+
error: any;
126+
} | {
127+
type: "complete";
128+
};
129+
130+
// @public (undocumented)
131+
export class ObservableStream<T> {
132+
constructor(observable: Observable<T> | Subscribable<T>);
133+
// Warning: (ae-forgotten-export) The symbol "TakeOptions" needs to be exported by the entry point index.d.ts
134+
// Warning: (ae-forgotten-export) The symbol "ObservableEvent" needs to be exported by the entry point index.d.ts
135+
//
136+
// (undocumented)
137+
peek({ timeout }?: TakeOptions): Promise<ObservableEvent<T>>;
138+
// (undocumented)
139+
take({ timeout }?: TakeOptions): Promise<ObservableEvent<T>>;
140+
// (undocumented)
141+
takeComplete(options?: TakeOptions): Promise<void>;
142+
// (undocumented)
143+
takeError(options?: TakeOptions): Promise<any>;
144+
// (undocumented)
145+
takeNext(options?: TakeOptions): Promise<T>;
146+
// (undocumented)
147+
unsubscribe(): void;
148+
}
149+
150+
// @public (undocumented)
151+
export interface PaginatedCaseData {
152+
// Warning: (ae-forgotten-export) The symbol "Letter" needs to be exported by the entry point index.d.ts
153+
//
154+
// (undocumented)
155+
letters: Letter[];
156+
}
157+
158+
// @public (undocumented)
159+
export interface PaginatedCaseVariables {
160+
// (undocumented)
161+
limit?: number;
162+
// (undocumented)
163+
offset?: number;
164+
}
165+
166+
// Warning: (ae-forgotten-export) The symbol "RendererableContainer" needs to be exported by the entry point index.d.ts
167+
// Warning: (ae-forgotten-export) The symbol "HydrateableContainer" needs to be exported by the entry point index.d.ts
168+
//
169+
// @public (undocumented)
170+
export function renderAsync<Q extends Queries = typeof queries, Container extends RendererableContainer | HydrateableContainer = HTMLElement, BaseElement extends RendererableContainer | HydrateableContainer = Container>(ui: React.ReactNode, options: RenderOptions<Q, Container, BaseElement>): Promise<RenderResult<Q, Container, BaseElement>>;
171+
172+
// @public (undocumented)
173+
export function renderAsync(ui: React.ReactNode, options?: Omit<RenderOptions, "queries"> | undefined): Promise<RenderResult>;
174+
175+
// @public (undocumented)
176+
type RendererableContainer = ReactDOMClient.Container;
177+
178+
// @public (undocumented)
179+
type RendererableContainer_2 = ReactDOMClient.Container;
180+
181+
// Warning: (ae-forgotten-export) The symbol "RendererableContainer_2" needs to be exported by the entry point index.d.ts
182+
// Warning: (ae-forgotten-export) The symbol "HydrateableContainer_2" needs to be exported by the entry point index.d.ts
183+
//
184+
// @public (undocumented)
185+
export function renderHookAsync<Result, Props, Q extends Queries = typeof queries, Container extends RendererableContainer_2 | HydrateableContainer_2 = HTMLElement, BaseElement extends RendererableContainer_2 | HydrateableContainer_2 = Container>(renderCallback: (initialProps: Props) => Result, options?: RenderHookOptions<Props, Q, Container, BaseElement> | undefined): Promise<RenderHookResult<Result, Props>>;
186+
187+
// @public
188+
export function resetApolloContext(): void;
189+
190+
// @public (undocumented)
191+
export function setupMaskedVariablesCase(): {
192+
mocks: MockedResponse<MaskedVariablesCaseData, Record<string, any>>[];
193+
query: MaskedDocumentNode<MaskedVariablesCaseData, VariablesCaseVariables>;
194+
unmaskedQuery: TypedDocumentNode<MaskedVariablesCaseData, VariablesCaseVariables>;
195+
};
196+
197+
// @public (undocumented)
198+
export function setupPaginatedCase(): {
199+
query: TypedDocumentNode<PaginatedCaseData, PaginatedCaseVariables>;
200+
link: ApolloLink;
201+
data: {
202+
__typename: string;
203+
letter: string;
204+
position: number;
205+
}[];
206+
};
207+
208+
// @public (undocumented)
209+
export function setupSimpleCase(): {
210+
query: TypedDocumentNode<SimpleCaseData, Record<string, never>>;
211+
mocks: MockedResponse<SimpleCaseData, Record<string, any>>[];
212+
};
213+
214+
// @public (undocumented)
215+
export function setupVariablesCase(): {
216+
mocks: MockedResponse<VariablesCaseData, Record<string, any>>[];
217+
query: TypedDocumentNode<VariablesCaseData, VariablesCaseVariables>;
218+
};
219+
220+
// @public (undocumented)
221+
export interface SimpleCaseData {
222+
// (undocumented)
223+
greeting: string;
224+
}
225+
226+
// Warning: (ae-forgotten-export) The symbol "ConsoleMethod" needs to be exported by the entry point index.d.ts
227+
//
228+
// @public (undocumented)
229+
type Spies<Keys extends ConsoleMethod[]> = Record<Keys[number], jest.SpyInstance<void, any[], any>>;
230+
231+
// Warning: (ae-forgotten-export) The symbol "Spies" needs to be exported by the entry point index.d.ts
232+
//
233+
// @public (undocumented)
234+
export function spyOnConsole<Keys extends ConsoleMethod[]>(...spyOn: Keys): Spies<Keys> & Disposable;
235+
236+
// @public (undocumented)
237+
export namespace spyOnConsole {
238+
var // (undocumented)
239+
takeSnapshots: <Keys extends ConsoleMethod[]>(...spyOn: Keys) => Spies<Keys> & Disposable;
240+
}
241+
242+
// @public (undocumented)
243+
interface TakeOptions {
244+
// (undocumented)
245+
timeout?: number;
246+
}
247+
248+
// @public (undocumented)
249+
export interface VariablesCaseData {
250+
// (undocumented)
251+
character: {
252+
__typename: "Character";
253+
id: string;
254+
name: string;
255+
};
256+
}
257+
258+
// @public (undocumented)
259+
export interface VariablesCaseVariables {
260+
// (undocumented)
261+
id: string;
262+
}
263+
264+
// @internal (undocumented)
265+
export function withCleanup<T extends object>(item: T, cleanup: (item: T) => void): T & Disposable;
266+
267+
// @public (undocumented)
268+
export function withProdMode(): {
269+
prevDEV: boolean;
270+
} & Disposable;
271+
272+
// Warnings were encountered during analysis:
273+
//
274+
// src/testing/internal/scenarios/index.ts:80:7 - (ae-forgotten-export) The symbol "MaskedVariablesCaseFragment" needs to be exported by the entry point index.d.ts
275+
276+
// (No @packageDocumentation comment for this package)
277+
278+
```

eslint-local-rules/import-from-export.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,60 @@ export const noInternalImportOfficialExport =
265265
},
266266
defaultOptions: [],
267267
});
268+
269+
/**
270+
* to be used in tests, so the test imports from the library instead of testing internals
271+
* (where possible)
272+
*/
273+
export const noRelativeImports = ESLintUtils.RuleCreator.withoutDocs({
274+
create(context, options) {
275+
return {
276+
ImportDeclaration(node) {
277+
if (!node.source.value.startsWith("..")) {
278+
// we're only interested in imports from parent folders outside of the test folder
279+
return;
280+
}
281+
if (node.importKind === "type") {
282+
// we're okay with internal types for now, although in most cases
283+
// they should probably be exports if they are important enough
284+
// that we need them for a test
285+
return;
286+
}
287+
const resolvedTarget = resolve(
288+
dirname(context.physicalFilename),
289+
node.source.value
290+
);
291+
if (options[0].ignoreFrom.includes(resolvedTarget)) {
292+
return;
293+
}
294+
context.report({
295+
node: node.source,
296+
messageId: "noRelativeImports",
297+
});
298+
},
299+
};
300+
},
301+
meta: {
302+
messages: {
303+
noRelativeImports:
304+
"Don't use relative imports in tests, import from official entry points instead.",
305+
},
306+
type: "problem",
307+
schema: [
308+
{
309+
type: "object",
310+
properties: {
311+
ignoreFrom: {
312+
type: "array",
313+
items: { type: "string" },
314+
},
315+
},
316+
},
317+
],
318+
},
319+
defaultOptions: [
320+
{
321+
ignoreFrom: [],
322+
},
323+
],
324+
});

eslint-local-rules/index.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
importFromInsideOtherExport,
55
noDuplicateExports,
66
noInternalImportOfficialExport,
7+
noRelativeImports,
78
} from "./import-from-export.ts";
89
import { rule as requireDisableActEnvironment } from "./require-disable-act-environment.ts";
910
import { rule as requireUsingDisposable } from "./require-using-disposable.ts";
@@ -16,4 +17,5 @@ export default {
1617
"import-from-inside-other-export": importFromInsideOtherExport,
1718
"no-internal-import-official-export": noInternalImportOfficialExport,
1819
"no-duplicate-exports": noDuplicateExports,
20+
"no-relative-imports": noRelativeImports,
1921
};

0 commit comments

Comments
 (0)