clock = new FrozenClock(); $this->randomGenerator = new TestableRandomGenerator(); $this->csrfTokenGenerator = new CsrfTokenGenerator($this->randomGenerator); $this->storage = new InMemorySessionStorage(); $this->sessionId = SessionId::fromString('testcomponentspersistencesessionid'); }); describe('Session Component Persistence', function () { test('flash messages persist across session save/load cycles', function () { // 1. Neue Session erstellen und Flash-Nachricht hinzufügen $session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session1->fromArray([]); // Initialisiert die Komponenten $session1->flash->add('success', 'Operation successful!'); $session1->flash->add('error', 'Something went wrong'); // 2. Session-Daten speichern $sessionData = $session1->all(); $this->storage->write($this->sessionId, $sessionData); // 3. Neue Session-Instanz laden $loadedData = $this->storage->read($this->sessionId); $session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session2->fromArray($loadedData); // 4. Flash-Nachrichten sollten verfügbar sein $successMessages = $session2->flash->get('success'); $errorMessages = $session2->flash->get('error'); expect($successMessages)->toBe(['Operation successful!']); expect($errorMessages)->toBe(['Something went wrong']); // 5. Nach dem Abrufen sollten die Nachrichten gelöscht sein (Flash-Verhalten) expect($session2->flash->get('success'))->toBe([]); expect($session2->flash->get('error'))->toBe([]); }); test('validation errors persist across session save/load cycles', function () { // 1. Session mit Validation Errors erstellen $session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session1->fromArray([]); $session1->validation->add('user_form', [ 'email' => ['Invalid email format'], 'password' => ['Password too short'], ]); $session1->validation->add('profile_form', [ 'email' => ['Email already exists'], ]); // 2. Session speichern $sessionData = $session1->all(); $this->storage->write($this->sessionId, $sessionData); // 3. Session laden $loadedData = $this->storage->read($this->sessionId); $session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session2->fromArray($loadedData); // 4. Validation Errors sollten verfügbar sein expect($session2->validation->has('user_form'))->toBeTrue(); expect($session2->validation->has('profile_form'))->toBeTrue(); $userFormErrors = $session2->validation->get('user_form'); $profileFormErrors = $session2->validation->get('profile_form'); expect($userFormErrors['email'])->toBe(['Invalid email format']); expect($userFormErrors['password'])->toBe(['Password too short']); expect($profileFormErrors['email'])->toBe(['Email already exists']); }); test('form data persists across session save/load cycles', function () { // 1. Session mit Form Data erstellen $session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session1->fromArray([]); $formData = [ 'name' => 'John Doe', 'email' => 'john@example.com', 'preferences' => [ 'theme' => 'dark', 'notifications' => true, ], ]; $session1->form->store('user_profile', $formData); // 2. Session speichern $sessionData = $session1->all(); $this->storage->write($this->sessionId, $sessionData); // 3. Session laden $loadedData = $this->storage->read($this->sessionId); $session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session2->fromArray($loadedData); // 4. Form Data sollte verfügbar sein expect($session2->form->get('user_profile'))->toBe($formData); expect($session2->form->has('user_profile'))->toBeTrue(); }); test('CSRF tokens persist across session save/load cycles', function () { // 1. Session mit CSRF Token erstellen $session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session1->fromArray([]); $token1 = $session1->csrf->generateToken('login_form'); $token2 = $session1->csrf->generateToken('profile_form'); // 2. Session speichern $sessionData = $session1->all(); $this->storage->write($this->sessionId, $sessionData); // 3. Session laden $loadedData = $this->storage->read($this->sessionId); $session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session2->fromArray($loadedData); // 4. Token sollten gültig sein expect($session2->csrf->validateToken('login_form', $token1))->toBeTrue(); expect($session2->csrf->validateToken('profile_form', $token2))->toBeTrue(); // Für ungültigen Token erstellen wir ein CsrfToken Objekt $invalidToken = \App\Framework\Security\CsrfToken::fromString('0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'); expect($session2->csrf->validateToken('login_form', $invalidToken))->toBeFalse(); }); test('all component data is stored in session under specific keys', function () { // 1. Session mit allen Komponenten-Daten erstellen $session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session->fromArray([]); // Komponenten verwenden $session->flash->add('info', 'Test message'); $session->validation->add('test_form', ['field' => ['Test error']]); $session->form->store('test_form', ['data' => 'test']); $session->csrf->generateToken('test_form'); // Auch normale Session-Daten hinzufügen $session->set('user_id', 123); $session->set('custom_data', 'custom_value'); // 2. Session-Daten analysieren $allData = $session->all(); // 3. Komponenten-Keys sollten existieren expect($allData)->toHaveKey(SessionKey::FLASH->value); expect($allData)->toHaveKey(SessionKey::VALIDATION_ERRORS->value); expect($allData)->toHaveKey(SessionKey::FORM_DATA->value); expect($allData)->toHaveKey(SessionKey::CSRF->value); // 4. Normale Session-Daten sollten auch existieren expect($allData)->toHaveKey('user_id'); expect($allData)->toHaveKey('custom_data'); expect($allData['user_id'])->toBe(123); expect($allData['custom_data'])->toBe('custom_value'); // 5. Komponenten-Daten sollten korrekt strukturiert sein expect($allData[SessionKey::FLASH->value])->toBeArray(); expect($allData[SessionKey::VALIDATION_ERRORS->value])->toBeArray(); expect($allData[SessionKey::FORM_DATA->value])->toBeArray(); expect($allData[SessionKey::CSRF->value])->toBeArray(); }); test('components work immediately after fromArray initialization', function () { // 1. Session-Daten mit bestehenden Komponenten-Daten laden $existingData = [ SessionKey::FLASH->value => [ 'success' => ['Pre-existing message'], ], SessionKey::VALIDATION_ERRORS->value => [ 'contact_form' => [ 'email' => ['Pre-existing error'], ], ], SessionKey::FORM_DATA->value => [ 'contact_form' => ['name' => 'Pre-existing Name'], ], 'user_id' => 456, ]; $session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session->fromArray($existingData); // 2. Komponenten sollten sofort die existierenden Daten haben expect($session->flash->get('success'))->toBe(['Pre-existing message']); $contactFormErrors = $session->validation->get('contact_form'); expect($contactFormErrors['email'])->toBe(['Pre-existing error']); expect($session->form->get('contact_form'))->toBe(['name' => 'Pre-existing Name']); expect($session->get('user_id'))->toBe(456); // 3. Neue Daten sollten zu den existierenden hinzugefügt werden $session->flash->add('info', 'New message'); $session->validation->add('login_form', ['password' => ['New error']]); expect($session->flash->get('info'))->toBe(['New message']); $loginFormErrors = $session->validation->get('login_form'); expect($loginFormErrors['password'])->toBe(['New error']); // Die ursprünglichen Flash-Messages sollten nach dem Abrufen gelöscht sein expect($session->flash->get('success'))->toBe([]); // Flash wurde bereits abgerufen }); test('component keys are created when components are first used', function () { // 1. Leere Session erstellen $session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator); $session->fromArray([]); // 2. Komponenten verwenden um ihre Keys zu initialisieren $session->flash->add('test', 'message'); $session->validation->add('form', ['field' => ['error']]); $session->form->store('form', ['data' => 'value']); $session->csrf->generateToken('form'); // 3. Alle Komponenten-Keys sollten jetzt existieren $allData = $session->all(); expect($allData)->toHaveKey(SessionKey::FLASH->value); expect($allData)->toHaveKey(SessionKey::VALIDATION_ERRORS->value); expect($allData)->toHaveKey(SessionKey::FORM_DATA->value); expect($allData)->toHaveKey(SessionKey::CSRF->value); // 4. Sie sollten die erwarteten Daten enthalten expect($allData[SessionKey::FLASH->value])->toHaveKey('test'); expect($allData[SessionKey::VALIDATION_ERRORS->value])->toHaveKey('form'); expect($allData[SessionKey::FORM_DATA->value])->toHaveKey('form'); expect($allData[SessionKey::CSRF->value])->toHaveKey('form'); }); });