Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a4f349805 | ||
| 517a268307 |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "flyer-crawler",
|
||||
"version": "0.2.29",
|
||||
"version": "0.2.30",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "flyer-crawler",
|
||||
"version": "0.2.29",
|
||||
"version": "0.2.30",
|
||||
"dependencies": {
|
||||
"@bull-board/api": "^6.14.2",
|
||||
"@bull-board/express": "^6.14.2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "flyer-crawler",
|
||||
"private": true,
|
||||
"version": "0.2.29",
|
||||
"version": "0.2.30",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm:start:dev\" \"vite\"",
|
||||
|
||||
@@ -12,11 +12,10 @@ vi.mock('util', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('util')>();
|
||||
return {
|
||||
...actual,
|
||||
default: actual,
|
||||
promisify: (fn: Function) => {
|
||||
return (...args: any[]) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fn(...args, (err: Error | null, stdout: unknown, stderr: unknown) => {
|
||||
fn(...args, (err: Error | null, stdout: string, stderr: string) => {
|
||||
if (err) {
|
||||
// Attach stdout/stderr to the error object to mimic child_process.exec behavior
|
||||
Object.assign(err, { stdout, stderr });
|
||||
@@ -41,7 +40,6 @@ vi.mock('child_process', () => {
|
||||
});
|
||||
|
||||
return {
|
||||
default: { exec: mockExec },
|
||||
exec: mockExec,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -127,12 +127,21 @@ describe('AnalyticsService', () => {
|
||||
throw new Error('Processing failed');
|
||||
}); // "Successfully generated..."
|
||||
|
||||
const promise = service.processWeeklyReportJob(job);
|
||||
// Wrap the async operation that is expected to reject in a function.
|
||||
// This prevents an "unhandled rejection" error by ensuring the `expect.rejects`
|
||||
// is actively waiting for the promise to reject when the timers are advanced.
|
||||
const testFunction = async () => {
|
||||
const promise = service.processWeeklyReportJob(job);
|
||||
// Advance timers to trigger the part of the code that throws.
|
||||
await vi.advanceTimersByTimeAsync(30000);
|
||||
// Await the promise to allow the rejection to be caught by `expect.rejects`.
|
||||
await promise;
|
||||
};
|
||||
|
||||
await vi.advanceTimersByTimeAsync(30000);
|
||||
|
||||
await expect(promise).rejects.toThrow('Processing failed');
|
||||
// Now, assert that the entire operation rejects as expected.
|
||||
await expect(testFunction()).rejects.toThrow('Processing failed');
|
||||
|
||||
// Verify the side effect (error logging) after the rejection is confirmed.
|
||||
expect(mockLoggerInstance.error).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
err: expect.any(Error),
|
||||
|
||||
@@ -1,70 +1,16 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// Set environment variables before importing the service
|
||||
process.env.JWT_SECRET = 'test-secret';
|
||||
process.env.FRONTEND_URL = 'http://localhost:3000';
|
||||
|
||||
import { authService } from './authService';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import crypto from 'crypto';
|
||||
import { userRepo, adminRepo } from './db/index.db';
|
||||
import { UniqueConstraintError } from './db/errors.db';
|
||||
import { logger } from './logger.server';
|
||||
import { sendPasswordResetEmail } from './emailService.server';
|
||||
import type { UserProfile } from '../types';
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('bcrypt');
|
||||
vi.mock('jsonwebtoken');
|
||||
vi.mock('crypto', () => ({
|
||||
default: {
|
||||
randomBytes: vi.fn().mockReturnValue({
|
||||
toString: vi.fn().mockReturnValue('mocked-random-string'),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('./db/index.db', () => ({
|
||||
userRepo: {
|
||||
createUser: vi.fn(),
|
||||
saveRefreshToken: vi.fn(),
|
||||
findUserByEmail: vi.fn(),
|
||||
createPasswordResetToken: vi.fn(),
|
||||
getValidResetTokens: vi.fn(),
|
||||
updateUserPassword: vi.fn(),
|
||||
deleteResetToken: vi.fn(),
|
||||
findUserByRefreshToken: vi.fn(),
|
||||
findUserProfileById: vi.fn(),
|
||||
deleteRefreshToken: vi.fn(),
|
||||
},
|
||||
adminRepo: {
|
||||
logActivity: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('./logger.server', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('./emailService.server', () => ({
|
||||
sendPasswordResetEmail: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('./db/connection.db', () => ({
|
||||
getPool: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../utils/authUtils', () => ({
|
||||
validatePasswordStrength: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('AuthService', () => {
|
||||
let authService: typeof import('./authService').authService;
|
||||
let bcrypt: typeof import('bcrypt');
|
||||
let jwt: typeof import('jsonwebtoken');
|
||||
let userRepo: typeof import('./db/index.db').userRepo;
|
||||
let adminRepo: typeof import('./db/index.db').adminRepo;
|
||||
let logger: typeof import('./logger.server').logger;
|
||||
let sendPasswordResetEmail: typeof import('./emailService.server').sendPasswordResetEmail;
|
||||
|
||||
const reqLog = {}; // Mock request logger object
|
||||
const mockUser = {
|
||||
user_id: 'user-123',
|
||||
@@ -76,8 +22,59 @@ describe('AuthService', () => {
|
||||
role: 'user',
|
||||
} as unknown as UserProfile;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
|
||||
// Set environment variables before any modules are imported
|
||||
process.env.JWT_SECRET = 'test-secret';
|
||||
process.env.FRONTEND_URL = 'http://localhost:3000';
|
||||
|
||||
// Mock all dependencies before dynamically importing the service
|
||||
vi.mock('bcrypt');
|
||||
vi.mock('jsonwebtoken');
|
||||
vi.mock('crypto', () => ({
|
||||
default: {
|
||||
randomBytes: vi.fn().mockReturnValue({
|
||||
toString: vi.fn().mockReturnValue('mocked-random-string'),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
vi.mock('./db/index.db', () => ({
|
||||
userRepo: {
|
||||
createUser: vi.fn(),
|
||||
saveRefreshToken: vi.fn(),
|
||||
findUserByEmail: vi.fn(),
|
||||
createPasswordResetToken: vi.fn(),
|
||||
getValidResetTokens: vi.fn(),
|
||||
updateUserPassword: vi.fn(),
|
||||
deleteResetToken: vi.fn(),
|
||||
findUserByRefreshToken: vi.fn(),
|
||||
findUserProfileById: vi.fn(),
|
||||
deleteRefreshToken: vi.fn(),
|
||||
},
|
||||
adminRepo: {
|
||||
logActivity: vi.fn(),
|
||||
},
|
||||
}));
|
||||
vi.mock('./logger.server', () => ({
|
||||
logger: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() },
|
||||
}));
|
||||
vi.mock('./emailService.server', () => ({
|
||||
sendPasswordResetEmail: vi.fn(),
|
||||
}));
|
||||
vi.mock('./db/connection.db', () => ({ getPool: vi.fn() }));
|
||||
vi.mock('../utils/authUtils', () => ({ validatePasswordStrength: vi.fn() }));
|
||||
|
||||
// Dynamically import modules to get the mocked versions and the service instance
|
||||
authService = (await import('./authService')).authService;
|
||||
bcrypt = await import('bcrypt');
|
||||
jwt = await import('jsonwebtoken');
|
||||
const dbModule = await import('./db/index.db');
|
||||
userRepo = dbModule.userRepo;
|
||||
adminRepo = dbModule.adminRepo;
|
||||
logger = (await import('./logger.server')).logger;
|
||||
sendPasswordResetEmail = (await import('./emailService.server')).sendPasswordResetEmail;
|
||||
});
|
||||
|
||||
describe('registerUser', () => {
|
||||
|
||||
@@ -242,7 +242,10 @@ export class FlyerProcessingService {
|
||||
// Mark subsequent critical stages as skipped
|
||||
for (let i = errorStageIndex + 1; i < stagesToReport.length; i++) {
|
||||
if (stagesToReport[i].critical) {
|
||||
stagesToReport[i] = { ...stagesToReport[i], status: 'skipped' };
|
||||
// When a stage is skipped, we don't need its previous 'detail' property.
|
||||
// This creates a clean 'skipped' state object by removing `detail` and keeping the rest.
|
||||
const { detail, ...restOfStage } = stagesToReport[i];
|
||||
stagesToReport[i] = { ...restOfStage, status: 'skipped' };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// src/services/systemService.test.ts
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { exec, type ExecException } from 'child_process';
|
||||
import { logger } from './logger.server';
|
||||
@@ -35,10 +36,11 @@ vi.mock('util', async (importOriginal) => {
|
||||
});
|
||||
|
||||
// Mock child_process
|
||||
vi.mock('child_process', () => {
|
||||
const mockExec = vi.fn();
|
||||
vi.mock('child_process', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('child_process')>();
|
||||
return {
|
||||
exec: mockExec,
|
||||
...actual,
|
||||
exec: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user