diff --git a/__tests__/__snapshots__/integration.test.ts.snap b/__tests__/__snapshots__/integration.test.ts.snap index d3af5cf..5f3eb80 100644 --- a/__tests__/__snapshots__/integration.test.ts.snap +++ b/__tests__/__snapshots__/integration.test.ts.snap @@ -49,6 +49,54 @@ enum EmailsOrderBy { PRIMARY_KEY_DESC } +type Forum implements Node { + """ + A globally unique identifier. Can be used in various places throughout the system to identify this single value. + """ + nodeId: ID! + id: Int! + title: String! + + """Reads and enables pagination through a set of \`Post\`.""" + postsByForumIdList( + """Only read the first \`n\` values of the set.""" + first: Int + + """Skip the first \`n\` values.""" + offset: Int + + """The method to use when ordering \`Post\`.""" + orderBy: [PostsOrderBy!] + + """ + A condition to be used in determining which values should be returned by the collection. + """ + condition: PostCondition + ): [Post!]! +} + +""" +A condition to be used against \`Forum\` object types. All fields are tested for equality and combined with a logical ‘and.’ +""" +input ForumCondition { + """Checks for equality with the object’s \`id\` field.""" + id: Int + + """Checks for equality with the object’s \`title\` field.""" + title: String +} + +"""Methods to use when ordering \`Forum\`.""" +enum ForumsOrderBy { + NATURAL + ID_ASC + ID_DESC + TITLE_ASC + TITLE_DESC + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC +} + """An object with a globally unique \`ID\`.""" interface Node { """ @@ -57,6 +105,46 @@ interface Node { nodeId: ID! } +type Post implements Node { + """ + A globally unique identifier. Can be used in various places throughout the system to identify this single value. + """ + nodeId: ID! + id: Int! + forumId: Int! + body: String! + + """Reads a single \`Forum\` that is related to this \`Post\`.""" + forumByForumId: Forum +} + +""" +A condition to be used against \`Post\` object types. All fields are tested for equality and combined with a logical ‘and.’ +""" +input PostCondition { + """Checks for equality with the object’s \`id\` field.""" + id: Int + + """Checks for equality with the object’s \`forumId\` field.""" + forumId: Int + + """Checks for equality with the object’s \`body\` field.""" + body: String +} + +"""Methods to use when ordering \`Post\`.""" +enum PostsOrderBy { + NATURAL + ID_ASC + ID_DESC + FORUM_ID_ASC + FORUM_ID_DESC + BODY_ASC + BODY_DESC + PRIMARY_KEY_ASC + PRIMARY_KEY_DESC +} + type Query { """Reads a set of \`Email\`.""" allEmailsList( @@ -131,6 +219,54 @@ type Query { """ nodeId: ID! ): UsersEmail + + """Reads a set of \`Forum\`.""" + allForumsList( + """Only read the first \`n\` values of the set.""" + first: Int + + """Skip the first \`n\` values.""" + offset: Int + + """The method to use when ordering \`Forum\`.""" + orderBy: [ForumsOrderBy!] + + """ + A condition to be used in determining which values should be returned by the collection. + """ + condition: ForumCondition + ): [Forum!] + + """Reads a set of \`Post\`.""" + allPostsList( + """Only read the first \`n\` values of the set.""" + first: Int + + """Skip the first \`n\` values.""" + offset: Int + + """The method to use when ordering \`Post\`.""" + orderBy: [PostsOrderBy!] + + """ + A condition to be used in determining which values should be returned by the collection. + """ + condition: PostCondition + ): [Post!] + forumById(id: Int!): Forum + postById(id: Int!): Post + + """Reads a single \`Forum\` using its globally unique \`ID\`.""" + forum( + """The globally unique \`ID\` to be used in selecting a single \`Forum\`.""" + nodeId: ID! + ): Forum + + """Reads a single \`Post\` using its globally unique \`ID\`.""" + post( + """The globally unique \`ID\` to be used in selecting a single \`Post\`.""" + nodeId: ID! + ): Post empty: ID } diff --git a/__tests__/integration.test.ts b/__tests__/integration.test.ts index 0a8d633..681ec34 100644 --- a/__tests__/integration.test.ts +++ b/__tests__/integration.test.ts @@ -23,13 +23,15 @@ afterAll(() => { } }); -function startPostgraphile(): Promise { - return new Promise(resolve => { +function startPostgraphile( + schema = "graphile_federation" +): Promise { + return new Promise((resolve) => { if (!pgPool) { throw new Error("pool not ready!"); } const httpServer = http.createServer( - postgraphile(pgPool, "graphile_federation", { + postgraphile(pgPool, schema, { disableDefaultMutations: true, appendPlugins: [federationPlugin], simpleCollections: "only", @@ -59,6 +61,7 @@ async function withFederatedExternalServices( cb: (_: { serverInfo: ServerInfo; schema: GraphQLSchema }) => Promise ) { const postgraphileServer = await startPostgraphile(); + const postgraphileServer2 = await startPostgraphile("graphile_federation2"); const externalServices = await Promise.all( Object.entries(startExternalServices).map( async ([name, serviceBuilder]) => { @@ -79,6 +82,10 @@ async function withFederatedExternalServices( name: "postgraphile", url: toUrl(postgraphileServer.address()!) + "/graphql", }, + { + name: "postgraphile2", + url: toUrl(postgraphileServer2.address()!) + "/graphql", + }, ...externalServices, ]; @@ -96,6 +103,7 @@ async function withFederatedExternalServices( await cb({ serverInfo, schema }); } finally { await postgraphileServer.close(); + await postgraphileServer2.close(); for (const external of externalServices) { await external.service.stop(); } @@ -114,7 +122,7 @@ test("federated service", async () => { expect(schema).toMatchSnapshot("federated schema"); const result = await axios.post(serverInfo.url, { - query: `{ allUsersList(first: 1) { firstName, lastName, fullName} }`, + query: `{ allUsersList(first: 1) { firstName, lastName, fullName} allForumsList { id title postsByForumIdList { id body } } }`, }); expect(result.data).toMatchObject({ @@ -126,6 +134,23 @@ test("federated service", async () => { lastName: "keys", }, ], + allForumsList: [ + { + id: 1, + title: "Cats", + postsByForumIdList: [{ id: 1, body: "They are sneaky" }], + }, + { + id: 2, + title: "Dogs", + postsByForumIdList: [{ id: 2, body: "They are loyal" }], + }, + { + id: 3, + title: "Postgres", + postsByForumIdList: [{ id: 3, body: "It's awesome" }], + }, + ], }, }); } diff --git a/__tests__/setupSchema.sql b/__tests__/setupSchema.sql index ad38638..c62fc9d 100644 --- a/__tests__/setupSchema.sql +++ b/__tests__/setupSchema.sql @@ -1,6 +1,6 @@ -- WARNING: this database is shared with postgraphile-core, don't run the tests in parallel! - DROP SCHEMA IF EXISTS graphile_federation CASCADE; + DROP SCHEMA IF EXISTS graphile_federation, graphile_federation2 CASCADE; CREATE SCHEMA graphile_federation; @@ -75,4 +75,25 @@ VALUES ( ( 1, 2 -); \ No newline at end of file +); + +CREATE SCHEMA graphile_federation2; +CREATE TABLE graphile_federation2.forums ( + id SERIAL PRIMARY KEY, + title TEXT NOT NULL +); +CREATE TABLE graphile_federation2.posts ( + id SERIAL PRIMARY KEY, + forum_id int not null references graphile_federation2.forums, + body TEXT NOT NULL +); + +insert into graphile_federation2.forums (title) values + ('Cats'), + ('Dogs'), + ('Postgres'); + +insert into graphile_federation2.posts (forum_id, body) values + (1, 'They are sneaky'), + (2, 'They are loyal'), + (3, 'It''s awesome');