import { randomUUID } from "node:crypto"; import { expect, test } from "@playwright/test"; import bcrypt from "../../../apps/server/node_modules/bcrypt/bcrypt.js"; import mysql from "../../../apps/server/node_modules/mysql2/promise.js"; import { loginViaUi } from "../support/login-via-ui"; // La cuenta secundaria solo se inserta en la BD efĂ­mera del launcher oficial. test("IDENTITY-TENANT-CACHE: cambio de empresa y logout/login descartan el formulario anterior", async ({ page, request, }) => { const email = process.env.E2E_USER_EMAIL; const password = process.env.E2E_USER_PASSWORD; if (!(email && password && process.env.DB_NAME?.startsWith("factuges_erp_e2e_"))) { throw new Error("Requires the official isolated E2E environment."); } const login = await request.post("http://127.0.0.1:3002/api/v1/identity/auth/login", { data: { email, password }, }); expect(login.status()).toBe(200); await loginViaUi(page); const tokens = await login.json(); const companyId = randomUUID(); const created = await request.post("http://127.0.0.1:3002/api/v1/companies", { headers: { authorization: `Bearer ${tokens.access_token}` }, data: { id: companyId, legal_name: "Tenant cache B", slug: `cache-${companyId}` }, }); expect(created.status()).toBe(201); const accountId = randomUUID(); const secondEmail = `cache-${accountId}@example.test`; const connection = await mysql.createConnection({ host: process.env.DB_HOST, port: Number(process.env.DB_PORT), database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASS, }); try { await connection.execute( "INSERT INTO identity_accounts (id,email,password_hash,name,language_code,status,created_at,updated_at) VALUES (?,?,?,?, 'es','active',NOW(),NOW())", [accountId, secondEmail, await bcrypt.hash(password, 4), "Tenant cache second user"] ); const membershipId = randomUUID(); const roleId = randomUUID(); await connection.execute( "INSERT INTO identity_roles (id,company_id,code,name,is_system,permission_codes,created_at,updated_at) VALUES (?,?,'commercial','Commercial',false,?,NOW(),NOW())", [roleId, companyId, JSON.stringify(["identity:permissions:read"])] ); await connection.execute( "INSERT INTO identity_company_memberships (id,account_id,company_id,status,created_at,updated_at) VALUES (?,?,?,'active',NOW(),NOW())", [membershipId, accountId, companyId] ); await connection.execute( "INSERT INTO identity_company_membership_roles (membership_id,role_id) VALUES (?,?)", [membershipId, roleId] ); await connection.execute( "INSERT INTO initial_onboardings (id,account_id,status,company_id,created_at,updated_at,completed_at) VALUES (?,?,'completed',?,NOW(),NOW(),NOW())", [randomUUID(), accountId, companyId] ); } finally { await connection.end(); } await page.goto("/settings/company/details"); const name = page.locator('input[name="legalName"]'); await expect(name).toBeVisible(); await name.fill("Unsaved tenant A"); await page.getByTestId("company-switcher-trigger").click(); await page.getByTestId(`company-option-${companyId}`).click(); await expect(name).toHaveValue("Tenant cache B"); await name.fill("Unsaved old account"); await page.locator("#account-menu").click(); await page.locator("#account-logout").click(); await expect(page.locator("#login-email")).toBeVisible(); await page.locator("#login-email").fill(secondEmail); await page.locator("#login-password").fill(password); await page.locator("#login-submit").click(); await expect(page.locator("#account-menu")).toBeVisible(); await page.goto("/settings/company/details"); await expect(name).toHaveValue("Tenant cache B"); await expect(page.getByTestId("company-switcher-trigger")).toContainText("Tenant cache B"); });