fix(sprint-6/etapa-3): localStorage key en ProfileSheet + eliminar setTimeout(350) + specs E2E de auth
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
This commit is contained in:
@@ -10,10 +10,21 @@ import { useAuth } from '@/auth/AuthContext'
|
||||
// Lee el access token directamente de localStorage sin pasar por el cliente Supabase.
|
||||
// Evita contención con processLock — el save de perfil no necesita refresh de token
|
||||
// porque es una operación rápida y el token está fresco en sesiones activas.
|
||||
// Clave verificada: STORAGE_KEY = 'supabase.auth.token' en @supabase/auth-js GoTrueClient.
|
||||
//
|
||||
// Clave real confirmada por diagnóstico (Sprint 6 Etapa 3, tests/e2e/auth-localStorage-key.spec.ts):
|
||||
// 'supabase.auth.token' es el STORAGE_KEY default de @supabase/auth-js's GoTrueClient en
|
||||
// aislamiento, pero @supabase/supabase-js's createClient() SOBRESCRIBE ese default calculando
|
||||
// `sb-${projectRef}-auth-token` desde la URL del proyecto (projectRef = hostname.split('.')[0]),
|
||||
// salvo que el caller pase un storageKey explícito — src/lib/supabase.ts no lo hace. El spec de
|
||||
// diagnóstico confirmó empíricamente: 'supabase.auth.token' NO existe en localStorage; la única
|
||||
// clave presente es `sb-${projectRef}-auth-token` con un access_token válido. Con la clave vieja,
|
||||
// getAccessToken() siempre retornaba null → el persist a Supabase nunca se ejecutaba (línea 68
|
||||
// silenciaba el error) — el usuario veía el cambio en UI pero no se guardaba.
|
||||
function getAccessToken(): string | null {
|
||||
try {
|
||||
const raw = localStorage.getItem('supabase.auth.token')
|
||||
const projectRef = new URL(SUPABASE_URL).hostname.split('.')[0]
|
||||
const storageKey = `sb-${projectRef}-auth-token`
|
||||
const raw = localStorage.getItem(storageKey)
|
||||
if (!raw) return null
|
||||
const parsed = JSON.parse(raw) as { access_token?: string }
|
||||
return parsed.access_token ?? null
|
||||
@@ -48,16 +59,13 @@ export function ProfileSheet({ open, onOpenChange }: ProfileSheetProps) {
|
||||
const savedName = name.trim()
|
||||
const savedCompany = company.trim() || undefined
|
||||
|
||||
// Cerramos el Sheet primero. updateUser() se difiere 350ms — más que la animación
|
||||
// de cierre de Radix (duration-300 = 300ms) — para que el cleanup de
|
||||
// @radix-ui/react-remove-scroll restaure pointer-events:none del body ANTES
|
||||
// de que el re-render de AuthContext vuelva a procesar el Sheet. Si updateUser
|
||||
// corre durante la animación, Radix no ejecuta el cleanup y body queda con
|
||||
// pointer-events:none permanente, bloqueando toda interacción fuera del canvas BPMN.
|
||||
// Cerramos el Sheet y actualizamos el estado local de inmediato — actualización
|
||||
// optimista. El fix para el bug de Radix/react-remove-scroll (pointer-events:none
|
||||
// atascado en el body tras cerrar) vive en src/components/ui/sheet.tsx (useEffect
|
||||
// que observa el prop `open` y limpia el body defensivamente). El defer de 350ms
|
||||
// que existía acá era redundante una vez resuelta la causa raíz ahí.
|
||||
onOpenChange(false)
|
||||
setTimeout(() => {
|
||||
updateUser({ name: savedName, company: savedCompany })
|
||||
}, 350)
|
||||
updateUser({ name: savedName, company: savedCompany })
|
||||
|
||||
// Persistir en Supabase en background — fire & forget.
|
||||
// Usamos raw fetch (no el cliente Supabase) para evitar contención con processLock.
|
||||
|
||||
Reference in New Issue
Block a user