- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
194 lines
8.1 KiB
PHP
194 lines
8.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\DateTime\FrozenClock;
|
|
use App\Framework\Http\Session\InMemorySessionStorage;
|
|
use App\Framework\Http\Session\Session;
|
|
use App\Framework\Http\Session\SessionId;
|
|
use App\Framework\Http\Session\SessionKey;
|
|
use App\Framework\Random\TestableRandomGenerator;
|
|
use App\Framework\Security\CsrfTokenGenerator;
|
|
|
|
beforeEach(function () {
|
|
$this->clock = new FrozenClock();
|
|
$this->randomGenerator = new TestableRandomGenerator();
|
|
$this->csrfTokenGenerator = new CsrfTokenGenerator($this->randomGenerator);
|
|
$this->sessionId = SessionId::fromString('testlazyinitsessionid1234567890ab');
|
|
});
|
|
|
|
describe('Session Component Lazy Initialization', function () {
|
|
test('only used component keys appear in session data', function () {
|
|
// 1. Session erstellen
|
|
$session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session->fromArray([]);
|
|
|
|
// 2. Nur einige Komponenten verwenden
|
|
$session->flash->add('info', 'Test message');
|
|
$session->csrf->generateToken('test_form');
|
|
// Bewusst NICHT verwenden: validation und form
|
|
|
|
// 3. Session-Daten prüfen
|
|
$sessionData = $session->all();
|
|
|
|
// 4. Nur verwendete Keys sollten existieren
|
|
expect($sessionData)->toHaveKey(SessionKey::FLASH->value);
|
|
expect($sessionData)->toHaveKey(SessionKey::CSRF->value);
|
|
|
|
// 5. Nicht verwendete Keys sollten NICHT existieren
|
|
expect($sessionData)->not->toHaveKey(SessionKey::VALIDATION_ERRORS->value);
|
|
expect($sessionData)->not->toHaveKey(SessionKey::FORM_DATA->value);
|
|
|
|
// 6. Inhalt der verwendeten Keys prüfen
|
|
expect($sessionData[SessionKey::FLASH->value])->toHaveKey('info');
|
|
expect($sessionData[SessionKey::CSRF->value])->toHaveKey('test_form');
|
|
});
|
|
|
|
test('accessing component creates its key even if empty', function () {
|
|
// 1. Session erstellen
|
|
$session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session->fromArray([]);
|
|
|
|
// 2. Komponente zugreifen ohne Daten hinzuzufügen
|
|
$errors = $session->validation->get('nonexistent_form'); // Sollte [] zurückgeben
|
|
expect($errors)->toBe([]);
|
|
|
|
// 3. Jetzt sollte der Key existieren (da Komponente initialisiert wurde)
|
|
$sessionData = $session->all();
|
|
expect($sessionData)->toHaveKey(SessionKey::VALIDATION_ERRORS->value);
|
|
expect($sessionData[SessionKey::VALIDATION_ERRORS->value])->toBe([]);
|
|
});
|
|
|
|
test('component keys persist after session reload', function () {
|
|
$storage = new InMemorySessionStorage();
|
|
|
|
// 1. Session mit gemischter Nutzung erstellen
|
|
$session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session1->fromArray([]);
|
|
|
|
$session1->flash->add('success', 'Saved!');
|
|
$session1->csrf->generateToken('edit_form');
|
|
// validation und form werden NICHT verwendet
|
|
|
|
// 2. Session speichern
|
|
$storage->write($this->sessionId, $session1->all());
|
|
|
|
// 3. Session neu laden
|
|
$loadedData = $storage->read($this->sessionId);
|
|
$session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session2->fromArray($loadedData);
|
|
|
|
// 4. Nur die Keys die vorher verwendet wurden sollten existieren
|
|
$reloadedData = $session2->all();
|
|
expect($reloadedData)->toHaveKey(SessionKey::FLASH->value);
|
|
expect($reloadedData)->toHaveKey(SessionKey::CSRF->value);
|
|
expect($reloadedData)->not->toHaveKey(SessionKey::VALIDATION_ERRORS->value);
|
|
expect($reloadedData)->not->toHaveKey(SessionKey::FORM_DATA->value);
|
|
|
|
// 5. Daten sollten korrekt geladen werden
|
|
expect($session2->flash->get('success'))->toBe(['Saved!']);
|
|
});
|
|
|
|
test('unused components can be accessed after session reload', function () {
|
|
$storage = new InMemorySessionStorage();
|
|
|
|
// 1. Session mit teilweiser Nutzung
|
|
$session1 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session1->fromArray([]);
|
|
$session1->flash->add('info', 'Test');
|
|
$storage->write($this->sessionId, $session1->all());
|
|
|
|
// 2. Session neu laden
|
|
$loadedData = $storage->read($this->sessionId);
|
|
$session2 = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session2->fromArray($loadedData);
|
|
|
|
// 3. Bisher unverwendete Komponenten sollten funktionieren
|
|
$session2->validation->add('new_form', ['field' => ['New error']]);
|
|
$session2->form->store('new_form', ['data' => 'New data']);
|
|
|
|
// 4. Nach Verwendung sollten die Keys existieren
|
|
$finalData = $session2->all();
|
|
expect($finalData)->toHaveKey(SessionKey::VALIDATION_ERRORS->value);
|
|
expect($finalData)->toHaveKey(SessionKey::FORM_DATA->value);
|
|
|
|
// 5. Ursprüngliche Daten sollten erhalten bleiben
|
|
expect($finalData)->toHaveKey(SessionKey::FLASH->value);
|
|
});
|
|
|
|
test('simulates live system behavior from your example', function () {
|
|
// 1. Simuliere eine typische Web-App Session
|
|
$session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session->fromArray([]);
|
|
|
|
// 2. Simuliere Security Tracking (automatisch durch Framework)
|
|
$session->security->updateActivity();
|
|
|
|
// 3. Simuliere CSRF Token Generierung für verschiedene Formulare
|
|
$session->csrf->generateToken('form_bf9d2e47868b');
|
|
$session->csrf->generateToken('form_386bb8ff6647');
|
|
|
|
// 4. Flash wird initialisiert aber ist leer (typisch nach Redirect)
|
|
// Simuliere: Flash wurde bereits abgerufen und ist jetzt leer
|
|
$session->flash->get('any_type'); // Initialisiert das Array
|
|
|
|
// 5. validation und form werden NICHT verwendet (kein Fehler, kein Form-Data)
|
|
|
|
// 6. Prüfe Session-Daten (sollte dem Live-System ähneln)
|
|
$sessionData = $session->all();
|
|
|
|
expect($sessionData)->toHaveKey('__security');
|
|
expect($sessionData)->toHaveKey('__csrf');
|
|
expect($sessionData)->toHaveKey('__flash');
|
|
expect($sessionData['__flash'])->toBe([]); // Leer, wie im Live-System
|
|
|
|
// Diese Keys fehlen - das ist korrekt!
|
|
expect($sessionData)->not->toHaveKey('__validation_errors');
|
|
expect($sessionData)->not->toHaveKey('__form_data');
|
|
|
|
// 7. CSRF sollte Tokens für verschiedene Formulare enthalten
|
|
expect($sessionData['__csrf'])->toHaveKey('form_bf9d2e47868b');
|
|
expect($sessionData['__csrf'])->toHaveKey('form_386bb8ff6647');
|
|
});
|
|
|
|
test('components become available when first needed', function () {
|
|
$storage = new InMemorySessionStorage();
|
|
|
|
// 1. Session wie im Live-System
|
|
$existingData = [
|
|
'__security' => [
|
|
'user_agent' => 'Mozilla/5.0 (Test Browser)',
|
|
'ip_address' => '127.0.0.1',
|
|
'last_activity' => time(),
|
|
],
|
|
'__csrf' => [
|
|
'test_form' => [
|
|
['token' => 'abc123', 'created_at' => time(), 'used_at' => null],
|
|
],
|
|
],
|
|
'__flash' => [],
|
|
];
|
|
|
|
$session = new Session($this->sessionId, $this->clock, $this->csrfTokenGenerator);
|
|
$session->fromArray($existingData);
|
|
|
|
// 2. Bisher fehlende Komponenten sind trotzdem verfügbar
|
|
expect($session->validation->has('any_form'))->toBeFalse();
|
|
expect($session->form->has('any_form'))->toBeFalse();
|
|
|
|
// 3. Wenn sie verwendet werden, funktionieren sie
|
|
$session->validation->add('contact_form', ['email' => ['Required']]);
|
|
$session->form->store('contact_form', ['name' => 'John']);
|
|
|
|
// 4. Jetzt sollten die Keys existieren
|
|
$finalData = $session->all();
|
|
expect($finalData)->toHaveKey('__validation_errors');
|
|
expect($finalData)->toHaveKey('__form_data');
|
|
|
|
// 5. Bestehende Daten bleiben erhalten
|
|
expect($finalData['__security']['user_agent'])->toBe('Mozilla/5.0 (Test Browser)');
|
|
expect($finalData['__csrf'])->toHaveKey('test_form');
|
|
expect($finalData['__flash'])->toBe([]);
|
|
});
|
|
});
|