mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-13 20:27:22 +00:00
fix(scheduler): reject 6-field cron in Scheduled Operations (#1435)
* fix(scheduler): reject 6-field cron in Scheduled Operations Create and edit validation parsed cron with cron-parser, which accepts both 5- and 6-field expressions, while the form, presets, and docs all describe a 5-field cron. Because the scheduler ticks once per minute, a leading seconds field can never improve precision, so a 6-field expression was silently accepted but never honored on its stated schedule. Add a field-count guard on both sides: the API rejects 6-field input at create and edit with a clear message, and the form surfaces the same error inline and disables save. Cron nicknames such as @daily still pass. Document the five-field requirement in the cron reference. * chore: merge main into scheduled cron validation * fix: avoid logging policy bypass actor in debug output
This commit is contained in:
@@ -177,6 +177,32 @@ describe('ScheduledOperationsView', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('disables Create when the cron expression has a seconds field', async () => {
|
||||
render(<ScheduledOperationsView />);
|
||||
|
||||
await userEvent.click(await screen.findByRole('button', { name: /New Schedule/ }));
|
||||
await userEvent.type(await screen.findByPlaceholderText('e.g. Nightly stack restart'), 'cleanup');
|
||||
|
||||
await userEvent.click(screen.getAllByRole('combobox')[0]);
|
||||
await userEvent.click(await screen.findByRole('button', { name: 'System Prune' }));
|
||||
await userEvent.click(screen.getAllByRole('combobox')[1]);
|
||||
await userEvent.click(await screen.findByRole('button', { name: 'hub' }));
|
||||
|
||||
const createButton = screen.getByRole('button', { name: 'Create' });
|
||||
expect(createButton).toBeEnabled();
|
||||
|
||||
const cronInput = screen.getByPlaceholderText('0 3 * * *');
|
||||
await userEvent.clear(cronInput);
|
||||
await userEvent.type(cronInput, '30 0 3 * * *');
|
||||
|
||||
expect(screen.getByText(/seconds field is not supported/i)).toBeInTheDocument();
|
||||
expect(createButton).toBeDisabled();
|
||||
|
||||
await userEvent.clear(cronInput);
|
||||
await userEvent.type(cronInput, '0 4 * * *');
|
||||
expect(createButton).toBeEnabled();
|
||||
});
|
||||
|
||||
it('keeps Create disabled for a prune until a node is selected', async () => {
|
||||
render(<ScheduledOperationsView />);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user