feat(allocation): implement resource allocation feature
- Add AllocationController with CRUD + bulk endpoints - Add AllocationValidationService for capacity/estimate validation - Add AllocationMatrixService for optimized matrix queries - Add AllocationPolicy for authorization - Add AllocationResource for API responses - Add frontend allocationService and matrix UI - Add E2E tests for allocation matrix (20 tests) - Add unit tests for validation service and policies - Fix month format conversion (YYYY-MM to YYYY-MM-01)
This commit is contained in:
116
frontend/tests/unit/capacity-components.test.ts
Normal file
116
frontend/tests/unit/capacity-components.test.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/svelte';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import CapacityCalendar from '$lib/components/capacity/CapacityCalendar.svelte';
|
||||
import CapacitySummary from '$lib/components/capacity/CapacitySummary.svelte';
|
||||
import type { Capacity, Revenue, TeamCapacity } from '$lib/types/capacity';
|
||||
|
||||
describe('capacity components', () => {
|
||||
it('4.1.25 CapacityCalendar displays selected month', () => {
|
||||
const capacity: Capacity = {
|
||||
team_member_id: 'member-1',
|
||||
month: '2026-02',
|
||||
working_days: 20,
|
||||
person_days: 20,
|
||||
hours: 160,
|
||||
details: [
|
||||
{
|
||||
date: '2026-02-02',
|
||||
day_of_week: 1,
|
||||
is_weekend: false,
|
||||
is_holiday: false,
|
||||
is_pto: false,
|
||||
availability: 1,
|
||||
effective_hours: 8
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
render(CapacityCalendar, {
|
||||
props: {
|
||||
month: '2026-02',
|
||||
capacity,
|
||||
holidays: [],
|
||||
ptos: []
|
||||
}
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('capacity-calendar')).toBeTruthy();
|
||||
expect(screen.getByText('2026-02')).toBeTruthy();
|
||||
expect(screen.getByText('Working days: 20')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('4.1.26 Availability editor toggles values', async () => {
|
||||
const capacity: Capacity = {
|
||||
team_member_id: 'member-1',
|
||||
month: '2026-02',
|
||||
working_days: 20,
|
||||
person_days: 20,
|
||||
hours: 160,
|
||||
details: [
|
||||
{
|
||||
date: '2026-02-10',
|
||||
day_of_week: 2,
|
||||
is_weekend: false,
|
||||
is_holiday: false,
|
||||
is_pto: false,
|
||||
availability: 1,
|
||||
effective_hours: 8
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
render(CapacityCalendar, {
|
||||
props: {
|
||||
month: '2026-02',
|
||||
capacity,
|
||||
holidays: [],
|
||||
ptos: []
|
||||
}
|
||||
});
|
||||
|
||||
const select = screen.getByLabelText('Availability for 2026-02-10') as HTMLSelectElement;
|
||||
expect(select.value).toBe('1');
|
||||
|
||||
await fireEvent.change(select, { target: { value: '0.5' } });
|
||||
|
||||
expect(select.value).toBe('0.5');
|
||||
});
|
||||
|
||||
it('4.1.27 CapacitySummary shows totals', () => {
|
||||
const teamCapacity: TeamCapacity = {
|
||||
month: '2026-02',
|
||||
total_person_days: 57,
|
||||
total_hours: 456,
|
||||
member_capacities: [
|
||||
{
|
||||
team_member_id: 'm1',
|
||||
team_member_name: 'VJ',
|
||||
role: 'Frontend Dev',
|
||||
person_days: 19,
|
||||
hours: 152,
|
||||
hourly_rate: 80
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const revenue: Revenue = {
|
||||
month: '2026-02',
|
||||
total_revenue: 45600,
|
||||
member_revenues: []
|
||||
};
|
||||
|
||||
render(CapacitySummary, {
|
||||
props: {
|
||||
teamCapacity,
|
||||
revenue,
|
||||
teamMembers: []
|
||||
}
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('team-capacity-card')).toBeTruthy();
|
||||
expect(screen.getByTestId('possible-revenue-card')).toBeTruthy();
|
||||
expect(screen.getByText('57.0d')).toBeTruthy();
|
||||
expect(screen.getByText('456 hrs')).toBeTruthy();
|
||||
expect(screen.getByText('$45,600.00')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user