clock = new FrozenClock(); $this->randomGenerator = new TestableRandomGenerator(); $this->csrfTokenGenerator = new CsrfTokenGenerator($this->randomGenerator); $this->sessionId = SessionId::fromString('testsessionid1234567890abcdefgh12'); $this->session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); }); describe('Session Basic Operations', function () { test('session starts correctly', function () { expect($this->session->isStarted())->toBeTrue(); }); test('session has correct id', function () { expect($this->session->id)->toBe($this->sessionId); }); test('session data operations work correctly', function () { // Set data $this->session->set('key1', 'value1'); $this->session->set('key2', 42); // Get data expect($this->session->get('key1'))->toBe('value1'); expect($this->session->get('key2'))->toBe(42); expect($this->session->get('nonexistent'))->toBeNull(); expect($this->session->get('nonexistent', 'default'))->toBe('default'); }); test('session has() method works correctly', function () { $this->session->set('existing_key', 'value'); expect($this->session->has('existing_key'))->toBeTrue(); expect($this->session->has('nonexistent_key'))->toBeFalse(); }); test('session remove() method works correctly', function () { $this->session->set('key_to_remove', 'value'); expect($this->session->has('key_to_remove'))->toBeTrue(); $this->session->remove('key_to_remove'); expect($this->session->has('key_to_remove'))->toBeFalse(); }); test('session all() method returns all data', function () { $this->session->set('key1', 'value1'); $this->session->set('key2', 'value2'); $allData = $this->session->all(); // Die Komponenten fügen ihre eigenen Keys hinzu expect($allData)->toHaveKey('key1'); expect($allData)->toHaveKey('key2'); expect($allData['key1'])->toBe('value1'); expect($allData['key2'])->toBe('value2'); // Komponenten-Keys sollten auch existieren expect($allData)->toHaveKey('__flash'); expect($allData)->toHaveKey('__validation_errors'); expect($allData)->toHaveKey('__form_data'); expect($allData)->toHaveKey('__csrf'); }); test('session clear() method removes all data', function () { $this->session->set('key1', 'value1'); $this->session->set('key2', 'value2'); $this->session->clear(); expect($this->session->all())->toBe([]); }); }); describe('Session fromArray functionality', function () { test('fromArray() sets session data correctly', function () { $data = [ 'user_id' => 123, 'username' => 'testuser', 'preferences' => ['theme' => 'dark'], ]; $this->session->fromArray($data); expect($this->session->get('user_id'))->toBe(123); expect($this->session->get('username'))->toBe('testuser'); expect($this->session->get('preferences'))->toBe(['theme' => 'dark']); }); test('fromArray() initializes components after setting data', function () { // Komponenten sollten nach fromArray() verfügbar sein $this->session->fromArray(['some' => 'data']); expect($this->session->flash)->toBeInstanceOf(\App\Framework\Http\Session\FlashBag::class); expect($this->session->validation)->toBeInstanceOf(\App\Framework\Http\Session\ValidationErrorBag::class); expect($this->session->form)->toBeInstanceOf(\App\Framework\Http\Session\FormDataStorage::class); expect($this->session->security)->toBeInstanceOf(\App\Framework\Http\Session\SecurityManager::class); expect($this->session->csrf)->toBeInstanceOf(\App\Framework\Http\Session\CsrfProtection::class); }); test('fromArray() preserves existing data structure', function () { // Teste ob komplexe Datenstrukturen korrekt gespeichert werden $complexData = [ 'user' => [ 'id' => 123, 'profile' => [ 'name' => 'Test User', 'settings' => [ 'notifications' => true, 'theme' => 'dark', ], ], ], 'session_data' => [ 'csrf_token' => 'token123', 'flash_messages' => [ 'success' => ['Message saved!'], 'error' => ['Validation failed!'], ], ], ]; $this->session->fromArray($complexData); expect($this->session->get('user'))->toBe($complexData['user']); expect($this->session->get('session_data'))->toBe($complexData['session_data']); // Teste nested access $user = $this->session->get('user'); expect($user['profile']['name'])->toBe('Test User'); }); }); describe('Session Component Integration', function () { test('components are properly initialized after fromArray()', function () { $this->session->fromArray([]); // Teste ob alle Komponenten korrekt initialisiert sind expect($this->session->flash)->toBeInstanceOf(\App\Framework\Http\Session\FlashBag::class); expect($this->session->validation)->toBeInstanceOf(\App\Framework\Http\Session\ValidationErrorBag::class); expect($this->session->form)->toBeInstanceOf(\App\Framework\Http\Session\FormDataStorage::class); expect($this->session->security)->toBeInstanceOf(\App\Framework\Http\Session\SecurityManager::class); expect($this->session->csrf)->toBeInstanceOf(\App\Framework\Http\Session\CsrfProtection::class); }); test('components can access session data', function () { $this->session->fromArray([ 'flash' => ['success' => ['Test message']], 'csrf_token' => 'test-token', ]); // Flash component sollte auf die Session-Daten zugreifen können expect($this->session->get('flash'))->toBe(['success' => ['Test message']]); expect($this->session->get('csrf_token'))->toBe('test-token'); }); test('double initialization is prevented', function () { $this->session->fromArray([]); $flash1 = $this->session->flash; // Zweite Initialisierung sollte die gleichen Instanzen zurückgeben $this->session->fromArray(['new' => 'data']); $flash2 = $this->session->flash; expect($flash1)->toBe($flash2); }); }); describe('Session Edge Cases', function () { test('handles null values correctly', function () { $this->session->set('null_value', null); expect($this->session->has('null_value'))->toBeTrue(); expect($this->session->get('null_value'))->toBeNull(); }); test('handles empty string values correctly', function () { $this->session->set('empty_string', ''); expect($this->session->has('empty_string'))->toBeTrue(); expect($this->session->get('empty_string'))->toBe(''); }); test('handles boolean values correctly', function () { $this->session->set('true_value', true); $this->session->set('false_value', false); expect($this->session->get('true_value'))->toBeTrue(); expect($this->session->get('false_value'))->toBeFalse(); }); test('handles array values correctly', function () { $arrayValue = ['nested' => ['deep' => 'value']]; $this->session->set('array_value', $arrayValue); expect($this->session->get('array_value'))->toBe($arrayValue); }); test('handles object serialization edge cases', function () { // Teste was passiert wenn Objekte in der Session gespeichert werden $stdClass = new stdClass(); $stdClass->property = 'value'; $this->session->set('object_value', $stdClass); $retrieved = $this->session->get('object_value'); expect($retrieved)->toBeInstanceOf(stdClass::class); expect($retrieved->property)->toBe('value'); }); }); describe('Session Debug Information', function () { test('__debugInfo() returns correct format', function () { $this->session->set('debug_key', 'debug_value'); $debugInfo = $this->session->__debugInfo(); expect($debugInfo[0])->toBe($this->sessionId->toString()); expect($debugInfo['debug_key'])->toBe('debug_value'); }); });