206 lines
5.8 KiB
TypeScript
206 lines
5.8 KiB
TypeScript
import { getSchedulerStatus, startScheduler, stopScheduler } from '$lib/server/scheduler';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
// Mock environment variables
|
|
const { mockEnv } = vi.hoisted(() => {
|
|
return {
|
|
mockEnv: {
|
|
AUTH_SCHEDULER_ENABLED: 'false',
|
|
AUTH_SCHEDULER_INTERVAL_MINUTES: '720'
|
|
}
|
|
};
|
|
});
|
|
|
|
vi.mock('$env/dynamic/private', () => ({
|
|
env: mockEnv
|
|
}));
|
|
|
|
// Mock the browser module
|
|
vi.mock('$lib/server/browser', () => ({
|
|
getBrowser: vi.fn(),
|
|
initializeBrowser: vi.fn(),
|
|
closeBrowser: vi.fn()
|
|
}));
|
|
|
|
// Mock fs operations
|
|
const mockFs = {
|
|
existsSync: vi.fn(),
|
|
mkdirSync: vi.fn(),
|
|
writeFileSync: vi.fn(),
|
|
readFileSync: vi.fn()
|
|
};
|
|
|
|
describe('Scheduler Service', () => {
|
|
beforeEach(() => {
|
|
// Reset environment variables
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'false';
|
|
mockEnv.AUTH_SCHEDULER_INTERVAL_MINUTES = '720';
|
|
|
|
// Clear all mocks
|
|
vi.clearAllMocks();
|
|
|
|
// Reset scheduler state by stopping if running
|
|
try {
|
|
stopScheduler();
|
|
} catch {
|
|
// Ignore if not running
|
|
}
|
|
});
|
|
|
|
afterEach(async () => {
|
|
// Ensure scheduler is stopped after each test
|
|
await stopScheduler();
|
|
});
|
|
|
|
describe('Configuration', () => {
|
|
it('should use default interval when AUTH_SCHEDULER_INTERVAL_MINUTES is not set', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockEnv.AUTH_SCHEDULER_INTERVAL_MINUTES = '';
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.config.intervalMinutes).toBe(720);
|
|
});
|
|
|
|
it('should parse custom interval minutes from environment', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockEnv.AUTH_SCHEDULER_INTERVAL_MINUTES = '30';
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.config.intervalMinutes).toBe(30);
|
|
});
|
|
|
|
it('should disable scheduler when AUTH_SCHEDULER_ENABLED is not true', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'false';
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.config.enabled).toBe(false);
|
|
expect(status.running).toBe(false);
|
|
});
|
|
|
|
it('should parse AUTH_SCHEDULER_ENABLED as true when set to "true"', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.config.enabled).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Scheduler Lifecycle', () => {
|
|
it('should not start when disabled', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'false';
|
|
|
|
await startScheduler();
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.running).toBe(false);
|
|
});
|
|
|
|
it('should start when enabled', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockFs.existsSync.mockReturnValue(true);
|
|
|
|
await startScheduler();
|
|
|
|
const status = getSchedulerStatus();
|
|
expect(status.running).toBe(true);
|
|
});
|
|
|
|
it('should not start twice', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockFs.existsSync.mockReturnValue(true);
|
|
|
|
await startScheduler();
|
|
const consoleSpy = vi.spyOn(console, 'warn');
|
|
|
|
await startScheduler();
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith('[Scheduler] Scheduler is already running');
|
|
});
|
|
|
|
it('should stop the scheduler', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockFs.existsSync.mockReturnValue(true);
|
|
|
|
await startScheduler();
|
|
expect(getSchedulerStatus().running).toBe(true);
|
|
|
|
await stopScheduler();
|
|
expect(getSchedulerStatus().running).toBe(false);
|
|
});
|
|
|
|
it('should handle stopping when not running', async () => {
|
|
const consoleSpy = vi.spyOn(console, 'log');
|
|
await stopScheduler();
|
|
expect(consoleSpy).toHaveBeenCalledWith('[Scheduler] Scheduler is not running');
|
|
});
|
|
});
|
|
|
|
describe('Status Reporting', () => {
|
|
it('should return scheduler status with default values', () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'false';
|
|
|
|
const status = getSchedulerStatus();
|
|
|
|
expect(status).toEqual({
|
|
running: false,
|
|
lastRenewalTime: null,
|
|
isRenewing: false,
|
|
config: {
|
|
enabled: false,
|
|
intervalMinutes: 720
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should report running state correctly', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockFs.existsSync.mockReturnValue(true);
|
|
|
|
await startScheduler();
|
|
const status = getSchedulerStatus();
|
|
|
|
expect(status.running).toBe(true);
|
|
expect(status.isRenewing).toBe(false);
|
|
});
|
|
|
|
it('should track configuration', async () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockEnv.AUTH_SCHEDULER_INTERVAL_MINUTES = '1440';
|
|
|
|
const status = getSchedulerStatus();
|
|
|
|
expect(status.config.enabled).toBe(true);
|
|
expect(status.config.intervalMinutes).toBe(1440);
|
|
});
|
|
});
|
|
|
|
describe('Auth Renewal', () => {
|
|
it('should skip renewal if no auth.json exists', async () => {
|
|
mockFs.existsSync.mockReturnValue(false);
|
|
|
|
// Note: In a real test, you'd import and call the renewal function directly
|
|
// This test verifies the behavior when auth file is missing
|
|
expect(mockFs.existsSync.mock.calls.length).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
it('should prevent concurrent renewal attempts', async () => {
|
|
// This would be tested through integration tests with actual browser context
|
|
// The scheduler maintains state.isRenewing flag to prevent concurrent calls
|
|
const status = getSchedulerStatus();
|
|
expect(status.isRenewing).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('Environment Variables', () => {
|
|
it('should handle empty AUTH_SCHEDULER_INTERVAL_MINUTES with default', () => {
|
|
mockEnv.AUTH_SCHEDULER_ENABLED = 'true';
|
|
mockEnv.AUTH_SCHEDULER_INTERVAL_MINUTES = '';
|
|
|
|
const status = getSchedulerStatus();
|
|
// Empty string should fall back to default due to parseInt('', 10) returning NaN
|
|
// and the || 720 fallback
|
|
expect(status.config.intervalMinutes).toBeDefined();
|
|
});
|
|
});
|
|
});
|