57 lines
3.5 KiB
PHP
57 lines
3.5 KiB
PHP
<?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();
|
|
});
|