Skip to content

Instantly share code, notes, and snippets.

@andycarrell
Last active November 12, 2019 01:10
Show Gist options
  • Save andycarrell/4a5a7e848cf21e6d9aae559aaf32d286 to your computer and use it in GitHub Desktop.
Save andycarrell/4a5a7e848cf21e6d9aae559aaf32d286 to your computer and use it in GitHub Desktop.
import React from "react";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink, Observable } from "apollo-link";
export const createErrorLink = ({ errors = null }) => {
if (errors) {
return new ApolloLink(
() =>
new Observable(observer => {
observer.next({ errors });
observer.complete();
}),
);
}
return new ApolloLink(
(operation, forward) =>
new Observable(observer => {
forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
});
}),
);
};
const ApolloErrorProvider = ({ children, graphQLErrors }) => {
const client = new ApolloClient({
cache: new InMemoryCache(),
link: createErrorLink({
errors: graphQLErrors || [{ message: "InternalServerError" }],
}),
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
import React from "react";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink, Observable } from "apollo-link";
const ApolloLoadingProvider = (props) => {
const link = new ApolloLink((operation) => {
return new Observable(() => {});
});
const client = new ApolloClient({
link,
cache: new InMemoryCache(),
});
return (
<ApolloProvider client={client}>
{props.children}
</ApolloProvider>
);
};
import React, { useRef } from "react";
import PropTypes from "prop-types";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { SchemaLink } from "apollo-link-schema";
import { ApolloLink, Observable } from "apollo-link";
import { makeMockedSchema } from "../schema";
import { createErrorLink } from "./ApolloErrorProvider";
const createDelayLink = ({ wait = 0 }) => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
return new ApolloLink(
(operation, forward) =>
new Observable(observer => {
let cleanup = () => {};
sleep(wait).then(() => {
const { unsubscribe } = forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
});
cleanup = () => unsubscribe();
});
return cleanup;
}),
);
};
function useMockClient({ mocks, wait, errors }) {
const client = useRef(null);
if (!client.current) {
client.current = new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([
createDelayLink({ wait }),
createErrorLink({ errors }),
new SchemaLink({ schema: makeMockedSchema({ mocks }) }),
]),
});
}
return client.current;
}
const ApolloMockProvider = ({ children, mocks, wait, graphQLErrors }) => {
const client = useMockClient({ mocks, wait, errors: graphQLErrors });
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
import { makeExecutableSchema, addMockFunctionsToSchema } from "graphql-tools";
import schemaDefinition from "./schemaDefinition"; // string definition of the schema
const defaultMocks = {
DateTime: () => new Date(casual.date()).toISOString(),
};
export default function makeMockedSchema({ mocks }) {
const schema = makeExecutableSchema({ typeDefs: schemaDefinition });
addMockFunctionsToSchema({
schema,
mocks: mergeResolvers(defaultMocks, mocks),
});
return schema;
}
function mergeResolvers(target, input) {
const inputTypenames = Object.keys(input);
const merged = inputTypenames.reduce(
(accum, key) => {
const inputResolver = input[key];
if (key in target) {
const targetResolver = target[key];
const resolvedInput = inputResolver();
const resolvedTarget = targetResolver();
if (
!!resolvedTarget &&
!!resolvedInput &&
typeof resolvedTarget === "object" &&
typeof resolvedInput === "object" &&
!Array.isArray(resolvedTarget) &&
!Array.isArray(resolvedInput)
) {
const newValue = { ...resolvedTarget, ...resolvedInput };
return {
...accum,
[key]: () => newValue,
};
}
}
return { ...accum, [key]: inputResolver };
},
{ ...target },
);
return merged;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment