'val1'], ['opt1' => 'val2'] ); $this->assertEquals('val1', $adapter->getArgument('arg1')); $this->assertEquals('default', $adapter->getArgument('arg2', 'default')); $this->assertEquals('val2', $adapter->getOption('opt1')); $this->assertTrue($adapter->hasOption('opt1')); $this->assertFalse($adapter->hasOption('opt2')); } public function testOutputAdapterFormatting(): void { $adapter = new OutputAdapter(true); ob_start(); $adapter->info('test'); $output = ob_get_clean(); $this->assertStringContainsString("\033[34mtest\033[0m", $output); $adapter = new OutputAdapter(false); ob_start(); $adapter->info('test'); $output = ob_get_clean(); $this->assertEquals("test" . PHP_EOL, $output); } public function testTableAdapter(): void { $output = new OutputAdapter(false); $table = new TableAdapter($output); $table->setHeaders(['ID', 'Name', 'Status']); $table->setColumnAlignments([0 => 'right', 1 => 'left', 2 => 'center']); $table->addRow([1, 'John', 'Active']); $table->addRow([100, 'Jane', 'Inactive']); ob_start(); $table->render(); $content = ob_get_clean(); // ID column (right aligned) $this->assertStringContainsString('| 1 |', $content); $this->assertStringContainsString('| 100 |', $content); // Name column (left aligned) $this->assertStringContainsString('| John |', $content); // Status column (center aligned) $this->assertStringContainsString('| Active |', $content); } public function testTableAdapterWithTags(): void { $output = new OutputAdapter(false); $table = new TableAdapter($output); // Header with tags (8 chars displayed, more in raw string) $table->setHeaders(['ID', 'Name']); $table->addRow(['1', 'John']); ob_start(); $table->render(); $content = ob_get_clean(); // If bug exists, the ID column width will be 13 (mb_strlen('ID')) // but it should be 2 (length of 'ID') // The separator line will have '-' x (width + 2) // Correct width 2 -> "+----+" // Buggy width 13 -> "+---------------+" $this->assertStringContainsString('+----+', $content); } public function testMarkdownConverter(): void { $output = new OutputAdapter(false); $converter = new MarkdownConverter($output); $this->assertEquals('Title', $converter->convert('# Title')); $this->assertEquals('Bold', $converter->convert('**Bold**')); $this->assertEquals('Italic', $converter->convert('*Italic*')); $this->assertEquals('code', $converter->convert('`code`')); } public function testMarkdownTableConverter(): void { $output = new OutputAdapter(false); $converter = new MarkdownConverter($output); $markdown = <<convert($markdown); $this->assertStringContainsString('| ID | Name |', $result); $this->assertStringContainsString('| 1 | John |', $result); } public function testInteractionAdapter(): void { $input = fopen('php://memory', 'r+'); if ($input === false) { $this->fail('Could not open memory stream'); } fwrite($input, "John\ny\nsecret\n1\n"); rewind($input); $adapter = new InteractionAdapter($input); ob_start(); $this->assertEquals('John', $adapter->ask('Name')); $this->assertTrue($adapter->confirm('Continue?')); $this->assertEquals('secret', $adapter->secret('Password')); $this->assertEquals('Choice 2', $adapter->choice('Select', ['0' => 'Choice 1', '1' => 'Choice 2'])); ob_end_clean(); fclose($input); } public function testProgressBarAdapter(): void { $output = new OutputAdapter(false); $bar = new ProgressBarAdapter($output); ob_start(); $bar->start(100); $bar->advance(50); $bar->finish(); $content = ob_get_clean(); $this->assertStringContainsString('50%', $content); $this->assertStringContainsString('100%', $content); } }