Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(tests): test for federating two schemas #29

Merged
merged 1 commit into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions __tests__/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
"""
Expand All @@ -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(
Expand Down Expand Up @@ -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
}

Expand Down
33 changes: 29 additions & 4 deletions __tests__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ afterAll(() => {
}
});

function startPostgraphile(): Promise<http.Server> {
return new Promise(resolve => {
function startPostgraphile(
schema = "graphile_federation"
): Promise<http.Server> {
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",
Expand Down Expand Up @@ -59,6 +61,7 @@ async function withFederatedExternalServices(
cb: (_: { serverInfo: ServerInfo; schema: GraphQLSchema }) => Promise<any>
) {
const postgraphileServer = await startPostgraphile();
const postgraphileServer2 = await startPostgraphile("graphile_federation2");
const externalServices = await Promise.all(
Object.entries(startExternalServices).map(
async ([name, serviceBuilder]) => {
Expand All @@ -79,6 +82,10 @@ async function withFederatedExternalServices(
name: "postgraphile",
url: toUrl(postgraphileServer.address()!) + "/graphql",
},
{
name: "postgraphile2",
url: toUrl(postgraphileServer2.address()!) + "/graphql",
},
...externalServices,
];

Expand All @@ -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();
}
Expand All @@ -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({
Expand All @@ -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" }],
},
],
},
});
}
Expand Down
25 changes: 23 additions & 2 deletions __tests__/setupSchema.sql
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -75,4 +75,25 @@ VALUES (
(
1,
2
);
);

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');