create(); $investigation = Investigation::factory()->for($user, 'owner')->create(); $this->actingAs($user) ->get(route('investigations.report', $investigation)) ->assertOk() ->assertSee($investigation->name); } public function test_unrelated_user_cannot_view_report(): void { $user = User::factory()->create(); $stranger = User::factory()->create(); $investigation = Investigation::factory()->for($user, 'owner')->create(); $this->actingAs($stranger) ->get(route('investigations.report', $investigation)) ->assertForbidden(); } public function test_csv_export_contains_finding_rows(): void { $user = User::factory()->create(); $investigation = Investigation::factory()->for($user, 'owner')->create(); $target = $investigation->targets()->create(['type' => 'username', 'value' => 'someone', 'created_by' => $user->id]); $source = \App\Models\Source::create([ 'key' => 'test-source', 'name' => 'Test Source', 'target_types' => ['username'], 'enabled' => true, ]); $target->findings()->create([ 'source_id' => $source->id, 'status' => 'completed', 'summary' => 'Found it', ]); $response = $this->actingAs($user)->get(route('investigations.export.csv', $investigation)); $response->assertOk(); $response->assertHeader('Content-Type', 'text/csv; charset=UTF-8'); $this->assertStringContainsString('Test Source', $response->getContent()); $this->assertStringContainsString('Found it', $response->getContent()); } public function test_csv_export_neutralizes_formula_injection_in_target_value(): void { $user = User::factory()->create(); $investigation = Investigation::factory()->for($user, 'owner')->create(); $target = $investigation->targets()->create(['type' => 'person', 'value' => 'safe name', 'created_by' => $user->id]); $source = \App\Models\Source::create([ 'key' => 'test-source', 'name' => 'Test Source', 'target_types' => ['person'], 'enabled' => true, ]); $target->findings()->create([ 'source_id' => $source->id, 'status' => 'completed', 'summary' => '=cmd|"/c calc"!A1', ]); $response = $this->actingAs($user)->get(route('investigations.export.csv', $investigation)); $this->assertStringContainsString("'=cmd", $response->getContent()); } public function test_json_export_includes_targets_and_findings(): void { $user = User::factory()->create(); $investigation = Investigation::factory()->for($user, 'owner')->create(); $investigation->targets()->create(['type' => 'domain', 'value' => 'example.com', 'created_by' => $user->id]); $response = $this->actingAs($user)->get(route('investigations.export.json', $investigation)); $response->assertOk(); $response->assertJsonPath('targets.0.value', 'example.com'); } }