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:
@@ -198,3 +198,81 @@ test.describe('Capacity Planning - Phase 1 Tests (RED)', () => {
|
||||
await expect(cell).toContainText('Full day');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Expert Mode E2E Tests', () => {
|
||||
let authToken: string;
|
||||
let mainMemberId: string;
|
||||
let createdMembers: string[] = [];
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
createdMembers = [];
|
||||
await login(page);
|
||||
authToken = await getAccessToken(page);
|
||||
await setPeriod(page, '2026-02');
|
||||
const member = await createTeamMember(page, authToken);
|
||||
mainMemberId = member.id;
|
||||
createdMembers.push(mainMemberId);
|
||||
await goToCapacity(page);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
for (const memberId of createdMembers.splice(0)) {
|
||||
await page.request.delete(`${API_BASE}/api/team-members/${memberId}`, {
|
||||
headers: { Authorization: `Bearer ${authToken}` }
|
||||
}).catch(() => null);
|
||||
}
|
||||
});
|
||||
|
||||
test.fixme('11.1 Expert Mode toggle appears on Capacity page and persists after reload', async ({ page }) => {
|
||||
await expect(page.getByLabel('Toggle Expert Mode')).toBeVisible();
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
await expect(page.getByLabel('Toggle Expert Mode')).toBeChecked();
|
||||
await page.reload();
|
||||
await expect(page.getByLabel('Toggle Expert Mode')).toBeChecked();
|
||||
});
|
||||
|
||||
test.fixme('11.2 Grid renders all team members as rows for selected month', async ({ page }) => {
|
||||
const extra = await createTeamMember(page, authToken, { name: 'Expert Mode Tester' });
|
||||
createdMembers.push(extra.id);
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
await expect(page.getByRole('row', { name: /Capacity Tester/ })).toBeVisible();
|
||||
await expect(page.getByRole('row', { name: /Expert Mode Tester/ })).toBeVisible();
|
||||
});
|
||||
|
||||
test.fixme('11.3 Typing invalid token shows red cell and disables Submit', async ({ page }) => {
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
|
||||
await cell.fill('invalid');
|
||||
await cell.blur();
|
||||
await expect(cell).toHaveClass(/border-error/);
|
||||
await expect(page.getByRole('button', { name: /Submit/ })).toBeDisabled();
|
||||
});
|
||||
|
||||
test.fixme('11.4 Typing valid tokens and clicking Submit saves and shows success toast', async ({ page }) => {
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
|
||||
await cell.fill('0.5');
|
||||
await cell.blur();
|
||||
await expect(page.getByRole('button', { name: /Submit/ })).toBeEnabled();
|
||||
await page.getByRole('button', { name: /Submit/ }).click();
|
||||
await expect(page.getByText(/saved/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test.fixme('11.5 KPI bar updates when cell value changes', async ({ page }) => {
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
|
||||
await cell.fill('0.5');
|
||||
await cell.blur();
|
||||
await expect(page.getByText(/Capacity:/)).toBeVisible();
|
||||
await expect(page.getByText(/Revenue:/)).toBeVisible();
|
||||
});
|
||||
|
||||
test.fixme('11.6 Switching off Expert Mode with dirty cells shows confirmation dialog', async ({ page }) => {
|
||||
await page.getByLabel('Toggle Expert Mode').check();
|
||||
const cell = page.getByRole('textbox', { name: /2026-02-03/ }).first();
|
||||
await cell.fill('0.5');
|
||||
await cell.blur();
|
||||
await page.getByLabel('Toggle Expert Mode').uncheck();
|
||||
await expect(page.getByRole('dialog')).toContainText('unsaved changes');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user