Refactor database services and add component tests

- Remove deprecated CouchDB service files
- Update database test configurations
- Add test files for components and auth modules
- Update user context and admin interface
- Remove migration script for unified config
- Fix User interface properties in tests (use status instead of isActive)
This commit is contained in:
William Valentin
2025-09-08 18:30:43 -07:00
parent 31e08d730d
commit ac3643f76d
10 changed files with 934 additions and 1614 deletions

View File

@@ -1,5 +1,3 @@
import { AccountStatus } from '../../auth/auth.constants';
// Mock the environment utilities
jest.mock('../../../utils/env', () => ({
getEnvVar: jest.fn(),
@@ -51,6 +49,9 @@ jest.mock('../ProductionDatabaseStrategy', () => ({
// Import after mocks are set up
import { DatabaseService } from '../DatabaseService';
import { testUtils } from '../../../tests/setup';
const { createMockUser } = testUtils;
describe('DatabaseService', () => {
let mockGetEnvVar: jest.MockedFunction<any>;
@@ -301,26 +302,6 @@ describe('DatabaseService', () => {
expect(result).toBe(medication);
});
test('should delegate updateMedication to strategy (legacy signature)', async () => {
const medication = {
_id: 'med1',
_rev: 'rev1',
name: 'Updated Aspirin',
dosage: '200mg',
frequency: 'Daily' as any,
startTime: '08:00',
notes: '',
};
mockStrategyMethods.updateMedication.mockResolvedValue(medication);
const result = await service.updateMedication('user1', medication);
expect(mockStrategyMethods.updateMedication).toHaveBeenCalledWith(
medication
);
expect(result).toBe(medication);
});
test('should delegate getMedications to strategy', async () => {
const medications = [{ _id: 'med1', _rev: 'rev1', name: 'Aspirin' }];
mockStrategyMethods.getMedications.mockResolvedValue(medications);
@@ -331,22 +312,12 @@ describe('DatabaseService', () => {
expect(result).toBe(medications);
});
test('should delegate deleteMedication to strategy (new signature)', async () => {
mockStrategyMethods.deleteMedication.mockResolvedValue(true);
test('should delegate deleteMedication to strategy', async () => {
mockStrategyMethods.deleteMedication.mockResolvedValue(undefined);
const result = await service.deleteMedication('med1');
await service.deleteMedication('med1');
expect(mockStrategyMethods.deleteMedication).toHaveBeenCalledWith('med1');
expect(result).toBe(true);
});
test('should delegate deleteMedication to strategy (legacy signature)', async () => {
mockStrategyMethods.deleteMedication.mockResolvedValue(true);
const result = await service.deleteMedication('user1', { _id: 'med1' });
expect(mockStrategyMethods.deleteMedication).toHaveBeenCalledWith('med1');
expect(result).toBe(true);
});
});
@@ -382,162 +353,112 @@ describe('DatabaseService', () => {
service = new DatabaseService();
});
test('should support legacy getSettings method', async () => {
const settings = { _id: 'settings1', theme: 'dark' };
mockStrategyMethods.getUserSettings.mockResolvedValue(settings);
describe('user management operations', () => {
test('should support suspendUser method', async () => {
const user = createMockUser();
const suspendedUser = { ...user, status: 'SUSPENDED' as any };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(suspendedUser);
const result = await service.getSettings('user1');
const result = await service.suspendUser('user1');
expect(mockStrategyMethods.getUserSettings).toHaveBeenCalledWith('user1');
expect(result).toBe(settings);
});
test('should support legacy addMedication method', async () => {
const medicationInput = {
name: 'Aspirin',
dosage: '100mg',
frequency: 'Daily' as any,
startTime: '08:00',
notes: '',
};
const medication = { _id: 'med1', _rev: 'rev1', ...medicationInput };
mockStrategyMethods.createMedication.mockResolvedValue(medication);
const result = await service.addMedication('user1', medicationInput);
expect(mockStrategyMethods.createMedication).toHaveBeenCalledWith(
'user1',
medicationInput
);
expect(result).toBe(medication);
});
test('should support legacy updateSettings method', async () => {
const currentSettings = {
_id: 'settings1',
_rev: 'rev1',
notificationsEnabled: true,
hasCompletedOnboarding: false,
};
const updatedSettings = {
_id: 'settings1',
_rev: 'rev2',
notificationsEnabled: false,
hasCompletedOnboarding: false,
};
mockStrategyMethods.getUserSettings.mockResolvedValue(currentSettings);
mockStrategyMethods.updateUserSettings.mockResolvedValue(updatedSettings);
const result = await service.updateSettings('user1', {
notificationsEnabled: false,
expect(mockStrategyMethods.getUserById).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
status: 'SUSPENDED',
});
expect(result).toBe(suspendedUser);
});
expect(mockStrategyMethods.getUserSettings).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.updateUserSettings).toHaveBeenCalledWith({
_id: 'settings1',
_rev: 'rev1',
notificationsEnabled: false,
hasCompletedOnboarding: false,
test('should support activateUser method', async () => {
const user = { ...createMockUser(), status: 'SUSPENDED' as any };
const activatedUser = { ...user, status: 'ACTIVE' as any };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(activatedUser);
const result = await service.activateUser('user1');
expect(mockStrategyMethods.getUserById).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
status: 'ACTIVE',
});
expect(result).toBe(activatedUser);
});
expect(result).toBe(updatedSettings);
});
test('should support suspendUser method', async () => {
const user = { _id: 'user1', _rev: 'rev1', status: AccountStatus.ACTIVE };
const suspendedUser = { ...user, status: AccountStatus.SUSPENDED };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(suspendedUser);
test('should support changeUserPassword method', async () => {
const user = createMockUser();
const updatedUser = { ...user, password: 'newPassword' };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(updatedUser);
const result = await service.suspendUser('user1');
const result = await service.changeUserPassword('user1', 'newPassword');
expect(mockStrategyMethods.getUserById).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
status: AccountStatus.SUSPENDED,
expect(mockStrategyMethods.getUserById).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
password: 'newPassword',
});
expect(result).toBe(updatedUser);
});
expect(result).toBe(suspendedUser);
});
test('should support activateUser method', async () => {
const user = {
_id: 'user1',
_rev: 'rev1',
status: AccountStatus.SUSPENDED,
};
const activeUser = { ...user, status: AccountStatus.ACTIVE };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(activeUser);
test('should support deleteAllUserData method', async () => {
const medications = [
{ _id: 'med1', _rev: 'rev1', name: 'Aspirin' },
{ _id: 'med2', _rev: 'rev2', name: 'Vitamin' },
];
const reminders = [{ _id: 'rem1', _rev: 'rev1', name: 'Doctor Visit' }];
const result = await service.activateUser('user1');
mockStrategyMethods.getMedications.mockResolvedValue(medications);
mockStrategyMethods.getCustomReminders.mockResolvedValue(reminders);
mockStrategyMethods.deleteMedication.mockResolvedValue(true);
mockStrategyMethods.deleteCustomReminder.mockResolvedValue(true);
mockStrategyMethods.deleteUser.mockResolvedValue(true);
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
status: AccountStatus.ACTIVE,
const result = await service.deleteAllUserData('user1');
expect(mockStrategyMethods.getMedications).toHaveBeenCalledWith(
'user1'
);
expect(mockStrategyMethods.getCustomReminders).toHaveBeenCalledWith(
'user1'
);
expect(mockStrategyMethods.deleteMedication).toHaveBeenCalledWith(
'med1'
);
expect(mockStrategyMethods.deleteMedication).toHaveBeenCalledWith(
'med2'
);
expect(mockStrategyMethods.deleteCustomReminder).toHaveBeenCalledWith(
'rem1'
);
expect(mockStrategyMethods.deleteUser).toHaveBeenCalledWith('user1');
expect(result).toBe(true);
});
expect(result).toBe(activeUser);
});
test('should support changeUserPassword method', async () => {
const user = { _id: 'user1', _rev: 'rev1', password: 'oldpass' };
const updatedUser = { ...user, password: 'newpass' };
mockStrategyMethods.getUserById.mockResolvedValue(user);
mockStrategyMethods.updateUser.mockResolvedValue(updatedUser);
test('should throw error when user not found in suspendUser', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
const result = await service.changeUserPassword('user1', 'newpass');
expect(mockStrategyMethods.updateUser).toHaveBeenCalledWith({
...user,
password: 'newpass',
await expect(service.suspendUser('user1')).rejects.toThrow(
'User not found'
);
});
expect(result).toBe(updatedUser);
});
test('should support deleteAllUserData method', async () => {
const medications = [{ _id: 'med1', _rev: 'rev1' }];
const reminders = [{ _id: 'rem1', _rev: 'rev1' }];
test('should throw error when user not found in activateUser', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
mockStrategyMethods.getMedications.mockResolvedValue(medications);
mockStrategyMethods.getCustomReminders.mockResolvedValue(reminders);
mockStrategyMethods.deleteMedication.mockResolvedValue(true);
mockStrategyMethods.deleteCustomReminder.mockResolvedValue(true);
mockStrategyMethods.deleteUser.mockResolvedValue(true);
await expect(service.activateUser('user1')).rejects.toThrow(
'User not found'
);
});
const result = await service.deleteAllUserData('user1');
test('should throw error when user not found in changeUserPassword', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
expect(mockStrategyMethods.getMedications).toHaveBeenCalledWith('user1');
expect(mockStrategyMethods.getCustomReminders).toHaveBeenCalledWith(
'user1'
);
expect(mockStrategyMethods.deleteMedication).toHaveBeenCalledWith('med1');
expect(mockStrategyMethods.deleteCustomReminder).toHaveBeenCalledWith(
'rem1'
);
expect(mockStrategyMethods.deleteUser).toHaveBeenCalledWith('user1');
expect(result).toBe(true);
});
test('should throw error when user not found in suspendUser', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
await expect(service.suspendUser('user1')).rejects.toThrow(
'User not found'
);
});
test('should throw error when user not found in activateUser', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
await expect(service.activateUser('user1')).rejects.toThrow(
'User not found'
);
});
test('should throw error when user not found in changeUserPassword', async () => {
mockStrategyMethods.getUserById.mockResolvedValue(null);
await expect(
service.changeUserPassword('user1', 'newpass')
).rejects.toThrow('User not found');
await expect(
service.changeUserPassword('user1', 'newPassword')
).rejects.toThrow('User not found');
});
});
});
});