test(backend): add comprehensive tests for reporting and allocation
Add test coverage for: - ReportTest: 9 tests for reporting API (payload, view types, filters, validation) - ProjectMonthPlanTest: CRUD operations for monthly planning - UntrackedAllocationTest: untracked allocation handling - ReconciliationCalculatorTest: plan vs estimate reconciliation logic - VarianceCalculatorTest: variance and status calculations All tests passing (157 total).
This commit is contained in:
134
backend/tests/Feature/ProjectMonthPlanTest.php
Normal file
134
backend/tests/Feature/ProjectMonthPlanTest.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectMonthPlan;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProjectMonthPlanTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function loginAsManager()
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
'email' => 'manager@test.com',
|
||||
'password' => bcrypt('password123'),
|
||||
'role' => 'manager',
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$response = $this->postJson('/api/auth/login', [
|
||||
'email' => 'manager@test.com',
|
||||
'password' => 'password123',
|
||||
]);
|
||||
|
||||
return $response->json('access_token');
|
||||
}
|
||||
|
||||
public function test_bulk_update_creates_new_plan_records(): void
|
||||
{
|
||||
$token = $this->loginAsManager();
|
||||
$project = Project::factory()->create();
|
||||
|
||||
$response = $this->withHeader('Authorization', "Bearer {$token}")
|
||||
->putJson('/api/project-month-plans/bulk', [
|
||||
'year' => 2026,
|
||||
'items' => [
|
||||
[
|
||||
'project_id' => $project->id,
|
||||
'month' => '2026-01',
|
||||
'planned_hours' => 100,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function test_validation_rejects_invalid_data(): void
|
||||
{
|
||||
$token = $this->loginAsManager();
|
||||
|
||||
$response = $this->withHeader('Authorization', "Bearer {$token}")
|
||||
->putJson('/api/project-month-plans/bulk', [
|
||||
'year' => 2026,
|
||||
'items' => [
|
||||
[
|
||||
'project_id' => 'invalid-uuid',
|
||||
'month' => '2026-01',
|
||||
'planned_hours' => 100,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
|
||||
public function test_index_returns_existing_plan_for_month(): void
|
||||
{
|
||||
$token = $this->loginAsManager();
|
||||
$project = Project::factory()->create();
|
||||
|
||||
ProjectMonthPlan::create([
|
||||
'project_id' => $project->id,
|
||||
'month' => '2026-02-01',
|
||||
'planned_hours' => 50,
|
||||
]);
|
||||
|
||||
$projectData = $this->fetchProjectPlan($token, $project);
|
||||
|
||||
$this->assertNotNull($projectData['months']['2026-02-01']);
|
||||
}
|
||||
|
||||
public function test_index_returns_null_for_missing_month(): void
|
||||
{
|
||||
$token = $this->loginAsManager();
|
||||
$project = Project::factory()->create();
|
||||
|
||||
$projectData = $this->fetchProjectPlan($token, $project);
|
||||
|
||||
$this->assertNull($projectData['months']['2026-03-01']);
|
||||
}
|
||||
|
||||
public function test_bulk_update_roundtrip_populates_month(): void
|
||||
{
|
||||
$token = $this->loginAsManager();
|
||||
$project = Project::factory()->create();
|
||||
|
||||
$this->withHeader('Authorization', "Bearer {$token}")
|
||||
->putJson('/api/project-month-plans/bulk', [
|
||||
'year' => 2026,
|
||||
'items' => [
|
||||
[
|
||||
'project_id' => $project->id,
|
||||
'month' => '2026-02',
|
||||
'planned_hours' => 72,
|
||||
],
|
||||
],
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$projectData = $this->fetchProjectPlan($token, $project);
|
||||
|
||||
$this->assertNotNull($projectData['months']['2026-02-01']);
|
||||
$this->assertEquals(72, $projectData['plan_sum']);
|
||||
}
|
||||
|
||||
private function fetchProjectPlan(string $token, Project $project): array
|
||||
{
|
||||
$response = $this->withHeader('Authorization', "Bearer {$token}")
|
||||
->getJson('/api/project-month-plans?year=2026');
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$projectData = collect($response->json('data'))->firstWhere('project_id', $project->id);
|
||||
|
||||
$this->assertNotNull($projectData);
|
||||
|
||||
return $projectData;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user