Skip to content

Commit

Permalink
fix graphql tests
Browse files Browse the repository at this point in the history
  • Loading branch information
asmeikal committed Feb 10, 2024
1 parent 1f50474 commit 7c82156
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 68 deletions.
2 changes: 2 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tools]
node = "20"
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"license": "MIT",
"sideEffects": false,
"scripts": {
"postinstall": "patch-package",
"build": "npm-run-all build:*",
"build:cjs": "npm-run-all build:cjs:*",
"build:cjs:code": "nest build --config ./nest-cli.json",
Expand Down Expand Up @@ -69,6 +70,8 @@
"jest": "^29.7.0",
"jsonwebtoken": "^9.0.2",
"npm-run-all": "^4.1.5",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^3.2.5",
"reflect-metadata": "^0.2.1",
"renamer": "^5.0.0",
Expand Down
26 changes: 26 additions & 0 deletions patches/@nestjs+core+10.3.2.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
diff --git a/node_modules/@nestjs/core/helpers/external-context-creator.js b/node_modules/@nestjs/core/helpers/external-context-creator.js
index e820c25..4c1b24f 100644
--- a/node_modules/@nestjs/core/helpers/external-context-creator.js
+++ b/node_modules/@nestjs/core/helpers/external-context-creator.js
@@ -133,16 +133,17 @@ class ExternalContextCreator {
const resolveParamValue = async (param) => {
const { index, extractValue, type, data, metatype, pipes: paramPipes, } = param;
const value = extractValue(...params);
- args[index] = await this.getParamValue(value, { metatype, type, data }, pipes.concat(paramPipes));
+ args[index] = (await this.getParamValue(value, { metatype, type, data }, pipes.concat(paramPipes))).value;
};
await Promise.all(paramsOptions.map(resolveParamValue));
};
return paramsOptions.length ? pipesFn : null;
}
async getParamValue(value, { metatype, type, data }, pipes) {
- return (0, shared_utils_1.isEmpty)(pipes)
- ? value
- : this.pipesConsumer.apply(value, { metatype, type, data }, pipes);
+ return {
+ value: (0, shared_utils_1.isEmpty)(pipes) ? value :
+ this.pipesConsumer.apply(value, { metatype, type, data }, pipes)
+ };
}
async transformToResult(resultOrDeferred) {
if ((0, rxjs_1.isObservable)(resultOrDeferred)) {
5 changes: 2 additions & 3 deletions src/security/cookie.jwt-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ export class CookieJwtStrategy
) {
super();
this.opaqueTokenExtractor = ExtractJwt.fromExtractors([
extractFromCookie(this.options.accessTokenHeaderKey),
extractFromCookie(this.options.opaqueTokenHeaderKey),
]);

this.accessTokenExtractor = ExtractJwt.fromExtractors([
extractFromCookie(this.options.opaqueTokenHeaderKey),
extractFromCookie(this.options.accessTokenHeaderKey),
]);
}

Expand Down
51 changes: 38 additions & 13 deletions tests/graphql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,32 @@ import {
NestFastifyApplication,
} from "@nestjs/platform-fastify";
import { Authenticated, CookieService, SecurityModule } from "../src";
import { Controller, Get, Post, Res } from "@nestjs/common";
import { FastifyReply } from "fastify";
import { FastifyRequest, FastifyReply } from "fastify";
import { sign } from "jsonwebtoken";
import fastifyCookie from "@fastify/cookie";
import {
Resolver,
Query,
Mutation,
GraphQLModule,
ObjectType,
Field,
Context,
} from "@nestjs/graphql";
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";

@ObjectType()
class Cat {
@Field(() => String)
hello: string;
}

@Controller()
class TestController {
@Resolver(() => Cat)
class TestResolver {
constructor(private readonly cookieService: CookieService) {}

@Post("/login")
async login(@Res({ passthrough: true }) response: FastifyReply) {
@Mutation(() => Boolean)
async login(@Context("res") res: FastifyReply) {
const accessToken = sign(
{
tokenType: "dog",
Expand All @@ -23,10 +38,11 @@ class TestController {
"secret",
);
const refreshToken = "refresh";
await this.cookieService.setCookies(response, accessToken, refreshToken);
await this.cookieService.setCookies(res, accessToken, refreshToken);
return true;
}

@Get("/cats")
@Query(() => Cat)
@Authenticated("dog")
async cats() {
return {
Expand All @@ -39,7 +55,15 @@ let app: NestFastifyApplication;

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
providers: [TestResolver],
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
context: (req: FastifyRequest, res: FastifyReply) => {
return { req, res };
},
}),
SecurityModule.forRoot({
type: "cookie",
accessTokenHeaderKey: "access_token",
Expand All @@ -50,7 +74,6 @@ beforeAll(async () => {
refreshTokenHeaderKey: "refresh_token",
}),
],
controllers: [TestController],
}).compile();

app = moduleRef.createNestApplication<NestFastifyApplication>(
Expand All @@ -71,9 +94,10 @@ beforeAll(async () => {
it(`/GET cats`, async () => {
const result = await app.inject({
method: "POST",
url: "/login",
url: "/graphql",
body: { query: `mutation { login }` },
});
expect(result.statusCode).toEqual(201);
expect(result.statusCode).toEqual(200);
expect(result.cookies).toHaveLength(2);

const cookies = result.cookies.reduce(
Expand All @@ -84,8 +108,9 @@ it(`/GET cats`, async () => {
{} as { [k: string]: string },
);
const result2 = await app.inject({
method: "GET",
url: "/cats",
method: "POST",
url: "/graphql",
body: { query: `{ cats { hello } }` },
cookies,
});
expect(result2.statusCode).toEqual(200);
Expand Down
72 changes: 24 additions & 48 deletions tests/rest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,17 @@ import {
NestFastifyApplication,
} from "@nestjs/platform-fastify";
import { Authenticated, CookieService, SecurityModule } from "../src";
import { FastifyRequest, FastifyReply } from "fastify";
import { Controller, Get, Post, Res } from "@nestjs/common";
import { FastifyReply } from "fastify";
import { sign } from "jsonwebtoken";
import fastifyCookie from "@fastify/cookie";
import { Resolver, Query, Mutation, GraphQLModule, ObjectType, Field, Context } from "@nestjs/graphql";
import { Module } from "@nestjs/common";
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@ObjectType()
class Cat {
@Field(() => String)
hello: string;
}

@Resolver(() => Cat)
class TestResolver {
@Controller()
class TestController {
constructor(private readonly cookieService: CookieService) {}

@Mutation(() => Boolean)
async login(@Context() req: FastifyRequest) {
const res = (req as any).res as FastifyReply;
@Post("/login")
async login(@Res({ passthrough: true }) response: FastifyReply) {
const accessToken = sign(
{
tokenType: "dog",
Expand All @@ -32,11 +23,10 @@ class TestResolver {
"secret",
);
const refreshToken = "refresh";
await this.cookieService.setCookies(res , accessToken, refreshToken);
return true;
await this.cookieService.setCookies(response, accessToken, refreshToken);
}

@Query(() => Cat)
@Get("/cats")
@Authenticated("dog")
async cats() {
return {
Expand All @@ -45,24 +35,11 @@ class TestResolver {
}
}

@Module({ providers: [TestResolver ]})
class ResolverModule {}

let app: NestFastifyApplication;

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
ResolverModule,
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
context: (req : FastifyRequest , res: FastifyReply) => {
//@ts-expect-error
req.res = res;
return req;
},
}),
SecurityModule.forRoot({
type: "cookie",
accessTokenHeaderKey: "access_token",
Expand All @@ -73,6 +50,7 @@ beforeAll(async () => {
refreshTokenHeaderKey: "refresh_token",
}),
],
controllers: [TestController],
}).compile();

app = moduleRef.createNestApplication<NestFastifyApplication>(
Expand All @@ -93,26 +71,24 @@ beforeAll(async () => {
it(`/GET cats`, async () => {
const result = await app.inject({
method: "POST",
url: "/graphql",
body: { query: `mutation { login }`}
url: "/login",
});
expect(result.statusCode).toEqual(200);
expect(result.statusCode).toEqual(201);
expect(result.cookies).toHaveLength(2);

// const cookies = result.cookies.reduce(
// (acc, val) => {
// acc[val.name] = val.value;
// return acc;
// },
// {} as { [k: string]: string },
// );
// const result2 = await app.inject({
// method: "POST",
// url: "/graphql",
// body: { query: `{ cats() { hello } }`},
// cookies,
// });
// expect(result2.statusCode).toEqual(200);
const cookies = result.cookies.reduce(
(acc, val) => {
acc[val.name] = val.value;
return acc;
},
{} as { [k: string]: string },
);
const result2 = await app.inject({
method: "GET",
url: "/cats",
cookies,
});
expect(result2.statusCode).toEqual(200);
});

afterAll(async () => {
Expand Down
1 change: 0 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"strict": true,
"strictNullChecks": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"esModuleInterop": true,
"moduleResolution": "node",
"skipLibCheck": true,
Expand Down
Loading

0 comments on commit 7c82156

Please sign in to comment.