Files
michaelschiemer/tests/Framework/Console/Helpers/TestConsoleOutput.php
Michael Schiemer 8f3c15ddbb fix(console): comprehensive TUI rendering fixes
- Fix Enter key detection: handle multiple Enter key formats (\n, \r, \r\n)
- Reduce flickering: lower render frequency from 60 FPS to 30 FPS
- Fix menu bar visibility: re-render menu bar after content to prevent overwriting
- Fix content positioning: explicit line positioning for categories and commands
- Fix line shifting: clear lines before writing, control newlines manually
- Limit visible items: prevent overflow with maxVisibleCategories/Commands
- Improve CPU usage: increase sleep interval when no events processed

This fixes:
- Enter key not working for selection
- Strong flickering of the application
- Menu bar not visible or being overwritten
- Top half of selection list not displayed
- Lines being shifted/misaligned
2025-11-10 11:06:07 +01:00

150 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Framework\Console\Helpers;
use App\Framework\Console\ConsoleColor;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\ConsoleStyle;
/**
* Enhanced test console output that captures all output for assertions
*/
final class TestConsoleOutput implements ConsoleOutputInterface
{
public array $capturedLines = [];
public array $capturedWrites = [];
public array $capturedErrors = [];
public array $capturedSuccesses = [];
public array $capturedWarnings = [];
public array $capturedInfos = [];
public int $newLineCount = 0;
public array $windowTitles = [];
public function write(string $message, ConsoleStyle|ConsoleColor|null $style = null): void
{
$this->capturedWrites[] = ['message' => $message, 'style' => $style];
}
public function writeLine(string $message = '', ?ConsoleColor $color = null): void
{
$this->capturedLines[] = ['message' => $message, 'color' => $color];
}
public function writeError(string $message): void
{
$this->capturedErrors[] = $message;
$this->capturedLines[] = ['message' => $message, 'type' => 'error'];
}
public function writeSuccess(string $message): void
{
$this->capturedSuccesses[] = $message;
$this->capturedLines[] = ['message' => $message, 'type' => 'success'];
}
public function writeWarning(string $message): void
{
$this->capturedWarnings[] = $message;
$this->capturedLines[] = ['message' => $message, 'type' => 'warning'];
}
public function writeInfo(string $message): void
{
$this->capturedInfos[] = $message;
$this->capturedLines[] = ['message' => $message, 'type' => 'info'];
}
public function newLine(int $count = 1): void
{
$this->newLineCount += $count;
for ($i = 0; $i < $count; $i++) {
$this->capturedLines[] = ['message' => '', 'type' => 'newline'];
}
}
public function askQuestion(string $question, ?string $default = null): string
{
$this->capturedLines[] = ['message' => $question, 'type' => 'question', 'default' => $default];
return $default ?? '';
}
public function confirm(string $question, bool $default = false): bool
{
$this->capturedLines[] = ['message' => $question, 'type' => 'confirm', 'default' => $default];
return $default;
}
public function writeWindowTitle(string $title, int $mode = 0): void
{
$this->windowTitles[] = ['title' => $title, 'mode' => $mode];
}
/**
* Get all captured output as plain text
*/
public function getOutput(): string
{
$output = [];
foreach ($this->capturedLines as $line) {
$output[] = $line['message'] ?? '';
}
return implode("\n", $output);
}
/**
* Get all captured writes
*/
public function getWrites(): array
{
return $this->capturedWrites;
}
/**
* Clear all captured output
*/
public function clear(): void
{
$this->capturedLines = [];
$this->capturedWrites = [];
$this->capturedErrors = [];
$this->capturedSuccesses = [];
$this->capturedWarnings = [];
$this->capturedInfos = [];
$this->newLineCount = 0;
$this->windowTitles = [];
}
/**
* Check if output contains a specific string
*/
public function contains(string $search): bool
{
$output = $this->getOutput();
return str_contains($output, $search);
}
/**
* Get last captured line
*/
public function getLastLine(): ?string
{
if (empty($this->capturedLines)) {
return null;
}
$last = end($this->capturedLines);
return $last['message'] ?? null;
}
}