From 515a875e889ce5df34abc5c9867f3fcbf4c29428 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sat, 18 Apr 2026 23:15:01 +0200 Subject: [PATCH] fix: allow deleting tablos with etapes --- apps/api/src/__tests__/routes/tablo.test.ts | 47 +++++++++++++++++++++ apps/api/src/routers/tablo.ts | 22 ++-------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/apps/api/src/__tests__/routes/tablo.test.ts b/apps/api/src/__tests__/routes/tablo.test.ts index 923fa38..a8fa3ea 100644 --- a/apps/api/src/__tests__/routes/tablo.test.ts +++ b/apps/api/src/__tests__/routes/tablo.test.ts @@ -5,6 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { createConfig } from "../../config.js"; import { MiddlewareManager } from "../../middlewares/middleware.js"; import { getMainRouter } from "../../routers/index.js"; +import { TEST_USERS } from "../fixtures/testData.js"; import type { TestUserData } from "../helpers/dbSetup.js"; import { getTestUser } from "../helpers/dbSetup.js"; @@ -109,6 +110,23 @@ describe("Tablo Endpoint", () => { ); }; + const signInAsTestUser = async (email: string, password: string) => { + const userClient = createClient(config.SUPABASE_URL, config.SUPABASE_SERVICE_ROLE_KEY, { + auth: { + autoRefreshToken: false, + persistSession: false, + }, + }); + + const { data, error } = await userClient.auth.signInWithPassword({ email, password }); + + if (error || !data.session) { + throw new Error(`Failed to sign in ${email}: ${error?.message ?? "missing session"}`); + } + + return userClient; + }; + // Helper function to get tablo members // biome-ignore lint/suspicious/noExplicitAny: testClient requires any for dynamic route access const getTabloMembersRequest = async (user: TestUserData, client: any, tabloId: string) => { @@ -415,6 +433,35 @@ describe("Tablo Endpoint", () => { expect(res.status).toBe(403); }); + + it("should allow owner to delete a tablo that contains etapes", async () => { + const createRes = await createTabloRequest(ownerUser, client, { + name: "Delete With Etape", + status: "todo", + color: "#804EEC", + }); + + expect(createRes.status).toBe(200); + const createData = await createRes.json(); + const createdTabloId = createData.tablo.id as string; + createdTabloIds.push(createdTabloId); + + const ownerClient = await signInAsTestUser(TEST_USERS.owner.email, TEST_USERS.owner.password); + const { error: createEtapeError } = await ownerClient.from("tasks").insert({ + tablo_id: createdTabloId, + title: "Delete me", + is_parent: true, + status: "todo", + }); + + expect(createEtapeError).toBeNull(); + + const res = await deleteTabloRequest(ownerUser, client, createdTabloId); + + expect(res.status).toBe(200); + const data = await res.json(); + expect(data.message).toBe("Tablo deleted successfully"); + }); }); describe("GET /tablos/members/:tablo_id - Get Tablo Members", () => { diff --git a/apps/api/src/routers/tablo.ts b/apps/api/src/routers/tablo.ts index 5ce02b7..105e21c 100644 --- a/apps/api/src/routers/tablo.ts +++ b/apps/api/src/routers/tablo.ts @@ -126,26 +126,10 @@ const deleteTablo = factory.createHandlers(async (c) => { const deletedAt = new Date().toISOString(); - const { error: tasksSoftDeleteError } = await supabase - .from("tasks") - .update({ deleted_at: deletedAt }) - .eq("tablo_id", id) - .is("deleted_at", null); + const { error: tasksDeleteError } = await supabase.from("tasks").delete().eq("tablo_id", id); - if (tasksSoftDeleteError) { - // Backward compatibility for environments where tasks.deleted_at is not migrated yet. - const isMissingDeletedAtColumn = - tasksSoftDeleteError.code === "42703" || - tasksSoftDeleteError.message?.toLowerCase().includes("deleted_at"); - - if (isMissingDeletedAtColumn) { - const { error: tasksDeleteError } = await supabase.from("tasks").delete().eq("tablo_id", id); - if (tasksDeleteError) { - return c.json({ error: tasksDeleteError.message }, 500); - } - } else { - return c.json({ error: tasksSoftDeleteError.message }, 500); - } + if (tasksDeleteError) { + return c.json({ error: tasksDeleteError.message }, 500); } const { error } = await supabase.from("tablos").update({ deleted_at: deletedAt }).eq("id", id);