ahmetuysal / nest-hackathon-starter

Hackathon starter project for NestJS. Includes Prisma, email verification, Passport-JWT authentication, Swagger and more
MIT License
409 stars 50 forks source link

Error in `auth.service` `sendChangeEmailMail` function #11

Closed jameskentTX closed 3 years ago

jameskentTX commented 3 years ago

There is:

const userEntity = await this.userService.getUserEntityByUsername(
      changeEmailRequest.newEmail,
    );

Should be:

const userEntity = await this.userService.getUserEntityByEmail(
      changeEmailRequest.newEmail,
    );

I'm learning to use jest in e2e testing, and I'm finding an error or two :)

ahmetuysal commented 3 years ago

Thank you! I am also not very experienced in jest, it would be awesome if you could share your tests so that I can add them to repo.

jameskentTX commented 3 years ago

I've made changes in database and in scripts, in config, env... Many changes. So my test won't work on your project. And many comments are in Polish, but code speaks for itself, of course. But I'll copy some code, maybe you can use it. I'm running e2e test with option --runInBand: "test:e2e": "jest --config ./test/jest-e2e.json --detectOpenHandles --runInBand --verbose",

Below are tests for username (my Regex is different than yours)

import { Test, TestingModule } from '@nestjs/testing';
import { Connection } from 'typeorm';
import * as request from 'supertest';
import { INestApplication, ValidationPipe } from '@nestjs/common';

import { UserEntity } from '../../src/user/entities/user.entity';
import { SignupRequest } from '../../src/auth/models';
import { AppModule } from '../../src/app.module';

describe('AuthController signup with invalid username (e2e)', () => {
  let app: INestApplication;
  let connection: Connection;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    // Request Validation
    app.useGlobalPipes(
      new ValidationPipe({
        whitelist: true,
        transform: true,
      }),
    );
    await app.init();
    connection = app.get(Connection); // important to end tests without delay

    await connection.createQueryBuilder().delete().from(UserEntity).execute();
  });

  afterAll(async (done) => {
    // Closing the DB connection allows Jest to exit successfully.
    connection.close();
    done();
  });

  describe("POST /signup, RegEx won't allow signup with improper username", () => {
    it('should not accept null username', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: '',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username of length 1', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'f',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username of length > 20', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: '12345678901234567890a',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username starting with big letter', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'A2345678901234567890',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username starting with number', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: '12345678901234567890',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept big letter in username', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: '123456789A1234567890',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);

      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with underscore', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid_username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with . (dot)', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid.username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character "', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid"username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character \'', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid\'username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character &', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid&username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character \\', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid\\username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character /', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid/username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character :', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid:username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character >', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid>username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character <', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid<username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with special character @', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test@test.com',
        password: 'password',
        username: 'invalid@username',
        displayName: 'Grzegorz',
      };
      const { body: body1 } = await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      expect(body1).toEqual(
        expect.objectContaining({
          statusCode: 400,
          error: 'Bad Request',
        }),
      );
      expect(body1.message).toEqual(
        expect.arrayContaining([
          'Unikalna nazwa użytkownika ma długość od dwóch do dwudziestu znaków. Musi zaczynać się małą literą. Dozwolone są tylko małe litery (bez polskich znaków) jak również cyfry.',
        ]),
      );
      done();
    });

    it('should not accept username with polish characters', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test3@test3.com',
        password: 'password1',
        username: 'przepióreczka',
        displayName: 'Piękny ptak...',
      };
      await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(400);
      done();
    });
  });

  describe('POST /signup, RegEx allow signup with correct username', () => {
    it('should accept username starting with small letter', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test1@test1.com',
        password: 'password',
        username: 'test1',
        displayName: 'test1',
      };
      await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(201);
      done();
    });

    it('should accept username containing numbers', async (done) => {
      const signupRequest: SignupRequest = {
        email: 'test2@test2.com',
        password: 'password',
        username: 'bond007',
        displayName: 'test2',
      };
      await request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupRequest)
        .expect(201);
      done();
    });
  });

  // testy poniżej zakładają że user1 jest zarejestrowany,
  // ogólnie to nie musi być prawdą, bezpieczniej byłoby utworzyć nowego usera

  describe('POST /check-username, checking username availability', () => {
    it('should retun `true`, username is available', async (done) => {
      await request(app.getHttpServer())
        .post('/auth/check-username')
        .send({ username: 'olga' })
        .expect({ isUsernameAvailable: true });
      done();
    });

    it('should retun `false`, username is not available', async (done) => {
      await request(app.getHttpServer())
        .post('/auth/check-username')
        .send({ username: 'test1' })
        .expect({ isUsernameAvailable: false });
      done();
    });
  });
});
ahmetuysal commented 3 years ago

Thank you! I will take a close look and add similar tests for the project when I have the time. I appreciate your contributions to the project :)