import { Test , TestingModule } from '@nestjs/testing' ; import { User } from '@prisma/client' ; import { decode } from 'jsonwebtoken' ; import { AppModule } from '../../../app.module' ; import { PrismaService } from '../../../prisma/prisma.service' ; import { AuthService } from '../../auth.service' ; import { Tokens } from '../../types' ; const user = { email : 'test@gmail.com' , password : 'super-secret-password' , } ; describe ( 'Auth Flow' , ( ) => { let prisma ; let authService ; let moduleRef ; beforeAll ( async ( ) => { moduleRef = await Test . createTestingModule ( { imports : [ AppModule ] , } ) . compile ( ) ; prisma = moduleRef . get ( PrismaService ) ; authService = moduleRef . get ( AuthService ) ; } ) ; afterAll ( async ( ) => { await moduleRef . close ( ) ; } ) ; describe ( 'signup' , ( ) => { beforeAll ( async ( ) => { await prisma . cleanDatabase ( ) ; } ) ; it ( 'should signup' , async ( ) => { const tokens = await authService . signupLocal ( { email : user . email , password : user . password , } ) ; expect ( tokens . access_token ) . toBeTruthy ( ) ; expect ( tokens . refresh_token ) . toBeTruthy ( ) ; } ) ; it ( 'should throw on duplicate user signup' , async ( ) => { let tokens ; try { tokens = await authService . signupLocal ( { email : user . email , password : user . password , } ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; } ) ; describe ( 'signin' , ( ) => { beforeAll ( async ( ) => { await prisma . cleanDatabase ( ) ; } ) ; it ( 'should throw if no existing user' , async ( ) => { let tokens ; try { tokens = await authService . signinLocal ( { email : user . email , password : user . password , } ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; it ( 'should login' , async ( ) => { await authService . signupLocal ( { email : user . email , password : user . password , } ) ; const tokens = await authService . signinLocal ( { email : user . email , password : user . password , } ) ; expect ( tokens . access_token ) . toBeTruthy ( ) ; expect ( tokens . refresh_token ) . toBeTruthy ( ) ; } ) ; it ( 'should throw if password incorrect' , async ( ) => { let tokens ; try { tokens = await authService . signinLocal ( { email : user . email , password : user . password + 'a' , } ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; } ) ; describe ( 'logout' , ( ) => { beforeAll ( async ( ) => { await prisma . cleanDatabase ( ) ; } ) ; it ( 'should pass if call to non existent user' , async ( ) => { const result = await authService . logout ( 4 ) ; expect ( result ) . toBeDefined ( ) ; } ) ; it ( 'should logout' , async ( ) => { await authService . signupLocal ( { email : user . email , password : user . password , } ) ; let userFromDb ; userFromDb = await prisma . user . findFirst ( { where : { email : user . email , } , } ) ; expect ( userFromDb ?. hashedRt ) . toBeTruthy ( ) ; await authService . logout ( userFromDb ! . id ) ; userFromDb = await prisma . user . findFirst ( { where : { email : user . email , } , } ) ; expect ( userFromDb ?. hashedRt ) . toBeFalsy ( ) ; } ) ; } ) ; describe ( 'refresh' , ( ) => { beforeAll ( async ( ) => { await prisma . cleanDatabase ( ) ; } ) ; it ( 'should throw if no existing user' , async ( ) => { let tokens ; try { tokens = await authService . refreshTokens ( 1 , '' ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; it ( 'should throw if user logged out' , async ( ) => { const _tokens = await authService . signupLocal ( { email : user . email , password : user . password , } ) ; const rt = _tokens . refresh_token ; const decoded = decode ( rt ) ; const userId = Number ( decoded ?. sub ) ; await authService . logout ( userId ) ; let tokens ; try { tokens = await authService . refreshTokens ( userId , rt ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; it ( 'should throw if refresh token incorrect' , async ( ) => { await prisma . cleanDatabase ( ) ; const _tokens = await authService . signupLocal ( { email : user . email , password : user . password , } ) ; console . log ( { _tokens , } ) ; const rt = _tokens . refresh_token ; const decoded = decode ( rt ) ; const userId = Number ( decoded ?. sub ) ; let tokens ; try { tokens = await authService . refreshTokens ( userId , rt + 'a' ) ; } catch ( error ) { expect ( error . status ) . toBe ( 403 ) ; } expect ( tokens ) . toBeUndefined ( ) ; } ) ; it ( 'should refresh tokens' , async ( ) => { await prisma . cleanDatabase ( ) ; const _tokens = await authService . signupLocal ( { email : user . email , password : user . password , } ) ; const rt = _tokens . refresh_token ; const at = _tokens . access_token ; const decoded = decode ( rt ) ; const userId = Number ( decoded ?. sub ) ; await new Promise ( ( resolve , reject ) => { setTimeout ( ( ) => { resolve ( true ) ; } , 1000 ) ; } ) ; const tokens = await authService . refreshTokens ( userId , rt ) ; expect ( tokens ) . toBeDefined ( ) ; expect ( tokens . access_token ) . not . toBe ( at ) ; expect ( tokens . refresh_token ) . not . toBe ( rt ) ; } ) ; } ) ; } ) ;