From 8546a1feb160470c3900d315a0eb5000b3bd4308 Mon Sep 17 00:00:00 2001 From: rever-tecnologia Date: Wed, 17 Dec 2025 10:38:07 -0300 Subject: [PATCH] fix(avatar): sincroniza avatar apos atualizar - Propaga Set-Cookie do Better Auth no endpoint de avatar\n- Forca refresh da sessao apos upload/remocao\n- Adiciona teste de propagacao e defaults de env para testes --- src/app/api/profile/avatar/route.ts | 6 +- src/components/settings/settings-content.tsx | 4 +- .../profile-avatar-cookie-propagation.test.ts | 72 +++++++++++++++++++ tests/setup/bun-test-env.ts | 1 + vitest.config.mts | 3 + vitest.setup.node.ts | 2 + 6 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 tests/profile-avatar-cookie-propagation.test.ts diff --git a/src/app/api/profile/avatar/route.ts b/src/app/api/profile/avatar/route.ts index 7d7e9b6..7ebda15 100644 --- a/src/app/api/profile/avatar/route.ts +++ b/src/app/api/profile/avatar/route.ts @@ -4,7 +4,7 @@ * DELETE - Remove a foto de perfil (volta ao padrĂ£o) */ -import { NextRequest, NextResponse } from "next/server" +import { NextResponse } from "next/server" import { getServerSession } from "@/lib/auth-server" import { auth } from "@/lib/auth" @@ -34,7 +34,7 @@ function extractSetCookies(headers: Headers) { return setCookieHeaders } -export async function POST(request: NextRequest) { +export async function POST(request: Request) { try { const session = await getServerSession() @@ -142,7 +142,7 @@ export async function POST(request: NextRequest) { } } -export async function DELETE(request: NextRequest) { +export async function DELETE(request: Request) { try { const session = await getServerSession() diff --git a/src/components/settings/settings-content.tsx b/src/components/settings/settings-content.tsx index 9521ed0..b672a7a 100644 --- a/src/components/settings/settings-content.tsx +++ b/src/components/settings/settings-content.tsx @@ -32,7 +32,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Separator } from "@/components/ui/separator" -import { useAuth, signOut } from "@/lib/auth-client" +import { refreshSession, signOut, useAuth } from "@/lib/auth-client" const ShaderBackground = dynamic( () => import("@/components/background-paper-shaders-wrapper"), @@ -442,6 +442,7 @@ function ProfileEditCard({ const avatarData = await avatarRes.json() setLocalAvatarUrl(avatarData.avatarUrl) + await refreshSession() // Limpa preview if (pendingAvatarPreview) { @@ -461,6 +462,7 @@ function ProfileEditCard({ setLocalAvatarUrl(null) setPendingRemoveAvatar(false) + await refreshSession() } // Processa outros dados do perfil se houver diff --git a/tests/profile-avatar-cookie-propagation.test.ts b/tests/profile-avatar-cookie-propagation.test.ts new file mode 100644 index 0000000..06b3524 --- /dev/null +++ b/tests/profile-avatar-cookie-propagation.test.ts @@ -0,0 +1,72 @@ +import { beforeEach, describe, expect, it, vi } from "vitest" + +import { DELETE } from "@/app/api/profile/avatar/route" +import { getServerSession } from "@/lib/auth-server" +import { auth } from "@/lib/auth" +import { prisma } from "@/lib/prisma" + +vi.mock("@/lib/auth-server", () => ({ + getServerSession: vi.fn(), +})) + +vi.mock("@/server/convex-client", () => ({ + createConvexClient: vi.fn(() => ({ mutation: vi.fn() })), +})) + +vi.mock("@/lib/prisma", () => ({ + prisma: { + authUser: { update: vi.fn() }, + }, +})) + +vi.mock("@/lib/auth", () => ({ + auth: { + api: { + updateUser: vi.fn(), + }, + }, +})) + +describe("DELETE /api/profile/avatar", () => { + beforeEach(() => { + vi.resetAllMocks() + vi.mocked(getServerSession).mockResolvedValue({ + session: { id: "sess-1", expiresAt: Date.now() + 60_000 }, + user: { + id: "user-1", + name: "Agente", + email: "agent@example.com", + role: "agent", + tenantId: null, + avatarUrl: "https://cdn.example.com/avatar.png", + machinePersona: null, + }, + }) + }) + + it("propaga Set-Cookie retornado pelo Better Auth (cookieCache)", async () => { + const upstreamHeaders = new Headers() + upstreamHeaders.append("set-cookie", "better-auth.session_data=abc; Path=/; HttpOnly") + upstreamHeaders.append("set-cookie", "better-auth.session_token=def; Path=/; HttpOnly") + + vi.mocked(auth.api.updateUser).mockResolvedValue( + new Response(JSON.stringify({ status: true }), { status: 200, headers: upstreamHeaders }) + ) + + const req = new Request("http://localhost/api/profile/avatar", { method: "DELETE" }) + const res = await DELETE(req) + + expect(res.status).toBe(200) + + const headersAny = res.headers as Headers & { getSetCookie?: () => string[] | undefined } + const setCookies = + typeof headersAny.getSetCookie === "function" + ? headersAny.getSetCookie() ?? [] + : [res.headers.get("set-cookie")].filter(Boolean) + + expect(setCookies.join("\n")).toContain("better-auth.session_data=abc") + expect(setCookies.join("\n")).toContain("better-auth.session_token=def") + + expect(vi.mocked(prisma.authUser.update)).not.toHaveBeenCalled() + }) +}) diff --git a/tests/setup/bun-test-env.ts b/tests/setup/bun-test-env.ts index 6d0f2b5..e35ff3e 100644 --- a/tests/setup/bun-test-env.ts +++ b/tests/setup/bun-test-env.ts @@ -6,6 +6,7 @@ import { JSDOM } from "jsdom" process.env.BETTER_AUTH_SECRET ??= "test-secret" process.env.NEXT_PUBLIC_APP_URL ??= "http://localhost:3000" process.env.BETTER_AUTH_URL ??= process.env.NEXT_PUBLIC_APP_URL +process.env.DATABASE_URL ??= "postgresql://postgres:postgres@localhost:5432/sistema_test?schema=public" process.env.NODE_ENV ??= "test" const OriginalDate = Date diff --git a/vitest.config.mts b/vitest.config.mts index 8253c42..0980ecf 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -10,6 +10,9 @@ const convexDir = path.resolve(__dirname, "./convex") const isCI = process.env.CI === "true" const isBrowserRun = process.env.VITEST_BROWSER === "true" +process.env.DATABASE_URL = + process.env.DATABASE_URL ?? "postgresql://postgres:postgres@localhost:5432/sistema_test?schema=public" + export default defineConfig({ root: __dirname, plugins: [tsconfigPaths()], diff --git a/vitest.setup.node.ts b/vitest.setup.node.ts index 5459c1f..af01e43 100644 --- a/vitest.setup.node.ts +++ b/vitest.setup.node.ts @@ -5,6 +5,8 @@ if (typeof process !== "undefined" && process.versions?.node) { process.env.BETTER_AUTH_SECRET = process.env.BETTER_AUTH_SECRET ?? "test-secret" process.env.NEXT_PUBLIC_APP_URL = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000" process.env.BETTER_AUTH_URL = process.env.BETTER_AUTH_URL ?? process.env.NEXT_PUBLIC_APP_URL + process.env.DATABASE_URL = + process.env.DATABASE_URL ?? "postgresql://postgres:postgres@localhost:5432/sistema_test?schema=public" } export {}