Files
crmPRO/tests/Domain/Finances/FakturowniaApiClientTest.php
2026-04-15 01:24:42 +02:00

169 lines
5.5 KiB
PHP

<?php
require_once __DIR__ . '/../../../autoload/Domain/Finances/FakturowniaApiClient.php';
use Domain\Finances\FakturowniaApiClient;
class FakeFakturowniaApiClient extends FakturowniaApiClient
{
public $calledPaths = [];
public $responses = [];
protected function request( $path, $query )
{
$this -> calledPaths[] = [ 'path' => $path, 'query' => $query ];
if ( !isset( $this -> responses[ $path ] ) )
return [ 'http_code' => 200, 'body' => '[]' ];
return $this -> responses[ $path ];
}
}
function run_fakturownia_api_client_tests()
{
// AC-1: /invoices.json?income=no jest pytane jako primary source,
// pusta odpowiedz /costs.json NIE konczy wczesniej i faktura 486639934 z /invoices.json trafia do wynikow.
$client = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
$client -> responses = [
'/invoices.json' => [
'http_code' => 200,
'body' => json_encode( [
'invoices' => [
[
'id' => 486639934,
'number' => 'FV 100/04/2026',
'kind' => 'vat',
'income' => false,
'issue_date' => '2026-04-05',
'seller_name' => 'Dostawca Sp. z o.o.',
'seller_tax_no' => '5252344567'
]
]
] )
],
'/costs.json' => [ 'http_code' => 200, 'body' => '[]' ],
'/expenses.json' => [ 'http_code' => 404, 'body' => '' ]
];
$result = $client -> fetchCostDocuments( '2026-04-01', 1 );
assert_true(
count( $result ) === 1,
'Expected faktura 486639934 to be returned from /invoices.json?income=no even when /costs.json is empty.'
);
assert_true(
(string)$result[0]['id'] === '486639934',
'Expected invoice id 486639934 in merged cost documents.'
);
$paths = array_map( function( $c ) { return $c['path']; }, $client -> calledPaths );
assert_true(
in_array( '/invoices.json', $paths, true ),
'Expected /invoices.json to be queried for cost documents.'
);
assert_true(
in_array( '/costs.json', $paths, true ),
'Expected /costs.json to be queried as secondary source.'
);
assert_true(
in_array( '/expenses.json', $paths, true ),
'Expected /expenses.json to be queried as tertiary source (bug 05-04: empty /costs.json must not short-circuit).'
);
// AC-2: period=more + date_from + date_to sa wysylane, by API filtrowalo po issue_date.
// Bez tego importer pobieralby wszystkie historyczne faktury i cron by sie zawiesil.
$invoicesCall = null;
foreach ( $client -> calledPaths as $call )
{
if ( $call['path'] === '/invoices.json' )
{
$invoicesCall = $call;
break;
}
}
assert_true( $invoicesCall !== null, 'Expected at least one call to /invoices.json.' );
assert_true(
( $invoicesCall['query']['period'] ?? '' ) === 'more',
'Expected period=more parameter so Fakturownia filters by date range server-side.'
);
assert_true(
( $invoicesCall['query']['date_from'] ?? '' ) === '2026-04-01',
'Expected date_from to match startDate passed to fetchCostDocuments.'
);
assert_true(
!empty( $invoicesCall['query']['date_to'] ?? '' ),
'Expected date_to to be set (default: today) to complete the range filter.'
);
assert_true(
( $invoicesCall['query']['income'] ?? '' ) === 'no',
'Expected income=no filter on /invoices.json for cost documents.'
);
// Dedup: ten sam id w /invoices.json i /costs.json trafia raz.
$dedupClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
$dedupClient -> responses = [
'/invoices.json' => [
'http_code' => 200,
'body' => json_encode( [
'invoices' => [
[ 'id' => 111, 'number' => 'A', 'income' => false ],
[ 'id' => 222, 'number' => 'B', 'income' => false ]
]
] )
],
'/costs.json' => [
'http_code' => 200,
'body' => json_encode( [
'costs' => [
[ 'id' => 222, 'number' => 'B' ],
[ 'id' => 333, 'number' => 'C' ]
]
] )
]
];
$merged = $dedupClient -> fetchCostDocuments( '2026-04-01', 1 );
$ids = array_map( function( $d ) { return (string)$d['id']; }, $merged );
sort( $ids );
assert_true(
$ids === [ '111', '222', '333' ],
'Expected merged cost documents to be deduplicated by id across endpoints.'
);
// Gdy wszystkie 3 sciezki zwroca HTTP >= 400, fetchCostDocuments rzuca wyjatek.
$errorClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
$errorClient -> responses = [
'/invoices.json' => [ 'http_code' => 500, 'body' => '' ],
'/costs.json' => [ 'http_code' => 500, 'body' => '' ],
'/expenses.json' => [ 'http_code' => 500, 'body' => '' ]
];
$threw = false;
try
{
$errorClient -> fetchCostDocuments( '2026-04-01', 1 );
}
catch ( \Throwable $e )
{
$threw = true;
}
assert_true(
$threw,
'Expected fetchCostDocuments to throw when all endpoints fail with HTTP errors.'
);
// Gdy wszystkie 3 sciezki zwroca pusta liste z HTTP 200, zwracamy [] (nie wyjatek).
$emptyClient = new FakeFakturowniaApiClient( 'https://example', 'token', 100 );
$emptyClient -> responses = [
'/invoices.json' => [ 'http_code' => 200, 'body' => '[]' ],
'/costs.json' => [ 'http_code' => 200, 'body' => '[]' ],
'/expenses.json' => [ 'http_code' => 200, 'body' => '[]' ]
];
$emptyResult = $emptyClient -> fetchCostDocuments( '2026-04-01', 1 );
assert_true(
is_array( $emptyResult ) && count( $emptyResult ) === 0,
'Expected empty array when all endpoints return HTTP 200 with empty lists.'
);
}