Teren-app/tests/Feature/SegmentExportTest.php
2025-12-10 21:15:53 +01:00

210 lines
6.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Exports\SegmentContractsExport;
use App\Http\Controllers\SegmentController;
use App\Http\Requests\ExportSegmentContractsRequest;
use App\Models\Client;
use App\Models\Contract;
use App\Models\Person\Person as PersonModel;
use App\Models\Segment;
use App\Models\User;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class SegmentExportTest extends \Tests\TestCase
{
public function test_exports_only_current_page_when_requested(): void
{
Excel::fake();
Carbon::setTestNow('2025-12-10 12:00:00');
$segment = Segment::factory()->create();
$contracts = Contract::factory()->count(2)->create();
foreach ($contracts as $contract) {
DB::table('contract_segment')->insert([
'contract_id' => $contract->id,
'segment_id' => $segment->id,
'active' => true,
'created_at' => now(),
'updated_at' => now(),
]);
}
$user = User::factory()->create();
$request = $this->makeExportRequest([
'scope' => 'current',
'columns' => ['reference', 'client'],
'page' => 1,
'per_page' => 1,
], $user);
$response = app(SegmentController::class)->export($request, $segment);
$this->assertInstanceOf(BinaryFileResponse::class, $response);
$expectedName = $this->expectedFilename($segment);
Excel::assertDownloaded($expectedName, function (SegmentContractsExport $export) {
$this->assertSame(1, $export->query()->get()->count());
return true;
});
}
public function test_exports_full_segment_when_scope_all(): void
{
Excel::fake();
Carbon::setTestNow('2025-12-10 12:05:00');
$segment = Segment::factory()->create();
$contracts = Contract::factory()->count(3)->create();
foreach ($contracts as $contract) {
DB::table('contract_segment')->insert([
'contract_id' => $contract->id,
'segment_id' => $segment->id,
'active' => true,
'created_at' => now(),
'updated_at' => now(),
]);
}
$user = User::factory()->create();
$request = $this->makeExportRequest([
'scope' => 'all',
'columns' => SegmentContractsExport::allowedColumns(),
], $user);
$response = app(SegmentController::class)->export($request, $segment);
$this->assertInstanceOf(BinaryFileResponse::class, $response);
$request = $this->makeExportRequest([
'scope' => 'all',
'columns' => SegmentContractsExport::allowedColumns(),
], $user);
$expectedName = $this->expectedFilename($segment);
Excel::assertDownloaded($expectedName, function (SegmentContractsExport $export) use ($contracts) {
$this->assertSame($contracts->count(), $export->query()->get()->count());
return true;
});
}
public function test_export_filename_includes_client_name_when_filtered(): void
{
Excel::fake();
Carbon::setTestNow('2025-12-10 12:10:00');
$segment = Segment::factory()->create(['name' => 'VIP Segment']);
$contract = Contract::factory()->create();
DB::table('contract_segment')->insert([
'contract_id' => $contract->id,
'segment_id' => $segment->id,
'active' => true,
'created_at' => now(),
'updated_at' => now(),
]);
$client = Client::factory()
->for(PersonModel::factory(['full_name' => 'Ana Novak']), 'person')
->create();
$contract->clientCase?->update(['client_id' => $client->id]);
$user = User::factory()->create();
$request = $this->makeExportRequest([
'scope' => 'all',
'columns' => ['reference'],
'client' => (string) $client->uuid,
], $user);
$expectedName = $this->expectedFilename($segment, 'Ana Novak');
$response = app(SegmentController::class)->export($request, $segment);
$this->assertInstanceOf(BinaryFileResponse::class, $response);
Excel::assertDownloaded($expectedName, function (SegmentContractsExport $export) {
$this->assertSame(1, $export->query()->get()->count());
return true;
});
}
public function test_column_formats_apply_to_reference_and_date_columns(): void
{
$export = new SegmentContractsExport(
Contract::query(),
['reference', 'start_date', 'client', 'end_date']
);
$this->assertSame(
[
'A' => SegmentContractsExport::TEXT_EXCEL_FORMAT,
'B' => SegmentContractsExport::DATE_EXCEL_FORMAT,
'D' => SegmentContractsExport::DATE_EXCEL_FORMAT,
],
$export->columnFormats()
);
}
public function test_date_values_are_converted_to_excel_serial_numbers(): void
{
$contract = Contract::factory()->make([
'start_date' => '2025-10-30',
]);
$export = new SegmentContractsExport(
Contract::query(),
['start_date']
);
$row = $export->map($contract);
$this->assertIsFloat($row[0]);
$this->assertGreaterThan(40000, $row[0]);
}
private function makeExportRequest(array $payload, User $user): ExportSegmentContractsRequest
{
$request = ExportSegmentContractsRequest::create('/segments/export', 'POST', $payload);
$request->setContainer($this->app);
$request->setRedirector($this->app->make(Redirector::class));
$request->setUserResolver(fn () => $user);
$request->setRouteResolver(fn () => (object) [
'parameter' => fn () => null,
]);
$request->validateResolved();
return $request;
}
private function expectedFilename(Segment $segment, ?string $clientName = null): string
{
$base = now()->format('dmy').'_'.$this->slugify($segment->name).'-Pogodbe';
if ($clientName) {
return sprintf('%s_%s.xlsx', $base, $this->slugify($clientName));
}
return sprintf('%s.xlsx', $base);
}
private function slugify(string $value): string
{
$slug = trim(preg_replace('/[^a-zA-Z0-9]+/', '-', $value), '-');
return $slug !== '' ? $slug : 'data';
}
}