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
This commit is contained in:
103
tests/Framework/Console/CommandResultProcessorTest.php
Normal file
103
tests/Framework/Console/CommandResultProcessorTest.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Framework\Console;
|
||||
|
||||
use App\Framework\Console\CommandResultProcessor;
|
||||
use App\Framework\Console\ExitCode;
|
||||
use App\Framework\Console\Result\TextResult;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
use Tests\Framework\Console\Helpers\TestConsoleOutput;
|
||||
|
||||
describe('CommandResultProcessor', function () {
|
||||
beforeEach(function () {
|
||||
$this->container = new DefaultContainer();
|
||||
$this->output = new TestConsoleOutput();
|
||||
$this->processor = new CommandResultProcessor($this->container, $this->output);
|
||||
});
|
||||
|
||||
it('processes ConsoleResult', function () {
|
||||
$result = TextResult::success('Test output');
|
||||
$exitCode = $this->processor->process($result);
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::SUCCESS);
|
||||
expect($this->output->getOutput())->toContain('Test output');
|
||||
});
|
||||
|
||||
it('renders ConsoleResult to output', function () {
|
||||
$result = TextResult::success('Rendered message');
|
||||
$this->processor->process($result);
|
||||
|
||||
expect($this->output->getOutput())->toContain('Rendered message');
|
||||
});
|
||||
|
||||
it('processes ExitCode directly', function () {
|
||||
$exitCode = $this->processor->process(ExitCode::SUCCESS);
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::SUCCESS);
|
||||
});
|
||||
|
||||
it('processes different ExitCode values', function () {
|
||||
expect($this->processor->process(ExitCode::GENERAL_ERROR))->toBe(ExitCode::GENERAL_ERROR);
|
||||
expect($this->processor->process(ExitCode::COMMAND_NOT_FOUND))->toBe(ExitCode::COMMAND_NOT_FOUND);
|
||||
expect($this->processor->process(ExitCode::INVALID_INPUT))->toBe(ExitCode::INVALID_INPUT);
|
||||
});
|
||||
|
||||
it('processes legacy int return values', function () {
|
||||
$exitCode = $this->processor->process(0);
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::SUCCESS);
|
||||
expect($exitCode->value)->toBe(0);
|
||||
});
|
||||
|
||||
it('converts int to ExitCode', function () {
|
||||
expect($this->processor->process(1))->toBe(ExitCode::GENERAL_ERROR);
|
||||
expect($this->processor->process(64))->toBe(ExitCode::COMMAND_NOT_FOUND);
|
||||
});
|
||||
|
||||
it('handles invalid return types', function () {
|
||||
$exitCode = $this->processor->process('invalid');
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::GENERAL_ERROR);
|
||||
});
|
||||
|
||||
it('handles null return type', function () {
|
||||
$exitCode = $this->processor->process(null);
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::GENERAL_ERROR);
|
||||
});
|
||||
|
||||
it('handles array return type', function () {
|
||||
$exitCode = $this->processor->process([]);
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::GENERAL_ERROR);
|
||||
});
|
||||
|
||||
it('handles object return type', function () {
|
||||
$exitCode = $this->processor->process(new \stdClass());
|
||||
|
||||
expect($exitCode)->toBe(ExitCode::GENERAL_ERROR);
|
||||
});
|
||||
|
||||
it('processes ConsoleResult with different exit codes', function () {
|
||||
$successResult = TextResult::success('Success');
|
||||
expect($this->processor->process($successResult))->toBe(ExitCode::SUCCESS);
|
||||
|
||||
$errorResult = TextResult::error('Error');
|
||||
expect($this->processor->process($errorResult))->toBe(ExitCode::FAILURE);
|
||||
});
|
||||
|
||||
it('renders multiple ConsoleResults correctly', function () {
|
||||
$result1 = TextResult::success('First message');
|
||||
$result2 = TextResult::success('Second message');
|
||||
|
||||
$this->processor->process($result1);
|
||||
$this->output->clear();
|
||||
$this->processor->process($result2);
|
||||
|
||||
expect($this->output->getOutput())->toContain('Second message');
|
||||
expect($this->output->getOutput())->not->toContain('First message');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user