Skip to content

Commit 972dad1

Browse files
committed
support relay 1.4, retain prop
1 parent 8c4f6dd commit 972dad1

File tree

8 files changed

+2183
-450
lines changed

8 files changed

+2183
-450
lines changed

.babelrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"presets": [
33
"es2015",
4+
"flow",
45
"react"
56
],
67
"plugins": [
8+
"transform-async-to-generator",
79
"transform-object-rest-spread",
810
"transform-class-properties"
911
]

__test__/.babelrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"flow",
5+
"react"
6+
],
7+
"plugins": [
8+
"relay",
9+
"transform-async-to-generator",
10+
"transform-object-rest-spread",
11+
"transform-class-properties"
12+
]
13+
}

__test__/__generated__/testQuery.graphql.js

Lines changed: 119 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

__test__/schema.graphql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
type Author {
2+
id: Int!
3+
firstName: String
4+
lastName: String
5+
posts: [Post] # the list of Posts by this author
6+
}
7+
type Post {
8+
id: Int!
9+
title: String
10+
author: Author
11+
votes: Int
12+
}
13+
# the schema allows the following query:
14+
type Query {
15+
posts: [Post]
16+
author(id: Int!): Author
17+
}
18+
# this schema allows the following mutation:
19+
type Mutation {
20+
upvotePost (
21+
postId: Int!
22+
): Post
23+
}

__test__/test.js

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
'use strict';
2+
3+
// get around warning from react for now
4+
global.requestAnimationFrame = (cb) => {
5+
setTimeout(cb, 0)
6+
};
7+
8+
const QueryRenderer = require('../src/index');
9+
const { configure, mount } = require('enzyme');
10+
const Adapter = require('enzyme-adapter-react-16');
11+
const React = require('react');
12+
const fs = require('fs');
13+
const path = require('path');
14+
const {
15+
graphql,
16+
Environment,
17+
Network,
18+
RecordSource,
19+
Store,
20+
fetchQuery
21+
} = require('relay-runtime');
22+
const getNetworkLayer = require('relay-mock-network-layer');
23+
24+
const query = graphql`
25+
query testQuery ($id: Int!) {
26+
author(id: $id) {
27+
firstName
28+
}
29+
}
30+
`;
31+
32+
configure({ adapter: new Adapter() });
33+
34+
function sleep() {
35+
return new Promise(resolve => setTimeout(resolve, 0));
36+
}
37+
38+
function getEnvironment() {
39+
const networkLayer = getNetworkLayer({
40+
schema: fs.readFileSync(
41+
path.resolve(__dirname, './schema.graphql'),
42+
{encoding: 'utf8'}
43+
)
44+
});
45+
const networkCall = jest.fn((...args) => networkLayer(...args));
46+
47+
const network = Network.create(networkCall);
48+
49+
const store = new Store(new RecordSource());
50+
return {
51+
environment: new Environment({network, store}),
52+
networkCall
53+
};
54+
}
55+
56+
describe('query lookup renderer', function () {
57+
let environment;
58+
let networkCall;
59+
beforeEach(function () {
60+
({environment, networkCall} = getEnvironment());
61+
});
62+
it('make sure environment mock is working', async () => {
63+
await fetchQuery(environment, query, {id: 123});
64+
expect(networkCall.mock.calls.length).toBe(1);
65+
});
66+
it('make sure environment mock is working 2', async () => {
67+
await fetchQuery(environment, query, {id: 123});
68+
await fetchQuery(environment, query, {id: 123});
69+
expect(networkCall.mock.calls.length).toBe(2);
70+
});
71+
it('should fetch data when not in the store', async () => {
72+
expect(networkCall.mock.calls.length).toBe(0);
73+
mount(
74+
<QueryRenderer
75+
lookup
76+
query={query}
77+
variables={{id: 123}}
78+
render={jest.fn(() => null)}
79+
environment={environment}
80+
/>
81+
);
82+
expect(networkCall.mock.calls.length).toBe(1);
83+
});
84+
it('should not fetch data when already in the store', async () => {
85+
await fetchQuery(environment, query, {id: 123});
86+
expect(networkCall.mock.calls.length).toBe(1);
87+
mount(
88+
<QueryRenderer
89+
lookup
90+
query={query}
91+
variables={{id: 123}}
92+
render={jest.fn(() => null)}
93+
environment={environment}
94+
/>
95+
);
96+
expect(networkCall.mock.calls.length).toBe(1);
97+
});
98+
it('should fetch data when different variables are in the store', async () => {
99+
await fetchQuery(environment, query, {id: 123});
100+
expect(networkCall.mock.calls.length).toBe(1);
101+
mount(
102+
<QueryRenderer
103+
lookup
104+
query={query}
105+
variables={{id: 124}}
106+
render={jest.fn(() => null)}
107+
environment={environment}
108+
/>
109+
);
110+
expect(networkCall.mock.calls.length).toBe(2);
111+
});
112+
it('should fetch data when different variables are in the store', async () => {
113+
await fetchQuery(environment, query, {id: 123});
114+
expect(networkCall.mock.calls.length).toBe(1);
115+
mount(
116+
<QueryRenderer
117+
lookup
118+
query={query}
119+
variables={{id: 124}}
120+
render={jest.fn(() => null)}
121+
environment={environment}
122+
/>
123+
);
124+
expect(networkCall.mock.calls.length).toBe(2);
125+
});
126+
it('should correctly handle updating props', async () => {
127+
await fetchQuery(environment, query, {id: 123});
128+
expect(networkCall.mock.calls.length).toBe(1);
129+
const baseProps = {
130+
lookup: true,
131+
query,
132+
variables: {id: 123},
133+
render: jest.fn(() => null),
134+
environment
135+
};
136+
const component = mount(
137+
<QueryRenderer {...baseProps} />
138+
);
139+
// already rendered
140+
expect(networkCall.mock.calls.length).toBe(1);
141+
142+
// not fetched
143+
component.setProps({...baseProps, variables: {id: 124}});
144+
expect(networkCall.mock.calls.length).toBe(2);
145+
146+
// already fetched
147+
component.setProps({...baseProps, variables: {id: 123}});
148+
expect(networkCall.mock.calls.length).toBe(2);
149+
});
150+
it('should dispose when unmounted', async () => {
151+
expect(networkCall.mock.calls.length).toBe(0);
152+
const component = mount(
153+
<QueryRenderer
154+
lookup
155+
query={query}
156+
variables={{id: 123}}
157+
render={jest.fn(() => null)}
158+
environment={environment}
159+
/>
160+
);
161+
// wait for network call to finish
162+
await sleep();
163+
expect(networkCall.mock.calls.length).toBe(1);
164+
component.unmount();
165+
166+
// wait for GC
167+
await sleep();
168+
169+
// disposed, will fetch again
170+
mount(
171+
<QueryRenderer
172+
lookup
173+
query={query}
174+
variables={{id: 123}}
175+
render={jest.fn(() => null)}
176+
environment={environment}
177+
/>
178+
);
179+
expect(networkCall.mock.calls.length).toBe(2);
180+
});
181+
it('should not dispose when retain is passed', async () => {
182+
expect(networkCall.mock.calls.length).toBe(0);
183+
const component = mount(
184+
<QueryRenderer
185+
lookup
186+
retain
187+
query={query}
188+
variables={{id: 123}}
189+
render={jest.fn(() => null)}
190+
environment={environment}
191+
/>
192+
);
193+
194+
// wait for network call to finish
195+
await sleep();
196+
expect(networkCall.mock.calls.length).toBe(1);
197+
component.unmount();
198+
199+
// wait for GC
200+
await sleep();
201+
202+
// should not fetch again
203+
mount(
204+
<QueryRenderer
205+
lookup
206+
retain
207+
query={query}
208+
variables={{id: 123}}
209+
render={jest.fn(() => null)}
210+
environment={environment}
211+
/>
212+
);
213+
expect(networkCall.mock.calls.length).toBe(1);
214+
});
215+
});
216+
217+

0 commit comments

Comments
 (0)