feat: expand live chat and work server tools
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
buildScheduledBoardPostTitle,
|
||||
buildScheduledPlanWorkIdBase,
|
||||
isPlanScheduledTaskDue,
|
||||
mapPlanScheduledTaskRow,
|
||||
shouldCreatePlanForScheduleExecution,
|
||||
updatePlanScheduledTaskSchema,
|
||||
} from './plan-schedule-service.js';
|
||||
|
||||
test('buildScheduledBoardPostTitle prefers the first memo line when present', () => {
|
||||
assert.equal(
|
||||
buildScheduledBoardPostTitle({
|
||||
work_id: '반복작업',
|
||||
note: ' 첫 줄 제목 \n둘째 줄 설명',
|
||||
}),
|
||||
'첫 줄 제목',
|
||||
);
|
||||
});
|
||||
|
||||
test('buildScheduledBoardPostTitle falls back to normalized work id when memo is empty', () => {
|
||||
assert.equal(
|
||||
buildScheduledBoardPostTitle({
|
||||
work_id: ' 작업 ID ',
|
||||
note: ' \n ',
|
||||
}),
|
||||
'반복작업',
|
||||
);
|
||||
});
|
||||
|
||||
test('buildScheduledPlanWorkIdBase uses the schedule work id for automation registration', () => {
|
||||
assert.equal(
|
||||
buildScheduledPlanWorkIdBase({
|
||||
work_id: ' 반복-정리 ',
|
||||
}),
|
||||
'반복-정리',
|
||||
);
|
||||
});
|
||||
|
||||
test('buildScheduledPlanWorkIdBase keeps managed-service runs on the schedule work id with schedule pk prefix', () => {
|
||||
assert.equal(
|
||||
buildScheduledPlanWorkIdBase({
|
||||
id: 10,
|
||||
work_id: ' 반복-정리 ',
|
||||
execution_mode: 'managed-service',
|
||||
}),
|
||||
'schedule-10-반복-정리',
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
buildScheduledPlanWorkIdBase({
|
||||
id: 10,
|
||||
work_id: '반복-정리-service',
|
||||
execution_mode: 'managed-service',
|
||||
}),
|
||||
'schedule-10-반복-정리-service',
|
||||
);
|
||||
});
|
||||
|
||||
test('buildScheduledPlanWorkIdBase falls back when managed-service schedule id is missing', () => {
|
||||
assert.equal(
|
||||
buildScheduledPlanWorkIdBase({
|
||||
work_id: '반복-정리-service',
|
||||
execution_mode: 'managed-service',
|
||||
}),
|
||||
'반복-정리-service',
|
||||
);
|
||||
});
|
||||
|
||||
test('shouldCreatePlanForScheduleExecution only returns true for managed-service schedules', () => {
|
||||
assert.equal(
|
||||
shouldCreatePlanForScheduleExecution({
|
||||
execution_mode: 'codex',
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
shouldCreatePlanForScheduleExecution({
|
||||
execution_mode: 'managed-service',
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('updatePlanScheduledTaskSchema keeps partial updates partial', () => {
|
||||
assert.deepEqual(updatePlanScheduledTaskSchema.parse({ recreateManagedServiceOnNextSave: true }), {
|
||||
recreateManagedServiceOnNextSave: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('updatePlanScheduledTaskSchema accepts second-based interval updates', () => {
|
||||
assert.deepEqual(
|
||||
updatePlanScheduledTaskSchema.parse({
|
||||
repeatIntervalValue: 10,
|
||||
repeatIntervalUnit: 'second',
|
||||
repeatIntervalSeconds: 10,
|
||||
}),
|
||||
{
|
||||
repeatIntervalValue: 10,
|
||||
repeatIntervalUnit: 'second',
|
||||
repeatIntervalSeconds: 10,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('interval schedule with start time waits until start time when immediate run is enabled', () => {
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: true,
|
||||
repeat_interval_minutes: 60,
|
||||
repeat_window_start_time: '09:00',
|
||||
created_at: '2026-04-30T07:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T08:59:00+09:00'),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: true,
|
||||
repeat_interval_minutes: 60,
|
||||
repeat_window_start_time: '09:00',
|
||||
created_at: '2026-04-30T07:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T09:00:00+09:00'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('interval schedule with start time waits one interval after the start when immediate run is disabled', () => {
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_minutes: 60,
|
||||
repeat_window_start_time: '09:00',
|
||||
created_at: '2026-04-30T07:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T09:59:00+09:00'),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_minutes: 60,
|
||||
repeat_window_start_time: '09:00',
|
||||
created_at: '2026-04-30T07:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T10:00:00+09:00'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('interval schedule supports second-based due calculation', () => {
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_unit: 'second',
|
||||
repeat_interval_value: 10,
|
||||
repeat_interval_seconds: 10,
|
||||
created_at: '2026-04-30T09:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T09:00:09+09:00'),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_unit: 'second',
|
||||
repeat_interval_value: 10,
|
||||
repeat_interval_seconds: 10,
|
||||
created_at: '2026-04-30T09:00:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T09:00:10+09:00'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('interval schedule uses repeat interval value and unit when stored seconds are stale', () => {
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_unit: 'minute',
|
||||
repeat_interval_value: 10,
|
||||
repeat_interval_seconds: 3600,
|
||||
created_at: '2026-04-30T09:50:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T09:59:59+09:00'),
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
isPlanScheduledTaskDue(
|
||||
{
|
||||
schedule_mode: 'interval',
|
||||
immediate_run_enabled: false,
|
||||
repeat_interval_unit: 'minute',
|
||||
repeat_interval_value: 10,
|
||||
repeat_interval_seconds: 3600,
|
||||
created_at: '2026-04-30T09:50:00+09:00',
|
||||
},
|
||||
new Date('2026-04-30T10:00:00+09:00'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('mapPlanScheduledTaskRow normalizes stale stored repeat interval seconds', () => {
|
||||
const mapped = mapPlanScheduledTaskRow({
|
||||
id: 2,
|
||||
work_id: 'stock-alert',
|
||||
schedule_mode: 'interval',
|
||||
repeat_interval_unit: 'minute',
|
||||
repeat_interval_value: 10,
|
||||
repeat_interval_seconds: 3600,
|
||||
repeat_interval_minutes: 60,
|
||||
});
|
||||
|
||||
assert.equal(mapped.repeatIntervalValue, 10);
|
||||
assert.equal(mapped.repeatIntervalUnit, 'minute');
|
||||
assert.equal(mapped.repeatIntervalSeconds, 600);
|
||||
assert.equal(mapped.repeatIntervalMinutes, 10);
|
||||
});
|
||||
Reference in New Issue
Block a user