cause: l'utilisateur ne pouvait pas retirer un projet du registre IdeA (projects.json) ; la seule issue laissait l'entrée fantôme dans la liste des projets, sans capacité générique de retrait. domain: port ProjectStore::remove_project(id) -> Option<Project> avec implémentation par défaut « not supported » pour ne pas casser les stores spécialisés. infrastructure: FsProjectStore implémente remove_project — retire l'entrée du registre persisté et la renvoie, None si id inconnu, ordre relatif du registre préservé ; test store dédié. application: use case RemoveProjectFromRegistry (remove.rs) — NotFound explicite si id absent, retourne le projet retiré + registre rafraîchi. backend/app-tauri/web-server: DTO RemoveProjectRequestDto/RemoveProjectResponseDto (removed, projects, restore_state, was_open), adapter partagé remove_project_for_adapter réutilisé par la commande Tauri remove_project et la route HTTP — même contrat desktop/web ; remove_project_and_deactivate désactive le projet s'il était ouvert, purge l'entrée open-projects restore correspondante et renvoie was_open/restore_state ; test adapter vérifiant le contrat de bout en bout (entrée retirée, restore purgé, root intact). frontend: DTO + ProjectGateway.removeProject (HTTP + mock), ProjectsView expose un menu d'actions projet (ProjectActionsMenu) avec entrée Retirer, RemoveProjectDialog — confirmation explicite précisant que le dossier disque n'est pas supprimé, invalidation/rechargement de la liste des projets après succès (useProjects), tests ProjectsView/projects/adapters/httpInvoker/services. QA verte: cargo targeted tests/check OK (domain, application project_usecases, infrastructure project_store, backend, app-tauri, web-server), npm targeted/typecheck/build OK ; suite npm test complète rouge non bloquante hors #308 (échecs préexistants listProjectSettings/web). Vérifications Git: git diff --check OK, cargo fmt --all -- --check OK. fichiers .ideai/tickets/308/, tickets/counter.json, tickets/index.json, attachments/ et scripts/ hors périmètre et préservés en worktree (sync store traité séparément) ; aucun push. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
const invoke = vi.fn();
|
|
vi.mock("@tauri-apps/api/core", () => ({
|
|
invoke: (...args: unknown[]) => invoke(...args),
|
|
}));
|
|
|
|
import { TauriProjectGateway } from "./project";
|
|
|
|
describe("TauriProjectGateway invoke payloads", () => {
|
|
beforeEach(() => invoke.mockReset().mockResolvedValue({}));
|
|
|
|
it("reads and updates the project context under .ideai", async () => {
|
|
invoke.mockResolvedValueOnce("# shared");
|
|
await expect(new TauriProjectGateway().readProjectContext("proj-1")).resolves.toBe(
|
|
"# shared",
|
|
);
|
|
expect(invoke).toHaveBeenCalledWith("read_project_context", {
|
|
projectId: "proj-1",
|
|
});
|
|
|
|
await new TauriProjectGateway().updateProjectContext("proj-1", "# next");
|
|
expect(invoke).toHaveBeenCalledWith("update_project_context", {
|
|
request: { projectId: "proj-1", content: "# next" },
|
|
});
|
|
});
|
|
|
|
it("maps the open-project restore commands to their exact request envelopes", async () => {
|
|
const gateway = new TauriProjectGateway();
|
|
|
|
await gateway.restoreOpenProjects();
|
|
expect(invoke).toHaveBeenCalledWith("restore_open_projects");
|
|
|
|
await gateway.retryOpenProjectRestore();
|
|
expect(invoke).toHaveBeenCalledWith("retry_open_project_restore", {
|
|
request: {},
|
|
});
|
|
await gateway.retryOpenProjectRestore("proj-1");
|
|
expect(invoke).toHaveBeenCalledWith("retry_open_project_restore", {
|
|
request: { projectId: "proj-1" },
|
|
});
|
|
|
|
await gateway.removeProjectFromRestore("proj-1");
|
|
expect(invoke).toHaveBeenCalledWith("remove_project_from_restore", {
|
|
request: { projectId: "proj-1" },
|
|
});
|
|
|
|
await gateway.saveOpenProjectRestoreOrder(["proj-2", "proj-1"]);
|
|
expect(invoke).toHaveBeenCalledWith("save_open_project_restore_order", {
|
|
request: { orderedProjectIds: ["proj-2", "proj-1"] },
|
|
});
|
|
|
|
await gateway.readOpenProjectRestoreState();
|
|
expect(invoke).toHaveBeenCalledWith("read_open_project_restore_state");
|
|
});
|
|
|
|
it("removes a project through the shared request envelope", async () => {
|
|
const gateway = new TauriProjectGateway();
|
|
|
|
await gateway.removeProject("proj-1");
|
|
|
|
expect(invoke).toHaveBeenCalledWith("remove_project", {
|
|
request: { projectId: "proj-1" },
|
|
});
|
|
});
|
|
});
|