diff --git a/src/index.ts b/src/index.ts index f33ae70..4fbb6b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ async function getTestCases(router: ReturnType) { import("./test-suites/abstract-types/index.js"), import("./test-suites/fed1-external-extends-resolvable/index.js"), import("./test-suites/requires-with-argument/index.js"), + import("./test-suites/requires-with-argument-conflict/index.js"), import("./test-suites/keys-mashup/index.js"), import("./test-suites/null-keys/index.js"), ].map((i) => i.then((e) => e.default)) diff --git a/src/test-suites/requires-with-argument-conflict/a.subgraph.ts b/src/test-suites/requires-with-argument-conflict/a.subgraph.ts new file mode 100644 index 0000000..a4c8e65 --- /dev/null +++ b/src/test-suites/requires-with-argument-conflict/a.subgraph.ts @@ -0,0 +1,83 @@ +import { createSubgraph } from "../../subgraph.js"; +import { products } from "./data.js"; + +export default createSubgraph("a", { + typeDefs: /* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.3" + import: ["@key", "@external", "@requires"] + ) + + type Product @key(fields: "upc") { + upc: String! + weight: Int @external + price(currency: String!): Int @external + shippingEstimate: Int + @requires( + fields: """ + price(currency: "USD") weight + """ + ) + shippingEstimateEUR: Int + @requires( + fields: """ + price(currency: "EUR") weight + """ + ) + category: Category @external + isExpensiveCategory: Boolean + @requires( + fields: """ + category { averagePrice(currency: "USD") } + """ + ) + } + + type Category @external { + averagePrice(currency: String!): Int + } + `, + resolvers: { + Product: { + __resolveReference( + key: { upc: string; price: number; weight: number } | { upc: string }, + ) { + const product = products.find((p) => p.upc === key.upc); + + if (!product) { + return null; + } + + if ("weight" in key && "price" in key) { + return { + upc: product.upc, + weight: key.weight, + price: key.price, + category: product.category, + }; + } + + return { + upc: product.upc, + category: product.category, + }; + }, + shippingEstimate( + product: { price: number; weight: number }, + args: { currency?: string }, + ) { + const value = product.price * product.weight * 10; + + if (args.currency === "EUR") { + return value * 1.5; + } + + return value; + }, + isExpensiveCategory(product: { category: { averagePrice: number } }) { + return product.category.averagePrice > 11; + }, + }, + }, +}); diff --git a/src/test-suites/requires-with-argument-conflict/b.subgraph.ts b/src/test-suites/requires-with-argument-conflict/b.subgraph.ts new file mode 100644 index 0000000..b192f97 --- /dev/null +++ b/src/test-suites/requires-with-argument-conflict/b.subgraph.ts @@ -0,0 +1,55 @@ +import { createSubgraph } from "../../subgraph.js"; +import { products } from "./data.js"; + +export default createSubgraph("b", { + typeDefs: /* GraphQL */ ` + extend schema + @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"]) + + type Query { + products: [Product] + } + + type Product @key(fields: "upc") { + upc: String! + name: String + price(currency: String!): Int + weight: Int + category: Category + } + + type Category { + averagePrice(currency: String!): Int + } + `, + resolvers: { + Query: { + products() { + return products.map((p) => ({ + upc: p.upc, + name: p.name, + price: p.price, + weight: p.weight, + category: p.category, + })); + }, + }, + Product: { + __resolveReference(key: { upc: string }) { + const product = products.find((p) => p.upc === key.upc); + + if (!product) { + return null; + } + + return { + upc: product.upc, + name: product.name, + price: product.price, + weight: product.weight, + category: product.category, + }; + }, + }, + }, +}); diff --git a/src/test-suites/requires-with-argument-conflict/data.ts b/src/test-suites/requires-with-argument-conflict/data.ts new file mode 100644 index 0000000..5423956 --- /dev/null +++ b/src/test-suites/requires-with-argument-conflict/data.ts @@ -0,0 +1,20 @@ +export const products = [ + { + upc: "p1", + name: "p-name-1", + price: 11, + weight: 1, + category: { + averagePrice: 11, + }, + }, + { + upc: "p2", + name: "p-name-2", + price: 22, + weight: 2, + category: { + averagePrice: 22, + }, + }, +]; diff --git a/src/test-suites/requires-with-argument-conflict/index.ts b/src/test-suites/requires-with-argument-conflict/index.ts new file mode 100644 index 0000000..fc865be --- /dev/null +++ b/src/test-suites/requires-with-argument-conflict/index.ts @@ -0,0 +1,6 @@ +import { serve } from "../../supergraph.js"; +import a from "./a.subgraph.js"; +import b from "./b.subgraph.js"; +import test from "./test.js"; + +export default serve("requires-with-argument-conflict", [a, b], test); diff --git a/src/test-suites/requires-with-argument-conflict/test.ts b/src/test-suites/requires-with-argument-conflict/test.ts new file mode 100644 index 0000000..59731ac --- /dev/null +++ b/src/test-suites/requires-with-argument-conflict/test.ts @@ -0,0 +1,37 @@ +import { createTest } from "../../testkit.js"; + +export default [ + createTest( + /* GraphQL */ ` + query { + products { + upc + name + shippingEstimate + shippingEstimateEUR + isExpensiveCategory + } + } + `, + { + data: { + products: [ + { + upc: "p1", + name: "p-name-1", + shippingEstimate: 110, + shippingEstimateEUR: 165, + isExpensiveCategory: false, + }, + { + upc: "p2", + name: "p-name-2", + shippingEstimate: 440, + shippingEstimateEUR: 660, + isExpensiveCategory: true, + }, + ], + }, + }, + ), +];