From b9b59d6e78ee6a26bc2fe09174190b71e9037a6a Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 14 Apr 2020 13:24:08 +0200 Subject: [PATCH 1/2] add test to catch broken reload --- test/schemas/cluster.test.ts | 2 +- test/server.data.json | 2 +- test/server.test.ts | 32 +++++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/test/schemas/cluster.test.ts b/test/schemas/cluster.test.ts index 3d73efc..935327a 100644 --- a/test/schemas/cluster.test.ts +++ b/test/schemas/cluster.test.ts @@ -21,7 +21,7 @@ describe('clusters', async() => { it('serves a basic graphql query', async() => { const resp = await chai.request(srv).get('/graphql').query( - { query: '{ clusters: clusters_v1 { name } }' } + { query: '{ clusters: clusters_v1 { name } }' }, ); resp.should.have.status(200); return resp.body.data.clusters[0].name.should.equal('example cluster'); diff --git a/test/server.data.json b/test/server.data.json index a73922c..2e44c48 100644 --- a/test/server.data.json +++ b/test/server.data.json @@ -1230,4 +1230,4 @@ "sha256sum": "ff" } } -} \ No newline at end of file +} diff --git a/test/server.test.ts b/test/server.test.ts index e4cbd29..2cb3ddb 100644 --- a/test/server.test.ts +++ b/test/server.test.ts @@ -11,6 +11,9 @@ chai.use(chaiHttp); import * as server from '../src/server'; import * as db from '../src/db'; +process.env.LOAD_METHOD = 'fs'; +process.env.DATAFILES_FILE = 'test/server.data.json'; + const should = chai.should(); const expect = chai.expect; @@ -24,7 +27,7 @@ describe('server', async() => { // Setup and teardown the GraphQL HTTP server. let srv: http.Server; before(async() => { - const app = await server.appFromBundle(db.bundleFromDisk('test/server.data.json')); + const app = await server.appFromBundle(db.bundleFromEnvironment()); srv = app.listen({ port: 4000 }); }); after(async() => await util.promisify(srv.close)); @@ -78,4 +81,31 @@ describe('server', async() => { responseIsNotAnError(response); return response.body.data.resources[0].content.should.equal('test resource'); }); + + it('can retrieve a field from an interface', async() => { + const query = `{ + roles: roles_v1(path: "/role-A.yml") { + permissions { + service + ... on PermissionGithubOrgTeam_v1 { + org + } + } + } + } + `; + + const response1 = await chai.request(srv).get('/graphql').query({ query }); + responseIsNotAnError(response1); + response1.body.data.roles[0].permissions[0].org.should.equal('org-A'); + + // check that it continues to work after a reload + await chai.request(srv).post('/reload'); + + const response2 = await chai.request(srv).get('/graphql').query({ query }); + responseIsNotAnError(response2); + + const perm = response2.body.data.roles[0].permissions[0]; + expect(perm.org).to.equal('org-A'); + }); }); From 05778163af1074adad78834540aef457723ce45e Mon Sep 17 00:00:00 2001 From: Jaime Melis Date: Tue, 14 Apr 2020 13:43:15 +0200 Subject: [PATCH 2/2] fix broken graphql after /reload After upgrading the apollo-server-express version, any queries that include interfaces will fail after reloading the server. In order to reproduce we can just make a query like this one: ``` { permissions_v1 (path:"") { service ... on PermissionGithubOrgTeam_v1 { org } } } ``` Before reloading the object will contain `org`, but once we reload the `org` parameter will be missing from the response. This is because with the new apollo-server-express version besides resetting the schema on a hot reload, we also need to make sure the `schemaDerivedData` is also generated. The solution to this issue was found here: https://github.com/apollographql/apollo-server/issues/1275#issuecomment-532183702 Note the `@ts-ignore` line, which is needed because we are accessing a private method `generateSchemaDerivedData`. Unless we have this line typescript will raise an error when compiling. This PR also adds a test that will catch this if there is a regression. --- src/server.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/server.ts b/src/server.ts index a63c0e6..8716a93 100644 --- a/src/server.ts +++ b/src/server.ts @@ -85,7 +85,13 @@ export const appFromBundle = async (bundle: Promise) => { req.app.set('bundle', bundle); const schema: GraphQLSchema = generateAppSchema(req.app as express.Express); + + // https://github.com/apollographql/apollo-server/issues/1275#issuecomment-532183702 + // @ts-ignore + const schemaDerivedData = await server.generateSchemaDerivedData(schema); + req.app.get('server').schema = schema; + req.app.get('server').schemaDerivedData = schemaDerivedData; // Count number of files for each schema type const reducer = (acc: IAcct, d: any) => {