Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,242 @@
<?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->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');
});
});