diff --git a/test/gateway/application-hooks.js b/test/gateway/application-hooks.js index 9e84e5b0..4d3c83a7 100644 --- a/test/gateway/application-hooks.js +++ b/test/gateway/application-hooks.js @@ -1,6 +1,6 @@ 'use strict' -const { test } = require('tap') +const { test, t } = require('tap') const FakeTimers = require('@sinonjs/fake-timers') const { GraphQLSchema } = require('graphql') const { promisify } = require('util') @@ -10,18 +10,24 @@ const buildFederationSchema = require('../../lib/federation') const immediate = promisify(setImmediate) +t.beforeEach(({ context }) => { + context.clock = FakeTimers.install({ + shouldClearNativeTimers: true, + shouldAdvanceTime: true, + advanceTimeDelta: 100 + }) +}) + +t.afterEach(({ context }) => { + context.clock.uninstall() +}) + // ---------------------- // onGatewayReplaceSchema // ---------------------- test('onGatewayReplaceSchema - polling interval with a new schema should trigger onGatewayReplaceSchema hook', async (t) => { t.plan(2) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const resolvers = { Query: { me: (root, args, context, info) => user @@ -95,7 +101,9 @@ test('onGatewayReplaceSchema - polling interval with a new schema should trigger ) userService.graphql.defineResolvers(resolvers) - await clock.tickAsync(2000) + for (let i = 0; i < 10; i++) { + await t.context.clock.tickAsync(200) + } // We need the event loop to actually spin twice to // be able to propagate the change @@ -106,12 +114,6 @@ test('onGatewayReplaceSchema - polling interval with a new schema should trigger test('onGatewayReplaceSchema - should log an error should any errors occur in the hook', async (t) => { t.plan(2) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const resolvers = { Query: { me: (root, args, context, info) => user @@ -194,7 +196,9 @@ test('onGatewayReplaceSchema - should log an error should any errors occur in th ) userService.graphql.defineResolvers(resolvers) - await clock.tickAsync(2000) + for (let i = 0; i < 10; i++) { + await t.context.clock.tickAsync(200) + } // We need the event loop to actually spin twice to // be able to propagate the change diff --git a/test/gateway/pollingInterval.js b/test/gateway/pollingInterval.js index d8f33d89..f4cf4e1a 100644 --- a/test/gateway/pollingInterval.js +++ b/test/gateway/pollingInterval.js @@ -1,6 +1,6 @@ 'use strict' -const { test } = require('tap') +const { test, t } = require('tap') const FakeTimers = require('@sinonjs/fake-timers') @@ -13,13 +13,19 @@ const WebSocket = require('ws') const buildFederationSchema = require('../../lib/federation') const GQL = require('../..') -test('Polling schemas with disable cache', async (t) => { - const clock = FakeTimers.install({ +t.beforeEach(({ context }) => { + context.clock = FakeTimers.install({ + shouldClearNativeTimers: true, shouldAdvanceTime: true, advanceTimeDelta: 40 }) - t.teardown(() => clock.uninstall()) +}) + +t.afterEach(({ context }) => { + context.clock.uninstall() +}) +test('Polling schemas with disable cache', async (t) => { const resolvers = { Query: { me: (root, args, context, info) => user @@ -103,12 +109,6 @@ test('Polling schemas with disable cache', async (t) => { }) test('Polling schemas', async (t) => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const resolvers = { Query: { me: (root, args, context, info) => user @@ -234,7 +234,9 @@ test('Polling schemas', async (t) => { ) userService.graphql.defineResolvers(resolvers) - await clock.tickAsync(2000) + for (let i = 0; i < 10; i++) { + await t.context.clock.tickAsync(200) + } // We need the event loop to actually spin twice to // be able to propagate the change @@ -336,12 +338,6 @@ test('Polling schemas (gateway.polling interval is not a number)', async (t) => }) test("Polling schemas (if service is down, schema shouldn't be changed)", async (t) => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const resolvers = { Query: { me: (root, args, context, info) => user @@ -381,7 +377,7 @@ test("Polling schemas (if service is down, schema shouldn't be changed)", async }) await userService.listen({ port: 0 }) - await clock.tickAsync() + await t.context.clock.tickAsync() const userServicePort = userService.server.address().port @@ -397,7 +393,7 @@ test("Polling schemas (if service is down, schema shouldn't be changed)", async } }) - await clock.tickAsync() + await t.context.clock.tickAsync() { const { body } = await gateway.inject({ @@ -418,7 +414,7 @@ test("Polling schemas (if service is down, schema shouldn't be changed)", async }) }) - await clock.tickAsync() + await t.context.clock.tickAsync() t.same(JSON.parse(body), { data: { @@ -463,7 +459,7 @@ test("Polling schemas (if service is down, schema shouldn't be changed)", async } await userService.close() - await clock.tickAsync(500) + await t.context.clock.tickAsync(500) { const { body } = await gateway.inject({ @@ -622,12 +618,6 @@ test('Polling schemas (if service is mandatory, exception should be thrown)', as }) test('Polling schemas (cache should be cleared)', async (t) => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const user = { id: 'u1', name: 'John', @@ -729,7 +719,9 @@ test('Polling schemas (cache should be cleared)', async (t) => { } }) - await clock.tickAsync(10000) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(100) + } // We need the event loop to actually spin twice to // be able to propagate the change @@ -793,11 +785,6 @@ test('Polling schemas (cache should be cleared)', async (t) => { }) test('Polling schemas (should properly regenerate the schema when a downstream service restarts)', async (t) => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) const oldSchema = ` type Query { me: User @@ -916,7 +903,9 @@ test('Polling schemas (should properly regenerate the schema when a downstream s await restartedUserService.listen({ port: userServicePort }) - await clock.tickAsync(10000) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(100) + } // We need the event loop to actually spin twice to // be able to propagate the change @@ -982,12 +971,6 @@ test('Polling schemas (should properly regenerate the schema when a downstream s test('Polling schemas (subscriptions should be handled)', async (t) => { t.plan(12) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const user = { id: 'u1', name: 'John', @@ -1172,7 +1155,7 @@ test('Polling schemas (subscriptions should be handled)', async (t) => { userService.graphql.defineResolvers(resolvers) - await clock.tickAsync(10000) + await t.context.clock.tickAsync(10000) // We need the event loop to actually spin twice to // be able to propagate the change diff --git a/test/gateway/retry-failed-services.js b/test/gateway/retry-failed-services.js index 3eb13e88..b8ba440f 100644 --- a/test/gateway/retry-failed-services.js +++ b/test/gateway/retry-failed-services.js @@ -1,6 +1,6 @@ 'use strict' -const { test } = require('tap') +const { test, t } = require('tap') const Fastify = require('fastify') const { GraphQLSchema } = require('graphql') const GQL = require('../..') @@ -112,17 +112,24 @@ const postService = { } } -test('gateway - retry mandatory failed services on startup', async (t) => { - t.plan(5) - const clock = FakeTimers.install({ +t.beforeEach(({ context }) => { + context.clock = FakeTimers.install({ + shouldClearNativeTimers: true, shouldAdvanceTime: true, advanceTimeDelta: 100 }) +}) + +t.afterEach(({ context }) => { + context.clock.uninstall() +}) +test('gateway - retry mandatory failed services on startup', async (t) => { + t.plan(5) const service1 = await createTestService(0, userService.schema, userService.resolvers) let service2 = null - setTimeout(async () => { + t.context.clock.setTimeout(async () => { service2 = await createTestService(5113, postService.schema, postService.resolvers) }, 5000) @@ -131,7 +138,6 @@ test('gateway - retry mandatory failed services on startup', async (t) => { await app.close() await service1.close() await service2.close() - clock.uninstall() }) await app.register(GQL, { @@ -178,7 +184,7 @@ test('gateway - retry mandatory failed services on startup', async (t) => { body: JSON.stringify({ query }) }) - t.same(JSON.parse(res.body), { + t.same(await res.json(), { errors: [ { message: 'Cannot query field "posts" on type "User".', @@ -188,8 +194,8 @@ test('gateway - retry mandatory failed services on startup', async (t) => { data: null }) - for (let i = 0; i < 10; i++) { - await clock.tickAsync(2000) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(100) } const res1 = await app.inject({ @@ -216,24 +222,18 @@ test('gateway - retry mandatory failed services on startup', async (t) => { test('gateway - should not call onGatewayReplaceSchemaHandler if the hook is not specified', async (t) => { t.plan(2) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 100 - }) - const service1 = await createTestService(0, userService.schema, userService.resolvers) let service2 = null - setTimeout(async () => { + t.context.clock.setTimeout(async () => { service2 = await createTestService(5111, postService.schema, postService.resolvers) - }, 5000) + }, 2000) const app = Fastify() t.teardown(async () => { await app.close() await service1.close() await service2.close() - clock.uninstall() }) await app.register(GQL, { @@ -276,7 +276,7 @@ test('gateway - should not call onGatewayReplaceSchemaHandler if the hook is not body: JSON.stringify({ query }) }) - t.same(JSON.parse(res.body), { + t.same(await res.json(), { errors: [ { message: 'Cannot query field "posts" on type "User".', @@ -286,8 +286,8 @@ test('gateway - should not call onGatewayReplaceSchemaHandler if the hook is not data: null }) - for (let i = 0; i < 10; i++) { - await clock.tickAsync(1000) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(100) } const res1 = await app.inject({ @@ -314,18 +314,13 @@ test('gateway - should not call onGatewayReplaceSchemaHandler if the hook is not test('gateway - dont retry non-mandatory failed services on startup', async (t) => { t.plan(2) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 100 - }) - const service1 = await createTestService(0, userService.schema, userService.resolvers) const app = Fastify() t.teardown(async () => { await app.close() await service1.close() - clock.uninstall() + t.context.clock.uninstall() }) app.register(GQL, { @@ -367,7 +362,7 @@ test('gateway - dont retry non-mandatory failed services on startup', async (t) body: JSON.stringify({ query }) }) - t.same(JSON.parse(res.body), { + t.same(await res.json(), { errors: [ { message: 'Cannot query field "posts" on type "User".', @@ -377,8 +372,8 @@ test('gateway - dont retry non-mandatory failed services on startup', async (t) data: null }) - for (let i = 0; i < 10; i++) { - await clock.tickAsync(1500) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(150) } const res1 = await app.inject({ @@ -388,7 +383,7 @@ test('gateway - dont retry non-mandatory failed services on startup', async (t) body: JSON.stringify({ query }) }) - t.same(JSON.parse(res1.body), { + t.same(await res1.json(), { errors: [ { message: 'Cannot query field "posts" on type "User".', @@ -401,16 +396,11 @@ test('gateway - dont retry non-mandatory failed services on startup', async (t) test('gateway - should log error if retry throws', async (t) => { t.plan(1) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 100 - }) - const service1 = await createTestService(0, userService.schema, userService.resolvers) let service2 = null - setTimeout(async () => { - service2 = await createTestService(5113, postService.schema, postService.resolvers) + t.context.clock.setTimeout(async () => { + service2 = await createTestService(5114, postService.schema, postService.resolvers) }, 2000) const app = Fastify() @@ -427,7 +417,6 @@ test('gateway - should log error if retry throws', async (t) => { await app.close() await service1.close() await service2.close() - clock.uninstall() }) await app.register(GQL, { @@ -441,12 +430,12 @@ test('gateway - should log error if retry throws', async (t) => { }, { name: 'post', - url: 'http://localhost:5113/graphql', + url: 'http://localhost:5114/graphql', mandatory: true } ], retryServicesCount: 1, - retryServicesInterval: 2000 + retryServicesInterval: 3000 } }) @@ -456,18 +445,13 @@ test('gateway - should log error if retry throws', async (t) => { await app.ready() - for (let i = 0; i < 100; i++) { - await clock.tickAsync(100) + for (let i = 0; i < 200; i++) { + await t.context.clock.tickAsync(50) } }) test('gateway - stop retrying after no. of retries exceeded', async (t) => { t.plan(1) - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 100 - }) - const service1 = await createTestService(0, userService.schema, userService.resolvers) const app = Fastify() @@ -483,7 +467,6 @@ test('gateway - stop retrying after no. of retries exceeded', async (t) => { t.teardown(async () => { await app.close() await service1.close() - clock.uninstall() }) await app.register(GQL, { @@ -497,7 +480,7 @@ test('gateway - stop retrying after no. of retries exceeded', async (t) => { }, { name: 'post', - url: 'http://localhost:5114/graphql', + url: 'http://localhost:5115/graphql', mandatory: true } ], @@ -508,7 +491,7 @@ test('gateway - stop retrying after no. of retries exceeded', async (t) => { await app.ready() - for (let i = 0; i < 10; i++) { - await clock.tickAsync(1500) + for (let i = 0; i < 100; i++) { + await t.context.clock.tickAsync(150) } }) diff --git a/test/gateway/value-types.js b/test/gateway/value-types.js index c7e9bc4c..8ffce767 100644 --- a/test/gateway/value-types.js +++ b/test/gateway/value-types.js @@ -1,6 +1,6 @@ 'use strict' -const { test } = require('tap') +const { test, t } = require('tap') const Fastify = require('fastify') const FakeTimers = require('@sinonjs/fake-timers') const { promisify } = require('util') @@ -485,6 +485,18 @@ const commentMutation = ` } ` +t.beforeEach(({ context }) => { + context.clock = FakeTimers.install({ + shouldClearNativeTimers: true, + shouldAdvanceTime: true, + advanceTimeDelta: 100 + }) +}) + +t.afterEach(({ context }) => { + context.clock.uninstall() +}) + test('Should be able to query with value types', async (t) => { const [userService, userServicePort] = await createService(t, userSchema, userResolvers) const [postService, postServicePort] = await createService(t, postSchema, postResolvers) @@ -705,12 +717,6 @@ test('Should be able to query top-level with value types', async (t) => { }) test('Should be able to query with value types and polling', async (t) => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - t.teardown(() => clock.uninstall()) - const [userService, userServicePort] = await createService(t, userSchema, userResolvers) const [postService, postServicePort] = await createService(t, postSchema, postResolvers) const [commentService, commentServicePort] = await createService(t, commentSchema, commentResolvers) @@ -797,7 +803,7 @@ test('Should be able to query with value types and polling', async (t) => { } }) - await clock.tickAsync(2000) + await t.context.clock.tickAsync(2000) // We need the event loop to actually spin twice to // be able to propagate the change diff --git a/test/subscription.js b/test/subscription.js index 30674643..143e1ff6 100644 --- a/test/subscription.js +++ b/test/subscription.js @@ -1,6 +1,6 @@ 'use strict' -const { test } = require('tap') +const { test, t } = require('tap') const Fastify = require('fastify') const WebSocket = require('ws') const mq = require('mqemitter') @@ -10,6 +10,18 @@ const GQL = require('..') const FakeTimers = require('@sinonjs/fake-timers') +t.beforeEach(({ context }) => { + context.clock = FakeTimers.install({ + shouldClearNativeTimers: true, + shouldAdvanceTime: true, + advanceTimeDelta: 40 + }) +}) + +t.afterEach(({ context }) => { + context.clock.uninstall() +}) + test('subscription server replies with connection_ack', t => { const app = Fastify() t.teardown(() => app.close()) @@ -730,15 +742,9 @@ test('subscription connection is closed if context function throws', t => { }) test('subscription server sends update to subscriptions with custom async context', t => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - const app = Fastify() t.teardown(async () => { await app.close() - clock.uninstall() }) const sendTestQuery = () => { @@ -837,7 +843,7 @@ test('subscription server sends update to subscriptions with custom async contex subscription: { emitter, context: async () => { - await clock.tickAsync(200) + await t.context.clock.tickAsync(200) return { topic: 'NOTIFICATION_ADDED' } } } @@ -917,15 +923,9 @@ test('subscription server sends update to subscriptions with custom async contex }) test('subscription connection is closed if async context function throws', t => { - const clock = FakeTimers.install({ - shouldAdvanceTime: true, - advanceTimeDelta: 40 - }) - const app = Fastify() t.teardown(async () => { await app.close() - clock.uninstall() }) const schema = ` @@ -945,7 +945,7 @@ test('subscription connection is closed if async context function throws', t => resolvers, subscription: { context: async function () { - await clock.tickAsync(200) + await t.context.clock.tickAsync(200) throw new Error('kaboom') } }