feat(backend,frontend): tâches planifiées projet — tool MCP idea_scheduled_task_* et menu utilisateur #305, fix transcript lié indisponible après reboot #314 (QA verte)
#305: nouvel agrégat durable ScheduledProjectTask dans domain (scheduled_task.rs, ids, ports ScheduledProjectTaskStore), source de vérité <app_data_dir>/scheduled-project-tasks/<projectId>.json, schedules bornés V1 interval/daily/weekly avec fuseau, cycle À approuver/Active/Suspendue avec approbation obligatoire des tâches demandées par agent; use cases application/scheduled_task (list/create/update/delete/run_now/reconcile/fire) réutilisant BackgroundTask pour les runs avec distinction planifié/manuel; store infrastructure dédié + scheduler reconcile au boot sans rattrapage en rafale, cwd confiné au projet; 7 tools MCP idea_scheduled_task_* (list/read lecture seule, create/update/delete/run_now/set_enabled write-actions soumises aux permissions natives); commandes Tauri + routes HTTP aux contrats DTO identiques (camelCase nextRunAtMs/lastRunAtMs/lastTaskId/createdBy/updatedBy); frontend: gateways Tauri/HTTP/mock + types ports/domain, surface projet 'Tâches planifiées' (liste utilisateur+agent unifiée, création/édition avec récapitulatif avant activation, approbation/refus, exécuter maintenant, suspendre/reprendre, suppression), catalogage surface web (webSurfaceCatalog/viewPlacement/ViewPanelBody/WebWorkspace); docs/scheduled-project-tasks.md et sdk docs/services.md (047c38b: pas un service plugin V1, pas d'émulation via cron système). #314: correction de 'Conversation liée — transcript indisponible' après reboot: restauration du transcript lié côté application (orchestrator service, lifecycle, session_limit, background sink, terminal registry) et côté frontend (adapters agent/http frames/stream/requestResponse, workStateNormalization, CustomAgentChatView avec état et action utile), tests dto_chat/agent_lifecycle/structured_registry_d1/background_completion_sink étendus. QA verte rapportée par QA sur feature/305-scheduled-project-tasks-mcp, sans bloquant, pour #305 et #314. Hors périmètre worktree: tickets non liés, attachments/, scripts/; aucun push.
This commit is contained in:
39
frontend/src/adapters/scheduledTask.test.ts
Normal file
39
frontend/src/adapters/scheduledTask.test.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const invoke = vi.fn();
|
||||
vi.mock("@tauri-apps/api/core", () => ({ invoke: (...args: unknown[]) => invoke(...args) }));
|
||||
|
||||
import { TauriScheduledTaskGateway } from "./scheduledTask";
|
||||
|
||||
const input = {
|
||||
name: "Nettoyage",
|
||||
command: { command: "find", args: ["dist", "-delete"], cwd: "." },
|
||||
schedule: { kind: "interval" as const, everyMinutes: 60 },
|
||||
timezone: "Europe/Paris",
|
||||
enabled: true,
|
||||
timeoutMs: 60_000,
|
||||
};
|
||||
|
||||
describe("TauriScheduledTaskGateway", () => {
|
||||
beforeEach(() => invoke.mockReset().mockResolvedValue({}));
|
||||
|
||||
it("uses the backend command envelopes for list/create/update", async () => {
|
||||
const gateway = new TauriScheduledTaskGateway();
|
||||
await gateway.list("p1");
|
||||
await gateway.create("p1", input);
|
||||
await gateway.update("p1", "s1", 4, input);
|
||||
expect(invoke).toHaveBeenNthCalledWith(1, "list_scheduled_project_tasks", { projectId: "p1" });
|
||||
expect(invoke).toHaveBeenNthCalledWith(2, "create_scheduled_project_task", { request: { projectId: "p1", ...input } });
|
||||
expect(invoke).toHaveBeenNthCalledWith(3, "update_scheduled_project_task", { request: { projectId: "p1", scheduledTaskId: "s1", auditRevision: 4, ...input } });
|
||||
});
|
||||
|
||||
it("uses flat identity arguments for actions", async () => {
|
||||
const gateway = new TauriScheduledTaskGateway();
|
||||
await gateway.runNow("p1", "s1");
|
||||
await gateway.setEnabled("p1", "s1", false);
|
||||
await gateway.delete("p1", "s1");
|
||||
expect(invoke).toHaveBeenNthCalledWith(1, "run_scheduled_project_task_now", { projectId: "p1", scheduledTaskId: "s1" });
|
||||
expect(invoke).toHaveBeenNthCalledWith(2, "set_scheduled_project_task_enabled", { projectId: "p1", scheduledTaskId: "s1", enabled: false });
|
||||
expect(invoke).toHaveBeenNthCalledWith(3, "delete_scheduled_project_task", { projectId: "p1", scheduledTaskId: "s1" });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user