Add unit tests for invoicing period pagination, normalization, and filtering logic

- Implemented `InvoicingPeriodPaginationTest` for testing period pagination modes, normalization of options, search functionality, and visibility filters.
- Added comprehensive tests to validate scenarios such as active period views, exact counts, and customer-card level search.
- Improved cURL timeout settings with `CURLOPT_CONNECTTIMEOUT` and `CURLOPT_TIMEOUT` adjustments.
- Introduced and documented helper classes/methods for local caching, pagination response structure, and customer name retrieval.
This commit is contained in:
Jeppe Bundgaard
2026-05-12 03:37:47 +02:00
parent 70080086da
commit 6c40810caf
21 changed files with 2261 additions and 158 deletions
@@ -1,5 +1,9 @@
<?php
app_require('routes/InvoicingPeriodRoute.php');
use routes\InvoicingPeriodRoute;
it('requires superuser permission for invoicing period distribution all endpoint', function (): void {
$routeFile = app_path('routes/InvoicingPeriodRoute.php');
$content = file_get_contents($routeFile);
@@ -18,3 +22,86 @@ it('uses shared date-range normalization across invoicing period endpoints', fun
expect(substr_count((string)$content, 'requireAndNormalizeDateRange()'))->toBeGreaterThanOrEqual(5);
});
it('keeps the main period response local-only for booked state and customer names', function (): void {
$routeFile = app_path('routes/InvoicingPeriodRoute.php');
$content = file_get_contents($routeFile);
expect($content)->not->toBeFalse();
$content = (string)$content;
expect($content)->not->toContain('isBooked(true)')
->and($content)->toContain('isTransactionBookedFromLocalState($transaction)')
->and($content)->toContain('SELECT booked_invoice_id FROM collected_order_invoices')
->and($content)->toContain('SELECT invoice_id FROM economic_module_orders')
->and($content)->toContain('getCustomerNames(array_keys($customer_numbers), false)')
->and($content)->toContain('getCustomerNames(array_map(\'intval\', $customer_numbers), false)');
});
it('streams the main period response instead of encoding the full payload at once', function (): void {
$routeFile = app_path('routes/InvoicingPeriodRoute.php');
$content = file_get_contents($routeFile);
expect($content)->not->toBeFalse();
$content = (string)$content;
expect($content)->toContain('private static function streamInvoicingPeriodResponse(array $period): void')
->and($content)->toContain('$period = self::getInvoicingPeriod($dateFrom, $dateTo, $customerNumbers);')
->and($content)->toContain('self::streamInvoicingPeriodResponse($period);')
->and($content)->not->toContain('$response->success([' . PHP_EOL . ' ...self::getInvoicingPeriod($dateFrom, $dateTo, $customerNumbers)')
->and($content)->toContain('echo self::jsonFragment($customer);');
});
it('maps batched period transaction rows to the legacy transaction response shape', function (): void {
$reflection = new ReflectionClass(InvoicingPeriodRoute::class);
$method = $reflection->getMethod('constructTransactionObjectFromPeriodRow');
$method->setAccessible(true);
$transaction = $method->invokeArgs(null, [[
'id' => '42',
'created_at' => '2026-04-10 12:34:56',
'net_amount' => '123.50',
'booked' => '1',
'department_id' => '7',
'customer_id' => '27983',
'order_reference' => 'REF-42',
'order_po' => 'PO-42',
'order_notes' => 'Driver note',
'reg_1' => 'AB12345',
'reg_2' => 'CD67890',
'reg_3' => '',
'invoice_collection_id' => '314',
'include_in_invoice_effective' => '0',
]]);
expect($transaction)->toMatchArray([
'id' => 42,
'date' => '2026-04-10 12:34:56',
'amount' => 123.5,
'booked' => true,
'department_id' => 7,
'customer_number' => 27983,
'reference' => 'REF-42',
'po' => 'PO-42',
'notes' => 'Driver note',
'reg_1' => 'AB12345',
'reg_2' => 'CD67890',
'reg_3' => '',
'excluded' => true,
'invoice_collection_id' => 314,
'queue_status' => null,
'queue_job_id' => null,
]);
});
it('uses batched period transactions and keyed customer maps in the main period route', function (): void {
$content = file_get_contents(app_path('routes/InvoicingPeriodRoute.php'));
expect($content)->not->toBeFalse();
$content = (string)$content;
expect($content)->toContain('getPeriodTransactionsForCustomersInDateRange(')
->and($content)->toContain('private static function indexCustomersByNumber(array $customers): array')
->and($content)->toContain('$customers_by_number = self::indexCustomersByNumber($customersWithTransactions);')
->and($content)->toContain('invoicing_period_utils::filterPossibleDuplicates($ordersByRegistration, 86400)')
->and($content)->not->toContain('getOrdersWithPossibleDuplicates($dateFrom, $dateTo)');
});