- 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
153 lines
5.4 KiB
PHP
153 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Framework\Console;
|
|
|
|
use App\Framework\Console\CommandCategorizer;
|
|
use App\Framework\Console\CommandList;
|
|
use App\Framework\Console\ConsoleCommand;
|
|
|
|
describe('CommandCategorizer', function () {
|
|
it('categorizes commands by namespace prefix', function () {
|
|
$commands = [
|
|
new ConsoleCommand('demo:hello', 'Hello command'),
|
|
new ConsoleCommand('demo:colors', 'Colors command'),
|
|
new ConsoleCommand('db:migrate', 'Migrate command'),
|
|
new ConsoleCommand('db:rollback', 'Rollback command'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
expect($categories)->toHaveKey('demo');
|
|
expect($categories)->toHaveKey('db');
|
|
expect($categories['demo'])->toHaveCount(2);
|
|
expect($categories['db'])->toHaveCount(2);
|
|
});
|
|
|
|
it('sorts categories alphabetically', function () {
|
|
$commands = [
|
|
new ConsoleCommand('zebra:command', 'Zebra command'),
|
|
new ConsoleCommand('alpha:command', 'Alpha command'),
|
|
new ConsoleCommand('beta:command', 'Beta command'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
$keys = array_keys($categories);
|
|
expect($keys)->toBe(['alpha', 'beta', 'zebra']);
|
|
});
|
|
|
|
it('handles commands without namespace', function () {
|
|
$commands = [
|
|
new ConsoleCommand('standalone', 'Standalone command'),
|
|
new ConsoleCommand('demo:hello', 'Hello command'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
expect($categories)->toHaveKey('standalone');
|
|
expect($categories)->toHaveKey('demo');
|
|
expect($categories['standalone'])->toHaveCount(1);
|
|
});
|
|
|
|
it('handles empty command list', function () {
|
|
$commandList = CommandList::empty();
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
expect($categories)->toBeEmpty();
|
|
});
|
|
|
|
it('groups multiple commands in same category', function () {
|
|
$commands = [
|
|
new ConsoleCommand('demo:hello', 'Hello'),
|
|
new ConsoleCommand('demo:colors', 'Colors'),
|
|
new ConsoleCommand('demo:interactive', 'Interactive'),
|
|
new ConsoleCommand('demo:menu', 'Menu'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
expect($categories['demo'])->toHaveCount(4);
|
|
});
|
|
|
|
it('handles commands with multiple colons', function () {
|
|
$commands = [
|
|
new ConsoleCommand('db:migrate:up', 'Migrate up'),
|
|
new ConsoleCommand('db:migrate:down', 'Migrate down'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
// Should use first part before first colon
|
|
expect($categories)->toHaveKey('db');
|
|
expect($categories['db'])->toHaveCount(2);
|
|
});
|
|
|
|
it('gets category description for known category', function () {
|
|
$categorizer = new CommandCategorizer();
|
|
|
|
expect($categorizer->getCategoryDescription('db'))->toBe('Database operations (migrations, health checks)');
|
|
expect($categorizer->getCategoryDescription('demo'))->toBe('Demo and example commands');
|
|
expect($categorizer->getCategoryDescription('cache'))->toBe('Cache management operations');
|
|
});
|
|
|
|
it('returns default description for unknown category', function () {
|
|
$categorizer = new CommandCategorizer();
|
|
|
|
expect($categorizer->getCategoryDescription('unknown'))->toBe('Various commands');
|
|
});
|
|
|
|
it('gets all category info', function () {
|
|
$categorizer = new CommandCategorizer();
|
|
$info = $categorizer->getCategoryInfo();
|
|
|
|
expect($info)->toBeArray();
|
|
expect($info)->toHaveKey('db');
|
|
expect($info)->toHaveKey('demo');
|
|
expect($info)->toHaveKey('cache');
|
|
});
|
|
|
|
it('handles single command in category', function () {
|
|
$commands = [
|
|
new ConsoleCommand('unique:command', 'Unique command'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
expect($categories)->toHaveKey('unique');
|
|
expect($categories['unique'])->toHaveCount(1);
|
|
});
|
|
|
|
it('preserves command order within category', function () {
|
|
$commands = [
|
|
new ConsoleCommand('demo:first', 'First'),
|
|
new ConsoleCommand('demo:second', 'Second'),
|
|
new ConsoleCommand('demo:third', 'Third'),
|
|
];
|
|
|
|
$commandList = new CommandList(...$commands);
|
|
$categorizer = new CommandCategorizer();
|
|
$categories = $categorizer->categorize($commandList);
|
|
|
|
$demoCommands = $categories['demo'];
|
|
expect($demoCommands[0]->name)->toBe('demo:first');
|
|
expect($demoCommands[1]->name)->toBe('demo:second');
|
|
expect($demoCommands[2]->name)->toBe('demo:third');
|
|
});
|
|
});
|
|
|