CRM/backend/tests/Feature/QualityScriptAuthorizationT...

140 خطوط
5.2 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Call;
use App\Models\Lead;
use App\Models\QualityReview;
use App\Models\SalesScript;
use App\Models\Team;
use App\Models\User;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class QualityScriptAuthorizationTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->seed(RolePermissionSeeder::class);
}
public function test_quality_review_derives_agent_from_call_and_versions_reviews(): void
{
[$supervisor, $agent] = $this->team();
$otherAgent = $this->user('agent');
$call = $this->makeCall($agent);
$first = $this->actingAs($supervisor)->postJson('/api/quality-reviews', $this->reviewPayload($call, [
'agent_id' => $otherAgent->id,
'is_shared_with_agent' => false,
]))->assertCreated();
$this->assertSame($agent->id, $first->json('agent_id'));
$this->assertSame(1, $first->json('version'));
$second = $this->actingAs($supervisor)->postJson('/api/quality-reviews', $this->reviewPayload($call, [
'is_shared_with_agent' => true,
]))->assertCreated();
$this->assertSame(2, $second->json('version'));
$this->assertFalse(QualityReview::findOrFail($first->json('id'))->is_current);
$this->assertTrue(QualityReview::findOrFail($second->json('id'))->is_current);
}
public function test_agent_only_sees_shared_own_review_and_cannot_create_one(): void
{
[$supervisor, $agent] = $this->team();
$call = $this->makeCall($agent);
$review = $this->actingAs($supervisor)->postJson('/api/quality-reviews', $this->reviewPayload($call, [
'is_shared_with_agent' => false,
]))->assertCreated()->json();
$this->actingAs($agent)->getJson("/api/quality-reviews/{$review['id']}")->assertForbidden();
$this->actingAs($agent)->postJson('/api/quality-reviews', $this->reviewPayload($call))->assertForbidden();
$this->actingAs($supervisor)->putJson("/api/quality-reviews/{$review['id']}", ['is_shared_with_agent' => true])->assertOk();
$this->actingAs($agent)->getJson("/api/quality-reviews/{$review['id']}")->assertOk();
}
public function test_sales_scripts_are_transactional_and_agents_only_see_active_scripts(): void
{
[$supervisor, $agent] = $this->team();
$scriptId = $this->actingAs($supervisor)->postJson('/api/scripts', [
'title' => 'Outbound sales',
'description' => 'Approved script',
'is_active' => true,
'assigned_user_ids' => [$agent->id],
'sections' => [
['title' => 'Greeting', 'content' => 'Hello', 'sort_order' => 0],
['title' => 'Discovery', 'content' => 'Ask questions', 'sort_order' => 1],
],
])->assertCreated()->json('id');
$this->assertDatabaseHas('script_sections', ['sales_script_id' => $scriptId, 'sort_order' => 0]);
$this->actingAs($agent)->getJson("/api/scripts/{$scriptId}")->assertOk();
$this->actingAs($agent)->postJson('/api/scripts', ['title' => 'Unauthorized'])->assertForbidden();
SalesScript::whereKey($scriptId)->update(['is_active' => false]);
$this->actingAs($agent)->getJson("/api/scripts/{$scriptId}")->assertForbidden();
$this->actingAs($supervisor)->postJson('/api/scripts', [
'title' => 'Invalid script',
'sections' => [['title' => 'Missing content']],
])->assertUnprocessable();
$this->assertDatabaseMissing('sales_scripts', ['title' => 'Invalid script']);
}
private function reviewPayload(Call $call, array $overrides = []): array
{
return array_merge([
'call_id' => $call->id,
'greeting_score' => 80,
'product_intro_score' => 75,
'needs_discovery_score' => 70,
'objection_handling_score' => 65,
'closing_score' => 60,
'crm_accuracy_score' => 90,
'follow_up_quality_score' => 85,
'feedback' => 'Useful feedback',
], $overrides);
}
private function team(): array
{
$supervisor = $this->user('supervisor');
$agent = $this->user('agent');
$team = Team::create(['name' => 'Sales Team', 'supervisor_id' => $supervisor->id, 'is_active' => true]);
$supervisor->teams()->attach($team);
$agent->teams()->attach($team);
return [$supervisor, $agent];
}
private function makeCall(User $agent): Call
{
$lead = Lead::create([
'company' => 'Call Company',
'first_name' => 'Sara',
'last_name' => 'Ahmadi',
'phone' => fake()->unique()->numerify('021########'),
'assigned_to' => $agent->id,
'is_unassigned' => false,
]);
return Call::create(['lead_id' => $lead->id, 'user_id' => $agent->id, 'direction' => 'outbound', 'phone' => $lead->phone]);
}
private function user(string $role): User
{
$user = User::factory()->create(['is_active' => true]);
$user->assignRole($role);
return $user;
}
}