Skip to content

Commit

Permalink
More tests
Browse files Browse the repository at this point in the history
  • Loading branch information
w3bdesign committed Nov 19, 2024
1 parent c951ea2 commit 1eeda22
Show file tree
Hide file tree
Showing 2 changed files with 384 additions and 0 deletions.
160 changes: 160 additions & 0 deletions backend/src/database/seeds/create-admin-user.seed.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { DataSource, Repository, FindOneOptions } from 'typeorm';
import { User, UserRole } from '../../users/entities/user.entity';
import { createAdminUser } from './create-admin-user.seed';
import * as bcrypt from 'bcrypt';

jest.mock('bcrypt');

describe('createAdminUser', () => {
let mockDataSource: Partial<DataSource>;
let mockUserRepository: Partial<Repository<User>>;
const originalEnv = process.env;

beforeEach(() => {
// Mock repository methods
mockUserRepository = {
findOne: jest.fn() as jest.Mock,
create: jest.fn() as jest.Mock,
save: jest.fn() as jest.Mock,
};

// Mock DataSource
mockDataSource = {
getRepository: jest.fn().mockReturnValue(mockUserRepository),
};

// Mock bcrypt
(bcrypt.hash as jest.Mock).mockResolvedValue('hashed-password');

// Setup test environment variables
process.env = {
...originalEnv,
ADMIN_EMAIL: '[email protected]',
ADMIN_PASSWORD: 'admin123',
};

// Mock console methods
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
process.env = originalEnv;
jest.clearAllMocks();
});

it('should create admin user when it does not exist', async () => {
// Mock that admin doesn't exist
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(null);

// Mock created user
const mockCreatedUser = {
email: '[email protected]',
password: 'hashed-password',
firstName: 'Admin',
lastName: 'User',
role: UserRole.ADMIN,
};
(mockUserRepository.create as jest.Mock).mockReturnValue(mockCreatedUser);
(mockUserRepository.save as jest.Mock).mockResolvedValue(mockCreatedUser);

await createAdminUser(mockDataSource as DataSource);

// Verify admin user was searched for
expect(mockUserRepository.findOne).toHaveBeenCalledWith({
where: { email: '[email protected]' },
});

// Verify password was hashed
expect(bcrypt.hash).toHaveBeenCalledWith('admin123', 10);

// Verify user was created with correct data
expect(mockUserRepository.create).toHaveBeenCalledWith({
email: '[email protected]',
password: 'hashed-password',
firstName: 'Admin',
lastName: 'User',
role: UserRole.ADMIN,
});

// Verify user was saved
expect(mockUserRepository.save).toHaveBeenCalledWith(mockCreatedUser);

// Verify success message was logged
expect(console.log).toHaveBeenCalledWith('Admin user created successfully');
});

it('should not create admin user when it already exists', async () => {
// Mock that admin already exists
const existingAdmin = {
email: '[email protected]',
role: UserRole.ADMIN,
};
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(existingAdmin);

await createAdminUser(mockDataSource as DataSource);

// Verify admin user was searched for
expect(mockUserRepository.findOne).toHaveBeenCalledWith({
where: { email: '[email protected]' },
});

// Verify no creation attempts were made
expect(mockUserRepository.create).not.toHaveBeenCalled();
expect(mockUserRepository.save).not.toHaveBeenCalled();

// Verify appropriate message was logged
expect(console.log).toHaveBeenCalledWith('Admin user already exists');
});

it('should throw error when admin email is missing', async () => {
delete process.env.ADMIN_EMAIL;

await expect(createAdminUser(mockDataSource as DataSource)).rejects.toThrow(
'Admin email and password must be set in environment variables',
);

// Verify no database operations were attempted
expect(mockUserRepository.findOne).not.toHaveBeenCalled();
expect(mockUserRepository.create).not.toHaveBeenCalled();
expect(mockUserRepository.save).not.toHaveBeenCalled();
});

it('should throw error when admin password is missing', async () => {
delete process.env.ADMIN_PASSWORD;

await expect(createAdminUser(mockDataSource as DataSource)).rejects.toThrow(
'Admin email and password must be set in environment variables',
);

// Verify no database operations were attempted
expect(mockUserRepository.findOne).not.toHaveBeenCalled();
expect(mockUserRepository.create).not.toHaveBeenCalled();
expect(mockUserRepository.save).not.toHaveBeenCalled();
});

it('should handle database errors', async () => {
// Mock database error
const dbError = new Error('Database connection failed');
(mockUserRepository.findOne as jest.Mock).mockRejectedValue(dbError);

await expect(createAdminUser(mockDataSource as DataSource)).rejects.toThrow(dbError);

// Verify error was logged
expect(console.error).toHaveBeenCalledWith('Error creating admin user:', dbError);
});

it('should handle password hashing errors', async () => {
// Mock that admin doesn't exist
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(null);

// Mock bcrypt error
const hashError = new Error('Hashing failed');
(bcrypt.hash as jest.Mock).mockRejectedValue(hashError);

await expect(createAdminUser(mockDataSource as DataSource)).rejects.toThrow(hashError);

// Verify error was logged
expect(console.error).toHaveBeenCalledWith('Error creating admin user:', hashError);
});
});
224 changes: 224 additions & 0 deletions backend/src/database/seeds/create-initial-data.seed.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import { DataSource, Repository, InsertQueryBuilder } from 'typeorm';
import { User, UserRole } from '../../users/entities/user.entity';
import { Employee } from '../../employees/entities/employee.entity';
import { Service } from '../../services/entities/service.entity';
import { createInitialData } from './create-initial-data.seed';
import * as bcrypt from 'bcrypt';

jest.mock('bcrypt');

describe('createInitialData', () => {
let mockDataSource: Partial<DataSource>;
let mockUserRepository: Partial<Repository<User>>;
let mockEmployeeRepository: Partial<Repository<Employee>>;
let mockServiceRepository: Partial<Repository<Service>>;
let mockQueryBuilder: Partial<InsertQueryBuilder<any>>;
const originalEnv = process.env;

beforeEach(() => {
// Mock repositories
mockUserRepository = {
findOne: jest.fn() as jest.Mock,
save: jest.fn() as jest.Mock,
};

mockEmployeeRepository = {
save: jest.fn() as jest.Mock,
};

mockServiceRepository = {
save: jest.fn() as jest.Mock,
};

// Mock query builder for service associations
mockQueryBuilder = {
insert: jest.fn().mockReturnThis(),
into: jest.fn().mockReturnThis(),
values: jest.fn().mockReturnThis(),
execute: jest.fn().mockResolvedValue(undefined),
};

// Mock DataSource
mockDataSource = {
getRepository: jest.fn((entity) => {
if (entity === User) return mockUserRepository;
if (entity === Employee) return mockEmployeeRepository;
if (entity === Service) return mockServiceRepository;
return {} as Repository<any>;
}),
createQueryBuilder: jest.fn().mockReturnValue(mockQueryBuilder),
};

// Mock bcrypt
(bcrypt.hash as jest.Mock).mockResolvedValue('hashed-password');

// Setup test environment variables
process.env = {
...originalEnv,
EMPLOYEE_EMAIL: '[email protected]',
EMPLOYEE_PASSWORD: 'employee123',
EMPLOYEE_PHONE: '+1234567890',
};

// Mock console methods
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
process.env = originalEnv;
jest.clearAllMocks();
});

it('should create services, employee user, and employee when they do not exist', async () => {
// Mock that employee doesn't exist
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(null);

// Mock created services
const mockServices = [
{ id: '1', name: 'Haircut' },
{ id: '2', name: 'Hair Coloring' },
{ id: '3', name: 'Styling' },
];
(mockServiceRepository.save as jest.Mock).mockResolvedValue(mockServices);

// Mock created employee user
const mockEmployeeUser = {
id: 'user-1',
email: '[email protected]',
role: UserRole.EMPLOYEE,
};
(mockUserRepository.save as jest.Mock).mockResolvedValue(mockEmployeeUser);

// Mock created employee
const mockEmployee = {
id: 'employee-1',
user: mockEmployeeUser,
};
(mockEmployeeRepository.save as jest.Mock).mockResolvedValue(mockEmployee);

await createInitialData(mockDataSource as DataSource);

// Verify services were created
expect(mockServiceRepository.save).toHaveBeenCalledWith([
expect.objectContaining({ name: 'Haircut' }),
expect.objectContaining({ name: 'Hair Coloring' }),
expect.objectContaining({ name: 'Styling' }),
]);

// Verify employee user was created
expect(mockUserRepository.save).toHaveBeenCalledWith(expect.objectContaining({
email: '[email protected]',
role: UserRole.EMPLOYEE,
}));

// Verify employee was created
expect(mockEmployeeRepository.save).toHaveBeenCalledWith(expect.objectContaining({
user: mockEmployeeUser,
specializations: ['haircut', 'coloring'],
}));

// Verify services were associated with employee
expect(mockQueryBuilder.insert).toHaveBeenCalled();
expect(mockQueryBuilder.into).toHaveBeenCalledWith('employee_services');
expect(mockQueryBuilder.values).toHaveBeenCalledWith(
mockServices.map(service => ({
employee_id: mockEmployee.id,
service_id: service.id,
})),
);

// Verify success message was logged
expect(console.log).toHaveBeenCalledWith('Initial data seeded successfully');
});

it('should not create employee when it already exists', async () => {
// Mock that employee already exists
const existingEmployee = {
email: '[email protected]',
role: UserRole.EMPLOYEE,
};
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(existingEmployee);

await createInitialData(mockDataSource as DataSource);

// Verify services were still created
expect(mockServiceRepository.save).toHaveBeenCalled();

// Verify no employee creation attempts were made
expect(mockUserRepository.save).not.toHaveBeenCalled();
expect(mockEmployeeRepository.save).not.toHaveBeenCalled();
expect(mockQueryBuilder.insert).not.toHaveBeenCalled();

// Verify appropriate message was logged
expect(console.log).toHaveBeenCalledWith('Employee user already exists');
});

it('should throw error when employee email is missing', async () => {
delete process.env.EMPLOYEE_EMAIL;

await expect(createInitialData(mockDataSource as DataSource)).rejects.toThrow(
'Employee email and password must be set in environment variables',
);

// Verify no database operations were attempted
expect(mockServiceRepository.save).not.toHaveBeenCalled();
expect(mockUserRepository.findOne).not.toHaveBeenCalled();
expect(mockUserRepository.save).not.toHaveBeenCalled();
expect(mockEmployeeRepository.save).not.toHaveBeenCalled();
});

it('should throw error when employee password is missing', async () => {
delete process.env.EMPLOYEE_PASSWORD;

await expect(createInitialData(mockDataSource as DataSource)).rejects.toThrow(
'Employee email and password must be set in environment variables',
);

// Verify no database operations were attempted
expect(mockServiceRepository.save).not.toHaveBeenCalled();
expect(mockUserRepository.findOne).not.toHaveBeenCalled();
expect(mockUserRepository.save).not.toHaveBeenCalled();
expect(mockEmployeeRepository.save).not.toHaveBeenCalled();
});

it('should handle database errors during service creation', async () => {
const dbError = new Error('Database error during service creation');
(mockServiceRepository.save as jest.Mock).mockRejectedValue(dbError);

await expect(createInitialData(mockDataSource as DataSource)).rejects.toThrow(dbError);

// Verify error was logged
expect(console.error).toHaveBeenCalledWith('Error creating initial data:', dbError);
});

it('should handle database errors during employee creation', async () => {
// Mock that employee doesn't exist
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(null);
// Mock services creation success
(mockServiceRepository.save as jest.Mock).mockResolvedValue([]);
// Mock employee creation error
const dbError = new Error('Database error during employee creation');
(mockUserRepository.save as jest.Mock).mockRejectedValue(dbError);

await expect(createInitialData(mockDataSource as DataSource)).rejects.toThrow(dbError);

// Verify error was logged
expect(console.error).toHaveBeenCalledWith('Error creating initial data:', dbError);
});

it('should handle password hashing errors', async () => {
// Mock that employee doesn't exist
(mockUserRepository.findOne as jest.Mock).mockResolvedValue(null);
// Mock services creation success
(mockServiceRepository.save as jest.Mock).mockResolvedValue([]);
// Mock bcrypt error
const hashError = new Error('Hashing failed');
(bcrypt.hash as jest.Mock).mockRejectedValue(hashError);

await expect(createInitialData(mockDataSource as DataSource)).rejects.toThrow(hashError);

// Verify error was logged
expect(console.error).toHaveBeenCalledWith('Error creating initial data:', hashError);
});
});

0 comments on commit 1eeda22

Please sign in to comment.