Skip to content

Commit 9750294

Browse files
authored
Normalize load query variables (#627)
1 parent 074b8bd commit 9750294

10 files changed

Lines changed: 631 additions & 23 deletions

packages/rescript-relay/__tests__/Test_mutation-tests.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,49 @@ describe("Mutation", () => {
200200
await t.screen.findByText("Provided variable mutation status: completed");
201201
});
202202

203+
test("mutation hook with no variables can spread a provided variable fragment", async () => {
204+
queryMock.mockQuery({
205+
name: "TestMutationQuery",
206+
data: {
207+
loggedInUser: {
208+
id: "user-1",
209+
firstName: "First",
210+
lastName: "Name",
211+
onlineStatus: "Online",
212+
memberOf,
213+
},
214+
},
215+
});
216+
217+
t.render(test_mutation());
218+
await t.screen.findByText("Provided variable mutation status: -");
219+
220+
queryMock.mockQuery({
221+
name: "TestMutationWithProvidedVariableFragmentMutation",
222+
variables: {
223+
__relay_internal__pv__ProvidedVariablesBool: true,
224+
},
225+
data: {
226+
updateUserAvatar: {
227+
user: {
228+
id: "user-1",
229+
someRandomArgField: "provided variable value",
230+
},
231+
},
232+
},
233+
});
234+
235+
ReactTestUtils.act(() => {
236+
t.fireEvent.click(
237+
t.screen.getByText("Run mutation hook with provided variable fragment")
238+
);
239+
});
240+
241+
await t.screen.findByText(
242+
"Provided variable mutation status: hook completed"
243+
);
244+
});
245+
203246
test("optimistic response works", async () => {
204247
queryMock.mockQuery({
205248
name: "TestMutationQuery",

packages/rescript-relay/__tests__/Test_mutation.res

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ module Test = {
102102
let query = Query.use(~variables=())
103103
let data = Fragment.use(query.loggedInUser.fragmentRefs)
104104
let (mutate, isMutating) = Mutation.use()
105+
let (mutateWithProvidedVariableFragment, _) = MutationWithProvidedVariableFragment.use()
105106
let (inlineStatus, setInlineStatus) = React.useState(_ => "-")
106107
let (providedVariableMutationStatus, setProvidedVariableMutationStatus) = React.useState(_ =>
107108
"-"
@@ -256,6 +257,19 @@ module Test = {
256257
>
257258
{React.string("Run mutation with provided variable fragment")}
258259
</button>
260+
<button
261+
onClick={_ => {
262+
mutateWithProvidedVariableFragment(~variables=(), ~onCompleted=(response, _) => {
263+
switch response {
264+
| {updateUserAvatar: Some({user: Some(_)})} =>
265+
setProvidedVariableMutationStatus(_ => "hook completed")
266+
| _ => setProvidedVariableMutationStatus(_ => "hook missing user")
267+
}
268+
})->RescriptRelay.Disposable.ignore
269+
}}
270+
>
271+
{React.string("Run mutation hook with provided variable fragment")}
272+
</button>
259273
<button
260274
onClick={_ => {
261275
let _ = {

packages/rescript-relay/__tests__/Test_providedVariables-tests.js

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,113 @@ const ReactTestUtils = require("react-dom/test-utils");
77
const { test_providedVariables } = require("./Test_providedVariables.bs");
88

99
describe("Provided variables", () => {
10-
test("provided variables work", async () => {
10+
const providedVariables = {
11+
__relay_internal__pv__ProvidedVariablesBool: true,
12+
__relay_internal__pv__ProvidedVariablesInputC: {
13+
intStr: "123",
14+
recursiveC: {
15+
intStr: "234",
16+
},
17+
},
18+
__relay_internal__pv__ProvidedVariablesInputCArr: [
19+
{
20+
intStr: "123",
21+
},
22+
],
23+
__relay_internal__pv__ProvidedVariablesIntStr: "456",
24+
__relay_internal__pv__ProvidedVariablesIntStrArr: ["456"],
25+
};
26+
27+
const mockProvidedVariablesQuery = (someRandomArgField) =>
1128
queryMock.mockQuery({
1229
name: "TestProvidedVariablesQuery",
13-
variables: {
14-
__relay_internal__pv__ProvidedVariablesBool: true,
15-
__relay_internal__pv__ProvidedVariablesInputC: {
16-
intStr: "123",
17-
recursiveC: {
18-
intStr: "234",
19-
},
20-
},
21-
__relay_internal__pv__ProvidedVariablesInputCArr: [
22-
{
23-
intStr: "123",
24-
},
25-
],
26-
__relay_internal__pv__ProvidedVariablesIntStr: "456",
27-
__relay_internal__pv__ProvidedVariablesIntStrArr: ["456"],
28-
},
30+
variables: providedVariables,
2931
data: {
3032
loggedInUser: {
3133
__typename: "User",
3234
id: "user-1",
33-
someRandomArgField: "hello",
35+
someRandomArgField,
3436
},
3537
},
3638
});
3739

40+
test("provided variables work", async () => {
41+
mockProvidedVariablesQuery("hello");
42+
43+
t.render(test_providedVariables());
44+
await t.screen.findByText("hello");
45+
});
46+
47+
test("loading a no-variable query with provided variables from the raw module works", async () => {
48+
mockProvidedVariablesQuery("hello");
49+
50+
t.render(test_providedVariables());
51+
await t.screen.findByText("hello");
52+
53+
ReactTestUtils.act(() => {
54+
t.fireEvent.click(t.screen.getByText("Test provided variable raw load"));
55+
});
56+
57+
await t.screen.findByText("Preloaded provided variable: hello");
58+
});
59+
60+
test("loading a no-variable query with provided variables through useLoader works", async () => {
61+
mockProvidedVariablesQuery("hello");
62+
63+
t.render(test_providedVariables());
64+
await t.screen.findByText("hello");
65+
66+
ReactTestUtils.act(() => {
67+
t.fireEvent.click(
68+
t.screen.getByText("Test provided variable query loader")
69+
);
70+
});
71+
72+
await t.screen.findByText("Preloaded provided variable: hello");
73+
});
74+
75+
test("fetching a no-variable query with provided variables works", async () => {
76+
mockProvidedVariablesQuery("hello");
77+
78+
t.render(test_providedVariables());
79+
await t.screen.findByText("hello");
80+
81+
mockProvidedVariablesQuery("fetch");
82+
83+
ReactTestUtils.act(() => {
84+
t.fireEvent.click(t.screen.getByText("Test provided variable fetch"));
85+
});
86+
87+
await t.screen.findByText("Provided variable fetch status: fetch");
88+
});
89+
90+
test("fetching a no-variable query with provided variables as a promise works", async () => {
91+
mockProvidedVariablesQuery("hello");
92+
3893
t.render(test_providedVariables());
3994
await t.screen.findByText("hello");
95+
96+
mockProvidedVariablesQuery("fetch promised");
97+
98+
ReactTestUtils.act(() => {
99+
t.fireEvent.click(
100+
t.screen.getByText("Test provided variable fetch promised")
101+
);
102+
});
103+
104+
await t.screen.findByText("Provided variable fetch status: fetch promised");
105+
});
106+
107+
test("retaining a no-variable query with provided variables works", async () => {
108+
mockProvidedVariablesQuery("hello");
109+
110+
t.render(test_providedVariables());
111+
await t.screen.findByText("hello");
112+
113+
ReactTestUtils.act(() => {
114+
t.fireEvent.click(t.screen.getByText("Test provided variable retain"));
115+
});
116+
117+
await t.screen.findByText("Provided variable retain status: retained");
40118
});
41119
});

packages/rescript-relay/__tests__/Test_providedVariables.res

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,84 @@ module Query = %relay(`
2828
}
2929
`)
3030

31+
module TestPreloaded = {
32+
@react.component
33+
let make = (~queryRef) => {
34+
let query = Query.usePreloaded(~queryRef)
35+
let user = Fragment.use(query.loggedInUser.fragmentRefs)
36+
37+
<div>
38+
{React.string(
39+
"Preloaded provided variable: " ++ user.someRandomArgField->Option.getOr("-"),
40+
)}
41+
</div>
42+
}
43+
}
44+
3145
module Test = {
3246
@react.component
3347
let make = () => {
48+
let environment = RescriptRelayReact.useEnvironmentFromContext()
3449
let query = Query.use(~variables=())
3550
let user = Fragment.use(query.loggedInUser.fragmentRefs)
51+
let (queryRefFromModule, setQueryRefFromModule) = React.useState(() => None)
52+
let (fetchedStatus, setFetchedStatus) = React.useState(() => "-")
53+
let (retainedStatus, setRetainedStatus) = React.useState(() => "-")
54+
let (loadedQueryRef, loadQuery, _dispose) = Query.useLoader()
3655

37-
<div> {React.string(user.someRandomArgField->Option.getOr("-"))} </div>
56+
<div>
57+
<div> {React.string(user.someRandomArgField->Option.getOr("-"))} </div>
58+
<div> {React.string("Provided variable fetch status: " ++ fetchedStatus)} </div>
59+
<div> {React.string("Provided variable retain status: " ++ retainedStatus)} </div>
60+
<button
61+
onClick={_ =>
62+
setQueryRefFromModule(_ => Some(
63+
TestProvidedVariablesQuery_graphql.load(
64+
~environment,
65+
~variables=(),
66+
~fetchPolicy=NetworkOnly,
67+
),
68+
))}
69+
>
70+
{React.string("Test provided variable raw load")}
71+
</button>
72+
<button onClick={_ => loadQuery(~variables=(), ~fetchPolicy=NetworkOnly)}>
73+
{React.string("Test provided variable query loader")}
74+
</button>
75+
<button
76+
onClick={_ =>
77+
Query.fetch(~environment, ~variables=(), ~onResult=result =>
78+
switch result {
79+
| Ok(_) => setFetchedStatus(_ => "fetch")
80+
| Error(_) => setFetchedStatus(_ => "fetch error")
81+
}
82+
)}
83+
>
84+
{React.string("Test provided variable fetch")}
85+
</button>
86+
<button
87+
onClick={_ => {
88+
let _ =
89+
Query.fetchPromised(~environment, ~variables=())->Promise.thenResolve(_ =>
90+
setFetchedStatus(_ => "fetch promised")
91+
)
92+
}}
93+
>
94+
{React.string("Test provided variable fetch promised")}
95+
</button>
96+
<button
97+
onClick={_ => {
98+
Query.retain(~environment, ~variables=())->RescriptRelay.Disposable.dispose
99+
setRetainedStatus(_ => "retained")
100+
}}
101+
>
102+
{React.string("Test provided variable retain")}
103+
</button>
104+
{switch (queryRefFromModule, loadedQueryRef) {
105+
| (_, Some(queryRef)) | (Some(queryRef), _) => <TestPreloaded queryRef />
106+
| _ => React.null
107+
}}
108+
</div>
38109
}
39110
}
40111

packages/rescript-relay/__tests__/Test_subscription-tests.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,51 @@ describe("Subscription", () => {
7878

7979
await t.screen.findByText("Ready - User First is offline");
8080
});
81+
82+
test("subscription with no variables can spread a provided variable fragment", async () => {
83+
queryMock.mockQuery({
84+
name: "TestSubscriptionQuery",
85+
data: {
86+
loggedInUser: {
87+
id: "user-1",
88+
firstName: "First",
89+
avatarUrl: null,
90+
onlineStatus: "Online",
91+
},
92+
},
93+
});
94+
95+
const testAssets = test_subscription();
96+
97+
t.render(testAssets.render());
98+
await t.screen.findByText("Ready - User First is online");
99+
100+
ReactTestUtils.act(() => {
101+
t.fireEvent.click(
102+
t.screen.getByText("Subscribe with provided variable fragment")
103+
);
104+
});
105+
106+
expect(testAssets.getLastSubscriptionVariables()).toEqual({
107+
__relay_internal__pv__ProvidedVariablesBool: true,
108+
});
109+
110+
ReactTestUtils.act(() => {
111+
testAssets.pushNext({
112+
data: {
113+
userUpdated: {
114+
user: {
115+
id: "user-1",
116+
onlineStatus: "Online",
117+
someRandomArgField: "provided variable value",
118+
},
119+
},
120+
},
121+
});
122+
});
123+
124+
await t.screen.findByText(
125+
"Provided variable subscription status: received"
126+
);
127+
});
81128
});

0 commit comments

Comments
 (0)