Skip to content

Commit

Permalink
Input unions (#481)
Browse files Browse the repository at this point in the history
* support input unions

* not needed

* the correct fork commit

* changelog

* add test case for oneOf fields

* docs for input unions
  • Loading branch information
zth authored Dec 27, 2023
1 parent 20e84a1 commit 9ccab15
Show file tree
Hide file tree
Showing 11 changed files with 405 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- Emit `@live` for union variant cases to prevent false positives in unions.
- Set `@rescript/tools` version explicitly.
- First class support for input unions, leveraging the `@oneOf` directive.

# 3.0.0-alpha.4

Expand Down
40 changes: 40 additions & 0 deletions packages/rescript-relay/__tests__/Test_inputUnion-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require("@testing-library/jest-dom/extend-expect");
const t = require("@testing-library/react");
const React = require("react");
const queryMock = require("./queryMock");

const { test_inputUnion } = require("./Test_inputUnion.bs");

describe("Query", () => {
test("conversion of input unions work", async () => {
queryMock.mockQuery({
name: "TestInputUnionQuery",
variables: {
location: {
byAddress: {
city: "City",
},
},
},
data: {
findByLocation: "Got it",
},
});

queryMock.mockQuery({
name: "TestInputUnionQuery",
variables: {
location: {
byId: "<id>",
},
},
data: {
findByLocation: "Got ID",
},
});

t.render(test_inputUnion());
await t.screen.findByText("Got it");
await t.screen.findByText("Got ID");
});
});
41 changes: 41 additions & 0 deletions packages/rescript-relay/__tests__/Test_inputUnion.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Query = %relay(`
query TestInputUnionQuery($location: Location!) {
findByLocation(location: $location)
}
`)

module Test = {
@react.component
let make = () => {
let data = Query.use(
~variables={
location: ByAddress({city: "City"}),
},
)

let data2 = Query.use(
~variables={
location: ById("<id>"),
},
)

<>
<div> {React.string(data.findByLocation->Belt.Option.getWithDefault("-"))} </div>
<div> {React.string(data2.findByLocation->Belt.Option.getWithDefault("-"))} </div>
</>
}
}

@live
let test_inputUnion = () => {
let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=RelayEnv.fetchQuery)

let environment = RescriptRelay.Environment.make(
~network,
~store=RescriptRelay.Store.make(~source=RescriptRelay.RecordSource.make()),
)

<TestProviders.Wrapper environment>
<Test />
</TestProviders.Wrapper>
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions packages/rescript-relay/__tests__/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ type Query {
): UserConnection
search(input: SearchInput!): String
searchPesticie(input: PesticideListSearchInput!): String
findByLocation(location: Location!): String
}

type Mutation {
Expand All @@ -223,3 +224,17 @@ type Mutation {
type Subscription {
userUpdated(id: ID!): UserUpdatedPayload
}

input ByAddress {
city: String!
}

input ByLoc {
lat: Float!
}

input Location @oneOf {
byAddress: ByAddress
byLoc: ByLoc
byId: ID
}
29 changes: 29 additions & 0 deletions packages/rescript-relay/__tests__/utils-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,35 @@ describe("conversion", () => {
});
});

it("handles input unions", () => {
expect(
traverser(
{
location: {
__$inputUnion: "byAddress",
_0: {
city: "City",
},
},
},
{
location: { byLoc: { r: "byLoc" }, byAddress: { r: "byAddress" } },
byAddress: {},
byLoc: {},
__root: { location: { r: "location" } },
},
{},
undefined
)
).toEqual({
location: {
byAddress: {
city: "City",
},
},
});
});

it("handles top level unions on fragments", () => {
expect(
traverser(
Expand Down
14 changes: 12 additions & 2 deletions packages/rescript-relay/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ function getTypename(v) {
}
}

function unwrapInputUnion(obj) {
if (obj != null && typeof obj === "object" && "__$inputUnion" in obj) {
return {
[obj["__$inputUnion"]]: obj["_0"],
};
}

return obj;
}

/**
* Runs on each object in the tree and follows the provided instructions
* to apply transforms etc.
Expand Down Expand Up @@ -128,7 +138,7 @@ function traverse(
}
if (shouldConvertRootObj) {
return traverser(
v,
unwrapInputUnion(v),
fullInstructionMap,
converters,
nullableValue,
Expand Down Expand Up @@ -198,7 +208,7 @@ function traverse(
if (shouldConvertRootObj) {
newObj = getNewObj(newObj, currentObj);
newObj[key] = traverser(
v,
unwrapInputUnion(v),
fullInstructionMap,
converters,
nullableValue,
Expand Down
Loading

0 comments on commit 9ccab15

Please sign in to comment.