Closed jkdowdle closed 6 years ago
Sorry I got really busy and didn't have time to reply to this. I have never used fragmentMatcher so I'm not sure what it does right now.
I think possibly having them all in the config object including the resolver might make it clearer. What do you think?
Also question - why does the config default to empty objects for the schema and also for the cache? Isn't the schema a string of typeDefs?
@jefflau Thanks for getting back to me! And no problem. I know we get busy.
This is the first time I have needed to use fragmentMatcher option in InMemoryCache, it is for apollo client to be aware of union / interface types in your schema so you can use fragments on those types. https://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher
I think possibly having them all in the config object including the resolver might make it clearer. What do you think?
I like this idea! I do think it makes it cleaner/clearer. So if I am understanding correctly it would be something like this, right?
function setupClient({ mockResolvers, ...rest }) { ... }
Also question - why does the config default to empty objects for the schema and also for the cache? Isn't the schema a string of typeDefs?
I'll do my best to explain my line of thinking, but there may be a better way to do it.
makeExectiableSchema takes an object with several options. Only typeDefs are required, however there could be other options that users will end up needing in the future. Maybe for debugging they want to pass in logging option, etc.
makeExecutableSchema({
typeDefs,
resolvers, // optional
logger, // optional
allowUndefinedInResolve = false, // optional
resolverValidationOptions = {}, // optional
directiveResolvers = null, // optional
schemaDirectives = null, // optional
parseOptions = {}, // optional
inheritResolversFromInterfaces = false // optional
})
https://www.apollographql.com/docs/graphql-tools/generate-schema.html#makeExecutableSchema
Similarly, InMemoryCache takes an object with a few different options, the one I needed was to pass in fragmentMatcher.
https://www.apollographql.com/docs/react/advanced/caching.html#configuration
Maybe this would be more clear by showing the way I am using the function.
import setupClient from 'apollo-client-mock'
import typeDefs from './schema.graphql'
import { fragmentMatcher } from '../client'
const defaultMocks = {
...
}
const config = {
schema: {
typeDefs,
resolverValidationOptions: {
requireResolversForResolveType: false
}
},
cache: { fragmentMatcher }
}
const createClient = setupClient(defaultMocks, config)
export default createClient
So I don't think that we need them to be default params to an empty object, but by allowing an object to be passed in to InMemoryCache and makeExectutableSchema the user is able to pass in any available options.
Maybe a more appropriate name for these properties is like cacheOptions, schemaOptions or even makeExecutableSchemaOptions. etc. It makes them kinda long, but more explicit. If you have a better naming convention come up, I am all for it.
Let me know if that is more clear and if it makes sense.
This is what I am using right now for a project.
const { ApolloClient } = require('apollo-client')
const { InMemoryCache } = require('apollo-cache-inmemory')
const { SchemaLink } = require('apollo-link-schema')
const {
makeExecutableSchema,
addMockFunctionsToSchema
} = require('graphql-tools')
const merge = require('lodash/merge')
function setupClient({ defaultMockResolvers = {}, makeExecutableSchemaOptions, inMemoryCacheOptions }) {
return function createClient(overwriteMocks = {}) {
const mergedMocks = merge({ ...defaultMockResolvers }, overwriteMocks)
const schema = makeExecutableSchema(makeExecutableSchemaOptions)
addMockFunctionsToSchema({
schema,
mocks: mergedMocks
})
const apolloCache = new InMemoryCache(inMemoryCacheOptions).restore(
window.__APOLLO_STATE__
)
const graphqlClient = new ApolloClient({
cache: apolloCache,
link: new SchemaLink({ schema })
})
return graphqlClient
}
}
module.exports = setupClient
And implementing it
import setupClient from 'apollo-client-mock'
import typeDefs from './schema.graphql'
import { fragmentMatcher } from '../client'
const defaultMockResolvers = {
Query: () => ({
viewer: () => null
})
}
const createClient = setupClient({
defaultMockResolvers,
makeExecutableSchemaOptions: {
typeDefs,
resolverValidationOptions: {
requireResolversForResolveType: false
}
},
inMemoryCacheOptions: { fragmentMatcher }
})
export default createClient
Hey @jkdowdle sorry again for the late reply. I think the basic idea of being able to customise the client with options is a good one so I'm happy to take a pull request for this. If you add this in with some tests for each options we support with documentation added in the README, I'll review it and see if we can get it merged in!
Just submitted a PR, let me know if it needs anything else. Thanks!
Feature Request Discussion
Hey @jefflau, I had another need come up to modify apollo-client-mock to pass in fragmentMatcher to InMemoryCache to support a union graphql type in my schema. After doing so I started getting a warning pop up in the console. To silence it I needed to pass in other config options to makeExecutableSchema.
On that same not, maybe I could add an example of mocking a union / interface type.
So before adding a PR I wanted to check with you what you thought might be the best api for this. I am not thrilled with what I came up with but it works! Here is an example.
So do you think something like that would work? Is there anything else we are missing that you need in your project that you're working on alongside this package? Do you see any adjustments that we would need in the future?
I haven't used any other apollo cache solution besides InMemoryCache, so I am not sure if the package would need to support other caches like hermes. I'd assume if a cache is compatible with apollo-client then it would be safe to run tests against InMemoryCache, but like I said I don't know.
Any way, I'd be happy to put in a pr based on this and any input you have if you'd like.