- 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
228 lines
6.3 KiB
PHP
228 lines
6.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Framework\Console;
|
|
|
|
use App\Framework\Console\InteractiveForm;
|
|
use App\Framework\Console\ParameterInspector;
|
|
use Tests\Framework\Console\Helpers\TestConsoleOutput;
|
|
|
|
class TestCommand
|
|
{
|
|
public function testMethod(string $name, int $age = 18): void
|
|
{
|
|
}
|
|
}
|
|
|
|
describe('InteractiveForm', function () {
|
|
beforeEach(function () {
|
|
$this->output = new TestConsoleOutput();
|
|
$this->inspector = new ParameterInspector();
|
|
$this->form = new InteractiveForm($this->output, $this->inspector);
|
|
});
|
|
|
|
it('can be instantiated', function () {
|
|
expect($this->form)->toBeInstanceOf(InteractiveForm::class);
|
|
});
|
|
|
|
it('creates form from command', function () {
|
|
$command = new TestCommand();
|
|
$form = InteractiveForm::forCommand($command, $this->output, 'testMethod');
|
|
|
|
expect($form)->toBeInstanceOf(InteractiveForm::class);
|
|
});
|
|
|
|
it('adds field to form', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'test',
|
|
'description' => 'Test field',
|
|
'type' => ['name' => 'string'],
|
|
'required' => true,
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('adds multiple fields', function () {
|
|
$form = $this->form
|
|
->addField(['name' => 'field1', 'description' => 'Field 1'])
|
|
->addField(['name' => 'field2', 'description' => 'Field 2']);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('merges default field configuration', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'test',
|
|
'description' => 'Test',
|
|
]);
|
|
|
|
// Should have default values merged
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('gets values', function () {
|
|
// Initially empty
|
|
expect($this->form->getValues())->toBeEmpty();
|
|
});
|
|
|
|
it('checks if form is completed', function () {
|
|
expect($this->form->isCompleted())->toBeFalse();
|
|
});
|
|
|
|
it('returns empty array when run with no fields', function () {
|
|
$values = $this->form->run();
|
|
|
|
expect($values)->toBeEmpty();
|
|
});
|
|
|
|
it('has run method', function () {
|
|
expect(method_exists($this->form, 'run'))->toBeTrue();
|
|
});
|
|
|
|
it('handles required fields', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'required_field',
|
|
'description' => 'Required field',
|
|
'required' => true,
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('handles optional fields with defaults', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'optional_field',
|
|
'description' => 'Optional field',
|
|
'required' => false,
|
|
'default' => 'default value',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('handles different field types', function () {
|
|
$form = $this->form
|
|
->addField(['name' => 'text', 'input_type' => 'text'])
|
|
->addField(['name' => 'boolean', 'input_type' => 'boolean'])
|
|
->addField(['name' => 'number', 'input_type' => 'number'])
|
|
->addField(['name' => 'password', 'input_type' => 'password'])
|
|
->addField(['name' => 'file', 'input_type' => 'file'])
|
|
->addField(['name' => 'list', 'input_type' => 'list']);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('handles validation rules', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'email',
|
|
'description' => 'Email address',
|
|
'validation_rules' => [
|
|
'type' => 'string',
|
|
'format' => 'email',
|
|
'required' => true,
|
|
],
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('handles min/max validation for numbers', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'age',
|
|
'description' => 'Age',
|
|
'input_type' => 'number',
|
|
'validation_rules' => [
|
|
'type' => 'integer',
|
|
'min' => 0,
|
|
'max' => 120,
|
|
'required' => true,
|
|
],
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('handles many fields', function () {
|
|
$form = $this->form;
|
|
for ($i = 1; $i <= 50; $i++) {
|
|
$form = $form->addField([
|
|
'name' => "field{$i}",
|
|
'description' => "Field {$i}",
|
|
]);
|
|
}
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
});
|
|
|
|
describe('InteractiveForm Field Configuration', function () {
|
|
beforeEach(function () {
|
|
$this->output = new TestConsoleOutput();
|
|
$this->inspector = new ParameterInspector();
|
|
$this->form = new InteractiveForm($this->output, $this->inspector);
|
|
});
|
|
|
|
it('creates text field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'name',
|
|
'description' => 'Name',
|
|
'input_type' => 'text',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('creates boolean field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'active',
|
|
'description' => 'Active',
|
|
'input_type' => 'boolean',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('creates number field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'count',
|
|
'description' => 'Count',
|
|
'input_type' => 'number',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('creates password field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'password',
|
|
'description' => 'Password',
|
|
'input_type' => 'password',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('creates file field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'file',
|
|
'description' => 'File path',
|
|
'input_type' => 'file',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
|
|
it('creates list field', function () {
|
|
$form = $this->form->addField([
|
|
'name' => 'items',
|
|
'description' => 'Items',
|
|
'input_type' => 'list',
|
|
]);
|
|
|
|
expect($form)->toBe($this->form);
|
|
});
|
|
});
|
|
|