Antes de la última revisión de etapa 4. Sprint 1. Previo al ajuste de look n feel de app, reportes, nombre y colores.
This commit is contained in:
132
tests/features/workspace/GlobalSettingsPanel.test.tsx
Normal file
132
tests/features/workspace/GlobalSettingsPanel.test.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Tests de la sección "Análisis de Impacto" del GlobalSettingsPanel.
|
||||
*
|
||||
* Los mocks usan vi.hoisted() para que currentProcess sea una referencia
|
||||
* estable entre renders (evita el loop infinito del useEffect de sync).
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react'
|
||||
import { TooltipProvider } from '@/components/ui/tooltip'
|
||||
|
||||
// ─── Mocks con referencia estable ─────────────────────────────────────────────
|
||||
|
||||
const processStoreMock = vi.hoisted(() => ({
|
||||
currentProcess: {
|
||||
id: 'p1', name: 'Proceso test', clientName: 'Cliente A',
|
||||
bpmnXml: '<def/>', currency: 'USD', overheadPercentage: 0.2,
|
||||
annualFrequency: 1000, analysisHorizonYears: 3, automationInvestment: 0,
|
||||
createdAt: 0, updatedAt: 0,
|
||||
},
|
||||
updateProcess: vi.fn(),
|
||||
subscribe: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/store/process-store', () => ({
|
||||
useProcessStore: () => processStoreMock,
|
||||
}))
|
||||
|
||||
vi.mock('@/store/simulation-store', () => ({
|
||||
useSimulationStore: () => ({
|
||||
resultActual: null,
|
||||
resultAutomated: null,
|
||||
invalidateResults: vi.fn(),
|
||||
}),
|
||||
}))
|
||||
|
||||
import { GlobalSettingsPanel } from '@/features/workspace/GlobalSettingsPanel'
|
||||
|
||||
// ─── Helper ───────────────────────────────────────────────────────────────────
|
||||
|
||||
function renderPanel() {
|
||||
return render(
|
||||
<TooltipProvider>
|
||||
<GlobalSettingsPanel />
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── Tests ────────────────────────────────────────────────────────────────────
|
||||
|
||||
beforeEach(() => {
|
||||
processStoreMock.updateProcess.mockReset()
|
||||
processStoreMock.updateProcess.mockResolvedValue(undefined)
|
||||
// Restaurar defaults del proceso
|
||||
processStoreMock.currentProcess.annualFrequency = 1000
|
||||
processStoreMock.currentProcess.analysisHorizonYears = 3
|
||||
processStoreMock.currentProcess.automationInvestment = 0
|
||||
})
|
||||
|
||||
describe('GlobalSettingsPanel — sección Análisis de Impacto', () => {
|
||||
it('renderiza los 3 campos de impacto con sus labels correctos', () => {
|
||||
renderPanel()
|
||||
expect(screen.getByLabelText(/Frecuencia anual/i)).toBeInTheDocument()
|
||||
expect(screen.getByText(/Horizonte de análisis/i)).toBeInTheDocument()
|
||||
expect(screen.getByLabelText(/Inversión en automatización/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('frecuencia anual muestra el default 1000 del proceso', () => {
|
||||
renderPanel()
|
||||
const freqInput = screen.getByLabelText(/Frecuencia anual/i) as HTMLInputElement
|
||||
expect(freqInput.value).toBe('1000')
|
||||
})
|
||||
|
||||
it('editar frecuencia y guardar incluye el nuevo valor en updateProcess', async () => {
|
||||
renderPanel()
|
||||
const freqInput = screen.getByLabelText(/Frecuencia anual/i)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(freqInput, { target: { value: '5000' } })
|
||||
})
|
||||
|
||||
// Después de cambiar, el botón debería mostrar "Guardar configuración"
|
||||
const guardarBtn = await screen.findByRole('button', { name: /Guardar/i })
|
||||
await act(async () => { fireEvent.click(guardarBtn) })
|
||||
|
||||
expect(processStoreMock.updateProcess).toHaveBeenCalledOnce()
|
||||
const calledWith = processStoreMock.updateProcess.mock.calls[0][0]
|
||||
expect(calledWith.annualFrequency).toBe(5000)
|
||||
})
|
||||
|
||||
it('horizonte de análisis se muestra en texto (default 3 años)', () => {
|
||||
renderPanel()
|
||||
expect(screen.getByText('3 años')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('guardar incluye horizonte actual en updateProcess', async () => {
|
||||
renderPanel()
|
||||
const freqInput = screen.getByLabelText(/Frecuencia anual/i)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(freqInput, { target: { value: '1200' } })
|
||||
})
|
||||
|
||||
const guardarBtn = await screen.findByRole('button', { name: /Guardar/i })
|
||||
await act(async () => { fireEvent.click(guardarBtn) })
|
||||
|
||||
const calledWith = processStoreMock.updateProcess.mock.calls[0][0]
|
||||
expect(calledWith.analysisHorizonYears).toBe(3)
|
||||
expect(calledWith.analysisHorizonYears).toBeGreaterThanOrEqual(1)
|
||||
expect(calledWith.analysisHorizonYears).toBeLessThanOrEqual(10)
|
||||
})
|
||||
|
||||
it('editar inversión en automatización y guardar la incluye correctamente', async () => {
|
||||
renderPanel()
|
||||
const investInput = screen.getByLabelText(/Inversión en automatización/i)
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(investInput, { target: { value: '75000' } })
|
||||
})
|
||||
|
||||
const guardarBtn = await screen.findByRole('button', { name: /Guardar/i })
|
||||
await act(async () => { fireEvent.click(guardarBtn) })
|
||||
|
||||
const calledWith = processStoreMock.updateProcess.mock.calls[0][0]
|
||||
expect(calledWith.automationInvestment).toBe(75000)
|
||||
})
|
||||
|
||||
it('sección "ANÁLISIS DE IMPACTO" aparece con su label de sección', () => {
|
||||
renderPanel()
|
||||
expect(screen.getByText(/Análisis de Impacto/i)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user