Files
flyer-crawler.projectium.com/src/services/notificationService.test.ts
Torben Sorensen d4739b5784
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled
Refactor and update various service and route tests for improved type safety and clarity
- Added a new notes file regarding the deprecation of the Google AI JavaScript SDK.
- Removed unused imports and fixed duplicate imports in admin and auth route tests.
- Enhanced type safety in error handling for unique constraint violations in auth routes.
- Simplified gamification route tests by removing unnecessary imports.
- Updated price route to improve type safety by casting request body.
- Improved mock implementations in system route tests for better type handling.
- Cleaned up user routes by removing unused imports.
- Enhanced AI API client tests with more robust type definitions for form data.
- Updated recipe database tests to remove unused error imports.
- Refactored flyer processing service tests for better type safety and clarity.
- Improved logger client to use `unknown` instead of `any` for better type safety.
- Cleaned up notification service tests to ensure proper type casting.
- Updated queue service tests to remove unnecessary imports and improve type handling.
- Refactored queue service workers tests for better type safety in job processors.
- Cleaned up user routes integration tests by removing unused imports.
- Enhanced tests setup for unit tests to improve type safety in mocked Express requests.
- Updated PDF converter tests for better type safety in mocked return values.
- Improved price parser tests to ensure proper handling of null and undefined inputs.
2025-12-14 18:02:16 -08:00

129 lines
4.5 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, beforeAll } from 'vitest';
import type { Toaster } from './notificationService';
// --- FIX LEDGER ---
// 1. Initial attempt: Spy on default export property. Failed (0 calls).
// 2. Attempt: Hoisted spies attached to default export. Failed (0 calls).
// 3. Attempt: Function-as-object mock. Failed (TS error / 0 calls).
// 4. Attempt: Plain object mock. Failed (0 calls).
// 5. Attempt: Mock default export as a simple object using Object.assign. Failed (0 calls).
// 6. Attempt: Remove mock factory. Import real module and use vi.spyOn on the default export. Failed (0 calls).
// 7. Strategy: Dependency Injection. Failed (0 calls). This indicates the exported function itself is a mock (spy), likely due to implicit automocking or preserved mock state.
// 8. Current Strategy: Explicitly unmock the service module to force Vitest to load the actual implementation.
// Remove the broken mock factory
vi.unmock('../lib/toast');
// Explicitly unmock the service under test
vi.unmock('./notificationService');
describe('Notification Service', () => {
beforeAll(() => {
if (typeof window === 'undefined') {
throw new Error('Test environment is not JSDOM. Window is undefined.');
}
// Polyfill matchMedia if it doesn't exist (common JSDOM issue)
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
});
});
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
});
describe('notifySuccess', () => {
it('should call the injected toaster.success with correct options', async () => {
const mockToaster = {
success: vi.fn(),
error: vi.fn(),
};
const { notifySuccess } = await import('./notificationService');
const message = 'Operation was successful!';
notifySuccess(message, mockToaster);
expect(mockToaster.success).toHaveBeenCalledTimes(1);
expect(mockToaster.success).toHaveBeenCalledWith(
message,
expect.objectContaining({
style: expect.any(Object),
iconTheme: {
primary: '#10B981',
secondary: '#fff',
},
})
);
});
it('should not throw an error and should log a warning if the toaster is invalid', async () => {
// Arrange
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const invalidToaster = { success: undefined, error: vi.fn() }; // Missing success method
const message = 'This should not appear';
const { notifySuccess } = await import('./notificationService');
// Act
notifySuccess(message, invalidToaster as unknown as Toaster);
// Assert
expect(consoleWarnSpy).toHaveBeenCalledWith('[NotificationService] toast.success is not available. Message:', message);
consoleWarnSpy.mockRestore();
});
});
describe('notifyError', () => {
it('should call the injected toaster.error with correct options', async () => {
const mockToaster = {
success: vi.fn(),
error: vi.fn(),
};
const { notifyError } = await import('./notificationService');
const message = 'Something went wrong!';
notifyError(message, mockToaster);
expect(mockToaster.error).toHaveBeenCalledTimes(1);
expect(mockToaster.error).toHaveBeenCalledWith(
message,
expect.objectContaining({
style: expect.any(Object),
iconTheme: {
primary: '#EF4444',
secondary: '#fff',
},
})
);
});
it('should not throw an error and should log a warning if the toaster is invalid', async () => {
// Arrange
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const invalidToaster = { success: vi.fn(), error: undefined }; // Missing error method
const message = 'This error should not appear';
const { notifyError } = await import('./notificationService');
// Act
notifyError(message, invalidToaster as unknown as Toaster);
// Assert
expect(consoleWarnSpy).toHaveBeenCalledWith('[NotificationService] toast.error is not available. Message:', message);
consoleWarnSpy.mockRestore();
});
});
});