All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 12m5s
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
// src/services/systemService.test.ts
|
|
import { describe, it, expect, vi, beforeEach, Mock } from 'vitest';
|
|
import { logger } from './logger.server';
|
|
import type { ExecException } from 'child_process';
|
|
|
|
// Mock logger
|
|
vi.mock('./logger.server', () => ({
|
|
logger: {
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
// Import the class, not the singleton instance, to apply Dependency Injection
|
|
import { SystemService } from './systemService';
|
|
|
|
describe('SystemService', () => {
|
|
let systemService: SystemService;
|
|
let mockExecAsync: Mock;
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
// Create a mock function for our dependency
|
|
mockExecAsync = vi.fn();
|
|
// Instantiate the service with the mock dependency
|
|
systemService = new SystemService(mockExecAsync);
|
|
});
|
|
|
|
describe('getPm2Status', () => {
|
|
it('should return success: true when process is online', async () => {
|
|
// This stdout mimics the output of `pm2 describe <app_name>`
|
|
const stdout = `Describing process with id 0 - name flyer-crawler-api
|
|
│ status │ online │
|
|
│ name │ flyer-crawler-api │`;
|
|
mockExecAsync.mockResolvedValue({ stdout, stderr: '' });
|
|
|
|
const result = await systemService.getPm2Status();
|
|
|
|
expect(result).toEqual({
|
|
success: true,
|
|
message: 'Application is online and running under PM2.',
|
|
});
|
|
});
|
|
|
|
it('should return success: false when process is stopped', async () => {
|
|
const stdout = `Describing process with id 0 - name flyer-crawler-api
|
|
│ status │ stopped │
|
|
│ name │ flyer-crawler-api │`;
|
|
mockExecAsync.mockResolvedValue({ stdout, stderr: '' });
|
|
|
|
const result = await systemService.getPm2Status();
|
|
|
|
expect(result).toEqual({
|
|
success: false,
|
|
message: 'Application process exists but is not online.',
|
|
});
|
|
});
|
|
|
|
it('should throw error if stderr has content', async () => {
|
|
mockExecAsync.mockResolvedValue({ stdout: 'some stdout', stderr: 'some stderr warning' });
|
|
|
|
await expect(systemService.getPm2Status()).rejects.toThrow(
|
|
'PM2 command produced an error: some stderr warning',
|
|
);
|
|
});
|
|
|
|
it('should return success: false when process does not exist', async () => {
|
|
const error = new Error('Command failed') as ExecException & { stdout?: string; stderr?: string };
|
|
error.code = 1;
|
|
error.stderr = "[PM2][ERROR] Process or Namespace flyer-crawler-api doesn't exist";
|
|
|
|
mockExecAsync.mockRejectedValue(error);
|
|
|
|
const result = await systemService.getPm2Status();
|
|
|
|
expect(result).toEqual({
|
|
success: false,
|
|
message: 'Application process is not running under PM2.',
|
|
});
|
|
expect(logger.warn).toHaveBeenCalledWith(
|
|
expect.stringContaining('PM2 process "flyer-crawler-api" not found'),
|
|
);
|
|
});
|
|
});
|
|
}); |