From 26fabdaeee27b804bb223a34aea5da7fef79c0c0 Mon Sep 17 00:00:00 2001 From: Shawn McKnight Date: Mon, 5 Feb 2024 18:21:36 -0500 Subject: [PATCH] Await graphql handler to avoid unhandled promise rejections --- src/service.js | 4 +-- test/unit/service.spec.js | 66 +++++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/service.js b/src/service.js index 19ce1d9..d480d79 100644 --- a/src/service.js +++ b/src/service.js @@ -770,7 +770,7 @@ module.exports = function (mixinOptions) { async "/"(req, res) { try { await this.prepareGraphQLSchema(); - return this.graphqlHandler(req, res); + return await this.graphqlHandler(req, res); } catch (err) { this.sendError(req, res, err); } @@ -778,6 +778,7 @@ module.exports = function (mixinOptions) { async "GET /.well-known/apollo/server-health"(req, res) { try { await this.prepareGraphQLSchema(); + return await this.graphqlHandler(req, res); } catch (err) { res.statusCode = 503; return this.sendResponse( @@ -787,7 +788,6 @@ module.exports = function (mixinOptions) { { responseType: "application/health+json" } ); } - return this.graphqlHandler(req, res); }, }, diff --git a/test/unit/service.spec.js b/test/unit/service.spec.js index b52d295..5fd67a0 100644 --- a/test/unit/service.spec.js +++ b/test/unit/service.spec.js @@ -77,7 +77,7 @@ describe("Test Service", () => { await stop(); }); - it("should call sendError if error occured", async () => { + it("should call sendError if error occurs when preparing graphql schema", async () => { const { svc, stop } = await startService(); const err = new Error("Something happened"); @@ -99,6 +99,29 @@ describe("Test Service", () => { await stop(); }); + + it("should call sendError if error occurs when handling graphql request", async () => { + const { svc, stop } = await startService(); + + const err = new Error("Something happened"); + svc.sendError = jest.fn(); + svc.prepareGraphQLSchema = jest.fn(); + svc.graphqlHandler = jest.fn(() => { + throw err; + }); + const fakeReq = { req: 1 }; + const fakeRes = { res: 1 }; + + const res = await svc.settings.routes[0].aliases["/"].call(svc, fakeReq, fakeRes); + + expect(res).toBeUndefined(); + expect(svc.prepareGraphQLSchema).toBeCalledTimes(1); + expect(svc.graphqlHandler).toBeCalledTimes(1); + expect(svc.sendError).toBeCalledTimes(1); + expect(svc.sendError).toBeCalledWith(fakeReq, fakeRes, err); + + await stop(); + }); }); describe("Test `GET /.well-known/apollo/server-health` route handler", () => { @@ -123,7 +146,7 @@ describe("Test Service", () => { await stop(); }); - it("should call sendError if error occured", async () => { + it("should call sendError if error occurs when preparing graphql schema", async () => { const { svc, stop } = await startService(); const err = new Error("Something happened"); @@ -146,13 +169,38 @@ describe("Test Service", () => { expect(svc.sendResponse).toBeCalledWith( fakeReq, fakeRes, - { - status: "fail", - schema: false, - }, - { - responseType: "application/health+json", - } + { status: "fail", schema: false }, + { responseType: "application/health+json" } + ); + + await stop(); + }); + + it("should call sendError if error occurs when handling graphql request", async () => { + const { svc, stop } = await startService(); + + const err = new Error("Something happened"); + svc.sendResponse = jest.fn(); + svc.prepareGraphQLSchema = jest.fn(); + svc.graphqlHandler = jest.fn(() => { + throw err; + }); + const fakeReq = { req: 1 }; + const fakeRes = { res: 1 }; + + const res = await svc.settings.routes[0].aliases[ + "GET /.well-known/apollo/server-health" + ].call(svc, fakeReq, fakeRes); + + expect(res).toBeUndefined(); + expect(svc.prepareGraphQLSchema).toBeCalledTimes(1); + expect(svc.graphqlHandler).toBeCalledTimes(1); + expect(svc.sendResponse).toBeCalledTimes(1); + expect(svc.sendResponse).toBeCalledWith( + fakeReq, + fakeRes, + { status: "fail", schema: false }, + { responseType: "application/health+json" } ); await stop();