@shopify/graphql-testing
Advanced tools
Comparing version 0.0.0-snapshot-20230216210221 to 0.0.0-snapshot-20230217161532
@@ -5,5 +5,3 @@ 'use strict'; | ||
var apolloLink = require('apollo-link'); | ||
var apolloCacheInmemory = require('apollo-cache-inmemory'); | ||
var client = require('./client.js'); | ||
var client = require('@apollo/client'); | ||
var operations = require('./operations.js'); | ||
@@ -16,6 +14,4 @@ var utilities = require('./utilities.js'); | ||
constructor(mock = {}, { | ||
unionOrIntersectionTypes = [], | ||
cacheOptions = {}, | ||
links = [], | ||
assumeImmutableResults = false | ||
links = [] | ||
} = {}) { | ||
@@ -37,19 +33,9 @@ this.client = void 0; | ||
const cache = new apolloCacheInmemory.InMemoryCache({ | ||
fragmentMatcher: new apolloCacheInmemory.IntrospectionFragmentMatcher({ | ||
introspectionQueryResultData: { | ||
__schema: { | ||
types: unionOrIntersectionTypes | ||
} | ||
} | ||
}), | ||
...cacheOptions | ||
}); | ||
const cache = new client.InMemoryCache(cacheOptions); | ||
this.mockLink = new mocks.MockLink(mock); | ||
const link = apolloLink.ApolloLink.from([...links, new inflight.InflightLink({ | ||
const link = client.ApolloLink.from([...links, new inflight.InflightLink({ | ||
onCreated: this.handleCreate, | ||
onResolved: this.handleResolve | ||
}), this.mockLink]); | ||
this.client = new client.TestingApolloClient({ | ||
assumeImmutableResults, | ||
this.client = new client.ApolloClient({ | ||
link, | ||
@@ -69,27 +55,25 @@ cache | ||
async resolveAll(options = {}) { | ||
let requestFilter; | ||
if (Object.keys(options).length) { | ||
const finalOperationName = utilities.operationNameFromFindOptions(options); | ||
requestFilter = ({ | ||
operation | ||
}) => { | ||
const nameMatchesOrWasNotSet = finalOperationName ? finalOperationName === operation.operationName : true; | ||
const customFilterMatchesOrWasNotSet = options.filter ? options.filter(operation) : true; | ||
return nameMatchesOrWasNotSet && customFilterMatchesOrWasNotSet; | ||
}; | ||
} | ||
await this.wrappers.reduce((perform, wrapper) => { | ||
return () => wrapper(perform); | ||
}, async () => { | ||
const finalOperationName = utilities.operationNameFromFindOptions(options); | ||
await this.withWrapper(async () => { | ||
const allPendingRequests = Array.from(this.pendingRequests); | ||
const matchingRequests = requestFilter ? allPendingRequests.filter(requestFilter) : allPendingRequests; | ||
const matchingRequests = finalOperationName ? allPendingRequests.filter(({ | ||
operation: { | ||
operationName | ||
} | ||
}) => operationName === finalOperationName) : allPendingRequests; | ||
await Promise.all(matchingRequests.map(({ | ||
resolve | ||
}) => resolve())); | ||
})(); | ||
}); | ||
} | ||
async waitForQueryUpdates() { | ||
// queryManager is an internal implementation detail that is a TS-private | ||
// property. We can access it in JS but TS thinks we can't so cast to any | ||
// to shut typescript up | ||
await this.withWrapper(async () => { | ||
await this.client.queryManager.broadcastQueries(); | ||
}); | ||
} | ||
wrap(wrapper) { | ||
@@ -99,4 +83,12 @@ this.wrappers.push(wrapper); | ||
async withWrapper(cb) { | ||
await this.wrappers.reduce((perform, wrapper) => { | ||
return () => wrapper(perform); | ||
}, async () => { | ||
await cb(); | ||
})(); | ||
} | ||
} | ||
exports.GraphQL = GraphQL; |
@@ -5,5 +5,6 @@ 'use strict'; | ||
var apolloLink = require('apollo-link'); | ||
var client = require('@apollo/client'); | ||
class InflightLink extends apolloLink.ApolloLink { | ||
/* eslint-disable promise/catch-or-return */ | ||
class InflightLink extends client.ApolloLink { | ||
constructor(options) { | ||
@@ -23,16 +24,20 @@ super(); | ||
}); | ||
let operationsCompleteResolver; | ||
const operationsCompletePromise = new Promise(resolve => { | ||
operationsCompleteResolver = resolve; | ||
}); | ||
const request = { | ||
operation, | ||
resolve: () => { | ||
resolve: async () => { | ||
resolver(); | ||
await operationsCompletePromise; | ||
this.options.onResolved(request); | ||
return promise; | ||
} | ||
}; | ||
this.options.onCreated(request); | ||
return new apolloLink.Observable(observer => { | ||
return new client.Observable(observer => { | ||
return nextLink(operation).subscribe({ | ||
complete() { | ||
const complete = observer.complete.bind(observer); | ||
promise.then(complete).catch(complete); | ||
promise.then(complete).catch(complete).finally(operationsCompleteResolver); | ||
}, | ||
@@ -42,3 +47,3 @@ | ||
const next = observer.next.bind(observer, result); | ||
promise.then(next).catch(next); | ||
promise.then(next).catch(next).finally(operationsCompleteResolver); | ||
}, | ||
@@ -48,3 +53,3 @@ | ||
const fail = observer.error.bind(observer, error); | ||
promise.then(fail).catch(fail); | ||
promise.then(fail).catch(fail).finally(operationsCompleteResolver); | ||
} | ||
@@ -51,0 +56,0 @@ |
@@ -5,6 +5,6 @@ 'use strict'; | ||
var apolloLink = require('apollo-link'); | ||
var client = require('@apollo/client'); | ||
var graphql = require('graphql'); | ||
class MockLink extends apolloLink.ApolloLink { | ||
class MockLink extends client.ApolloLink { | ||
constructor(mock) { | ||
@@ -20,3 +20,3 @@ super(); | ||
request(operation) { | ||
return new apolloLink.Observable(obs => { | ||
return new client.Observable(obs => { | ||
const { | ||
@@ -23,0 +23,0 @@ mock |
@@ -7,6 +7,5 @@ 'use strict'; | ||
query, | ||
mutation, | ||
operationName | ||
mutation | ||
}) { | ||
const passedOptions = [query, mutation, operationName].filter(Boolean); | ||
const passedOptions = [query, mutation].filter(Boolean); | ||
@@ -16,6 +15,6 @@ if (passedOptions.length === 0) { | ||
} else if (passedOptions.length > 1) { | ||
throw new Error('You can only pass one of query, mutation, or operationName when finding a GraphQL operation'); | ||
throw new Error('You can only pass one of query or mutation'); | ||
} | ||
return operationName || operationNameFromDocument(query || mutation); | ||
return operationNameFromDocument(query || mutation); | ||
} | ||
@@ -22,0 +21,0 @@ function operationNameFromDocument(document) { |
@@ -1,15 +0,8 @@ | ||
import { ApolloLink } from 'apollo-link'; | ||
import { InMemoryCacheConfig } from 'apollo-cache-inmemory'; | ||
import { ApolloClient } from 'apollo-client'; | ||
import { ApolloClient, ApolloLink, InMemoryCacheConfig } from '@apollo/client'; | ||
import { Operations } from './operations'; | ||
import { GraphQLMock, MockRequest, FindOptions } from './types'; | ||
import { GraphQLMock, FindOptions } from './types'; | ||
export interface Options { | ||
unionOrIntersectionTypes?: any[]; | ||
cacheOptions?: InMemoryCacheConfig; | ||
links?: ApolloLink[]; | ||
assumeImmutableResults?: boolean; | ||
} | ||
interface ResolveAllFindOptions extends FindOptions { | ||
filter?: (operation: MockRequest['operation']) => boolean; | ||
} | ||
interface Wrapper { | ||
@@ -24,10 +17,12 @@ (perform: () => Promise<void>): Promise<void>; | ||
private readonly mockLink; | ||
constructor(mock?: GraphQLMock, { unionOrIntersectionTypes, cacheOptions, links, assumeImmutableResults, }?: Options); | ||
constructor(mock?: GraphQLMock, { cacheOptions, links }?: Options); | ||
update(mock: GraphQLMock): void; | ||
resolveAll(options?: ResolveAllFindOptions): Promise<void>; | ||
resolveAll(options?: FindOptions): Promise<void>; | ||
waitForQueryUpdates(): Promise<void>; | ||
wrap(wrapper: Wrapper): void; | ||
private handleCreate; | ||
private handleResolve; | ||
private withWrapper; | ||
} | ||
export {}; | ||
//# sourceMappingURL=graphql-controller.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import { ApolloLink, Observable, Operation, NextLink, FetchResult } from 'apollo-link'; | ||
import { ApolloLink, Observable, Operation, NextLink, FetchResult } from '@apollo/client'; | ||
import { MockRequest } from '../types'; | ||
@@ -3,0 +3,0 @@ interface Options { |
@@ -1,2 +0,2 @@ | ||
import { ApolloLink, Observable, Operation } from 'apollo-link'; | ||
import { ApolloLink, Observable, Operation } from '@apollo/client'; | ||
import { GraphQLMock } from '../types'; | ||
@@ -3,0 +3,0 @@ export declare class MockLink extends ApolloLink { |
@@ -1,2 +0,2 @@ | ||
import { Operation } from 'apollo-link'; | ||
import { Operation } from '@apollo/client'; | ||
export declare function assertIsGraphQL(graphQL: unknown, { expectation, isNot }: { | ||
@@ -3,0 +3,0 @@ expectation: string; |
@@ -1,2 +0,2 @@ | ||
import { Operation } from 'apollo-link'; | ||
import { Operation } from '@apollo/client'; | ||
import { FindOptions } from './types'; | ||
@@ -3,0 +3,0 @@ export declare class Operations { |
import { DocumentNode } from 'graphql'; | ||
import { GraphQLRequest, Operation } from 'apollo-link'; | ||
import { GraphQLRequest, Operation } from '@apollo/client'; | ||
export interface FindOptions { | ||
@@ -10,6 +10,2 @@ query?: DocumentNode | { | ||
mutation?: DocumentNode; | ||
/** | ||
* @deprecated Please use `query` or `mutation` instead. | ||
*/ | ||
operationName?: string; | ||
} | ||
@@ -16,0 +12,0 @@ export type MockGraphQLResponse = Error | object; |
import { DocumentNode } from 'graphql'; | ||
import { FindOptions } from './types'; | ||
export declare function operationNameFromFindOptions({ query, mutation, operationName, }: FindOptions): string | undefined; | ||
export declare function operationNameFromFindOptions({ query, mutation }: FindOptions): string | undefined; | ||
export declare function operationNameFromDocument(document: DocumentNode | { | ||
@@ -5,0 +5,0 @@ resolver: { |
{ | ||
"name": "@shopify/graphql-testing", | ||
"version": "0.0.0-snapshot-20230216210221", | ||
"version": "0.0.0-snapshot-20230217161532", | ||
"license": "MIT", | ||
@@ -34,5 +34,3 @@ "description": "Utilities to create mock GraphQL factories", | ||
"dependencies": { | ||
"apollo-cache-inmemory": ">=1.0.0 <2.0.0", | ||
"apollo-client": ">=2.0.0 <3.0.0", | ||
"apollo-link": ">=1.0.0 <2.0.0", | ||
"@apollo/client": "^3.5.8", | ||
"graphql": ">=14.5.0 <16.0.0", | ||
@@ -39,0 +37,0 @@ "jest-matcher-utils": "^26.6.2" |
@@ -20,7 +20,9 @@ # `@shopify/graphql-testing` | ||
The default utility exported by this library is `createGraphQLFactory`. This factory accepts an optional options argument that allows you to pass a `unionOrIntersectionTypes` array and/ or additional `cacheOptions` that will be used to construct an Apollo in-memory cache and/ or `links` which can contain `ApolloLink`s that will be passed to the apollo client links. | ||
The default utility exported by this library is `createGraphQLFactory`. This factory accepts an optional options argument that allows you to pass a `cacheOptions` that will be used to construct an Apollo in-memory cache and/ or `links` which can contain `ApolloLink`s that will be passed to the apollo client links. | ||
```js | ||
const createGraphQL = createGraphQLFactory({ | ||
unionOrIntersectionTypes: [], | ||
cacheOptions: { | ||
possibleTypes: {}, | ||
}, | ||
}); | ||
@@ -52,3 +54,3 @@ ``` | ||
You can also pass a `query`, `mutation` or `filter` option to `resolveAll`. `query` and `mutation` will filter the pending operations and only resolve the ones with a matching operation. `filter` allows you to write your own custom filter function based upon the operation, for instace this will allow you to filter by the variables passed to the query. If `filter` is passed in addition to `query` or `mutation` then both filters shall be applied. | ||
You can also pass a `query` or `mutation` option to `resolveAll`, which will filter the pending operations and only resolve the ones with a matching operation. | ||
@@ -59,14 +61,13 @@ ```js | ||
```js | ||
await graphQL.resolveAll({ | ||
query: petQuery, | ||
filter: (operation) => operation.variables.id === '1', | ||
}); | ||
``` | ||
Note that, until a GraphQL operation has been resolved, it does not appear in the `operations` list described below. | ||
#### `waitForQueryUpdates()` | ||
Apollo 3.6.0+ batches updates to the cache asynchronously. This means that in cases where you trigger fetching more data using `fetchMore` often the cache is persisted in the next tick and thus the component making the query does not update in the expected act block. This can result in flaky tests where you request data, and use resolveAll to fetch it, but the React component under test does not update. | ||
The `waitForQueryUpdates()` method shall ensure all cache updates are resolved. | ||
#### `wrap()` | ||
The `wrap()` method allows you to wrap all GraphQL resolutions in a function call. This can be useful when working with React components, which require that all operations that lead to state changes be wrapped in an `act()` call. The following example demonstrates using this with [`@shopify/react-testing`](../react-testing): | ||
The `wrap()` method allows you to wrap all calls to `resolveAll()` and `waitForQueryUpdates()` in a function call. This can be useful when working with React components, which require that all operations that lead to state changes be wrapped in an `act()` call. The following example demonstrates using this with [`@shopify/react-testing`](../react-testing): | ||
@@ -73,0 +74,0 @@ ```tsx |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3
191
60388
62
830
+ Added@apollo/client@^3.5.8
+ Added@apollo/client@3.12.3(transitive)
+ Added@graphql-typed-document-node/core@3.2.0(transitive)
+ Added@wry/caches@1.0.1(transitive)
+ Added@wry/context@0.7.4(transitive)
+ Added@wry/equality@0.5.7(transitive)
+ Added@wry/trie@0.5.0(transitive)
+ Addedgraphql-tag@2.12.6(transitive)
+ Addedhoist-non-react-statics@3.3.2(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedoptimism@0.18.1(transitive)
+ Addedprop-types@15.8.1(transitive)
+ Addedreact-is@16.13.1(transitive)
+ Addedrehackt@0.1.0(transitive)
+ Addedresponse-iterator@0.2.6(transitive)
+ Addedsymbol-observable@4.0.0(transitive)
+ Addedts-invariant@0.10.3(transitive)
+ Addedtslib@2.8.1(transitive)
+ Addedzen-observable-ts@1.2.5(transitive)
- Removedapollo-cache-inmemory@>=1.0.0 <2.0.0
- Removedapollo-client@>=2.0.0 <3.0.0
- Removedapollo-link@>=1.0.0 <2.0.0
- Removed@types/zen-observable@0.8.7(transitive)
- Removed@wry/context@0.4.4(transitive)
- Removed@wry/equality@0.1.11(transitive)
- Removedapollo-cache@1.3.5(transitive)
- Removedapollo-cache-inmemory@1.6.6(transitive)
- Removedapollo-client@2.6.10(transitive)
- Removedapollo-link@1.2.14(transitive)
- Removedapollo-utilities@1.3.4(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedoptimism@0.10.3(transitive)
- Removedsymbol-observable@1.2.0(transitive)
- Removedts-invariant@0.4.4(transitive)
- Removedtslib@1.14.1(transitive)
- Removedzen-observable-ts@0.8.21(transitive)