From 30dd503082331986b129da837a66f0826b468bd2 Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Sun, 19 Oct 2025 15:00:25 -0300 Subject: [PATCH] fix: clear persona links and use esm vitest config --- convex/machines.ts | 9 ++- tests/machines.updatePersona.test.ts | 107 ++++++++++++++++++++++++++ vitest.config.ts => vitest.config.mts | 6 +- 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tests/machines.updatePersona.test.ts rename vitest.config.ts => vitest.config.mts (77%) diff --git a/convex/machines.ts b/convex/machines.ts index f33f4f9..694dd30 100644 --- a/convex/machines.ts +++ b/convex/machines.ts @@ -915,11 +915,18 @@ export const updatePersona = mutation({ nextAssignedRole = trimmedRole || undefined } + if (personaProvided && !nextPersona) { + nextAssignedUserId = undefined + nextAssignedEmail = undefined + nextAssignedName = undefined + nextAssignedRole = undefined + } + if (nextPersona && !nextAssignedUserId) { throw new ConvexError("Associe um usuário ao definir a persona da máquina") } - if (nextAssignedUserId) { + if (nextPersona && nextAssignedUserId) { const assignedUser = await ctx.db.get(nextAssignedUserId) if (!assignedUser) { throw new ConvexError("Usuário vinculado não encontrado") diff --git a/tests/machines.updatePersona.test.ts b/tests/machines.updatePersona.test.ts new file mode 100644 index 0000000..7aa3dfa --- /dev/null +++ b/tests/machines.updatePersona.test.ts @@ -0,0 +1,107 @@ +import { afterAll, beforeAll, describe, expect, it, vi } from "vitest" + +import { updatePersona } from "../convex/machines" +import type { Doc, Id } from "../convex/_generated/dataModel" + +const FIXED_NOW = 1_706_071_200_000 + +function buildMachine(overrides: Partial> = {}): Doc<"machines"> { + const machine: Record = { + _id: "machine_1" as Id<"machines">, + tenantId: "tenant-1", + companyId: undefined, + companySlug: undefined, + authUserId: undefined, + authEmail: undefined, + persona: "collaborator", + assignedUserId: "user_1" as Id<"users">, + assignedUserEmail: "old@example.com", + assignedUserName: "Legacy User", + assignedUserRole: "COLLABORATOR", + hostname: "desktop-01", + osName: "Windows", + osVersion: "11", + architecture: "x86_64", + macAddresses: ["001122334455"], + serialNumbers: [], + fingerprint: "fingerprint", + metadata: {}, + lastHeartbeatAt: FIXED_NOW - 1000, + status: "online", + isActive: true, + createdAt: FIXED_NOW - 10_000, + updatedAt: FIXED_NOW - 5_000, + registeredBy: "agent:desktop", + } + return { ...(machine as Doc<"machines">), ...overrides } +} + +describe("convex.machines.updatePersona", () => { + let restoreConsole: (() => void) | undefined + + beforeAll(() => { + vi.useFakeTimers() + vi.setSystemTime(FIXED_NOW) + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}) + const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}) + restoreConsole = () => { + errorSpy.mockRestore() + warnSpy.mockRestore() + } + }) + + afterAll(() => { + restoreConsole?.() + vi.useRealTimers() + }) + + it("clears persona even when legacy assigned user no longer exists", async () => { + const machine = buildMachine() + const patch = vi.fn(async () => undefined) + const get = vi.fn(async (id: Id<"machines"> | Id<"users">) => { + if (id === machine._id) return machine + return null + }) + + const ctx = { db: { get, patch } } as unknown as Parameters[0] + + const result = await updatePersona(ctx, { machineId: machine._id, persona: "" }) + + expect(result).toEqual({ ok: true, persona: null }) + expect(patch).toHaveBeenCalledTimes(1) + expect(patch).toHaveBeenCalledWith( + machine._id, + expect.objectContaining({ + persona: undefined, + assignedUserId: undefined, + assignedUserEmail: undefined, + assignedUserName: undefined, + assignedUserRole: undefined, + updatedAt: FIXED_NOW, + }) + ) + }) + + it("still validates persona assignments when user cannot be found", async () => { + const machine = buildMachine({ persona: undefined, assignedUserId: undefined }) + const missingUserId = "user_missing" as Id<"users"> + const patch = vi.fn(async () => undefined) + const get = vi.fn(async (id: Id<"machines"> | Id<"users">) => { + if (id === machine._id) return machine + if (id === missingUserId) return null + return null + }) + + const ctx = { db: { get, patch } } as unknown as Parameters[0] + + await expect( + updatePersona(ctx, { + machineId: machine._id, + persona: "collaborator", + assignedUserId: missingUserId, + }) + ).rejects.toThrow("Usuário vinculado não encontrado") + + expect(patch).not.toHaveBeenCalled() + }) +}) diff --git a/vitest.config.ts b/vitest.config.mts similarity index 77% rename from vitest.config.ts rename to vitest.config.mts index 5c9c6b7..0b80e08 100644 --- a/vitest.config.ts +++ b/vitest.config.mts @@ -1,5 +1,8 @@ -import { defineConfig } from "vitest/config" import path from "path" +import { fileURLToPath } from "url" +import { defineConfig } from "vitest/config" + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) export default defineConfig({ resolve: { @@ -9,6 +12,7 @@ export default defineConfig({ }, }, test: { + pool: "vmThreads", environment: "node", globals: true, include: ["src/**/*.test.ts", "tests/**/*.test.ts"],