From fc651044884dfcd3e4aeb0c612b2030c4e130f1a Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Tue, 22 Oct 2024 16:48:32 +0300 Subject: [PATCH] New scenario: null keys (#75) Co-authored-by: Kamil Kisiela --- README.md | 10 ++--- REPORT.md | 22 ++++++++--- gateways/apollo-gateway/results.txt | 6 ++- gateways/apollo-router/results.txt | 6 ++- gateways/cosmo-router/results.txt | 6 ++- gateways/grafbase-gateway/results.txt | 10 +++-- gateways/hive-gateway/install.sh | 2 +- gateways/hive-gateway/results.txt | 6 ++- src/index.ts | 1 + src/test-suites/null-keys/a.subgraph.ts | 43 ++++++++++++++++++++++ src/test-suites/null-keys/b.subgraph.ts | 45 +++++++++++++++++++++++ src/test-suites/null-keys/c.subgraph.ts | 49 +++++++++++++++++++++++++ src/test-suites/null-keys/data.ts | 32 ++++++++++++++++ src/test-suites/null-keys/index.ts | 7 ++++ src/test-suites/null-keys/test.ts | 46 +++++++++++++++++++++++ website/index.html | 30 +++++++-------- 16 files changed, 282 insertions(+), 39 deletions(-) create mode 100644 src/test-suites/null-keys/a.subgraph.ts create mode 100644 src/test-suites/null-keys/b.subgraph.ts create mode 100644 src/test-suites/null-keys/c.subgraph.ts create mode 100644 src/test-suites/null-keys/data.ts create mode 100644 src/test-suites/null-keys/index.ts create mode 100644 src/test-suites/null-keys/test.ts diff --git a/README.md b/README.md index de67e82..77f74bd 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ This repository contains a set of tests to evaluate and compare the compatibilit | Gateway | Compatibility | Test Cases | Test Suites | | :------------------------------------------------: | :-----------: | :----------: | :---------: | -| [Hive Gateway](https://the-guild.dev/graphql/hive) | 100.00% | 🟢 170 | 🟢 40 | -| [Apollo Router](https://www.apollographql.com/) | 97.65% | 🟢 166 ❌ 4 | 🟢 38 ❌ 2 | -| [Apollo Gateway](https://www.apollographql.com/) | 97.06% | 🟢 165 ❌ 5 | 🟢 37 ❌ 3 | -| [Cosmo Router](https://wundergraph.com) | 70.00% | 🟢 119 ❌ 51 | 🟢 19 ❌ 21 | -| [Grafbase Gateway](https://grafbase.com) | 60.00% | 🟢 102 ❌ 68 | 🟢 19 ❌ 21 | +| [Hive Gateway](https://the-guild.dev/graphql/hive) | 100.00% | 🟢 171 | 🟢 41 | +| [Apollo Router](https://www.apollographql.com/) | 97.66% | 🟢 167 ❌ 4 | 🟢 39 ❌ 2 | +| [Apollo Gateway](https://www.apollographql.com/) | 97.08% | 🟢 166 ❌ 5 | 🟢 38 ❌ 3 | +| [Cosmo Router](https://wundergraph.com) | 69.59% | 🟢 119 ❌ 52 | 🟢 19 ❌ 22 | +| [Grafbase Gateway](https://grafbase.com) | 59.06% | 🟢 101 ❌ 70 | 🟢 19 ❌ 22 | diff --git a/REPORT.md b/REPORT.md index 6967d2e..c3ddc95 100644 --- a/REPORT.md +++ b/REPORT.md @@ -4,11 +4,11 @@ | Gateway | Compatibility | Test Cases | Test Suites | | :------------------------------------------------: | :-----------: | :----------: | :---------: | -| [Hive Gateway](https://the-guild.dev/graphql/hive) | 100.00% | 🟢 170 | 🟢 40 | -| [Apollo Router](https://www.apollographql.com/) | 97.65% | 🟢 166 ❌ 4 | 🟢 38 ❌ 2 | -| [Apollo Gateway](https://www.apollographql.com/) | 97.06% | 🟢 165 ❌ 5 | 🟢 37 ❌ 3 | -| [Cosmo Router](https://wundergraph.com) | 70.00% | 🟢 119 ❌ 51 | 🟢 19 ❌ 21 | -| [Grafbase Gateway](https://grafbase.com) | 60.00% | 🟢 102 ❌ 68 | 🟢 19 ❌ 21 | +| [Hive Gateway](https://the-guild.dev/graphql/hive) | 100.00% | 🟢 171 | 🟢 41 | +| [Apollo Router](https://www.apollographql.com/) | 97.66% | 🟢 167 ❌ 4 | 🟢 39 ❌ 2 | +| [Apollo Gateway](https://www.apollographql.com/) | 97.08% | 🟢 166 ❌ 5 | 🟢 38 ❌ 3 | +| [Cosmo Router](https://wundergraph.com) | 69.59% | 🟢 119 ❌ 52 | 🟢 19 ❌ 22 | +| [Grafbase Gateway](https://grafbase.com) | 59.06% | 🟢 101 ❌ 70 | 🟢 19 ❌ 22 | ## Detailed Results @@ -65,6 +65,8 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id
🟢
non-resolvable-interface-object
🟢🟢🟢🟢🟢🟢🟢
+null-keys +
🟢
override-type-interface
🟢🟢🟢🟢
override-with-requires @@ -156,6 +158,8 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id
🟢
non-resolvable-interface-object
🟢🟢🟢🟢🟢🟢🟢
+null-keys +
🟢
override-type-interface
🟢🟢🟢🟢
override-with-requires @@ -247,6 +251,8 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id
🟢
non-resolvable-interface-object
🟢❌🟢🟢🟢🟢🟢
+null-keys +
🟢
override-type-interface
🟢🟢🟢🟢
override-with-requires @@ -338,6 +344,8 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id
🟢
non-resolvable-interface-object
🟢🟢🟢🟢❌🟢❌
+null-keys +
override-type-interface
🟢❌🟢🟢
override-with-requires @@ -429,6 +437,8 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id
🟢
non-resolvable-interface-object
❌🟢❌🟢🟢🟢❌
+null-keys +
override-type-interface
❌❌🟢🟢
override-with-requires @@ -468,5 +478,5 @@ You can look at the full list of tests [here](./src/test-suites/). Every test id union-interface-distributed
🟢🟢🟢🟢🟢🟢🟢
union-intersection -
🟢🟢❌❌🟢🟢🟢❌
+
🟢🟢🟢❌❌🟢❌❌
diff --git a/gateways/apollo-gateway/results.txt b/gateways/apollo-gateway/results.txt index 2f9c416..15924fb 100644 --- a/gateways/apollo-gateway/results.txt +++ b/gateways/apollo-gateway/results.txt @@ -38,6 +38,8 @@ node . non-resolvable-interface-object .X..... +null-keys +. override-type-interface .... override-with-requires @@ -80,6 +82,6 @@ union-intersection ........ --- -Total: 170 -Passed: 165 +Total: 171 +Passed: 166 Failed: 5 \ No newline at end of file diff --git a/gateways/apollo-router/results.txt b/gateways/apollo-router/results.txt index e6dcc3a..b02ca7a 100644 --- a/gateways/apollo-router/results.txt +++ b/gateways/apollo-router/results.txt @@ -38,6 +38,8 @@ node . non-resolvable-interface-object ....... +null-keys +. override-type-interface .... override-with-requires @@ -80,6 +82,6 @@ union-intersection ........ --- -Total: 170 -Passed: 166 +Total: 171 +Passed: 167 Failed: 4 \ No newline at end of file diff --git a/gateways/cosmo-router/results.txt b/gateways/cosmo-router/results.txt index 4ddc043..3d257cc 100644 --- a/gateways/cosmo-router/results.txt +++ b/gateways/cosmo-router/results.txt @@ -38,6 +38,8 @@ node . non-resolvable-interface-object ....X.X +null-keys +X override-type-interface .X.. override-with-requires @@ -80,6 +82,6 @@ union-intersection XXXXXXXX --- -Total: 170 +Total: 171 Passed: 119 -Failed: 51 \ No newline at end of file +Failed: 52 \ No newline at end of file diff --git a/gateways/grafbase-gateway/results.txt b/gateways/grafbase-gateway/results.txt index c09287b..a404c64 100644 --- a/gateways/grafbase-gateway/results.txt +++ b/gateways/grafbase-gateway/results.txt @@ -38,6 +38,8 @@ node . non-resolvable-interface-object X.X...X +null-keys +X override-type-interface XX.. override-with-requires @@ -77,9 +79,9 @@ unavailable-override union-interface-distributed ....... union-intersection -..XX...X +...XX.XX --- -Total: 170 -Passed: 102 -Failed: 68 \ No newline at end of file +Total: 171 +Passed: 101 +Failed: 70 \ No newline at end of file diff --git a/gateways/hive-gateway/install.sh b/gateways/hive-gateway/install.sh index 795f588..dc07582 100755 --- a/gateways/hive-gateway/install.sh +++ b/gateways/hive-gateway/install.sh @@ -1 +1 @@ -curl -sSL https://graphql-hive.com/install-gateway.sh | sh -s "1.0.9" \ No newline at end of file +curl -sSL https://graphql-hive.com/install-gateway.sh | sh -s "1.3.1" \ No newline at end of file diff --git a/gateways/hive-gateway/results.txt b/gateways/hive-gateway/results.txt index 623a540..c1d86b3 100644 --- a/gateways/hive-gateway/results.txt +++ b/gateways/hive-gateway/results.txt @@ -38,6 +38,8 @@ node . non-resolvable-interface-object ....... +null-keys +. override-type-interface .... override-with-requires @@ -80,6 +82,6 @@ union-intersection ........ --- -Total: 170 -Passed: 170 +Total: 171 +Passed: 171 Failed: 0 \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 11aa409..cbdec81 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,7 @@ const testCases = await Promise.all( import("./test-suites/fed1-external-extends-resolvable/index.js"), import("./test-suites/requires-with-argument/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/null-keys/a.subgraph.ts b/src/test-suites/null-keys/a.subgraph.ts new file mode 100644 index 0000000..40b421f --- /dev/null +++ b/src/test-suites/null-keys/a.subgraph.ts @@ -0,0 +1,43 @@ +import { createSubgraph } from "../../subgraph.js"; +import { books } from "./data.js"; + +export default createSubgraph("a", { + typeDefs: /* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.3" + import: ["@key"] + ) + + type Query { + bookContainers: [BookContainer] + } + type BookContainer { + book: Book + } + type Book @key(fields: "upc") { + upc: ID! + } + `, + resolvers: { + Query: { + bookContainers() { + return books.map((book) => ({ book: { upc: book.upc } })); + } + }, + Book: { + __resolveReference(reference: { upc: String; }) { + if (reference != null) { + let book = books.find((book) => book.upc === reference.upc); + if (book != null && book.upc !== null) { + return { + __typename: "Book", + upc: book.upc + }; + } + } + throw new Error("Invalid reference"); + }, + } + }, +}); diff --git a/src/test-suites/null-keys/b.subgraph.ts b/src/test-suites/null-keys/b.subgraph.ts new file mode 100644 index 0000000..8bda525 --- /dev/null +++ b/src/test-suites/null-keys/b.subgraph.ts @@ -0,0 +1,45 @@ +import { createSubgraph } from "../../subgraph.js"; +import { books } from "./data.js"; + +export default createSubgraph("b", { + typeDefs: /* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.3" + import: ["@key"] + ) + + type Book @key(fields: "id") @key(fields: "upc") { + id: ID! + upc: ID! + } + `, + resolvers: { + Book: { + __resolveReference(reference: { id: String; } | { upc: String; }) { + if (reference != null) { + let book: { id: string; upc: string; } | undefined; + if ('id' in reference) { + book = books.find((book) => book.id === reference.id); + } + if ('upc' in reference) { + book = books.find((book) => book.upc === reference.upc); + } + if (book != null) { + // `a` has `Book` entities with upc: `b1, b2, b3`, but `b` has `Book` entities with only `b1` and `b2`. + // `b3` is not available and this subgraph is the only possible step to get to the other subgraph (need of `id` field) to resolve the author. + if (book.id === '3') { + return null; + } + return { + __typename: "Book", + id: book.id, + upc: book.upc + }; + } + } + throw new Error("Invalid reference"); + } + } + }, +}); diff --git a/src/test-suites/null-keys/c.subgraph.ts b/src/test-suites/null-keys/c.subgraph.ts new file mode 100644 index 0000000..bfb0842 --- /dev/null +++ b/src/test-suites/null-keys/c.subgraph.ts @@ -0,0 +1,49 @@ +import { createSubgraph } from "../../subgraph.js"; +import { books } from "./data.js"; + +export default createSubgraph("c", { + typeDefs: /* GraphQL */ ` + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.3" + import: ["@key"] + ) + + type Book @key(fields: "id") { + id: ID! + author: Author + } + + type Author { + id: ID! + name: String + } + `, + resolvers: { + Book: { + __resolveReference(reference: { id: String; } | { upc: String; }) { + if (reference != null) { + let book: { id: string; author: { id: string; name: string; } } | undefined; + if ('id' in reference && reference.id !== null) { + book = books.find((book) => book.id === reference.id); + } + if ('upc' in reference && reference.upc !== null) { + book = books.find((book) => book.upc === reference.upc); + } + if (book != null) { + return { + __typename: "Book", + id: book.id, + author: { + __typename: "Author", + id: book.author.id, + name: book.author.name + } + }; + } + } + throw new Error("Invalid reference"); + } + } + }, +}); diff --git a/src/test-suites/null-keys/data.ts b/src/test-suites/null-keys/data.ts new file mode 100644 index 0000000..764348c --- /dev/null +++ b/src/test-suites/null-keys/data.ts @@ -0,0 +1,32 @@ +export const books = [ + { + __typename: "Book", + id: "1", + upc: "b1", + author: { + __typename: "Author", + id: "a1", + name: "Alice" + } + }, + { + __typename: "Book", + id: "2", + upc: "b2", + author: { + __typename: "Author", + id: "a2", + name: "Bob" + } + }, + { + __typename: "Book", + id: "3", + upc: "b3", + author: { + __typename: "Author", + id: "a3", + name: "Jack" + } + } +] \ No newline at end of file diff --git a/src/test-suites/null-keys/index.ts b/src/test-suites/null-keys/index.ts new file mode 100644 index 0000000..00dbce2 --- /dev/null +++ b/src/test-suites/null-keys/index.ts @@ -0,0 +1,7 @@ +import { serve } from "../../supergraph.js"; +import a from "./a.subgraph.js"; +import b from "./b.subgraph.js"; +import c from "./c.subgraph.js"; +import test from "./test.js"; + +export default serve("null-keys", [a, b, c], test); diff --git a/src/test-suites/null-keys/test.ts b/src/test-suites/null-keys/test.ts new file mode 100644 index 0000000..4289b7a --- /dev/null +++ b/src/test-suites/null-keys/test.ts @@ -0,0 +1,46 @@ +import { createTest } from "../../testkit.js"; + +export default [ + createTest( + /* GraphQL */ ` + query { + bookContainers { + book { + upc + author { + name + } + } + } + } + `, + { + data: { + bookContainers: [ + { + book: { + upc: "b1", + author: { + name: "Alice" + } + } + }, + { + book: { + upc: "b2", + author: { + name: "Bob" + } + } + }, + { + book: { + upc: "b3", + author: null, + } + } + ] + }, + }, + ), +]; diff --git a/website/index.html b/website/index.html index aaab471..1ed055d 100644 --- a/website/index.html +++ b/website/index.html @@ -230,10 +230,10 @@

100.00% - ✓ 170 + ✓ 171 - ✓ 40 + ✓ 41 Apollo Router - 97.65% + 97.66% - ✓ 166 + ✓ 167 ✗ 4 - ✓ 38 + ✓ 39 ✗ 2 @@ -286,13 +286,13 @@

Apollo Gateway - 97.06% + 97.08% - ✓ 165 + ✓ 166 ✗ 5 - ✓ 37 + ✓ 38 ✗ 3 @@ -316,14 +316,14 @@

Cosmo Router - 70.00% + 69.59% ✓ 119 - ✗ 51 + ✗ 52 ✓ 19 - ✗ 21 + ✗ 22 Grafbase Gateway - 60.00% + 59.06% - ✓ 102 - ✗ 68 + ✓ 101 + ✗ 70 ✓ 19 - ✗ 21 + ✗ 22