fischerX/packages/core/src/index.test.ts

425 lines
11 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest'
import { UserService, AuthService, PermissionService, FileService } from './index'
import type { Config } from '@fischerx/config'
import type { User } from '@fischerx/types'
import { ROLES, PERMISSIONS } from '@fischerx/constants'
const mockConfig: Config = {
app: {
name: 'TestApp',
version: '0.1.0',
description: 'Test',
},
server: {
port: 3001,
host: 'localhost',
corsOrigins: ['http://localhost:3000'],
nodeEnv: 'test',
},
database: {
host: 'localhost',
port: 5432,
name: 'test',
username: 'test',
password: 'test',
url: 'postgresql://test:test@localhost:5432/test',
},
redis: {
host: 'localhost',
port: 6379,
password: '',
db: 0,
url: 'redis://localhost:6379',
},
jwt: {
secret: 'test-secret',
expiresIn: '15m',
refreshSecret: 'test-refresh',
refreshExpiresIn: '7d',
algorithm: 'HS256',
},
}
describe('Core Services', () => {
describe('UserService', () => {
let userService: UserService
beforeEach(async () => {
userService = new UserService(mockConfig)
await userService.init()
})
it('should create user', async () => {
const user = await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
expect(user.email).toBe('test@example.com')
expect(user.name).toBe('Test User')
expect(user.role.name).toBe(ROLES.USER)
})
it('should find user by id', async () => {
const created = await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const found = await userService.findById(created.id)
expect(found).not.toBeNull()
expect(found?.email).toBe('test@example.com')
})
it('should find user by email', async () => {
await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const found = await userService.findByEmail('test@example.com')
expect(found).not.toBeNull()
expect(found?.name).toBe('Test User')
})
it('should update user', async () => {
const user = await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const updated = await userService.update(user.id, {
name: 'Updated Name',
})
expect(updated.name).toBe('Updated Name')
})
it('should delete user', async () => {
const user = await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const deleted = await userService.delete(user.id)
expect(deleted).toBe(true)
const found = await userService.findById(user.id)
expect(found).toBeNull()
})
it('should list users with pagination', async () => {
await userService.create({
email: 'test1@example.com',
name: 'Test 1',
password: 'Strong1!password',
})
await userService.create({
email: 'test2@example.com',
name: 'Test 2',
password: 'Strong1!password',
})
const result = await userService.list(1, 10)
expect(result.success).toBe(true)
expect(result.data?.length).toBeGreaterThanOrEqual(2)
expect(result.meta?.total).toBeGreaterThanOrEqual(2)
})
it('should reject invalid email', async () => {
await expect(
userService.create({
email: 'invalid',
name: 'Test',
password: 'Strong1!password',
})
).rejects.toThrow('Invalid email')
})
it('should reject weak password', async () => {
await expect(
userService.create({
email: 'test@example.com',
name: 'Test',
password: 'weak',
})
).rejects.toThrow()
})
})
describe('AuthService', () => {
let authService: AuthService
let userService: UserService
beforeEach(async () => {
userService = new UserService(mockConfig)
await userService.init()
authService = new AuthService(mockConfig, userService)
await authService.init()
})
it('should register user', async () => {
const result = await authService.register({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
expect(result.accessToken).toBeDefined()
expect(result.refreshToken).toBeDefined()
expect(result.user.email).toBe('test@example.com')
})
it('should login user', async () => {
await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const result = await authService.login({
email: 'test@example.com',
password: 'Strong1!password',
})
expect(result.accessToken).toBeDefined()
expect(result.user.email).toBe('test@example.com')
})
it('should reject login with wrong password', async () => {
await userService.create({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const user = await userService.findByEmail('test@example.com')
expect(user).not.toBeNull()
})
it('should logout user', async () => {
const result = await authService.register({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
await authService.logout(result.accessToken)
const valid = await authService.validateToken(result.accessToken)
expect(valid).toBeNull()
})
it('should refresh token', async () => {
const result = await authService.register({
email: 'test@example.com',
name: 'Test User',
password: 'Strong1!password',
})
const refreshed = await authService.refreshToken(result.refreshToken)
expect(refreshed).not.toBeNull()
expect(refreshed?.accessToken).toBeDefined()
expect(refreshed?.refreshToken).toBeDefined()
})
})
describe('PermissionService', () => {
let permissionService: PermissionService
beforeEach(async () => {
permissionService = new PermissionService(mockConfig)
await permissionService.init()
})
it('should check if user is admin', () => {
const adminUser: User = {
id: '1',
email: 'admin@example.com',
name: 'Admin',
role: {
id: 'admin',
name: ROLES.ADMIN,
description: 'Admin',
permissions: [],
createdAt: new Date(),
updatedAt: new Date(),
},
permissions: [],
createdAt: new Date(),
updatedAt: new Date(),
}
expect(permissionService.isAdmin(adminUser)).toBe(true)
})
it('should check user permissions', () => {
const user: User = {
id: '1',
email: 'user@example.com',
name: 'User',
role: {
id: 'user',
name: ROLES.USER,
description: 'User',
permissions: [],
createdAt: new Date(),
updatedAt: new Date(),
},
permissions: [
{
id: '1',
name: PERMISSIONS.FILE.READ,
description: 'Read files',
resource: 'file',
action: 'read',
},
],
createdAt: new Date(),
updatedAt: new Date(),
}
expect(permissionService.hasPermission(user, PERMISSIONS.FILE.READ)).toBe(true)
expect(permissionService.hasPermission(user, PERMISSIONS.FILE.UPDATE)).toBe(false)
})
it('should check resource access', () => {
const user: User = {
id: '1',
email: 'user@example.com',
name: 'User',
role: {
id: 'user',
name: ROLES.USER,
description: 'User',
permissions: [],
createdAt: new Date(),
updatedAt: new Date(),
},
permissions: [
{
id: '1',
name: PERMISSIONS.FILE.READ,
description: 'Read files',
resource: 'file',
action: 'read',
},
],
createdAt: new Date(),
updatedAt: new Date(),
}
expect(permissionService.canAccess(user, 'file', 'read')).toBe(true)
expect(permissionService.canAccess(user, 'file', 'write')).toBe(false)
})
})
describe('FileService', () => {
let fileService: FileService
beforeEach(async () => {
fileService = new FileService(mockConfig)
await fileService.init()
})
it('should create file', async () => {
const file = await fileService.create({
name: 'document.pdf',
originalName: 'my-document.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://example.com/file.pdf',
ownerId: 'user-1',
})
expect(file.name).toBe('document.pdf')
expect(file.ownerId).toBe('user-1')
})
it('should find file by id', async () => {
const created = await fileService.create({
name: 'document.pdf',
originalName: 'my-document.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://example.com/file.pdf',
ownerId: 'user-1',
})
const found = await fileService.findById(created.id)
expect(found).not.toBeNull()
expect(found?.name).toBe('document.pdf')
})
it('should find files by owner', async () => {
await fileService.create({
name: 'file1.pdf',
originalName: 'file1.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://example.com/file1.pdf',
ownerId: 'user-test-1',
})
await new Promise(resolve => setTimeout(resolve, 10))
await fileService.create({
name: 'file2.pdf',
originalName: 'file2.pdf',
mimeType: 'application/pdf',
size: 2048,
url: 'https://example.com/file2.pdf',
ownerId: 'user-test-1',
})
const files = await fileService.findByOwnerId('user-test-1')
expect(files.length).toBe(2)
})
it('should delete file', async () => {
const file = await fileService.create({
name: 'document.pdf',
originalName: 'my-document.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://example.com/file.pdf',
ownerId: 'user-1',
})
const deleted = await fileService.delete(file.id)
expect(deleted).toBe(true)
const found = await fileService.findById(file.id)
expect(found).toBeNull()
})
it('should list files with pagination', async () => {
await fileService.create({
name: 'file1.pdf',
originalName: 'file1.pdf',
mimeType: 'application/pdf',
size: 1024,
url: 'https://example.com/file1.pdf',
ownerId: 'user-test-2',
})
await new Promise(resolve => setTimeout(resolve, 10))
await fileService.create({
name: 'file2.pdf',
originalName: 'file2.pdf',
mimeType: 'application/pdf',
size: 2048,
url: 'https://example.com/file2.pdf',
ownerId: 'user-test-2',
})
const result = await fileService.list(1, 10)
expect(result.success).toBe(true)
expect(result.data?.length).toBe(2)
expect(result.meta?.total).toBe(2)
})
})
})