Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

End to End tests with Passport JWT #5522

Closed
rungwe opened this issue Oct 3, 2020 · 10 comments
Closed

End to End tests with Passport JWT #5522

rungwe opened this issue Oct 3, 2020 · 10 comments
Labels
needs triage This issue has not been looked into type: question 🙌

Comments

@rungwe
Copy link

rungwe commented Oct 3, 2020

I am struggling to implement e2e test. Outside test environment in production my application works well with passport, but as soon as I import the main module in my e2e tests, I am getting a strange error from TypeError: passport.use is not a function. I am using Passport JWT Strategy implementation. I cannot seem to get past this


describe('Stand Module', () => {

  let app: INestApplication;

  beforeEach(async () => {

    const moduleRef = await Test.createTestingModule({
      imports: [
        AppModule
      ]

    })
      //.overrideProvider(StandService)
      //.useValue(standServiceMock)
      .compile();


    app = moduleRef.createNestApplication();
    await app.init();

  });

  it('/GET all stands', () => {
    return request(app.getHttpServer())
    .get('/stand')
    .expect(HttpStatus.UNAUTHORIZED);
  });

  afterAll(async () => {
    await app.close();
  });
});

Below is what I am getting but in production everything works just fine.

PASS  src/stand/service/stand.service.spec.ts
 PASS  src/stand/controller/stand.controller.spec.ts
 FAIL  src/stand/stand.e2e.spec.ts (6.304s)
  ● Stand Module › /GET all stands

    TypeError: passport.use is not a function

       9 | export class JwtStrategy extends PassportStrategy(Strategy) {
      10 |   constructor(private readonly authService: AuthService) {
    > 11 |     super({
         |     ^
      12 |       jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      13 |       secretOrKey: AppConfigs.secret,
      14 |     });

@kamilmysliwiec I really appreciate your help

@rungwe rungwe added needs triage This issue has not been looked into type: question 🙌 labels Oct 3, 2020
@jmcdo29
Copy link
Member

jmcdo29 commented Oct 3, 2020

Please provide a minimum reproduction repository.

@woodchuck
Copy link

I started to work up a minimum reproduction repository and it kept working. I narrowed it down to this moduleDirectories line, which I'd added in my failing version:

+++ b/test/jest-e2e.json
@@ -1,5 +1,4 @@
 {
-  "moduleDirectories": ["node_modules", "../"],
   "moduleFileExtensions": ["js", "json", "ts"],
   "rootDir": ".",
   "testEnvironment": "node",

@woodchuck
Copy link

Here's a repo that reproduces the problem: https://github.com/woodchuck/nestjs-issue-5522
The first commit is the initial nest-generated app, the second sets up a JwtAuthGuard, and the third has the change that introduces the error.

@jmcdo29
Copy link
Member

jmcdo29 commented Oct 22, 2020

@woodchuck Why do you change the moduleDirectories property? It works just fine as moduleDirectories: [node_modules].

I'm able to reproduce the problem, but if I use the property above without the ../ then there is no issue with running the code

@woodchuck
Copy link

Hi @jmcdo29. I wanted to reference imports in some areas of the code based on the root dir, rather than using a relative path. For instance, I like using

import { FooModel } from 'src/database/models/foo.model';

vs.

import { FooModel } from '../../database/models/foo.model';

@rungwe
Copy link
Author

rungwe commented Oct 22, 2020

@jmcdo29 If you happen to use absolute imports, the below moduleDirectories config is necessary

-  "moduleDirectories": ["node_modules", "./"],

@jmcdo29
Copy link
Member

jmcdo29 commented Oct 22, 2020

@woodchuck @rungwe Gotcha. Well, by saying to import from '../' that affects all import statements, not just the ones in your application, so when there is an import * as passport from 'passport' call in this file, it finds the first directory called passport which happens to be @nestjs/passport. The exports from here are:

{
      __esModule: true,
      AbstractStrategy: [class AbstractStrategy],
      AuthGuard: [Function (anonymous)],
      AuthModuleOptions: [class AuthModuleOptions],
      PassportModule: [class PassportModule],
      PassportSerializer: [class PassportSerializer],
      PassportStrategy: [Function: PassportStrategy]
    }

Which obviously does not have a use method. Normally, passport's exports look like this:

Authenticator {
      _key: 'passport',
      _strategies: {
        session: SessionStrategy {
          name: 'session',
          _deserializeUser: [Function: bound ]
        }
      },
      _serializers: [],
      _deserializers: [],
      _infoTransformers: [],
      _framework: {
        initialize: [Function: initialize],
        authenticate: [Function: authenticate]
      },
      _userProperty: 'user',
      _sm: SessionManager {
        _key: 'passport',
        _serializeUser: [Function: bound ]
      },
      Authenticator: [Function: Authenticator],
      Passport: [Function: Authenticator],
      Strategy: <ref *1> [Function: Strategy] { Strategy: [Circular *1] },
      strategies: { SessionStrategy: [Function: SessionStrategy] }
    }

To solve this,you can use "<rootDir>/../" instead of ../ and it will only resolve from your rootDir (which is the test directory)

@rungwe
Copy link
Author

rungwe commented Oct 22, 2020

@jmcdo29 thanks a lot that solved the problem. The solution works perfectly

@woodchuck
Copy link

@jmcdo29 Works for me too. Thanks!

@mabdullahadeel
Copy link

mabdullahadeel commented Apr 4, 2022

@woodchuck @rungwe Gotcha. Well, by saying to import from '../' that affects all import statements, not just the ones in your application, so when there is an import * as passport from 'passport' call in this file, it finds the first directory called passport which happens to be @nestjs/passport. The exports from here are:

{
      __esModule: true,
      AbstractStrategy: [class AbstractStrategy],
      AuthGuard: [Function (anonymous)],
      AuthModuleOptions: [class AuthModuleOptions],
      PassportModule: [class PassportModule],
      PassportSerializer: [class PassportSerializer],
      PassportStrategy: [Function: PassportStrategy]
    }

Which obviously does not have a use method. Normally, passport's exports look like this:

Authenticator {
      _key: 'passport',
      _strategies: {
        session: SessionStrategy {
          name: 'session',
          _deserializeUser: [Function: bound ]
        }
      },
      _serializers: [],
      _deserializers: [],
      _infoTransformers: [],
      _framework: {
        initialize: [Function: initialize],
        authenticate: [Function: authenticate]
      },
      _userProperty: 'user',
      _sm: SessionManager {
        _key: 'passport',
        _serializeUser: [Function: bound ]
      },
      Authenticator: [Function: Authenticator],
      Passport: [Function: Authenticator],
      Strategy: <ref *1> [Function: Strategy] { Strategy: [Circular *1] },
      strategies: { SessionStrategy: [Function: SessionStrategy] }
    }

To solve this,you can use "<rootDir>/../" instead of ../ and it will only resolve from your rootDir (which is the test directory)

This resolved my issue as well. This approach is still working.

#5522 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage This issue has not been looked into type: question 🙌
Projects
None yet
Development

No branches or pull requests

5 participants