fix(app-tauri,frontend): la fenêtre Tâches planifiées s'affiche en mode détaché — #359 (QA verte)
cause: le panneau Tâches planifiées n'avait aucune variante dans l'enum ViewPanel, open_view_window("scheduledTasks") rejetait INVALID et detachPanel ne touchait le placement qu'en cas de succès — même famille que #299, aucun effet visible ni message.
fix: variante ViewPanel::ScheduledTasks avec contrat stable label view-scheduledTasks / url index.html?panel=scheduledTasks / titre « Scheduled tasks », identité persistée des fenêtres view-scheduledTasks acceptée à la restauration #50; frontend ViewWindow rend le ScheduledTasksPanel du projet focalisé et ProjectsView expose le placement Fenêtre détachée via WindowGateway; retrait de la variante Projects devenue morte après #315 — le panneau Projects (coquille de la fenêtre principale) n'est plus détachable, refus INVALID gardé par tests.
QA verte: view_window_tests dont scheduled_tasks_view_window_contract_is_stable et projects_panel_is_not_detachable, persisted_identity_accepts_scheduled_tasks_view_labels, frontend ViewWindow/window gateway/ProjectsView.detach verts.
This commit is contained in:
@ -41,6 +41,14 @@ describe("TauriWindowGateway (#23)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("passes scheduledTasks unchanged to the detached-window command", async () => {
|
||||
await new TauriWindowGateway().openViewWindow("scheduledTasks");
|
||||
|
||||
expect(invoke).toHaveBeenCalledWith("open_view_window", {
|
||||
panel: "scheduledTasks",
|
||||
});
|
||||
});
|
||||
|
||||
it("opens plugin layout windows through the backend command", async () => {
|
||||
invoke.mockResolvedValueOnce({
|
||||
label: "view-plugin-layout",
|
||||
|
||||
@ -10,6 +10,7 @@ import { render, screen, waitFor, act, fireEvent } from "@testing-library/react"
|
||||
|
||||
import { DIProvider } from "@/app/di";
|
||||
import {
|
||||
createMockGateways,
|
||||
MockAgentGateway,
|
||||
MockFocusedProjectGateway,
|
||||
MockProjectGateway,
|
||||
@ -66,6 +67,13 @@ describe("parseViewWindowParams (#47)", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts the detachable scheduled tasks panel", () => {
|
||||
expect(parseViewWindowParams("?panel=scheduledTasks")).toEqual({
|
||||
kind: "panel",
|
||||
panel: "scheduledTasks",
|
||||
});
|
||||
});
|
||||
|
||||
it("parses a plugin layout window query from the backend base64url contract", () => {
|
||||
expect(
|
||||
parseViewWindowParams(
|
||||
@ -170,6 +178,29 @@ describe("PluginLayoutWindow (#143)", () => {
|
||||
});
|
||||
|
||||
describe("ViewWindow (#47)", () => {
|
||||
it("renders ScheduledTasksPanel for a focused project", async () => {
|
||||
const gateways = createMockGateways();
|
||||
const project = await gateways.project.createProject("alpha", "/p/a");
|
||||
const focusedProject = new MockFocusedProjectGateway();
|
||||
gateways.focusedProject = focusedProject;
|
||||
await focusedProject.setFocusedProject({
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
root: project.root,
|
||||
});
|
||||
|
||||
render(
|
||||
<DIProvider gateways={gateways}>
|
||||
<ViewWindow panel="scheduledTasks" />
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() => expect(screen.getByText("· alpha")).toBeTruthy());
|
||||
expect(screen.getByRole("heading", { name: "Tâches planifiées", level: 1 })).toBeTruthy();
|
||||
expect(await screen.findByRole("button", { name: "Nouvelle tâche planifiée" })).toBeTruthy();
|
||||
expect(await screen.findByText("Aucune tâche planifiée pour ce projet")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("keeps the latest focused project when the initial snapshot is delayed", async () => {
|
||||
const system = new MockSystemGateway();
|
||||
const project = new MockProjectGateway();
|
||||
|
||||
@ -92,6 +92,17 @@ describe("ProjectsView detach to OS window (#23)", () => {
|
||||
expect(screen.queryByRole("dialog", { name: "MCP" })).toBeNull();
|
||||
});
|
||||
|
||||
it("detaches scheduled tasks through WindowGateway", async () => {
|
||||
const { windowGateway } = await renderWithProject();
|
||||
const openViewWindow = vi.spyOn(windowGateway, "openViewWindow");
|
||||
|
||||
pickPlacement("Tâches planifiées", "Fenêtre détachée");
|
||||
|
||||
await waitFor(() => expect(openViewWindow).toHaveBeenCalledWith("scheduledTasks"));
|
||||
expect(windowGateway.open.has("scheduledTasks")).toBe(true);
|
||||
expect(screen.queryByRole("dialog", { name: "Tâches planifiées" })).toBeNull();
|
||||
});
|
||||
|
||||
it("detaches project settings through the same retry-safe window path", async () => {
|
||||
const { windowGateway } = await renderWithProject();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user