161 lines
8.5 KiB
PHP
161 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\InterestRequest;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
use Tests\TestCase;
|
|
|
|
class BusinessMarketplacePublicTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
config(['existing-business.enabled' => true]);
|
|
}
|
|
|
|
public function test_public_catalogue_and_detail_exclude_reserved_fields_and_locations(): void
|
|
{
|
|
$business = $this->publishedBusiness();
|
|
|
|
$this->getJson('/api/v1/business-opportunities')->assertOk()
|
|
->assertJsonPath('data.0.title', 'Public synthetic opportunity')
|
|
->assertJsonMissingPath('data.0.owner_user_id')
|
|
->assertJsonMissingPath('data.0.payload')
|
|
->assertJsonMissingPath('data.0.geom');
|
|
$this->getJson('/api/v1/business-opportunities/'.$business['public_slug'])->assertOk()
|
|
->assertJsonPath('data.title', 'Public synthetic opportunity')
|
|
->assertJsonMissingPath('data.payload')
|
|
->assertJsonMissingPath('data.owner_user_id');
|
|
}
|
|
|
|
public function test_interest_is_limited_to_published_business_and_deduplicated_idempotently(): void
|
|
{
|
|
$this->withoutVite();
|
|
config(['portal.notifications_enabled' => false]);
|
|
$business = $this->publishedBusiness();
|
|
$payload = [
|
|
'existingBusinessId' => $business['id'],
|
|
'modality' => 'company_sale',
|
|
'fullName' => 'Synthetic investor',
|
|
'email' => 'portal-integration-test@gmail.com',
|
|
'phone' => '+258 840000000',
|
|
'investorType' => 'empresa',
|
|
'country' => 'PT',
|
|
'declared_origin_country_code' => 'ZA',
|
|
'sectorInterest' => 'Energia',
|
|
'message' => 'Synthetic interest for the published business listing.',
|
|
'privacyConsent' => true,
|
|
];
|
|
$key = (string) Str::uuid();
|
|
$this->get('/negocios/'.$business['public_slug'].'/manifestar-interesse')->assertInertia(fn (Assert $p) => $p
|
|
->component('investment/business-interest')->has('countries', 249)->where('record.id', $business['id']));
|
|
$this->postJson('/api/v1/interest-requests', [...$payload, 'country' => 'ZZ'], ['Idempotency-Key' => (string) Str::uuid()])->assertUnprocessable();
|
|
$this->assertDatabaseCount('interest_requests', 0);
|
|
|
|
$first = $this->postJson('/api/v1/interest-requests', $payload, ['Idempotency-Key' => $key])->assertCreated();
|
|
$second = $this->postJson('/api/v1/interest-requests', $payload, ['Idempotency-Key' => $key])->assertCreated();
|
|
$this->assertSame($first->json(), $second->json());
|
|
$this->assertDatabaseHas('interest_requests', [
|
|
'existing_business_id' => $business['id'],
|
|
'modality' => 'company_sale',
|
|
'status' => 'received',
|
|
]);
|
|
$this->assertDatabaseCount('interest_requests', 1);
|
|
$this->assertDatabaseCount('outbox_events', 1);
|
|
|
|
$this->postJson('/api/v1/interest-requests', [...$payload, 'message' => 'Another valid message for this active interest.'])
|
|
->assertStatus(409);
|
|
$this->assertDatabaseCount('interest_requests', 1);
|
|
$interest = InterestRequest::firstOrFail();
|
|
$this->assertSame('PT', $interest->country);
|
|
$this->assertSame('ZA', $interest->metadata['declared_origin_country_code']);
|
|
$manager = User::factory()->create();
|
|
config(['portal.managers' => [$manager->email]]);
|
|
$this->actingAs($manager)->get('/management/interests/'.$interest->id)->assertInertia(fn (Assert $p) => $p
|
|
->where('interest.country', 'PT')->where('declaredOrigin.code', 'ZA'));
|
|
$this->get('/management/interests?country=PT&origin=ZA')->assertInertia(fn (Assert $p) => $p
|
|
->where('requests.total', 1)->where('originStatistics.interests.0.code', 'ZA')->where('originStatistics.interests.0.count', 1)
|
|
->has('originStatistics.businesses', 0));
|
|
$this->get('/management/interests?origin=PT')->assertInertia(fn (Assert $p) => $p->where('requests.total', 0)->has('originStatistics.interests', 0));
|
|
$this->actingAs(User::factory()->create())->get('/management/interests/'.$interest->id)->assertForbidden();
|
|
}
|
|
|
|
public function test_public_catalogue_filters_by_existing_opportunity_modality_and_opens_response_flow(): void
|
|
{
|
|
$business = $this->publishedBusiness('real_estate');
|
|
$companySale = $this->publishedBusiness('company_sale');
|
|
$landRight = $this->publishedBusiness('land_right');
|
|
|
|
$this->getJson('/api/v1/business-opportunities?modality=real_estate')->assertOk()
|
|
->assertJsonCount(1, 'data')->assertJsonPath('data.0.modality', 'real_estate');
|
|
$this->getJson('/api/v1/business-opportunities?modality=company_sale')->assertOk()
|
|
->assertJsonCount(1, 'data')->assertJsonPath('data.0.modality', 'company_sale');
|
|
$this->getJson('/api/v1/business-opportunities?modality=land_right')->assertOk()
|
|
->assertJsonCount(1, 'data')->assertJsonPath('data.0.modality', 'land_right');
|
|
|
|
$this->get('/negocios?modality=real_estate')->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-marketplace')
|
|
->where('filters.modality', 'real_estate')->has('results.data', 1));
|
|
$this->get('/negocios/'.$business['public_slug'])->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-opportunity')
|
|
->where('record.modality', 'real_estate'));
|
|
$this->get('/negocios/'.$business['public_slug'].'/manifestar-interesse')->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-interest')
|
|
->where('record.modality', 'real_estate'));
|
|
$this->get('/negocios?modality=company_sale')->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-marketplace')
|
|
->where('filters.modality', 'company_sale')->has('results.data', 1));
|
|
$this->get('/negocios/'.$companySale['public_slug'])->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-opportunity')
|
|
->where('record.modality', 'company_sale'));
|
|
$this->get('/negocios?modality=land_right')->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-marketplace')
|
|
->where('filters.modality', 'land_right')->has('results.data', 1));
|
|
$this->get('/negocios/'.$landRight['public_slug'])->assertOk()
|
|
->assertInertia(fn ($page) => $page->component('investment/business-opportunity')
|
|
->where('record.modality', 'land_right'));
|
|
|
|
$this->postJson('/api/v1/interest-requests', [
|
|
'existingBusinessId' => $business['id'], 'modality' => 'real_estate',
|
|
'fullName' => 'Synthetic investor', 'email' => 'portal-integration-test@gmail.com', 'phone' => '+258 840000000',
|
|
'investorType' => 'empresa', 'country' => 'MZ', 'sectorInterest' => 'Imobiliário',
|
|
'message' => 'Synthetic interest in the published real estate opportunity.',
|
|
'privacyConsent' => true,
|
|
])->assertCreated();
|
|
$this->assertDatabaseHas('interest_requests', ['existing_business_id' => $business['id'], 'modality' => 'real_estate', 'status' => 'received']);
|
|
}
|
|
|
|
/** @return array{id:string,public_slug:string} */
|
|
private function publishedBusiness(string $modality = 'company_sale'): array
|
|
{
|
|
$id = (string) Str::uuid();
|
|
$slug = 'public-synthetic-'.$id;
|
|
$now = now();
|
|
DB::table('existing_businesses')->insert([
|
|
'id' => $id,
|
|
'code' => 'SYN-'.strtoupper(substr(str_replace('-', '', $id), 0, 12)),
|
|
'owner_user_id' => User::factory()->create()->id,
|
|
'modality' => $modality,
|
|
'status' => 'published',
|
|
'classification' => 'confidential',
|
|
'version_no' => 1,
|
|
'payload' => Crypt::encryptString(json_encode(['title' => 'Private synthetic title'], JSON_THROW_ON_ERROR)),
|
|
'public_title' => 'Public synthetic opportunity',
|
|
'public_slug' => $slug,
|
|
'published_at' => $now,
|
|
'created_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
|
|
return ['id' => $id, 'public_slug' => $slug];
|
|
}
|
|
}
|