diff --git a/.flowconfig b/.flowconfig
new file mode 100644
index 0000000000..c2a4545473
--- /dev/null
+++ b/.flowconfig
@@ -0,0 +1,12 @@
+[ignore]
+.*/examples/**/.*
+.*/node_modules/art/.*
+.*/node_modules/react-native/**/.*
+
+[include]
+
+[libs]
+./index.js.flow
+
+[options]
+suppress_comment= \\(.\\|\n\\)*\\$ExpectError
diff --git a/Changelog.md b/Changelog.md
index e455bf7861..b807098753 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,9 +1,13 @@
# Change log
-Expect active development and potentially significant breaking changes in the `0.x` track. We'll try to be diligent about releasing a `1.0` version in a timely fashion (ideally within 1 or 2 months), so that we can take advantage of SemVer to signify breaking changes from that point on.
-
### vNext
+### 1.4.0
+#### BREAKING FOR TYPESCRIPT USERS
+- Feature: Enhanced typescript definitions to allow for more valid type checking of graphql HOC [PR #695](https://github.com/apollographql/react-apollo/pull/695)
+- Feature: Flow types: [PR #695](https://github.com/apollographql/react-apollo/pull/695)
+
+
### 1.3.0
- Feature: Support tree shaking and smaller (marginally) bundles via rollup [PR #691](https://github.com/apollographql/react-apollo/pull/691)
- Fix: Render full markup on the server when using the `cache-and-network` fetchPolicy [PR #688](https://github.com/apollographql/react-apollo/pull/688)
diff --git a/index.js.flow b/index.js.flow
new file mode 100644
index 0000000000..dca467b241
--- /dev/null
+++ b/index.js.flow
@@ -0,0 +1,165 @@
+import type {
+ ApolloClient,
+ MutationQueryReducersMap,
+ ApolloQueryResult,
+ ApolloError,
+ FetchPolicy,
+ FetchMoreOptions,
+ UpdateQueryOptions,
+ FetchMoreQueryOptions,
+ SubscribeToMoreOptions,
+} from "apollo-client";
+import type { Store } from "redux";
+import type { DocumentNode, VariableDefinitionNode } from "graphql";
+
+declare module "react-apollo" {
+ declare type StatelessComponent
= (props: P) => ?React$Element;
+
+ declare export interface ProviderProps {
+ store?: Store,
+ client: ApolloClient,
+ }
+
+ declare export class ApolloProvider extends React$Component {
+ props: ProviderProps,
+ childContextTypes: {
+ store: Store,
+ client: ApolloClient,
+ },
+ contextTypes: {
+ store: Store,
+ },
+ getChildContext(): {
+ store: Store,
+ client: ApolloClient,
+ },
+ render(): React$Element<*>,
+ }
+ declare export type MutationFunc = (
+ opts: MutationOpts
+ ) => Promise>;
+
+ declare export type DefaultChildProps = {
+ data: QueryProps & R,
+ mutate: MutationFunc,
+ } & P;
+
+ declare export interface MutationOpts {
+ variables?: { [key: string]: mixed },
+ optimisticResponse?: Object,
+ updateQueries?: MutationQueryReducersMap,
+ }
+
+ declare export interface QueryOpts {
+ ssr?: boolean,
+ variables?: {
+ [key: string]: mixed,
+ },
+ fetchPolicy?: FetchPolicy,
+ pollInterval?: number,
+ skip?: boolean,
+ }
+
+ declare export interface QueryProps {
+ error?: ApolloError,
+ networkStatus: number,
+ loading: boolean,
+ variables: {
+ [variable: string]: any,
+ },
+ fetchMore: (
+ fetchMoreOptions: FetchMoreQueryOptions & FetchMoreOptions
+ ) => Promise>,
+ refetch: (variables?: any) => Promise>,
+ startPolling: (pollInterval: number) => void,
+ stopPolling: () => void,
+ subscribeToMore: (options: SubscribeToMoreOptions) => () => void,
+ updateQuery: (
+ mapFn: (previousQueryResult: any, options: UpdateQueryOptions) => any
+ ) => void,
+ }
+
+ declare export interface OptionProps {
+ ownProps: TProps,
+ data?: QueryProps & TResult,
+ mutate?: MutationFunc,
+ }
+
+ declare export type OptionDescription = (
+ props: P
+ ) => QueryOpts | MutationOpts;
+
+ declare export interface OperationOption {
+ options?: OptionDescription,
+ props?: (props: OptionProps) => any,
+ skip?: boolean | ((props: any) => boolean),
+ name?: string,
+ withRef?: boolean,
+ shouldResubscribe?: (props: TProps, nextProps: TProps) => boolean,
+ alias?: string,
+ }
+
+ declare export interface OperationComponent<
+ TResult: Object = {},
+ TOwnProps: Object = {},
+ TMergedProps = DefaultChildProps
+ > {
+ (
+ component:
+ | StatelessComponent
+ | React$Component<*, TMergedProps, *>
+ ): React$Component<*, TOwnProps, *>,
+ }
+
+ declare export function graphql(
+ document: DocumentNode,
+ operationOptions?: OperationOption
+ ): OperationComponent;
+
+ declare export interface IDocumentDefinition {
+ type: DocumentType,
+ name: string,
+ variables: VariableDefinitionNode[],
+ }
+
+ declare export function parser(document: DocumentNode): IDocumentDefinition;
+
+ declare export interface Context {
+ client?: ApolloClient,
+ store?: Store,
+ [key: string]: any
+ }
+
+ declare export interface QueryTreeArgument {
+ rootElement: React$Element<*>,
+ rootContext?: Context
+ }
+
+ declare export interface QueryResult {
+ query: Promise>,
+ element: React$Element<*>,
+ context: Context
+ }
+
+ declare export function walkTree(
+ element: React$Element<*>,
+ context: Context,
+ visitor: (
+ element: React$Element<*>,
+ instance: any,
+ context: Context
+ ) => boolean | void
+ ): void;
+
+ declare export function getDataFromTree(
+ rootElement: React$Element<*>,
+ rootContext?: any,
+ fetchRoot?: boolean
+ ): Promise;
+
+ declare export function renderToStringWithData(
+ component: React$Element<*>
+ ): Promise;
+
+ declare export function cleanupApolloState(apolloState: any): void;
+}
diff --git a/package.json b/package.json
index cad815d2b6..94742c54a9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-apollo",
- "version": "1.3.0",
+ "version": "1.4.0",
"description": "React data container for Apollo Client",
"main": "lib/react-apollo.umd.js",
"module": "./lib/index.js",
@@ -14,10 +14,11 @@
"test-watch": "jest --watch",
"posttest": "npm run lint",
"filesize": "npm run compile:browser && ./scripts/filesize.js --file=./dist/index.min.js --maxGzip=20",
+ "flow-check": "flow check",
"compile": "tsc",
- "bundle": "rollup -c && rollup -c rollup.browser.config.js && rollup -c rollup.test-utils.config.js",
+ "bundle": "rollup -c && rollup -c rollup.browser.config.js && rollup -c rollup.test-utils.config.js && cp ./index.js.flow ./lib",
"compile:browser": "rm -rf ./dist && mkdir ./dist && browserify ./lib/react-apollo.browser.umd.js --i graphql-tag --i react --i apollo-client -o=./dist/index.js && npm run minify:browser && npm run compress:browser",
- "minify:browser": "uglifyjs --compress --mangle --screw-ie8 -o=./dist/index.min.js -- ./dist/index.js",
+ "minify:browser": "uglifyjs -c -m -o ./dist/index.min.js -- ./dist/index.js",
"compress:browser": "./scripts/gzip.js --file=./dist/index.min.js",
"watch": "tsc -w",
"lint": "tslint 'src/*.ts*' && tslint 'test/*.ts*'"
@@ -54,9 +55,10 @@
"json"
],
"modulePathIgnorePatterns": [
- "/examples"
+ "/examples",
+ "/test/flow.js"
],
- "testRegex": "/test/.*.test.(ts|tsx|js)$",
+ "testRegex": "(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"collectCoverage": true
},
"license": "MIT",
@@ -92,7 +94,7 @@
"@types/redux-form": "^6.3.2",
"@types/redux-immutable": "^3.0.30",
"@types/sinon": "^2.1.1",
- "babel-jest": "^20.0.0",
+ "babel-jest": "^19.0.0",
"babel-preset-react-native": "^1.9.0",
"browserify": "^14.1.0",
"cheerio": "^0.22.0",
@@ -103,7 +105,7 @@
"graphql": "^0.9.1",
"immutable": "^3.8.1",
"isomorphic-fetch": "^2.2.1",
- "jest": "^20.0.0",
+ "jest": "^19.0.0",
"jest-react-native": "^18.0.0",
"jsdom": "^11.0.0",
"lodash": "^4.16.6",
@@ -114,7 +116,7 @@
"react": "^15.5.4",
"react-addons-test-utils": "^15.5.1",
"react-dom": "^15.5.4",
- "react-native": "^0.44.1",
+ "react-native": "^0.42.3",
"react-redux": "^5.0.3",
"react-test-renderer": "^15.5.4",
"recompose": "^0.23.0",
@@ -127,10 +129,10 @@
"swapi-graphql": "0.0.6",
"travis-weigh-in": "^1.0.2",
"tslint": "^5.1.0",
- "typescript": "^2.2.0",
+ "typescript": "^2.3.0",
"typescript-require": "^0.2.9-1",
"typings": "^2.1.0",
- "uglify-js": "^2.6.2"
+ "uglify-js": "^3.0.13"
},
"dependencies": {
"apollo-client": "^1.2.2",
diff --git a/src/browser.ts b/src/browser.ts
index 1893bd351f..fd8c7160c5 100644
--- a/src/browser.ts
+++ b/src/browser.ts
@@ -1,5 +1,14 @@
export { default as ApolloProvider } from './ApolloProvider';
-export { default as graphql, InjectedGraphQLProps } from './graphql';
+export {
+ default as graphql,
+ MutationOpts,
+ QueryOpts,
+ QueryProps,
+ MutationFunc,
+ OptionProps,
+ DefaultChildProps,
+ OperationOption,
+ } from './graphql';
export { withApollo } from './withApollo';
// expose easy way to join queries from redux
diff --git a/src/graphql.tsx b/src/graphql.tsx
index 2c3d911905..a68ec8c219 100644
--- a/src/graphql.tsx
+++ b/src/graphql.tsx
@@ -29,19 +29,19 @@ import ApolloClient, {
} from 'apollo-client';
import {
- // GraphQLResult,
+ ExecutionResult,
DocumentNode,
} from 'graphql';
import { parser, DocumentType } from './parser';
-export declare interface MutationOptions {
+export declare interface MutationOpts {
variables?: Object;
optimisticResponse?: Object;
updateQueries?: MutationQueryReducersMap;
}
-export declare interface QueryOptions {
+export declare interface QueryOpts {
ssr?: boolean;
variables?: { [key: string]: any };
fetchPolicy?: FetchPolicy;
@@ -50,7 +50,7 @@ export declare interface QueryOptions {
skip?: boolean;
}
-export interface GraphQLDataProps {
+export interface QueryProps {
error?: ApolloError;
networkStatus: number;
loading: boolean;
@@ -65,8 +65,33 @@ export interface GraphQLDataProps {
updateQuery: (mapFn: (previousQueryResult: any, options: UpdateQueryOptions) => any) => void;
}
-export interface InjectedGraphQLProps {
- data?: T & GraphQLDataProps;
+export type MutationFunc = (opts: MutationOpts) => Promise>;
+
+export interface OptionProps {
+ ownProps: TProps;
+ data?: QueryProps & TResult;
+ mutate?: MutationFunc;
+}
+
+export type DefaultChildProps = P & { data?: QueryProps & R, mutate?: MutationFunc };
+
+export interface OperationOption {
+ options?: QueryOpts | MutationOpts | ((props: TProps) => QueryOpts | MutationOpts);
+ props?: (props: OptionProps) => any;
+ skip?: boolean | ((props: any) => boolean);
+ name?: string;
+ withRef?: boolean;
+ shouldResubscribe?: (props: TProps, nextProps: TProps) => boolean;
+ alias?: string;
+}
+
+export type CompositeComponent = ComponentClass
| StatelessComponent
;
+
+export interface ComponentDecorator {
+ (component: CompositeComponent): ComponentClass;
+}
+export interface InferableComponentDecorator {
+ >(component: T): T;
}
const defaultMapPropsToOptions = props => ({});
@@ -94,29 +119,19 @@ function getDisplayName(WrappedComponent) {
// Helps track hot reloading.
let nextVersion = 0;
-export interface OperationOption {
- options?: Object | ((props: any) => QueryOptions | MutationOptions);
- props?: (props: any) => any;
- skip?: boolean | ((props: any) => boolean);
- name?: string;
- withRef?: boolean;
- shouldResubscribe?: (props: any, nextProps: any) => boolean;
- alias?: string;
-}
-
-export interface WrapWithApollo {
- | StatelessComponent
)>(component: TComponentConstruct): TComponentConstruct;
-}
-
-export default function graphql(
+export default function graphql>(
document: DocumentNode,
- operationOptions: OperationOption = {},
-) {
+ operationOptions: OperationOption = {},
+): ComponentDecorator {
// extract options
- const { options = defaultMapPropsToOptions, skip = defaultMapPropsToSkip, alias = 'Apollo' } = operationOptions;
+ const {
+ options = defaultMapPropsToOptions,
+ skip = defaultMapPropsToSkip,
+ alias = 'Apollo',
+ } = operationOptions;
- let mapPropsToOptions = options as (props: any) => QueryOptions | MutationOptions;
+ let mapPropsToOptions = options as (props: any) => QueryOpts | MutationOpts;
if (typeof mapPropsToOptions !== 'function') mapPropsToOptions = () => options;
let mapPropsToSkip = skip as (props: any) => boolean;
@@ -130,7 +145,7 @@ export default function graphql(
// Helps track hot reloading.
const version = nextVersion++;
- const wrapWithApolloComponent: WrapWithApollo = WrappedComponent => {
+ function wrapWithApolloComponent(WrappedComponent) {
const graphQLDisplayName = `${alias}(${getDisplayName(WrappedComponent)})`;
@@ -142,7 +157,7 @@ export default function graphql(
// However, this is an unlikely scenario.
const recycler = new ObservableQueryRecycler();
- class GraphQL extends Component {
+ class GraphQL extends Component {
static displayName = graphQLDisplayName;
static WrappedComponent = WrappedComponent;
static contextTypes = {
@@ -297,11 +312,11 @@ export default function graphql(
return opts;
}
- calculateResultProps(result) {
+ calculateResultProps(result: (QueryProps & TResult) | MutationFunc) {
let name = this.type === DocumentType.Mutation ? 'mutate' : 'data';
if (operationOptions.name) name = operationOptions.name;
- const newResult = { [name]: result, ownProps: this.props };
+ const newResult: OptionProps = { [name]: result, ownProps: this.props };
if (mapResultToProps) return mapResultToProps(newResult);
return { [name]: defaultMapResultToProps(result) };
@@ -314,12 +329,12 @@ export default function graphql(
// Create the observable but don't subscribe yet. The query won't
// fire until we do.
- const opts: QueryOptions = this.calculateOptions(this.props);
+ const opts: QueryOpts = this.calculateOptions(this.props);
this.createQuery(opts);
}
- createQuery(opts: QueryOptions) {
+ createQuery(opts: QueryOpts) {
if (this.type === DocumentType.Subscription) {
this.queryObservable = this.client.subscribe(assign({
query: document,
@@ -346,7 +361,7 @@ export default function graphql(
}
updateQuery(props) {
- const opts = this.calculateOptions(props) as QueryOptions;
+ const opts = this.calculateOptions(props) as QueryOpts;
// if we skipped initially, we may not have yet created the observable
if (!this.queryObservable) {
@@ -441,7 +456,7 @@ export default function graphql(
shouldSkip(props = this.props) {
return mapPropsToSkip(props) ||
- (mapPropsToOptions(props) as QueryOptions).skip;
+ (mapPropsToOptions(props) as QueryOpts).skip;
}
forceRenderChildren() {
@@ -461,7 +476,7 @@ export default function graphql(
dataForChild() {
if (this.type === DocumentType.Mutation) {
- return (mutationOpts: MutationOptions) => {
+ return (mutationOpts: MutationOpts) => {
const opts = this.calculateOptions(this.props, mutationOpts);
if (typeof opts.variables === 'undefined') delete opts.variables;
@@ -520,7 +535,7 @@ export default function graphql(
this.previousData = currentResult.data;
}
}
- return data;
+ return (data as QueryProps & TResult);
}
render() {
@@ -547,7 +562,7 @@ export default function graphql(
// Make sure we preserve any custom statics on the original component.
return hoistNonReactStatics(GraphQL, WrappedComponent, {});
- };
+ }
return wrapWithApolloComponent;
}
@@ -611,7 +626,7 @@ class ObservableQueryRecycler {
* All mutations that occured between the time of recycling and the time of
* reusing have been applied.
*/
- public reuse (options: QueryOptions): ObservableQuery {
+ public reuse (options: QueryOpts): ObservableQuery {
if (this.observableQueries.length <= 0) {
return null;
}
diff --git a/src/server.ts b/src/server.ts
index a272e6612b..f052590e2e 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -1,34 +1,34 @@
-import { Children } from 'react';
+import { Children, ReactElement, ComponentClass, StatelessComponent } from 'react';
import * as ReactDOM from 'react-dom/server';
-import ApolloClient from 'apollo-client';
+import ApolloClient, { ApolloQueryResult } from 'apollo-client';
const assign = require('object-assign');
-declare interface Context {
+export declare interface Context {
client?: ApolloClient;
store?: any;
[key: string]: any;
}
-declare interface QueryTreeArgument {
- rootElement: any;
+export declare interface QueryTreeArgument {
+ rootElement: ReactElement;
rootContext?: Context;
}
-declare interface QueryResult {
- query: Promise;
- element: any;
- context: any;
+export declare interface QueryResult {
+ query: Promise>;
+ element: ReactElement;
+ context: Context;
}
// Recurse an React Element tree, running visitor on each element.
// If visitor returns `false`, don't call the element's render function
// or recurse into its child elements
export function walkTree(
- element: any,
- context: any,
- visitor: (element: any, instance: any, context: any) => boolean | void,
+ element: ReactElement,
+ context: Context,
+ visitor: (element: ReactElement, instance: any, context: Context) => boolean | void,
) {
const Component = element.type;
// a stateless functional component or a class
@@ -40,7 +40,10 @@ export function walkTree(
// Are we are a react class?
// https://github.com/facebook/react/blob/master/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js#L66
if (Component.prototype && Component.prototype.isReactComponent) {
- const instance = new Component(props, context);
+ // typescript force casting since typescript doesn't have definitions for class
+ // methods
+ const _component = Component as any;
+ const instance = new _component(props, context);
// In case the user doesn't pass these to super in the constructor
instance.props = instance.props || props;
instance.context = instance.context || context;
@@ -73,7 +76,9 @@ export function walkTree(
return;
}
- child = Component(props, context);
+ // typescript casting for stateless component
+ const _component = Component as StatelessComponent;
+ child = _component(props, context);
}
if (child) {
@@ -118,7 +123,7 @@ function getQueriesFromTree(
}
// XXX component Cache
-export function getDataFromTree(rootElement, rootContext: any = {}, fetchRoot: boolean = true): Promise {
+export function getDataFromTree(rootElement: ReactElement, rootContext: any = {}, fetchRoot: boolean = true): Promise {
let queries = getQueriesFromTree({ rootElement, rootContext }, fetchRoot);
@@ -149,7 +154,7 @@ export function getDataFromTree(rootElement, rootContext: any = {}, fetchRoot: b
});
}
-export function renderToStringWithData(component) {
+export function renderToStringWithData(component: ReactElement): Promise {
return getDataFromTree(component)
.then(() => ReactDOM.renderToString(component));
}
diff --git a/src/withApollo.tsx b/src/withApollo.tsx
index 2145845ab3..81637cea08 100644
--- a/src/withApollo.tsx
+++ b/src/withApollo.tsx
@@ -33,19 +33,15 @@ import {
import { parser, DocumentType } from './parser';
import {
OperationOption,
- MutationOptions,
- QueryOptions,
- GraphQLDataProps,
- InjectedGraphQLProps,
} from './graphql';
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
-export function withApollo(
+export function withApollo(
WrappedComponent,
- operationOptions: OperationOption = {},
+ operationOptions: OperationOption = {},
) {
const withDisplayName = `withApollo(${getDisplayName(WrappedComponent)})`;
diff --git a/test/flow.js b/test/flow.js
new file mode 100644
index 0000000000..4c1fb0d3e9
--- /dev/null
+++ b/test/flow.js
@@ -0,0 +1,34 @@
+/*
+
+ This file is used to validate the flow typings for react-apollo.
+ Currently it just serves as a smoke test around used imports and
+ common usage patterns.
+
+ Ideally this should include tests for all of the functionality of
+ react-apollo
+
+*/
+
+// @flow
+import { graphql } from "react-apollo";
+import type { OperationComponent } from "react-apollo";
+import type { DocumentNode } from "graphql";
+import gql from "graphql-tag";
+
+const query: DocumentNode = gql`{ foo }`;
+const mutation: DocumentNode = gql`mutation { foo }`;
+
+type IQuery = {
+ foo: string,
+};
+
+// common errors
+
+const withData: OperationComponent = graphql(query);
+
+const ComponentWithData = withData(({ data: { foo }}) => {
+ // $ExpectError
+ if (foo > 1) return ;
+
+ return null;
+});
diff --git a/test/index.ts b/test/index.ts
deleted file mode 100644
index e36c6bbe79..0000000000
--- a/test/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { install } from 'source-map-support';
-
-install({ environment: 'node' });
diff --git a/test/react-web/client/graphql/queries/index.test.tsx b/test/react-web/client/graphql/queries/index.test.tsx
index 8b39db915f..f97be216d9 100644
--- a/test/react-web/client/graphql/queries/index.test.tsx
+++ b/test/react-web/client/graphql/queries/index.test.tsx
@@ -15,6 +15,7 @@ declare function require(name: string);
import { mockNetworkInterface } from '../../../../../src/test-utils';
import { ApolloProvider, graphql} from '../../../../../src';
+import { DocumentType } from '../../../../../src/parser';
// XXX: this is also defined in apollo-client
// I'm not sure why mocha doesn't provide something like this, you can't
@@ -40,9 +41,15 @@ describe('queries', () => {
const networkInterface = mockNetworkInterface({ request: { query }, result: { data } });
const client = new ApolloClient({ networkInterface, addTypename: false });
- const ContainerWithData = graphql(query)(({ data }) => { // tslint:disable-line
+ type ResultData = {
+ allPeople?: {
+ people: { name: string }[]
+ }
+ }
+
+
+ const ContainerWithData = graphql(query)(({ data }) => { // tslint:disable-line
expect(data).toBeTruthy();
- expect(data.ownProps).toBeFalsy();
expect(data.loading).toBe(true);
return null;
});
diff --git a/test/react-web/client/graphql/queries/reducer.test.tsx b/test/react-web/client/graphql/queries/reducer.test.tsx
index 355e306ba2..575754c111 100644
--- a/test/react-web/client/graphql/queries/reducer.test.tsx
+++ b/test/react-web/client/graphql/queries/reducer.test.tsx
@@ -40,8 +40,15 @@ describe('[queries] reducer', () => {
const networkInterface = mockNetworkInterface({ request: { query }, result: { data } });
const client = new ApolloClient({ networkInterface, addTypename: false });
- const props = ({ data }) => ({ showSpinner: data.loading });
- const ContainerWithData = graphql(query, { props })(({ showSpinner }) => {
+ type ResultData = {
+ getThing: { thing: boolean }
+ }
+ type ResultShape = {
+ showSpinner: boolean
+ }
+
+ const props = (result) => ({ showSpinner: result.data && result.data.loading });
+ const ContainerWithData = graphql(query, { props })(({ showSpinner }) => {
expect(showSpinner).toBe(true);
return null;
});
@@ -60,7 +67,16 @@ describe('[queries] reducer', () => {
expect(ownProps.sample).toBe(1);
return { showSpinner: data.loading };
};
- const ContainerWithData = graphql(query, { props })(({ showSpinner }) => {
+ type ResultData = {
+ getThing: { thing: boolean }
+ }
+ type ReducerResult = {
+ showSpinner: boolean,
+ }
+ type Props = {
+ sample: number
+ }
+ const ContainerWithData = graphql(query, { props })(({ showSpinner }) => {
expect(showSpinner).toBe(true);
return null;
});
@@ -77,9 +93,20 @@ describe('[queries] reducer', () => {
const networkInterface = mockNetworkInterface({ request: { query }, result: { data } });
const client = new ApolloClient({ networkInterface, addTypename: false });
- @graphql(query, { props: ({ data }) => ({ thingy: data.getThing }) }) // tslint:disable-line
- class Container extends React.Component {
- componentWillReceiveProps(props) {
+ type Result = {
+ getThing?: { thing: boolean }
+ }
+
+ type PropsResult = {
+ thingy: boolean
+ }
+
+ const withData = graphql(query, {
+ props: ({ data }) => ({ thingy: data.getThing })
+ })
+
+ class Container extends React.Component {
+ componentWillReceiveProps(props: PropsResult) {
expect(props.thingy).toEqual(data.getThing);
done();
}
@@ -88,7 +115,9 @@ describe('[queries] reducer', () => {
}
};
- renderer.create();
+ const ContainerWithData = withData(Container);
+
+ renderer.create();
});