'test_login', 'services.supplier.password' => 'test_password', 'services.supplier.portal_url' => 'https://crm.bp-gr.ru', ]); Cache::store('redis')->forget('supplier:session'); }); afterEach(function () { Cache::store('redis')->forget('supplier:session'); Mockery::close(); }); test('writes session data to Redis cache key supplier:session with 6h TTL', function () { $bridge = Mockery::mock(PlaywrightBridge::class); /** @var PlaywrightBridge $bridge */ $bridge->shouldReceive('refreshSession') ->once() ->with('test_login', 'test_password', 'https://crm.bp-gr.ru') ->andReturn([ 'phpsessid' => 'sess123', 'csrf' => 'csrf456', 'refreshed_at' => '2026-05-11T10:00:00Z', ]); (new RefreshSupplierSessionJob)->handle($bridge); $cached = Cache::store('redis')->get('supplier:session'); expect($cached)->toBeArray() ->and($cached['phpsessid'])->toBe('sess123') ->and($cached['csrf'])->toBe('csrf456') ->and($cached['refreshed_at'])->toBe('2026-05-11T10:00:00Z'); }); test('rethrows SupplierAuthException from PlaywrightBridge', function () { $bridge = Mockery::mock(PlaywrightBridge::class); /** @var PlaywrightBridge $bridge */ $bridge->shouldReceive('refreshSession') ->andThrow(new SupplierAuthException('Login rejected')); expect(fn () => (new RefreshSupplierSessionJob)->handle($bridge)) ->toThrow(SupplierAuthException::class); }); // NOTE: artisan() command test moved to tests/Feature/Supplier/SupplierSessionRefreshCommandTest.php // (Pest Unit/ + $this->artisan() + uses(TestCase::class) триггерит laravel/pao stream_filter // conflict при кросс-файловом запуске tests/Unit/Supplier/).