Skip to content

Commit

Permalink
[core] 🧪 tests: fix company tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnPetros committed Dec 3, 2024
1 parent b6c8d3a commit 617dd75
Show file tree
Hide file tree
Showing 17 changed files with 149 additions and 112 deletions.
2 changes: 1 addition & 1 deletion packages/core/__tests__/fakers/users-faker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export class UsersFaker {
static fakeDto(baseDto?: Partial<UserDto>): UserDto {
return {
id: faker.string.uuid(),
role: RolesFaker.fakeDto(),
role: faker.helpers.arrayElement(['admin', 'manager', 'employee']),
email: faker.internet.email(),
name: faker.person.fullName(),
password: faker.internet.password(),
Expand Down
13 changes: 13 additions & 0 deletions packages/core/__tests__/mocks/providers/ai-provider-mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { IAiProvider } from '../../../src/interfaces'

export class AiProviderMock implements IAiProvider {
propmt = ''

async generateContent(
propmt: string,
onGenerateChunk: (chunk: string) => void,
): Promise<void> {
this.propmt = propmt
onGenerateChunk('fake chunk')
}
}
1 change: 1 addition & 0 deletions packages/core/__tests__/mocks/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { FileStorageProviderMock } from './filte-storage-provider-mock'
export { CsvProviderMock } from './csv-provider-mock'
export { QueueProviderMock } from './queue-provider-mock'
export { CryptoProviderMock } from './crypto-provider-mock'
export { AiProviderMock } from './ai-provider-mock'
Original file line number Diff line number Diff line change
@@ -1,28 +1,53 @@
import type { Company } from "../../../src/domain/entities";
import type { ICompaniesRepository } from "../../../src/interfaces";
import type { Company } from '../../../src/domain/entities'
import type { Role } from '../../../src/domain/structs'
import type { ICompaniesRepository } from '../../../src/interfaces'

export class CompanyRepositoryMock implements ICompaniesRepository {
companies: Company[] = []
companies: Company[] = []
roles: Record<string, Role[]> = {}

async add(company: Company): Promise<void> {
this.companies.push(company)
}
async add(company: Company): Promise<void> {
this.companies.push(company)
}

async delete(companyId: string): Promise<void> {
this.companies = this.companies.filter((company) => company.id !== companyId);
}
async delete(companyId: string): Promise<void> {
this.companies = this.companies.filter((company) => company.id !== companyId)
}

async findByCnpj(companyCnpj: string): Promise<Company | null> {
const company = this.companies.find((company) => company.cnpj === companyCnpj) ?? null
return company
}
async findByCnpj(companyCnpj: string): Promise<Company | null> {
const company = this.companies.find((company) => company.cnpj === companyCnpj) ?? null
return company
}

async findById(companyId: string): Promise<Company | null> {
const company = this.companies.find((company) => company.id === companyId) ?? null
return company
}
async findById(companyId: string): Promise<Company | null> {
const company = this.companies.find((company) => company.id === companyId) ?? null
return company
}

async update(company: Company, companyId: string): Promise<Company> {
throw new Error('Method not implemented.')
}

async update(company: Company, companyId: string): Promise<Company> {
throw new Error('Method not implemented.')
async addRole(role: Role, companyId: string): Promise<void> {
if (!(companyId in this.roles)) {
this.roles[companyId] = []
}
}

this.roles[companyId]?.push(role)
}

async findRolesById(companyId: string): Promise<Role[]> {
return this.roles[companyId] ?? []
}

async findRoleById(roleName: string, companyId: string): Promise<Role | null> {
console.log('roles', await this.findRolesById(companyId))
return (
(await this.findRolesById(companyId)).find((role) => role.name === roleName) ?? null
)
}

async updateRole(role: Role, companyId: string): Promise<void> {
this.roles[companyId] = [role]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export class InventoryMovementsRepositoryMock implements IInventoryMovementsRepo
endDate,
movementType,
companyId,
employeeId,
}: InventoryMovementsListParams): Promise<{
inventoryMovements: InventoryMovement[]
count: number
Expand Down Expand Up @@ -68,7 +67,9 @@ export class InventoryMovementsRepositoryMock implements IInventoryMovementsRepo
}

async findAllByCompany(companyId: string): Promise<InventoryMovement[]> {
throw new Error('Method not implemented.')
return this.inventoryMovements.filter(
(movement) => movement.product?.companyId === companyId,
)
}

async findByDateRange(params: FindByDateRangeParams): Promise<InventoryMovement[]> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ISuppliersRepository } from '../../../src/interfaces'
import type { SuppliersListParams } from '../../../src/types'

export class SuppliersRepositoryMock implements ISuppliersRepository {

suppliers: Supplier[] = []

async findMany({ page }: SuppliersListParams): Promise<{ suppliers: Supplier[], count: number }> {
Expand Down Expand Up @@ -37,6 +38,10 @@ export class SuppliersRepositoryMock implements ISuppliersRepository {
this.suppliers.push(supplier)
}

async addMany(suppliers: Supplier[]): Promise<void> {
for (const supplier of suppliers) this.add(supplier)
}

async update(supplier: Supplier): Promise<void> {
this.suppliers = this.suppliers.map((existingSupplier) =>
existingSupplier.id === supplier.id ? supplier : existingSupplier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ export class UsersRepositoryMock implements IUsersRepository {
this.users.push(user)
}

async findAllByCompany(companyId: string): Promise<User[]> {
throw new Error('Method not implemented.')
}

async addMany(users: User[]): Promise<void> {
throw new Error('Method not implemented.')
}

async findByEmail(userEmail: string): Promise<User | null> {
const email = this.users.find((user) => user.email === userEmail) ?? null
return email
Expand Down
5 changes: 5 additions & 0 deletions packages/core/__tests__/mocks/sockets/notifications-socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import type { INotificationsSocket } from '../../../src/interfaces'

export class NotificationsSocketMock implements INotificationsSocket {
emittedStockLevelNotifications: StockLevelNotification[] = []
emittedCompanyDeletedNotificationsCount = 0

emitStockLevelNotification(notification: StockLevelNotification): void {
this.emittedStockLevelNotifications.push(notification)
}

emitCompanyDeletedNotification(): void {
this.emittedCompanyDeletedNotificationsCount += 1
}
}
8 changes: 5 additions & 3 deletions packages/core/src/domain/entities/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class Category extends Entity<CategoryProps> {
this.subCategories.push(category)
}

update(partialDto: Partial<CategoryDto>): Category {
return Category.create({ ...this.dto, ...partialDto })
}

get hasParentCategory(): boolean {
return Boolean(this.props.parentCategoryId)
}
Expand All @@ -51,7 +55,5 @@ export class Category extends Entity<CategoryProps> {
}
}

update(partialDto: Partial<CategoryDto>): Category {
return Category.create({ ...this.dto, ...partialDto })
}

}
4 changes: 2 additions & 2 deletions packages/core/src/domain/entities/tests/batch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ describe('Batch entity', () => {

it('should return the days to expiration', () => {
const differenceInDays = 10
const fakeExpirationDate = new Datetime().subtractDays(differenceInDays)
const fakeExpirationDate = new Datetime().addDays(differenceInDays)
const batch = BatchesFaker.fake({ expirationDate: fakeExpirationDate })

expect(batch.daysToExpiration).toBe(10)
expect(batch.daysToExpiration).toBe(differenceInDays - 1)
})
})
26 changes: 0 additions & 26 deletions packages/core/src/domain/entities/tests/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,6 @@ import { UsersFaker } from '../../../../__tests__/fakers'
import { ValidationError } from '../../../errors'

describe('User entity', () => {
it('should not be created if its role is invalid', () => {
expect(() => {
UsersFaker.fake({ role: 'invalid role' })
}).toThrowError(ValidationError)
})

it('should validate role', () => {
let user = UsersFaker.fake({ role: 'admin' })

expect(user.hasValidRole('admin')).toBeTruthy()
expect(user.hasValidRole('manager')).toBeTruthy()
expect(user.hasValidRole('employee')).toBeTruthy()

user = UsersFaker.fake({ role: 'manager' })

expect(user.hasValidRole('admin')).toBeFalsy()
expect(user.hasValidRole('manager')).toBeTruthy()
expect(user.hasValidRole('employee')).toBeTruthy()

user = UsersFaker.fake({ role: 'employee' })

expect(user.hasValidRole('admin')).toBeFalsy()
expect(user.hasValidRole('manager')).toBeFalsy()
expect(user.hasValidRole('employee')).toBeTruthy()
})

it('should be update', () => {
const user = UsersFaker.fake({ role: 'admin' })

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ import { beforeEach, describe, expect, it } from 'vitest'
import { QueueProviderMock } from '../../../../__tests__/mocks/providers'
import { CryptoProviderMock } from '../../../../__tests__/mocks/providers/crypto-provider-mock'
import { RequestPasswordResetUseCase } from '../request-password-reset-use-case'
import { UsersRepositoryMock } from '../../../../__tests__/mocks/repositories'
import { UsersFaker } from '../../../../__tests__/fakers'

let usersRepository: UsersRepositoryMock
let cryptoProvider: CryptoProviderMock
let queueProvider: QueueProviderMock
let useCase: RequestPasswordResetUseCase

describe('Request password reset use case', () => {
beforeEach(() => {
usersRepository = new UsersRepositoryMock()
cryptoProvider = new CryptoProviderMock()
queueProvider = new QueueProviderMock()
useCase = new RequestPasswordResetUseCase(cryptoProvider, queueProvider)
useCase = new RequestPasswordResetUseCase(usersRepository, cryptoProvider, queueProvider)
})

it('should push to the queue a job that sends password reset email', async () => {
const fakeRecipientEmail = '[email protected]'

await usersRepository.add(UsersFaker.fake({email: fakeRecipientEmail}))
expect(queueProvider.jobs).toHaveLength(0)

const confirmationToken = await useCase.execute(fakeRecipientEmail)
Expand All @@ -33,4 +37,13 @@ describe('Request password reset use case', () => {
},
])
})

it('should not push a job to the queue when the recipient user does not exist', async () => {
const fakeRecipientEmail = '[email protected]'
expect(queueProvider.jobs).toHaveLength(0)

await useCase.execute(fakeRecipientEmail)
expect(queueProvider.jobs).toHaveLength(0)

})
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,39 @@ import { CompanyRepositoryMock } from '../../../../__tests__/mocks/repositories'
import { NotFoundError } from '../../../errors'
import { CompanyFaker } from '../../../../__tests__/fakers'
import { DeleteCompanyUseCase } from '../delete-company-use-case'
import { NotificationsSocketMock } from '../../../../__tests__/mocks/sockets'

let useCase: DeleteCompanyUseCase
let companyRepository: CompanyRepositoryMock
let notificationsSocket: NotificationsSocketMock

describe('Delete company use case', () => {
beforeEach(() => {
notificationsSocket = new NotificationsSocketMock()
companyRepository = new CompanyRepositoryMock()
useCase = new DeleteCompanyUseCase(companyRepository)
useCase = new DeleteCompanyUseCase(companyRepository, notificationsSocket)
})

it('should delete a company by its ID', async () => {
const fakeCompany = CompanyFaker.fake()

await companyRepository.add(fakeCompany)

expect(companyRepository.companies).toHaveLength(1)

await useCase.execute({ companyId: fakeCompany.id })

expect(companyRepository.companies).toHaveLength(0)
})

it('should emit company deleted notification on delete company', async () => {
const fakeCompany = CompanyFaker.fake()
await companyRepository.add(fakeCompany)

expect(notificationsSocket.emittedCompanyDeletedNotificationsCount).toBe(0)

await useCase.execute({ companyId: fakeCompany.id })
expect(notificationsSocket.emittedCompanyDeletedNotificationsCount).toBe(1)
})

it('should throw an error if company does not exist', async () => {
const fakeCompany = CompanyFaker.fake()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NotFoundError } from '../../errors'
import { NotAllowedError, NotFoundError } from '../../errors'
import type {
IAiProvider,
ICompaniesRepository,
IInventoryMovementsRepository,
IUsersRepository,
} from '../../interfaces'
Expand All @@ -14,13 +15,23 @@ export class ReportInventoryWithAiUseCase {
constructor(
private readonly inventoryMovementsRepository: IInventoryMovementsRepository,
private readonly usersRepository: IUsersRepository,
private readonly companiesRepository: ICompaniesRepository,
private readonly aiProvider: IAiProvider,
) {}

async execute({ userId, onGenerateChunck }: Request) {
const user = await this.usersRepository.findById(userId)
if (!user) throw new NotFoundError('Usuário não encontrado')

const userRole = await this.companiesRepository.findRoleById(
user.role,
user.companyId,
)

if (!userRole || !userRole.hasPermission('reports')) {
throw new NotAllowedError('Permissão não concedida a esse usuário')
}

const movements = await this.inventoryMovementsRepository.findAllByCompany(
user.companyId,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ describe('Export inventory to csv file use case', () => {
})

it('should return the buffer of the csv file containing the products', async () => {
const fileBuffer = await useCase.execute()
const fileBuffer = await useCase.execute({
companyId: '',
categoryId: '',
locationId: '',
supplierId: '',
productName: '',
stockLevel: 'average',
})
expect(fileBuffer).toEqual(
Buffer.from(
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describe('Report weekly inventory movements use case', () => {

const weeklyInventoryMovements = await useCase.execute({
endDate: endDate.getDate(),
companyId: '',
})

expect(weeklyInventoryMovements).toEqual([
Expand Down Expand Up @@ -112,6 +113,7 @@ describe('Report weekly inventory movements use case', () => {
await useCase.execute({
endDate: currentDate.getDate(),
productId: fakeProduct.id,
companyId: '',
})
}).rejects.toThrowError(NotFoundError)
})
Expand All @@ -138,6 +140,7 @@ describe('Report weekly inventory movements use case', () => {
const weeklyInventoryMovements = await useCase.execute({
endDate: endDate.getDate(),
productId: fakeProduct.id,
companyId: '',
})

expect(weeklyInventoryMovements?.at(-1)).toEqual({
Expand Down
Loading

0 comments on commit 617dd75

Please sign in to comment.