Files
compras/tests/Feature/PublicNavigationTest.php
2026-10-30 20:14:24 +02:00

83 lines
4.3 KiB
PHP

<?php
use App\Enums\PurchasingRole;
use App\Models\Tenant;
use App\Models\User;
use App\Services\PublicNavigation;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Inertia\Testing\AssertableInertia as Assert;
beforeEach(function () {
config(['public_navigation.enabled' => true]);
$this->withoutVite();
});
test('anonymous visitors enter the real dashboard without creating an authenticated identity', function () {
$this->get('/')->assertRedirect('/dashboard');
$this->get('/dashboard')->assertInertia(fn (Assert $p) => $p->component('dashboard')->where('auth.user', null)->where('company', null)->where('stats.total', 0)->where('publicNavigation.dataScope', 'none'));
$this->assertGuest('web');
expect(User::query()->count())->toBe(0);
});
test('all allowlisted real screens support direct anonymous navigation without business queries', function () {
$queries = [];
DB::listen(function ($query) use (&$queries) {
$queries[] = $query->sql;
});
$fixtures = [];
foreach (PublicNavigation::PAGES as $path => $component) {
$response = $this->get($path)->assertOk()->assertInertia(fn (Assert $p) => $p->component($component)->where('auth.user', null));
$fixtures[$component] = $response->original->getData()['page'];
$this->assertGuest('web');
}
expect($queries)->toBe([]);
file_put_contents(storage_path('app/private/public-navigation-fixtures.json'), json_encode($fixtures, JSON_THROW_ON_ERROR));
});
test('anonymous searches pagination and filters stay empty and never select either organisation', function () {
foreach (['Empresa reservada A', 'Empresa reservada B'] as $name) {
$tenant = Tenant::query()->create(['name' => $name]);
User::factory()->create(['tenant_id' => $tenant->id, 'name' => 'Nome confidencial']);
}
$this->get('/requisicoes?search=Empresa&page=2&status=pending')->assertInertia(fn (Assert $p) => $p->where('filters.search', 'Empresa')->where('requisitions.data', [])->where('requisitions.current_page', 2))->assertDontSee('Nome confidencial')->assertDontSee('Empresa reservada');
$this->get('/stock?search=Nome&warehouse_id=1')->assertInertia(fn (Assert $p) => $p->where('items', [])->where('filters.search', 'Nome'));
});
test('sensitive records access settings exports and every business write remain authenticated', function () {
foreach (['/pessoas/cadastro', '/pessoas/1', '/fornecedores/1/dados-bancarios', '/administracao/parametrizacao', '/relatorios', '/relatorios/compras.csv', '/settings/profile'] as $path) {
$this->get($path)->assertRedirect();
}
$this->get('/api/supplier-payables')->assertUnauthorized();
foreach (['/requisicoes', '/pessoas', '/stock/artigos', '/administracao/parametrizacao/tax'] as $path) {
$this->postJson($path, [])->assertUnauthorized();
}
});
test('authenticated sessions retain their original controllers and permissions and disabled mode remains private', function () {
$tenant = Tenant::query()->create(['name' => 'Empresa autenticada']);
$user = User::factory()->create(['tenant_id' => $tenant->id, 'purchasing_role' => PurchasingRole::Requester]);
$this->actingAs($user)->get('/dashboard')->assertInertia(fn (Assert $p) => $p->where('company.name', 'Empresa autenticada')->missing('publicNavigation'));
$this->get('/administracao/parametrizacao')->assertForbidden();
auth()->logout();
config(['public_navigation.enabled' => false]);
$this->get('/dashboard')->assertRedirect();
});
test('every authenticated mutation route remains inaccessible to an anonymous visitor', function () {
$checked = 0;
foreach (Route::getRoutes() as $route) {
if (! collect($route->gatherMiddleware())->contains(fn ($middleware) => $middleware === 'auth' || str_starts_with($middleware, 'auth:'))) {
continue;
}
$uri = '/'.preg_replace('/\{[^}]+\}/', '1', $route->uri());
foreach (array_intersect($route->methods(), ['POST', 'PUT', 'PATCH', 'DELETE']) as $method) {
$response = $this->json($method, $uri, []);
expect(in_array($response->status(), [401, 404], true))->toBeTrue($method.' '.$uri.' must remain protected');
$checked++;
}
}
expect($checked)->toBeGreaterThan(50);
$this->assertGuest('web');
});