diff --git a/package.json b/package.json index d207d55b..576e68c1 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@typescript-eslint/eslint-plugin": "^3.1.0", "@typescript-eslint/parser": "^3.1.0", "apollo-server-express": "^2.14.3", + "apollo-server-fastify": "^2.14.3", "conventional-changelog-cli": "^2.0.31", "cz-conventional-changelog": "^3.1.0", "eslint": "^7.2.0", diff --git a/test/app/resolvers/app.resolver.ts b/test/app/resolvers/app.resolver.ts index 1c43c01f..c5af58fa 100644 --- a/test/app/resolvers/app.resolver.ts +++ b/test/app/resolvers/app.resolver.ts @@ -1,5 +1,18 @@ -import { Resolver } from '@nestjs/graphql'; +import { Resolver, Query, Mutation } from '@nestjs/graphql'; import { ResolveType } from './resolve.model'; +import { AppService } from '../app.service'; @Resolver(ResolveType) -export class AppResolver {} +export class AppResolver { + constructor(private readonly appService: AppService) {} + + @Query(() => ResolveType) + appQuery() { + return this.appService.success(); + } + + @Mutation(() => ResolveType) + appMutation() { + return this.appService.success(); + } +} diff --git a/test/app/resolvers/resolve.model.ts b/test/app/resolvers/resolve.model.ts index 71bca836..65035e5a 100644 --- a/test/app/resolvers/resolve.model.ts +++ b/test/app/resolvers/resolve.model.ts @@ -2,6 +2,6 @@ import { Field, ObjectType } from '@nestjs/graphql'; @ObjectType() export class ResolveType { - @Field() + @Field((type) => Boolean) success = true; } diff --git a/test/app/resolvers/resolver.module.ts b/test/app/resolvers/resolver.module.ts index b0e6b9dc..7c648c09 100644 --- a/test/app/resolvers/resolver.module.ts +++ b/test/app/resolvers/resolver.module.ts @@ -1,5 +1,6 @@ import { Module } from '@nestjs/common'; import { ThrottlerModule } from '../../../src'; +import { AppService } from '../app.service'; import { AppResolver } from './app.resolver'; import { DefaultResolver } from './default.resolver'; import { LimitResolver } from './limit.resolver'; @@ -11,6 +12,6 @@ import { LimitResolver } from './limit.resolver'; ttl: 60, }), ], - providers: [AppResolver, DefaultResolver, LimitResolver], + providers: [AppResolver, DefaultResolver, LimitResolver, AppService], }) export class ResolverModule {} diff --git a/test/resolver.e2e-spec.ts b/test/resolver.e2e-spec.ts index 98cf9144..c08b6ab1 100644 --- a/test/resolver.e2e-spec.ts +++ b/test/resolver.e2e-spec.ts @@ -1 +1,96 @@ -it.todo('implement gql tests'); +import { INestApplication } from '@nestjs/common'; +import { AbstractHttpAdapter, APP_GUARD } from '@nestjs/core'; +import { GraphQLModule } from '@nestjs/graphql'; +import { ExpressAdapter } from '@nestjs/platform-express'; +import { FastifyAdapter } from '@nestjs/platform-fastify'; +import { Test, TestingModule } from '@nestjs/testing'; +import { ThrottlerGuard } from '../src'; +import { ResolverModule } from './app/resolvers/resolver.module'; +import { httPromise } from './utility/httpromise'; + +function queryFactory(prefix: string): Record { + return { + query: `query ${prefix}Query{ ${prefix}Query{ success }}`, + }; +} + +function mutationFactory(prefix: string): Record { + return { + query: `mutation ${prefix}Mutation{ ${prefix}Mutation{ success }}`, + }; +} + +describe.each` + adapter | adapterName | context + ${new ExpressAdapter()} | ${'Express'} | ${({ req, res }) => ({ req, res })} + ${new FastifyAdapter()} | ${'Fastify'} | ${({}) => ({})} +`( + '$adapterName Throttler', + ({ adapter, context }: { adapter: AbstractHttpAdapter; context: () => any }) => { + let app: INestApplication; + + beforeAll(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [ + ResolverModule, + GraphQLModule.forRoot({ + autoSchemaFile: true, + context, + }), + ], + providers: [ + { + provide: APP_GUARD, + useClass: ThrottlerGuard, + }, + ], + }).compile(); + + app = moduleFixture.createNestApplication(adapter); + await app.listen(0); + }); + + afterAll(async () => { + await app.close(); + }); + + describe('Resolvers', () => { + let appUrl: string; + beforeAll(async () => { + appUrl = (await app.getUrl()) + '/graphql'; + }); + + /** + * Tests for setting `@Throttle()` at the method level and for ignore routes + */ + describe('AppResolver', () => { + it.todo('Implement AppResolver tests'); + it.each` + type + ${'query'} + ${'mutation'} + `('$type', async ({ type }: { type: string }) => { + const res = await httPromise( + appUrl, + 'POST', + {}, + type === 'query' ? queryFactory('app') : mutationFactory('app'), + ); + expect(res).toEqual({ success: true }); + }); + }); + /** + * Tests for setting `@Throttle()` at the class level and overriding at the method level + */ + describe('LimitResolver', () => { + it.todo('Implement LimitResolver test'); + }); + /** + * Tests for setting throttle values at the `forRoot` level + */ + describe('DefaultResolver', () => { + it.todo('implement DefaultResolver Test'); + }); + }); + }, +); diff --git a/yarn.lock b/yarn.lock index 2534f58c..3e939446 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2487,6 +2487,19 @@ apollo-server-express@^2.14.3: subscriptions-transport-ws "^0.9.16" type-is "^1.6.16" +apollo-server-fastify@^2.14.3: + version "2.14.3" + resolved "https://registry.yarnpkg.com/apollo-server-fastify/-/apollo-server-fastify-2.14.3.tgz#633992f81dd70c288c8f53c4d77eb0c29bdf756e" + integrity sha512-qihLp9VUDxM/NZOpmdyCKp4/oq43tKf3aX94us4inbHIBu2lPCpREe4toJZL+9M45TQ2oTKF18gtlx3QEEtw7g== + dependencies: + "@apollographql/graphql-playground-html" "1.6.24" + apollo-server-core "^2.14.3" + apollo-server-types "^0.5.0" + fastify-accepts "^1.0.0" + fastify-cors "^0.2.0" + graphql-subscriptions "^1.0.0" + graphql-tools "^4.0.0" + apollo-server-plugin-base@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.0.tgz#777f720a1ee827a66b8c159073ca30645f8bc625" @@ -5100,6 +5113,14 @@ fast-safe-stringify@2.0.7, fast-safe-stringify@^2.0.7: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== +fastify-accepts@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fastify-accepts/-/fastify-accepts-1.0.0.tgz#8475d1e4c4eaf777eb916144ddc904f92d3c726a" + integrity sha512-JVI/zKXjVfwIAdXDZvNKM7CCEWkbTFSZQUEQxrH4KBprbopGxq3R4RSIsVxqhdkVanm90yyVcPtgEa2MnDwPyg== + dependencies: + accepts "^1.3.5" + fastify-plugin "^1.2.0" + fastify-cors@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/fastify-cors/-/fastify-cors-3.0.3.tgz#c1b2227983d7b02feff73fd642d81041adfbe124" @@ -5108,6 +5129,14 @@ fastify-cors@3.0.3: fastify-plugin "^1.6.0" vary "^1.1.2" +fastify-cors@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/fastify-cors/-/fastify-cors-0.2.0.tgz#8fce0a2a5ba05ac08c7d6f2ca4c501b0ae638e39" + integrity sha512-bw14FmjHm8oF4TDLkwj2TpssH6O2gE0NpsRqLe7F1Gh9Jf30Lx9ZzIznhqaAKOYS+LJqLIt5snurv7urgqYntA== + dependencies: + fastify-plugin "^1.2.0" + vary "^1.1.2" + fastify-formbody@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/fastify-formbody/-/fastify-formbody-3.2.0.tgz#638de5bcc91d40352bca130dc4dc292b452a251e" @@ -5116,7 +5145,7 @@ fastify-formbody@3.2.0: fastify-plugin "^1.6.1" qs "^6.9.4" -fastify-plugin@^1.6.0, fastify-plugin@^1.6.1: +fastify-plugin@^1.2.0, fastify-plugin@^1.6.0, fastify-plugin@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-1.6.1.tgz#122f5a5eeb630d55c301713145a9d188e6d5dd5b" integrity sha512-APBcb27s+MjaBIerFirYmBLatoPCgmHZM6XP0K+nDL9k0yX8NJPWDY1RAC3bh6z+AB5ULS2j31BUfLMT3uaZ4A==