72 lines
2.9 KiB
TypeScript
72 lines
2.9 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { cronToFormState } from './cronForm';
|
|
|
|
/**
|
|
* The backend's convertToCron (src/scheduler.ts) — mirrored here so the test
|
|
* asserts a true round-trip: editing a saved schedule and saving it back must
|
|
* not change the cron expression.
|
|
*/
|
|
function convertToCron(f: ReturnType<typeof cronToFormState>): string {
|
|
const m = f.minute ?? 0;
|
|
const h = f.hour ?? 0;
|
|
switch (f.scheduleType) {
|
|
case 'daily': return `${m} ${h} * * *`;
|
|
case 'weekly': return `${m} ${h} * * ${f.dayOfWeek ?? 0}`;
|
|
case 'monthly': return `${m} ${h} ${f.dayOfMonth ?? 1} * *`;
|
|
case 'cron': return f.cronExpression;
|
|
case 'once': return 'once';
|
|
}
|
|
}
|
|
|
|
describe('cronToFormState', () => {
|
|
it('classifies simple presets (daily/weekly/monthly)', () => {
|
|
expect(cronToFormState('0 9 * * *')).toMatchObject({ scheduleType: 'daily', hour: 9, minute: 0 });
|
|
expect(cronToFormState('30 14 * * *')).toMatchObject({ scheduleType: 'daily', hour: 14, minute: 30 });
|
|
expect(cronToFormState('0 9 * * 3')).toMatchObject({ scheduleType: 'weekly', hour: 9, minute: 0, dayOfWeek: 3 });
|
|
expect(cronToFormState('0 9 15 * *')).toMatchObject({ scheduleType: 'monthly', hour: 9, minute: 0, dayOfMonth: 15 });
|
|
});
|
|
|
|
it("keeps custom expressions as 'cron' and preserves the raw expression", () => {
|
|
for (const expr of [
|
|
'0 9 * * 1-5', '*/30 * * * *', '0 */2 * * *', '0 9,17 * * *', '15 9 1,15 * *', '0 9 1 6 *',
|
|
'0 9 * * 7', // Sunday-as-7 is out of the editor's 0-6 select range
|
|
'0 9 * * *', // double space → 6 tokens, not a clean preset
|
|
]) {
|
|
const f = cronToFormState(expr);
|
|
expect(f.scheduleType).toBe('cron');
|
|
expect(f.cronExpression).toBe(expr);
|
|
}
|
|
});
|
|
|
|
it('classifies Sunday-as-0 weekly', () => {
|
|
expect(cronToFormState('0 9 * * 0')).toMatchObject({ scheduleType: 'weekly', dayOfWeek: 0 });
|
|
});
|
|
|
|
it('never produces NaN fields for custom expressions', () => {
|
|
const f = cronToFormState('0 9 * * 1-5');
|
|
expect(Number.isNaN(f.hour)).toBe(false);
|
|
expect(Number.isNaN(f.minute)).toBe(false);
|
|
expect(Number.isNaN(f.dayOfWeek)).toBe(false);
|
|
expect(Number.isNaN(f.dayOfMonth)).toBe(false);
|
|
});
|
|
|
|
it("maps 'once' to the once type", () => {
|
|
expect(cronToFormState('once')).toMatchObject({ scheduleType: 'once' });
|
|
});
|
|
|
|
it('treats a malformed (non 5-field) string as a raw cron expression', () => {
|
|
expect(cronToFormState('garbage')).toMatchObject({ scheduleType: 'cron', cronExpression: 'garbage' });
|
|
});
|
|
|
|
it('round-trips losslessly through the backend convertToCron', () => {
|
|
const cases = [
|
|
'0 9 * * *', '30 14 * * *', '0 9 * * 3', '0 9 15 * *',
|
|
'0 9 * * 1-5', '*/30 * * * *', '0 */2 * * *', '0 9,17 * * *',
|
|
'15 9 1,15 * *', '0 9 1 6 *', 'once',
|
|
];
|
|
for (const expr of cases) {
|
|
expect(convertToCron(cronToFormState(expr))).toBe(expr);
|
|
}
|
|
});
|
|
});
|