'http://test-server.local', 'logistics.api_key' => 'test-api-key', 'logistics.folder' => 'testfolder', 'logistics.timeout' => 30, 'logistics.connect_timeout' => 10, 'logistics.retry.times' => 1, 'logistics.retry.sleep_ms' => 0, ]); $this->actingAs(User::factory()->create()); }); it('defaults to read mode', function () { Livewire::test(Tiers::class) ->assertSet('mode', 'read'); }); it('can switch between read and write modes', function () { Livewire::test(Tiers::class) ->set('mode', 'write') ->assertSet('mode', 'write') ->set('mode', 'read') ->assertSet('mode', 'read'); }); it('has correct default select value', function () { Livewire::test(Tiers::class) ->assertSet('select', 'custid,name'); }); it('shows validation error when search is empty', function () { Http::fake(); Livewire::test(Tiers::class) ->call('searchTiers') ->assertSet('hasSearched', false) ->assertSet('errorMessage', 'Le champ de recherche (search) est obligatoire.'); Http::assertNothingSent(); }); it('searches tiers via third_list', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => [['custid' => '0100002174', 'name' => 'ESI SPRL']], 'metadata' => ['rowCount' => 1, 'source' => 'DBF', 'executionTimeMs' => 112, 'searchColumns' => 'name,groupid,vat', 'selectColumns' => 'custid,name', 'searchTerms' => 'ESI'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('search', 'ESI') ->set('select', 'custid,name') ->call('searchTiers') ->assertSet('hasSearched', true) ->assertSet('data', [['custid' => '0100002174', 'name' => 'ESI SPRL']]) ->assertSet('errorMessage', null); Http::assertSent(function ($request) { return str_contains($request->url(), 'third_list') && $request->data()['search'] === 'ESI'; }); }); it('sends select and results parameters to third_list', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => [['custid' => '0100002174', 'name' => 'ESI SPRL']], 'metadata' => ['rowCount' => 1, 'source' => 'DBF', 'executionTimeMs' => 100, 'searchColumns' => 'name,groupid,vat', 'selectColumns' => 'custid,name', 'searchTerms' => 'test'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('search', 'test') ->set('select', 'custid,name,vat') ->set('results', 20) ->call('searchTiers'); Http::assertSent(function ($request) { $data = $request->data(); return str_contains($request->url(), 'third_list') && $data['search'] === 'test' && $data['select'] === 'custid,name,vat' && $data['results'] === 20; }); }); it('sets hasSearched even when no results', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => [], 'metadata' => ['rowCount' => 0, 'source' => 'DBF', 'executionTimeMs' => 100, 'searchColumns' => 'name,groupid,vat', 'selectColumns' => 'custid,name', 'searchTerms' => 'nonexistent'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('search', 'nonexistent') ->call('searchTiers') ->assertSet('hasSearched', true) ->assertSet('data', []); }); it('stores metadata from third_list response', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => [['custid' => '0100002174', 'name' => 'ESI SPRL']], 'metadata' => ['rowCount' => 1, 'source' => 'DBF', 'executionTimeMs' => 112, 'searchColumns' => 'name,groupid,vat', 'selectColumns' => 'custid,name', 'searchTerms' => 'ESI'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('search', 'ESI') ->call('searchTiers') ->assertSet('metadata.rowCount', 1) ->assertSet('metadata.searchColumns', 'name,groupid,vat'); }); it('shows validation error when historyThirdId is empty', function () { Http::fake(); Livewire::test(Tiers::class) ->call('getArtHistory') ->assertSet('hasHistory', false) ->assertSet('errorMessage', 'Le champ identifiant tiers (thirdid) est obligatoire.'); Http::assertNothingSent(); }); it('gets art history for a third party', function () { Http::fake([ '*/third_GetArtHistory' => Http::response([ 'data' => [ [ 'artid' => 'ART001', 'artname' => 'Article Test', 'jnl' => '03VEN', 'unitprice' => 220, 'qty' => 1, 'vatid' => '21', 'vatpc' => 21, 's_credate' => '2025-06-03', ], ], 'metadata' => ['rowCount' => 1, 'source' => 'DBF'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('historyThirdId', 'CUST001') ->call('getArtHistory') ->assertSet('hasHistory', true) ->assertSet('errorMessage', null); Http::assertSent(function ($request) { return str_contains($request->url(), 'third_GetArtHistory') && $request->data()['thirdid'] === 'CUST001'; }); }); it('sends thirdid in lowercase key to third_GetArtHistory', function () { Http::fake([ '*/third_GetArtHistory' => Http::response([ 'data' => [], 'metadata' => ['rowCount' => 0, 'source' => 'DBF'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('historyThirdId', '0100002174') ->call('getArtHistory'); Http::assertSent(function ($request) { return str_contains($request->url(), 'third_GetArtHistory') && array_key_exists('thirdid', $request->data()) && ! array_key_exists('THIRDID', $request->data()); }); }); it('displays error message on third_list API failure', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => null, 'metadata' => ['rowcount' => 0, 'issuccess' => false], 'error' => 'Search terms are required. Please provide a search query.', ]), ]); Livewire::test(Tiers::class) ->set('search', 'test') ->call('searchTiers') ->assertSet('hasSearched', true) ->assertSet('data', []); }); it('displays error message on third_GetArtHistory API failure', function () { Http::fake([ '*/third_GetArtHistory' => Http::response([ 'data' => null, 'metadata' => ['isSuccess' => false], 'error' => ['thirdid parameter is required.'], ], 400), ]); Livewire::test(Tiers::class) ->set('historyThirdId', 'INVALID') ->call('getArtHistory') ->assertSet('hasHistory', true) ->assertSet('historyData', []); }); it('handles third_GetArtHistory returning empty data for unknown thirdid', function () { Http::fake([ '*/third_GetArtHistory' => Http::response([ 'data' => [], 'metadata' => ['rowCount' => 0, 'source' => 'DBF'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('historyThirdId', 'XXXXXX') ->call('getArtHistory') ->assertSet('hasHistory', true) ->assertSet('historyData', []) ->assertSet('errorMessage', null); }); it('filters out empty select parameter', function () { Http::fake([ '*/third_list' => Http::response([ 'data' => [['custid' => '0100002174', 'name' => 'ESI SPRL']], 'metadata' => ['rowCount' => 1, 'source' => 'DBF', 'executionTimeMs' => 100, 'searchColumns' => 'name,groupid,vat', 'selectColumns' => 'custid,name', 'searchTerms' => 'test'], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('search', 'test') ->set('select', '') ->call('searchTiers'); Http::assertSent(function ($request) { $data = $request->data(); return str_contains($request->url(), 'third_list') && ! array_key_exists('select', $data); }); }); // --- third_add --- it('adds a third party via third_add', function () { Http::fake([ '*/third_add' => Http::response([ 'data' => ['thirdid' => '_@00036051'], 'metadata' => ['rowcount' => 1, 'issuccess' => true], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('mode', 'write') ->set('addName', 'Test Company') ->set('addVat', 'BE0123456789') ->set('addEmail', 'test@example.com') ->call('addTiers') ->assertSet('hasAdded', true) ->assertSet('addResult', ['thirdid' => '_@00036051']) ->assertSet('errorMessage', null); Http::assertSent(function ($request) { $body = $request->data(); return str_contains($request->url(), 'third_add') && $body['NAME'] === 'Test Company' && $body['VAT'] === 'BE0123456789' && $body['EMAIL'] === 'test@example.com'; }); }); it('omits optional params when empty on third_add', function () { Http::fake([ '*/third_add' => Http::response([ 'data' => ['thirdid' => '_@00036052'], 'metadata' => ['rowcount' => 1, 'issuccess' => true], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('mode', 'write') ->set('addName', '') ->set('addVat', '') ->set('addEmail', '') ->call('addTiers'); Http::assertSent(function ($request) { $body = $request->data(); return str_contains($request->url(), 'third_add') && ! array_key_exists('NAME', $body) && ! array_key_exists('VAT', $body) && ! array_key_exists('EMAIL', $body); }); }); it('handles exception on addTiers', function () { Http::fake([ '*/third_add' => Http::response('Server Error', 500), ]); $component = Livewire::test(Tiers::class) ->set('mode', 'write') ->set('addName', 'Test') ->call('addTiers'); expect($component->get('errorMessage'))->not->toBeNull(); expect($component->get('addResult'))->toBe([]); }); // --- third_mod --- it('modifies a third party via third_mod', function () { Http::fake([ '*/third_mod' => Http::response([ 'data' => ['thirdid' => 'CUST001'], 'metadata' => ['rowcount' => 1, 'issuccess' => true], 'error' => null, ]), ]); Livewire::test(Tiers::class) ->set('mode', 'write') ->set('modCustId', 'CUST001') ->set('modName', 'Updated Company') ->set('modVat', 'BE0987654321') ->call('modTiers') ->assertSet('hasModified', true) ->assertSet('modResult', ['thirdid' => 'CUST001']) ->assertSet('errorMessage', null); Http::assertSent(function ($request) { $body = $request->data(); return str_contains($request->url(), 'third_mod') && $body['CUSTID'] === 'CUST001' && $body['NAME'] === 'Updated Company'; }); }); it('shows validation error when modCustId is empty', function () { Http::fake(); Livewire::test(Tiers::class) ->set('mode', 'write') ->call('modTiers') ->assertSet('hasModified', false) ->assertSet('errorMessage', 'Le champ identifiant tiers (CUSTID) est obligatoire.'); Http::assertNothingSent(); }); it('handles API error on third_mod (not found)', function () { Http::fake([ '*/third_mod' => Http::response([ 'data' => ['xml' => '001Custid not exist'], 'metadata' => ['rowcount' => 1, 'issuccess' => false], 'error' => ['Code: 001, Description: Custid not exist'], ]), ]); $component = Livewire::test(Tiers::class) ->set('mode', 'write') ->set('modCustId', 'INEXISTANT') ->call('modTiers'); expect($component->get('errorMessage'))->toContain('Custid not exist'); });