feat: explore the public opportunity catalogue by corridor
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-10-23 12:08:33 +02:00
parent 165c2f6171
commit 203492997e
9 changed files with 201 additions and 7 deletions
@@ -0,0 +1,30 @@
<?php
namespace Tests\Feature;
use Illuminate\Support\Facades\DB;
use Inertia\Testing\AssertableInertia as Assert;
use Tests\TestCase;
class OpportunityCorridorExplorerTest extends TestCase
{
public function test_the_public_agribusiness_catalogue_groups_all_34_records_without_page_truncation(): void
{
$target = DB::selectOne('select current_database() as name, inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
$this->withoutVite();
$this->get('/oportunidades?sector=agronegocio&view=corridors')->assertOk()->assertInertia(fn (Assert $page) => $page
->component('investment/catalogue')
->has('corridorGroups', 6)
->where('results.total', 34)
->where('corridorGroups', function ($groups) {
$groups = collect($groups);
$ids = $groups->flatMap(fn ($g) => collect($g['opportunities'])->pluck('id'));
return $ids->count() === 34 && $ids->unique()->count() === 34
&& $groups->pluck('count', 'name')->get('Corredor da Beira') === 7
&& $groups->pluck('count', 'name')->get('Corredor de Maputo') === 5
&& ! str_contains(json_encode($groups), 'source_sha256');
}));
}
}
@@ -0,0 +1,36 @@
<?php
namespace Tests\Unit;
use App\Models\Opportunity;
use App\Services\InvestmentCatalogue;
use App\Services\OpportunityCorridorExplorer;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Mockery;
use Tests\TestCase;
class OpportunityCorridorExplorerTest extends TestCase
{
public function test_multiple_groups_keep_one_identity_and_unassociated_records_remain_accessible(): void
{
$first = new Opportunity(['title' => 'Primeira', 'province' => 'Sofala', 'district' => 'Dondo']);
$first->id = 101;
$other = new Opportunity(['title' => 'Outra']); $other->id = 102;
$query = Mockery::mock(Builder::class);
$query->shouldReceive('get')->once()->andReturn(new Collection([$first, $other]));
$catalogue = Mockery::mock(InvestmentCatalogue::class);
$filters = ['sector' => 'agronegocio', 'view' => 'corridors'];
$catalogue->shouldReceive('query')->with($filters)->once()->andReturn($query);
$catalogue->shouldReceive('context')->with(101)->once()->andReturn(['corridors' => collect([(object)['id'=>'a','name'=>'Corredor A'],(object)['id'=>'b','name'=>'Corredor B']])]);
$catalogue->shouldReceive('context')->with(102)->once()->andReturn(['corridors'=>collect()]);
$this->app->instance(InvestmentCatalogue::class, $catalogue);
$groups = app(OpportunityCorridorExplorer::class)->groups($filters);
$this->assertSame(['Corredor A','Corredor B','Outras localizações'], array_column($groups,'name'));
$this->assertSame([101,101,102], array_map(fn($g)=>$g['opportunities'][0]['id'], $groups));
$this->assertSame([1,1,1], array_column($groups,'count'));
$this->assertSame(['Sofala / Dondo'], $groups[0]['locations']);
$this->assertSame([], $groups[2]['locations']);
$this->assertSame([], $groups[0]['opportunities'][0]['stages']);
}
}