React Apollo 2.1 mock schema error - graphql

I'm trying to provide a mock schema to a component using React Apollo 2.1. However, it returns this error.
Error: Network error: No more mocked responses for the query: {
me {
id
email
username
first_name
last_name
bio
website
}
}
, variables: {}
at new ApolloError (ApolloError.js:43)
at ObservableQuery.currentResult (ObservableQuery.js:107)
at Query._this.getQueryResult (react-apollo.browser.umd.js:319)
at Query.render (react-apollo.browser.umd.js:421)
at finishClassComponent (react-dom.development.js:8389)
at updateClassComponent (react-dom.development.js:8357)
at beginWork (react-dom.development.js:8982)
at performUnitOfWork (react-dom.development.js:11814)
at workLoop (react-dom.development.js:11843)
at renderRoot (react-dom.development.js:11874)
How did you add mock functionality on React Apollo 2.1? I tried searching the solutions but both information for older versions and newer ones and couldn't resolve this.
Here's the code.
index.stories.js
import React from 'react';
import { storiesOf } from '#storybook/react';
import { action } from '#storybook/addon-actions';
import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
import gql from 'graphql-tag'
import { MemoryRouter } from 'react-router';
import { MockedProvider } from 'react-apollo/test-utils';
import { buildMockedClient } from '../../../mockedApolloClient';
import AccountSettings from './index';
const typeDefs = `
interface User {
id: ID!,
email: String!,
username: String,
first_name: String,
last_name: String,
bio: String,
website: String
}
type Student implements User {
id: ID!,
email: String!,
username: String,
first_name: String,
last_name: String,
bio: String,
website: String
}
type InputError {
key: String!
message: String!
}
type UserResult {
errors: InputError,
user: User
}
input UpdateAccountInput {
first_name: String
last_name:String
email: String
username: String
bio: String
website: String
}
type Query {
me: User
}
type Mutation {
updateAccount(params: UpdateAccountInput!): UserResult!
}
`
const typeResolvers = {
User: {
__resolveType(data) {
return data.__typename // typename property must be set by your mock functions
}
}
}
const me = {
id: () => 1,
email: () => 'testuser#test.jp',
username: () => 'hiro1107',
first_name: () => 'Atsuhiro',
last_name: () => 'Teshima',
bio: () => 'test',
website: () => 'https://www.test.jp',
}
const schema = makeExecutableSchema({
typeDefs,
typeResolvers
})
const mocks = {
User: () => ({
id: () => 1,
email: () => 'testuser#codegrit.jp',
username: () => 'hiro1107',
first_name: () => 'Atsuhiro',
last_name: () => 'Teshima',
bio: () => 'test',
website: () => 'https://www.codegrit.jp',
__typename: () => 'Student'
}),
Query: () => ({
me: () => me
})
}
addMockFunctionsToSchema({
schema,
mocks,
preserveResolvers: false
});
storiesOf('Account Settings', module)
.addDecorator(story => (
<MockedProvider client={mockedClient} mocks={mocks} >
<MemoryRouter initialEntries={['/']}>{story()}</MemoryRouter>
</MockedProvider>
))
.add('With Mock', () => (
<AccountSettings />
));
const mockedClient = buildMockedClient(schema);
storiesOf('Account Settings', module)
.addDecorator(story => (
<MockedProvider client={mockedClient} mocks={mocks} >
<MemoryRouter initialEntries={['/']}>{story()}</MemoryRouter>
</MockedProvider>
))
.add('With Mock', () => (
<AccountSettings />
));
mockedApolloClient.js
import { ApolloClient } from 'apollo-client';
import { SchemaLink } from 'apollo-link-schema';
import { InMemoryCache } from 'apollo-cache-inmemory';
const apolloCache = new InMemoryCache(window.__APOLLO_STATE__);
export function buildMockedClient(schema) {
return new ApolloClient({
cache: apolloCache,
link: new SchemaLink({ schema })
})
}
package.json
"apollo-cache-inmemory": "^1.1.9",
"apollo-client": "^2.2.5",
"apollo-link-context": "^1.0.7",
"apollo-link-http": "^1.5.2",
"apollo-link-schema": "^1.1.0",
"graphql": "^0.13.1",
"graphql-tag": "^2.8.0",
"graphql-tools": "^2.24.0",
"react": "^16.3.1",
"react-apollo": "^2.1.0",
"react-dom": "^16.3.1",

I found out that I need to use ApolloProvider instead MockedProvider.
So, this code will work.
import React from 'react';
import { storiesOf } from '#storybook/react';
import { action } from '#storybook/addon-actions';
import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
import gql from 'graphql-tag'
import { MemoryRouter } from 'react-router';
import { ApolloProvider, Query } from 'react-apollo';
import { buildMockedClient } from '../../../mockedApolloClient';
import AccountSettings from './index';
const typeDefs = `
type Query {
me: User!
}
type Mutation {
updateAccount(params: UpdateAccountInput!): UserResult!
}
interface User {
id: ID!,
email: String!,
username: String,
first_name: String,
last_name: String,
bio: String,
website: String
}
type Student implements User {
id: ID!,
email: String!,
username: String,
first_name: String,
last_name: String,
bio: String,
website: String
}
type InputError {
key: String!
message: String!
}
type UserResult {
errors: InputError,
user: User
}
input UpdateAccountInput {
first_name: String
last_name:String
email: String
username: String
bio: String
website: String
}
`
const typeResolvers = {
User: {
__resolveType(data) {
return data.__typename()
}
}
}
const mocks = {
User: () => ({
id: () => 1,
email: 'testuser#codegrit.jp',
username: 'hiro1107',
first_name: 'Atsuhiro',
last_name: 'Teshima',
bio: 'test',
website: 'https://www.test.jp',
__typename: 'Student',
}),
Student: () => ({
id: () => 1,
email: 'testuser#test.jp',
username: 'hiro1107',
first_name: 'Atsuhiro',
last_name: 'Teshima',
bio: 'test',
website: 'https://www.test.jp',
__typename: () => 'Student'
}),
query: () => ({
me: () => ({
id: () => 1,
email: 'testuser#test.jp',
username: 'hiro1107',
first_name: 'Atsuhiro',
last_name: 'Teshima',
bio: 'test',
website: 'https://www.test.jp',
__typename: () => 'Student'
})
})
}
const schema = makeExecutableSchema({
typeDefs,
resolvers: typeResolvers
})
addMockFunctionsToSchema({
schema,
mocks,
preserveResolvers: true
});
const client = buildMockedClient(schema);
const userQuery = gql`
query {
me {
id
email
username
first_name
last_name
bio
website
}
}
`
storiesOf('Account Settings', module)
.addDecorator(story => (
<ApolloProvider client={client} >
<MemoryRouter initialEntries={['/']}>{story()}</MemoryRouter>
</ApolloProvider>
))
.add('With Mock', () => (
<AccountSettings />
));

Related

I have error on apollo server and grapghql

This is the error am getting
node_modules\apollo-server-core\dist\ApolloServer.js:358
throw Error('Apollo Server requires either an existing schema, modules or typeDefs');
Here is my code:
users.typeDefs.js
On top I have "import { gql } from "apollo-server";
export default gql `"
type User {
id: String!
firstName: String!
lastName: String
username: String!
email: String!
createdAt: String!
updatedAt: String!
}
type Mutation {
createAccount(
firstName: String!
lastName: String
username: String!
email: String!
password: String!
): User
}
type Query {
seeProfile(username:String): User
}
`;
Here is my users.mutations.js
On top I have:
import { PrismaClient } from "#prisma/client";
import client from "../client";"
Here is the main code:
export default {
Mutation: {
createAccount: async (
_, {
firstName,
lastName,
username,
email,
password
}
) => {
//check if username or email are already on DB.
const existingUser = await client.user.findFirst({
where: {
OR: [
{
username,
},
{
email,
}
],
},
});
console.log(existingUser);
// hash password
// save and return the user
},
} ,
};
The users.queries.js is export default,
Here is my schema.js and client.js
import { mergeTypeDefs, mergeResolvers, } from "#graphql-tools/merge";
import { loadFilesSync } from "#graphql-tools/load-files";
import { makeExecutableSchema } from "#graphql-tools/schema";
const loadedTypes = loadFilesSync(`${__dirname}/**/*.typeDefs.js`);
const loadedResolvers = loadFilesSync(`${__dirname}/**/*.{queries,mutations}.js`);
const typeDefs = mergeTypeDefs(loadedTypes);
const resolvers = mergeResolvers(loadedResolvers);
const schema = makeExecutableSchema({typeDefs, resolvers});
export default schema;
import { PrismaClient } from "#prisma/client";
const client = new PrismaClient ();
export default client;
Here is also my server.js
require ("dotenv").config();
import { ApolloServer, gql } from "apollo-server";
import {schema} from "./schema";
const server = new ApolloServer({
schema,
});
const PORT = process.env.PORT
server.listen(PORT).then(() => {
console.log(`🚀 Server ready at http://localhost:${PORT} ✅ `);
});

Apollo-client graphql localstate management setup

I'm sitting for 2 days trying to get my setup right. My target is Next.js with ApolloGraphQl for Database request as well as local state management handling.
My problem is the setup for the local state management. Don't know why i'm unable to correctly get it to work. I hope you can help me out.
I pushed my actual status of the project on github using the following repo:
https://github.com/Maetes/apollo-next-local
UPDATE:
it is fine to query and mutate the state when i just call the cache object itself so all is fine. But when i try to trigger a resolver, nothing happens. I'ts like the Apollo-client does not see the typedefs and resolvers.
Here is my useApollo Hook with Client init:
import { IncomingMessage, ServerResponse } from 'http';
import { useMemo } from 'react';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache, NormalizedCacheObject } from 'apollo-cache-inmemory';
import { resolvers } from './localResolvers';
import { typeDefs } from './localTypeDefs';
import {
CREATE_USER,
GET_CURRENT_USER,
SET_CURRENT_USER,
ALL_USERS,
} from './localDocuments';
let apolloClient: ApolloClient<NormalizedCacheObject> | undefined;
export type ResolverContext = {
req?: IncomingMessage;
res?: ServerResponse;
};
function createIsomorphLink(context: ResolverContext = {}) {
if (typeof window === 'undefined') {
const { SchemaLink } = require('apollo-link-schema');
const { schema } = require('../pages/api/index');
return new SchemaLink({ schema, context });
} else {
const { HttpLink } = require('apollo-link-http');
return new HttpLink({
uri: 'http://localhost:3000/api',
credentials: 'same-origin',
});
}
}
function createApolloClient(context?: ResolverContext) {
let cache = new InMemoryCache();
cache.writeData({
data: {
currentUser: {
__typename: 'CurrentUser',
email: '',
nachname: '',
title: '',
id: '',
},
},
});
let client = new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createIsomorphLink(context),
cache: cache,
typeDefs,
resolvers,
});
// client.writeData({
// data: {
// currentUser: {
// __typename: 'CurrentUser',
// email: '',
// nachname: '',
// title: '',
// id: '',
// },
// },
// });
return client;
}
export function initializeApollo(
initialState: any = null,
// Pages with Next.js data fetching methods, like `getStaticProps`, can send
// a custom context which will be used by `SchemaLink` to server render pages
context?: ResolverContext
) {
const _apolloClient = apolloClient ?? createApolloClient(context);
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState);
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function useApollo(initialState: any) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
This is my typedef file:
import gql from 'graphql-tag';
export const typeDefs = gql`
extend type Query {
getCurrentUser: CurrentUser!
}
type CurrentUser {
email: String!
nachname: String!
title: String!
id: ID!
__typename: String!
}
extend type Mutation {
setCurrentUser(
email: String!
nachname: String!
title: String!
id: ID!
): CurrentUser!
}
`;
this are my resolvers:
import { InMemoryCache } from 'apollo-cache-inmemory';
import { GET_CURRENT_USER } from './localDocuments';
export const resolvers = {
CurrentUser: {
currentUser: (_: {}, { cache }: { cache: InMemoryCache }) => {
console.log('Resolver Query triggered');
// const { user }: any = cache.readQuery({
// query: GET_CURRENT_USER,
// });
const data: any = {};
data.__typename = 'CurrentUser';
return data;
},
getCurrentUser: (_: {}, { cache }: { cache: InMemoryCache }) => {
console.log('Resolver Query triggered');
// const { user }: any = cache.readQuery({
// query: GET_CURRENT_USER,
// });
const data: any = {};
data.__typename = 'CurrentUser';
return data;
},
},
Query: {
getCurrentUser: (_: {}, { cache }: { cache: InMemoryCache }) => {
console.log('Resolver Query triggered');
// const { user }: any = cache.readQuery({
// query: GET_CURRENT_USER,
// });
const data: any = {};
data.__typename = 'CurrentUser';
return data;
},
currentUser: (_: {}, { cache }: { cache: InMemoryCache }) => {
console.log('Resolver Query triggered');
// const { user }: any = cache.readQuery({
// query: GET_CURRENT_USER,
// });
const data: any = {};
data.__typename = 'CurrentUser';
return data;
},
},
Mutation: {
setCurrentUser: (
_: {},
variables: any,
{ cache }: { cache: InMemoryCache }
) => {
const { currentUser }: any = cache.readQuery({ query: GET_CURRENT_USER });
console.log('mutationResolver Triggered');
console.log(
'olduser',
currentUser.email,
currentUser.nachname,
currentUser.title
);
const newUser = {
email: variables.email,
title: variables.title,
nachname: variables.nachname,
__typename: 'CurrentUser',
};
console.log('newUser', newUser);
const erg = cache.writeQuery({
query: GET_CURRENT_USER,
data: newUser,
});
return newUser;
},
},
};
And finaly my Document file for individual input. Please note in the GetCurrentUserQuery query when i change "getCurrentUser" to "currentUser" all is working fine cause apollo targets the raw object itself.
import gql from 'graphql-tag';
//Server
export const ALL_USERS = gql`
query allUsersQuery {
allUsers {
title
nachname
email
id
__typename
}
}
`;
//client
export const GET_CURRENT_USER = gql`
query GetCurrentUserQuery {
getCurrentUser #client(always: true) {
email
nachname
title
__typename
}
}
`;
//Client
export const SET_CURRENT_USER = gql`
mutation SetCurrentUserMutation(
$email: String!
$nachname: String!
$title: String!
$id: String!
) {
setCurrentUser(email: $email, nachname: $nachname, title: $title) #client {
email
title
nachname
id
__typename
}
}
`;
//Server
export const CREATE_USER = gql`
mutation CreateUserMutation(
$email: String!
$nachname: String!
$title: String!
$password: String!
) {
createUser(
email: $email
nachname: $nachname
title: $title
password: $password
) {
__typename
email
nachname
title
password
id
}
}
`;

Prisma cannot create a user type because of array argument?

this is my InputType in schema.graphql:
input RegisterInput {
birthday: String!
email: String!
firstName: String!
gender: String!
interests: [String!]!
lastName: String!
password: String!
}
and this is my mutation:
const RegisterInput = inputObjectType({
name: 'RegisterInput',
definition(t) {
t.string('birthday', { nullable: false });
t.string('email', { nullable: false });
t.string('firstName', { nullable: false });
t.string('lastName', { nullable: false });
t.string('gender', { nullable: false });
t.string('password', { nullable: false });
t.list.field('interests', {
type: 'String',
nullable: false,
});
},
});
const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.field('register', {
type: User,
args: {
data: arg({ type: RegisterInput }),
},
resolve: async (
_root,
{ data: { password, interests, ...userData } },
{ prisma }
) => {
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
...userData,
interests: [...interests],
password: hashedPassword,
},
});
return user;
},
});
my interests is just an array of strings, .e.g: ['abcd', 'def']
but i got this error:
Unknown arg `0` in data.interests.0 for type UserCreateInterestInput. Available args:
type UserCreateInterestsInput {
set?: List<String>
}
that error will repeat depending of how many items is in the array, e.g.: Unknown arg '1' and so on, same error message, how do i fix this?
You must provide a list of strings to set argument, such as:
type UserCreateInterestsInput {
set?: List<String>
}
Refer to this issue for more information.
const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.field('register', {
type: User,
args: {
data: arg({ type: RegisterInput }),
},
resolve: async (
_root,
{ data: { password, interests, ...userData } },
{ prisma }
) => {
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
...userData,
interests: {set: interests},
password: hashedPassword,
},
});
return user;
},
});
Hope this helps
Happened to me earlier, turns out it was a query mistake.
mutation {
createFruit(data:{
name: "Banana",
images: {
set: ["image_1.img", "image_2.img"]
}
}) {
name
images
}
}
Note it's not images: ["image_1.img", "image_2.img"]
fyi with prisma you can do t.model.interest() when defining objectType

What is wrong with mutation call in Apollo GraphQL server?

The call:
mutation {
upvotePost(postId: 1) {
id
}
}
The response:
Below the code:
const { ApolloServer, gql } = require('apollo-server');
const typeDefs = `
type Author {
id: Int!
firstName: String
lastName: String
"""
the list of Posts by this author
"""
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
# the schema allows the following query:
type Query {
posts: [Post]
author(id: Int!): Author
}
# this schema allows the following mutation:
type Mutation {
upvotePost (
postId: Int!
): Post
}
`;
// example data
const authors = [
{ id: 1, firstName: 'Tom', lastName: 'Coleman' },
{ id: 2, firstName: 'Sashko', lastName: 'Stubailo' },
{ id: 3, firstName: 'Mikhail', lastName: 'Novikov' },
];
const posts = [
{ id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2 },
{ id: 2, authorId: 2, title: 'Welcome to Meteor', votes: 3 },
{ id: 3, authorId: 2, title: 'Advanced GraphQL', votes: 1 },
{ id: 4, authorId: 3, title: 'Launchpad is Cool', votes: 7 },
];
const resolvers = {
Query: {
posts: () => posts,
author: (_, { id }) => find(authors, { id }),
},
Mutation: {
upvotePost: (_, { postId }) => {
const post = find(posts, { id: postId });
if (!post) {
throw new Error(`Couldn't find post with id ${postId}`);
}
post.votes += 1;
return post;
},
},
Author: {
posts: author => filter(posts, { authorId: author.id }),
},
Post: {
author: post => find(authors, { id: post.authorId }),
},
};
// The ApolloServer constructor requires two parameters: your schema
// definition and your set of resolvers.
const server = new ApolloServer({ typeDefs, resolvers });
// The `listen` method launches a web server.
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
In order to use the 'find' method you need to import lodash
npm install lodash
Then in your file require lodash like this:
const { find, filter } = require('lodash');

Creating a mutation component

I am trying to create a graphql mutation component. My goal is to be able to import it and call registerUser(userInfo) to run and execute my mutation.
const registerUser = (user) => {
const REGISTER_USER = gql`
mutation RegisterUser($email: String!, $password: String!, $username: String!){
RegisterUser(email: $email, password: $password, username: $username){
id
username
email
}
}
`
const variables = {
email: user.email,
password: user.password,
username: user.username,
};
return (
<Mutation mutation={REGISTER_USER} variables={variables}>
{(registerUser, { error, data }) => {
if (error) console.log('error', error);
if (data) console.log('data', data);
registerUser()
}}
</Mutation>
)
}
export default registerUser;

Resources