-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TM-1312] Set up sequelize and factory girl for all tests.
- Loading branch information
Showing
18 changed files
with
348 additions
and
201 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,42 +2,22 @@ import { Test, TestingModule } from '@nestjs/testing'; | |
import { AuthService } from './auth.service'; | ||
import { JwtService } from '@nestjs/jwt'; | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { FactoryGirl, SequelizeAdapter } from 'factory-girl-ts'; | ||
import bcrypt from 'bcryptjs'; | ||
import { User } from '@terramatch-microservices/database/entities'; | ||
import { UserFactory } from '@terramatch-microservices/database/factories'; | ||
import { Sequelize } from 'sequelize-typescript'; | ||
import * as Entities from '@terramatch-microservices/database/entities'; | ||
|
||
describe('AuthService', () => { | ||
let service: AuthService; | ||
let jwtService: DeepMocked<JwtService>; | ||
|
||
const sequelize = new Sequelize({ | ||
dialect: 'mariadb', | ||
host: 'localhost', | ||
port: 3360, | ||
username: 'wri', | ||
password: 'wri', | ||
database: 'terramatch_microservices_test', | ||
models: Object.values(Entities), | ||
logging: false, | ||
}); | ||
|
||
beforeAll(async () => { | ||
await sequelize.sync({ force: true }); | ||
FactoryGirl.setAdapter(new SequelizeAdapter()); | ||
}) | ||
|
||
afterAll(async () => { | ||
await sequelize.close(); | ||
}) | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [ | ||
AuthService, | ||
{ provide: JwtService, useValue: jwtService = createMock<JwtService>() } | ||
{ | ||
provide: JwtService, | ||
useValue: (jwtService = createMock<JwtService>()), | ||
}, | ||
], | ||
}).compile(); | ||
|
||
|
@@ -46,21 +26,27 @@ describe('AuthService', () => { | |
|
||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
}) | ||
}); | ||
|
||
it('should return null with invalid email', async () => { | ||
jest.spyOn(User, 'findOne').mockImplementation(() => Promise.resolve(null)); | ||
expect(await service.login('[email protected]', 'asdfasdfsadf')).toBeNull() | ||
}) | ||
expect(await service.login('[email protected]', 'asdfasdfsadf')).toBeNull(); | ||
}); | ||
|
||
it('should return null with an invalid password', async () => { | ||
const { emailAddress } = await UserFactory.create({ password: 'fakepasswordhash' }); | ||
const { emailAddress } = await UserFactory.create({ | ||
password: 'fakepasswordhash', | ||
}); | ||
expect(await service.login(emailAddress, 'fakepassword')).toBeNull(); | ||
}) | ||
}); | ||
|
||
it('should return a token and id with a valid password', async () => { | ||
const { id, emailAddress } = await UserFactory.create({ password: 'fakepasswordhash' }); | ||
jest.spyOn(bcrypt, 'compare').mockImplementation(() => Promise.resolve(true)); | ||
const { id, emailAddress } = await UserFactory.create({ | ||
password: 'fakepasswordhash', | ||
}); | ||
jest | ||
.spyOn(bcrypt, 'compare') | ||
.mockImplementation(() => Promise.resolve(true)); | ||
|
||
const token = 'fake jwt token'; | ||
jwtService.signAsync.mockReturnValue(Promise.resolve(token)); | ||
|
@@ -74,13 +60,15 @@ describe('AuthService', () => { | |
|
||
it('should update the last logged in date on the user', async () => { | ||
const user = await UserFactory.create({ password: 'fakepasswordhash' }); | ||
jest.spyOn(bcrypt, 'compare').mockImplementation(() => Promise.resolve(true)); | ||
jest | ||
.spyOn(bcrypt, 'compare') | ||
.mockImplementation(() => Promise.resolve(true)); | ||
jwtService.signAsync.mockResolvedValue('fake jwt token'); | ||
|
||
await service.login(user.emailAddress, 'fakepassword'); | ||
|
||
const { lastLoggedInAt } = user; | ||
await user.reload(); | ||
expect(lastLoggedInAt).not.toBe(user.lastLoggedInAt); | ||
}) | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,5 +10,7 @@ module.exports = { | |
lines: 95, | ||
statements: 95, | ||
} | ||
} | ||
}, | ||
|
||
setupFilesAfterEnv: ['./setup-jest.ts'], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const IS_PROD = process.env['NODE_ENV'] === 'production'; | ||
const IS_TEST = process.env['NODE_ENV'] === 'test'; | ||
|
||
// TODO: Add Sentry support | ||
export default class Log { | ||
static debug(message: any, ...optionalParams: any[]) { | ||
if (!IS_PROD && !IS_TEST) console.debug(message, ...optionalParams); | ||
} | ||
|
||
static info(message: any, ...optionalParams: any[]) { | ||
if (!IS_PROD && !IS_TEST) console.info(message, ...optionalParams); | ||
} | ||
|
||
static warn(message: any, ...optionalParams: any[]) { | ||
if (!IS_TEST) console.warn(message, ...optionalParams); | ||
} | ||
|
||
static error(message: any, ...optionalParams: any[]) { | ||
if (!IS_TEST) console.error(message, ...optionalParams); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { PolicyService } from './policy.service'; | ||
import { UnauthorizedException } from '@nestjs/common'; | ||
import { | ||
ModelHasRole, | ||
User, | ||
} from '@terramatch-microservices/database/entities'; | ||
import { RequestContext } from 'nestjs-request-context'; | ||
|
||
export function mockUserId(userId?: number) { | ||
jest | ||
.spyOn(RequestContext, 'currentContext', 'get') | ||
.mockReturnValue({ req: { authenticatedUserId: userId }, res: {} }); | ||
} | ||
|
||
describe('PolicyService', () => { | ||
let service: PolicyService; | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [PolicyService], | ||
}).compile(); | ||
|
||
service = module.get<PolicyService>(PolicyService); | ||
}); | ||
|
||
afterEach(async () => { | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
it('should throw an error if no authed user is found', async () => { | ||
mockUserId(); | ||
await expect(() => service.authorize('foo', new User())).rejects.toThrow( | ||
UnauthorizedException | ||
); | ||
}); | ||
|
||
it('should throw an error if there is no policy defined', async () => { | ||
mockUserId(123); | ||
await expect(() => service.authorize('foo', new ModelHasRole())).rejects.toThrow( | ||
UnauthorizedException | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
import { Column, ForeignKey, Model, Table } from 'sequelize-typescript'; | ||
import { Role } from './role.entity'; | ||
import { BIGINT } from 'sequelize'; | ||
import { BIGINT, STRING } from 'sequelize'; | ||
|
||
@Table({ tableName: 'model_has_roles', underscored: true, timestamps: false }) | ||
export class ModelHasRole extends Model { | ||
@ForeignKey(() => Role) | ||
@Column({ type: BIGINT.UNSIGNED, primaryKey: true }) | ||
roleId: number; | ||
|
||
@Column({ primaryKey: true }) | ||
@Column({ type: STRING, primaryKey: true }) | ||
modelType: string; | ||
|
||
@Column({ primaryKey: true }) | ||
modelId: bigint; | ||
@Column({ type: BIGINT.UNSIGNED, primaryKey: true }) | ||
modelId: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.