diff --git a/src/web/src/features/users/pages/UserDetailPage.tsx b/src/web/src/features/users/pages/UserDetailPage.tsx
index 2e2cbff..3c48b2f 100644
--- a/src/web/src/features/users/pages/UserDetailPage.tsx
+++ b/src/web/src/features/users/pages/UserDetailPage.tsx
@@ -4,11 +4,14 @@ import { Badge } from '@/components/ui/badge'
import { useUser } from '../hooks/useUser'
import { useDeactivateUser } from '../hooks/useDeactivateUser'
import { useReactivateUser } from '../hooks/useReactivateUser'
+import { ResetPasswordModal } from '../components/ResetPasswordModal'
+import { useAuthStore } from '@/stores/authStore'
export function UserDetailPage() {
const { id } = useParams<{ id: string }>()
const userId = Number(id)
const navigate = useNavigate()
+ const loggedUserId = useAuthStore((s) => s.user?.id)
const { data: user, isLoading } = useUser(userId)
const { mutate: deactivate, isPending: deactivating } = useDeactivateUser()
@@ -90,6 +93,8 @@ export function UserDetailPage() {
{reactivating ? 'Reactivando...' : 'Reactivar'}
)}
+
+ {loggedUserId !== userId && }
)
diff --git a/src/web/src/tests/features/users/UserDetailPage.test.tsx b/src/web/src/tests/features/users/UserDetailPage.test.tsx
new file mode 100644
index 0000000..4936b8c
--- /dev/null
+++ b/src/web/src/tests/features/users/UserDetailPage.test.tsx
@@ -0,0 +1,78 @@
+import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'
+import { render, screen, waitFor } from '@testing-library/react'
+import { http, HttpResponse } from 'msw'
+import { setupServer } from 'msw/node'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { MemoryRouter, Routes, Route } from 'react-router-dom'
+import { UserDetailPage } from '../../../features/users/pages/UserDetailPage'
+import { useAuthStore } from '../../../stores/authStore'
+
+const API_URL = 'http://localhost:5000'
+
+const adminUser = {
+ id: 1, username: 'admin', nombre: 'Admin', rol: 'admin',
+ permisos: ['administracion:usuarios:gestionar'],
+ mustChangePassword: false,
+}
+
+const target = {
+ id: 5,
+ username: 'cajero1',
+ nombre: 'Juan',
+ apellido: 'Perez',
+ email: 'juan@test.com',
+ rol: 'cajero',
+ activo: true,
+ permisosJson: '[]',
+ fechaModificacion: null,
+ ultimoLogin: null,
+}
+
+const server = setupServer()
+
+beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
+afterEach(() => {
+ server.resetHandlers()
+ useAuthStore.getState().clearAuth()
+})
+afterAll(() => server.close())
+
+function renderDetail(userId: number) {
+ useAuthStore.setState({ user: adminUser })
+ const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } })
+ return render(
+
+
+
+ } />
+
+
+ ,
+ )
+}
+
+describe('UserDetailPage — reset password wiring', () => {
+ it('shows "Resetear contraseña" button when viewing another user', async () => {
+ server.use(
+ http.get(`${API_URL}/api/v1/users/5`, () => HttpResponse.json(target)),
+ )
+
+ renderDetail(5)
+
+ await waitFor(() => expect(screen.getByText('Juan Perez')).toBeInTheDocument())
+ expect(screen.getByRole('button', { name: /resetear contraseña/i })).toBeInTheDocument()
+ })
+
+ it('hides "Resetear contraseña" button when viewing own profile (prevent cannot-self-reset)', async () => {
+ server.use(
+ http.get(`${API_URL}/api/v1/users/1`, () =>
+ HttpResponse.json({ ...target, id: 1, username: 'admin', nombre: 'Admin', apellido: 'Root', rol: 'admin' }),
+ ),
+ )
+
+ renderDetail(1)
+
+ await waitFor(() => expect(screen.getByText('Admin Root')).toBeInTheDocument())
+ expect(screen.queryByRole('button', { name: /resetear contraseña/i })).not.toBeInTheDocument()
+ })
+})