Commit inicial - upload de todos os arquivos da pasta

This commit is contained in:
2026-06-13 17:32:41 -03:00
commit 759e2663ec
311 changed files with 31868 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ClientContractItemCreatePage } from '../ClientContractItemCreatePage';
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
return {
...actual,
useNavigate: () => vi.fn(),
useParams: () => ({ id: 'cli-1' }),
};
});
vi.mock('../../../hooks/useClients', () => ({
useClient: () => ({ data: { id: 'cli-1', name: 'Cliente A' } }),
}));
vi.mock('../../../hooks/useBreadcrumbs', () => ({
useBreadcrumbs: () => [{ label: 'Dashboard', to: '/' }],
}));
vi.mock('../../../components/ui/Toast', () => ({
useToast: () => ({ showToast: vi.fn() }),
}));
vi.mock('../../../hooks/usePageTitle', () => ({
usePageTitle: () => ({ setPageTitle: vi.fn() }),
}));
vi.mock('../../../services/contract-items.service', () => ({
createContractItem: vi.fn(),
}));
function renderPage() {
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
return render(
<QueryClientProvider client={client}>
<MemoryRouter>
<ClientContractItemCreatePage />
</MemoryRouter>
</QueryClientProvider>,
);
}
describe('ClientContractItemCreatePage', () => {
it('renderiza select de tipo e branch UST com timeboxes por padrão', () => {
renderPage();
expect(screen.getByText('Tipo do item')).toBeInTheDocument();
expect(screen.getByText('Total UST')).toBeInTheDocument();
expect(screen.getByText('Descoberta (h/semana)')).toBeInTheDocument();
expect(screen.getByText('Design (h/semana)')).toBeInTheDocument();
});
it('alterna para SAAS_LICENSE escondendo timeboxes e mostrando Quantidade + Valor unitário', async () => {
const user = userEvent.setup();
const { container } = renderPage();
const typeSelect = container.querySelector<HTMLSelectElement>('select[name="itemType"]')!;
await user.selectOptions(typeSelect, 'SAAS_LICENSE');
expect(screen.getByText('Quantidade')).toBeInTheDocument();
expect(screen.getByText('Valor unitário (R$)')).toBeInTheDocument();
expect(screen.queryByText('Descoberta (h/semana)')).not.toBeInTheDocument();
expect(screen.queryByText('Design (h/semana)')).not.toBeInTheDocument();
expect(screen.queryByText('Arquitetura (h/semana)')).not.toBeInTheDocument();
expect(screen.queryByText('Construção (h/semana)')).not.toBeInTheDocument();
});
it('Zod bloqueia submit SAAS sem ustValue', async () => {
const user = userEvent.setup();
const { container } = renderPage();
const typeSelect = container.querySelector<HTMLSelectElement>('select[name="itemType"]')!;
await user.selectOptions(typeSelect, 'SAAS_LICENSE');
await user.type(container.querySelector<HTMLInputElement>('input[name="code"]')!, 'IC-1');
await user.type(container.querySelector<HTMLInputElement>('input[name="name"]')!, 'Licença');
await user.type(container.querySelector<HTMLInputElement>('input[name="totalUst"]')!, '10');
await user.click(screen.getByRole('button', { name: /Salvar/i }));
const errorMessages = await screen.findAllByText(/obrigatório/i);
expect(errorMessages.length).toBeGreaterThan(0);
});
});

View File

@@ -0,0 +1,93 @@
import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ClientContractItemEditPage } from '../ClientContractItemEditPage';
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
return {
...actual,
useNavigate: () => vi.fn(),
useParams: () => ({ id: 'cli-1', itemId: 'item-1' }),
};
});
vi.mock('../../../hooks/useClients', () => ({
useClient: () => ({ data: { id: 'cli-1', name: 'Cliente A' } }),
}));
vi.mock('../../../hooks/useBreadcrumbs', () => ({
useBreadcrumbs: () => [{ label: 'Dashboard', to: '/' }],
}));
vi.mock('../../../components/ui/Toast', () => ({
useToast: () => ({ showToast: vi.fn() }),
}));
vi.mock('../../../hooks/usePageTitle', () => ({
usePageTitle: () => ({ setPageTitle: vi.fn() }),
}));
vi.mock('../../../services/contract-items.service', () => ({
updateContractItem: vi.fn(),
}));
const useContractItemMock = vi.fn();
vi.mock('../../../hooks/useContractItems', () => ({
useContractItem: (...args: unknown[]) => useContractItemMock(...args),
}));
function renderPage() {
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
return render(
<QueryClientProvider client={client}>
<MemoryRouter>
<ClientContractItemEditPage />
</MemoryRouter>
</QueryClientProvider>,
);
}
describe('ClientContractItemEditPage', () => {
it('mantém select de tipo desabilitado em modo edit', () => {
useContractItemMock.mockReturnValue({
data: {
id: 'item-1',
code: 'IC-1',
name: 'Item',
description: '',
itemType: 'UST',
totalUst: 1000,
ustValue: 100,
timeboxDescoberta: null,
timeboxDesign: null,
timeboxArquitetura: null,
timeboxConstrucao: null,
},
isLoading: false,
});
const { container } = renderPage();
const select = container.querySelector<HTMLSelectElement>('select[name="itemType"]')!;
expect(select).toBeDisabled();
});
it('hidrata branch SAAS_LICENSE com Quantidade e Valor unitário sem timeboxes', () => {
useContractItemMock.mockReturnValue({
data: {
id: 'item-1',
code: 'IC-2',
name: 'Licença',
description: '',
itemType: 'SAAS_LICENSE',
totalUst: 50,
ustValue: 200,
},
isLoading: false,
});
renderPage();
expect(screen.getByText('Quantidade')).toBeInTheDocument();
expect(screen.getByText('Valor unitário (R$)')).toBeInTheDocument();
expect(screen.queryByText('Descoberta (h/semana)')).not.toBeInTheDocument();
});
});