@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\PurchasingRole;
|
||||
use App\Models\User;
|
||||
use App\Services\AiPreparationPlan;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
|
||||
require_once __DIR__.'/../Support/ReceiptFixture.php';
|
||||
require_once __DIR__.'/../Support/AiPlanFixture.php';
|
||||
|
||||
beforeEach(function () {
|
||||
$this->f = receiptFixture();
|
||||
$this->actingAs($this->f['issuer']);
|
||||
Http::fake();
|
||||
});
|
||||
|
||||
function prepareAiPlan(object $test, array $changes = []): void
|
||||
{
|
||||
$plan = app(AiPreparationPlan::class)->checked([...aiPlanInput(), ...$changes]);
|
||||
$test->f['tenant']->update(['intelligence_policy' => ['revision' => 1, 'configured' => true, 'procurement_brief' => false, 'people_brief' => true, 'ai_plan' => $plan]]);
|
||||
}
|
||||
|
||||
test('AI preparation filters facts by scope preserves the report and exposes no company budget or source hashes', function () {
|
||||
prepareAiPlan($this, ['data_scopes' => ['process_state']]);
|
||||
$this->get('/requisicoes/'.$this->f['r']->id.'/relatorio')->assertOk()->assertInertia(fn (Assert $page) => $page
|
||||
->where('brief', null)->where('report.requisition.id', $this->f['r']->id)->where('aiPreparation.status', 'draft')
|
||||
->where('aiPreparation.external_execution_enabled', false)->where('aiPreparation.usage_checked', false)
|
||||
->has('aiPreparation.facts', 1)->where('aiPreparation.facts.0.id', 'request')
|
||||
->missing('aiPreparation.monthly_budget_usd')->missing('aiPreparation.facts.0.basis_sha256'));
|
||||
Http::assertNotSent(fn ($request) => ! in_array(parse_url($request->url(), PHP_URL_HOST), ['127.0.0.1', 'localhost'], true));
|
||||
});
|
||||
|
||||
test('AI preparation respects financial access even when finance is allowed in the organisation plan', function () {
|
||||
prepareAiPlan($this, ['data_scopes' => ['financial_counts']]);
|
||||
$this->get('/requisicoes/'.$this->f['r']->id.'/relatorio')->assertInertia(fn (Assert $page) => $page->where('aiPreparation.status', 'no_permitted_facts')->where('aiPreparation.facts', []));
|
||||
$finance = User::factory()->create(['tenant_id' => $this->f['tenant']->id, 'purchasing_role' => PurchasingRole::Finance]);
|
||||
$this->actingAs($finance)->get('/requisicoes/'.$this->f['r']->id.'/relatorio')->assertInertia(fn (Assert $page) => $page->where('aiPreparation.facts.0.id', 'finance')->has('aiPreparation.facts', 1));
|
||||
Http::assertNotSent(fn ($request) => ! in_array(parse_url($request->url(), PHP_URL_HOST), ['127.0.0.1', 'localhost'], true));
|
||||
});
|
||||
|
||||
test('AI preparation rejects an excluded domain and never truncates a payload to make it fit', function () {
|
||||
prepareAiPlan($this, ['domains' => ['people']]);
|
||||
$this->get('/requisicoes/'.$this->f['r']->id.'/relatorio')->assertInertia(fn (Assert $page) => $page->where('aiPreparation.status', 'outside_scope')->where('aiPreparation.facts', []));
|
||||
prepareAiPlan($this, ['data_scopes' => array_keys(AiPreparationPlan::SCOPES), 'max_input_bytes' => 512]);
|
||||
$this->get('/requisicoes/'.$this->f['r']->id.'/relatorio')->assertInertia(fn (Assert $page) => $page->where('aiPreparation.status', 'input_exceeds_limit')->where('aiPreparation.facts', [])
|
||||
->where('aiPreparation.input_bytes', fn ($bytes) => $bytes > 512));
|
||||
Http::assertNotSent(fn ($request) => ! in_array(parse_url($request->url(), PHP_URL_HOST), ['127.0.0.1', 'localhost'], true));
|
||||
});
|
||||
|
||||
test('AI preparation cannot disclose another company report or query an external provider', function () {
|
||||
$other = receiptFixture();
|
||||
prepareAiPlan($this);
|
||||
$this->actingAs($this->f['issuer'])->get('/requisicoes/'.$other['r']->id.'/relatorio')->assertNotFound();
|
||||
Http::assertNothingSent();
|
||||
});
|
||||
Reference in New Issue
Block a user