Skip to content

Commit cd74785

Browse files
committed
fix: refactor inconsistent behavior on CLI::write() and CLI::error()
1 parent 246cbd4 commit cd74785

File tree

9 files changed

+117
-52
lines changed

9 files changed

+117
-52
lines changed

system/CLI/CLI.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ public static function prompt(string $field, $options = null, $validation = null
255255
}
256256

257257
static::fwrite(STDOUT, $field . (trim($field) !== '' ? ' ' : '') . $extraOutput . ': ');
258+
static::$lastWrite = 'write';
258259

259260
// Read the input from keyboard.
260261
$input = trim(static::$io->input());
@@ -458,7 +459,8 @@ public static function write(string $text = '', ?string $foreground = null, ?str
458459
}
459460

460461
if (static::$lastWrite !== 'write') {
461-
$text = PHP_EOL . $text;
462+
$text = PHP_EOL . $text;
463+
462464
static::$lastWrite = 'write';
463465
}
464466

@@ -473,13 +475,20 @@ public static function write(string $text = '', ?string $foreground = null, ?str
473475
public static function error(string $text, string $foreground = 'light_red', ?string $background = null)
474476
{
475477
// Check color support for STDERR
476-
$stdout = static::$isColored;
478+
$stdout = static::$isColored;
479+
477480
static::$isColored = static::hasColorSupport(STDERR);
478481

479482
if ($foreground !== '' || (string) $background !== '') {
480483
$text = static::color($text, $foreground, $background);
481484
}
482485

486+
if (static::$lastWrite !== 'write') {
487+
$text = PHP_EOL . $text;
488+
489+
static::$lastWrite = 'write';
490+
}
491+
483492
static::fwrite(STDERR, $text . PHP_EOL);
484493

485494
// return STDOUT color support

tests/system/CLI/CLITest.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ protected function setUp(): void
3737

3838
Services::injectMock('superglobals', new Superglobals());
3939

40+
CLI::reset();
4041
CLI::init();
4142
}
4243

@@ -393,24 +394,41 @@ public function testError(): void
393394
{
394395
CLI::error('test');
395396

396-
// red expected cuz stderr
397-
$expected = "\033[1;31mtest\033[0m" . PHP_EOL;
397+
$expected = PHP_EOL . "\033[1;31mtest\033[0m" . PHP_EOL;
398398
$this->assertSame($expected, $this->getStreamFilterBuffer());
399399
}
400400

401+
public function testMixedWriteError(): void
402+
{
403+
CLI::write('test 1');
404+
CLI::error('test 2');
405+
CLI::write('test 3');
406+
407+
$this->assertSame(
408+
<<<'EOT'
409+
410+
test 1
411+
test 2
412+
test 3
413+
414+
EOT,
415+
preg_replace('/\e\[[^m]+m/u', '', $this->getStreamFilterBuffer()),
416+
);
417+
}
418+
401419
public function testErrorForeground(): void
402420
{
403421
CLI::error('test', 'purple');
404422

405-
$expected = "\033[0;35mtest\033[0m" . PHP_EOL;
423+
$expected = PHP_EOL . "\033[0;35mtest\033[0m" . PHP_EOL;
406424
$this->assertSame($expected, $this->getStreamFilterBuffer());
407425
}
408426

409427
public function testErrorBackground(): void
410428
{
411429
CLI::error('test', 'purple', 'green');
412430

413-
$expected = "\033[0;35m\033[42mtest\033[0m" . PHP_EOL;
431+
$expected = PHP_EOL . "\033[0;35m\033[42mtest\033[0m" . PHP_EOL;
414432
$this->assertSame($expected, $this->getStreamFilterBuffer());
415433
}
416434

tests/system/CLI/CommandsTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public function testRunOnUnknownCommandButWithOneAlternative(): void
7474
$this->assertSame(EXIT_ERROR, $commands->run('app:inf', []));
7575
$this->assertSame(
7676
<<<'EOT'
77+
7778
Command "app:inf" not found.
7879
7980
Did you mean this?
@@ -91,6 +92,7 @@ public function testRunOnUnknownCommandButWithMultipleAlternatives(): void
9192
$this->assertSame(EXIT_ERROR, $commands->run('app:', []));
9293
$this->assertSame(
9394
<<<'EOT'
95+
9496
Command "app:" not found.
9597
9698
Did you mean one of these?

tests/system/Commands/Cache/ClearCacheTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use CodeIgniter\Cache\CacheFactory;
1717
use CodeIgniter\Cache\Handlers\FileHandler;
18+
use CodeIgniter\CLI\CLI;
1819
use CodeIgniter\Test\CIUnitTestCase;
1920
use CodeIgniter\Test\StreamFilterTrait;
2021
use Config\Services;
@@ -32,6 +33,7 @@ protected function setUp(): void
3233
{
3334
parent::setUp();
3435

36+
CLI::reset();
3537
$this->resetServices();
3638

3739
// Make sure we are testing with the correct handler (override injections)
@@ -42,6 +44,7 @@ protected function tearDown(): void
4244
{
4345
parent::tearDown();
4446

47+
CLI::reset();
4548
$this->resetServices();
4649
}
4750

@@ -50,7 +53,7 @@ public function testClearCacheInvalidHandler(): void
5053
command('cache:clear junk');
5154

5255
$this->assertSame(
53-
"Cache driver \"junk\" is not a valid cache handler.\n",
56+
"\nCache driver \"junk\" is not a valid cache handler.\n",
5457
preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()),
5558
);
5659
}
@@ -79,7 +82,7 @@ public function testClearCacheFails(): void
7982
command('cache:clear');
8083

8184
$this->assertSame(
82-
"Error while clearing the cache.\n",
85+
"\nError while clearing the cache.\n",
8386
preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()),
8487
);
8588
}

tests/system/Commands/Database/ShowTableInfoMockIOTest.php

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ protected function setUp(): void
3333
{
3434
parent::setUp();
3535

36+
CLI::reset();
37+
3638
putenv('NO_COLOR=1');
3739
CLI::init();
3840
}
@@ -41,6 +43,8 @@ protected function tearDown(): void
4143
{
4244
parent::tearDown();
4345

46+
CLI::reset();
47+
4448
putenv('NO_COLOR');
4549
CLI::init();
4650
}
@@ -58,17 +62,25 @@ public function testDbTableWithInputs(): void
5862

5963
$result = $io->getOutput();
6064

61-
$expectedPattern = '/Which table do you want to see\? \[0, 1, 2, 3, 4, 5, 6, 7, 8, 9.*?\]: a
62-
The "Which table do you want to see\?" field must be one of: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.*?./';
63-
$this->assertMatchesRegularExpression($expectedPattern, $result);
64-
65-
$expected = 'Data of Table "db_migrations":';
66-
$this->assertStringContainsString($expected, $result);
67-
68-
$expectedPattern = '/\| id[[:blank:]]+\| version[[:blank:]]+\| class[[:blank:]]+\| group[[:blank:]]+\| namespace[[:blank:]]+\| time[[:blank:]]+\| batch \|/';
69-
$this->assertMatchesRegularExpression($expectedPattern, $result);
70-
71-
// Remove MockInputOutput.
72-
CLI::resetInputOutput();
65+
$this->assertMatchesRegularExpression(
66+
'/Which table do you want to see\? \[[\d,\s]+\]\: a/',
67+
$result,
68+
);
69+
$this->assertMatchesRegularExpression(
70+
'/The "Which table do you want to see\?" field must be one of: [\d,\s]+./',
71+
$result,
72+
);
73+
$this->assertMatchesRegularExpression(
74+
'/Which table do you want to see\? \[[\d,\s]+\]\: 0/',
75+
$result,
76+
);
77+
$this->assertMatchesRegularExpression(
78+
'/Data of Table "db_migrations"\:/',
79+
$result,
80+
);
81+
$this->assertMatchesRegularExpression(
82+
'/\| id[[:blank:]]+\| version[[:blank:]]+\| class[[:blank:]]+\| group[[:blank:]]+\| namespace[[:blank:]]+\| time[[:blank:]]+\| batch \|/',
83+
$result,
84+
);
7385
}
7486
}

tests/system/Commands/Generators/TestGeneratorTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,6 @@ protected function setUp(): void
3333
parent::setUp();
3434

3535
$this->resetStreamFilterBuffer();
36-
37-
putenv('NO_COLOR=1');
38-
CLI::init();
3936
}
4037

4138
protected function tearDown(): void
@@ -44,14 +41,16 @@ protected function tearDown(): void
4441

4542
$this->clearTestFiles();
4643
$this->resetStreamFilterBuffer();
44+
}
4745

48-
putenv('NO_COLOR');
49-
CLI::init();
46+
private function getUndecoratedBuffer(): string
47+
{
48+
return preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer());
5049
}
5150

5251
private function clearTestFiles(): void
5352
{
54-
preg_match('/File created: (.*)/', $this->getStreamFilterBuffer(), $result);
53+
preg_match('/File created: (.*)/', $this->getUndecoratedBuffer(), $result);
5554

5655
$file = str_replace('ROOTPATH' . DIRECTORY_SEPARATOR, ROOTPATH, $result[1] ?? '');
5756
if (is_file($file)) {
@@ -71,7 +70,7 @@ public function testGenerateTestFiles(string $name, string $expectedClass): void
7170

7271
$expectedTestFile = str_replace('/', DIRECTORY_SEPARATOR, sprintf('%stests/%s.php', ROOTPATH, $expectedClass));
7372
$expectedMessage = sprintf('File created: %s', str_replace(ROOTPATH, 'ROOTPATH' . DIRECTORY_SEPARATOR, $expectedTestFile));
74-
$this->assertStringContainsString($expectedMessage, $this->getStreamFilterBuffer());
73+
$this->assertStringContainsString($expectedMessage, $this->getUndecoratedBuffer());
7574
$this->assertFileExists($expectedTestFile);
7675
}
7776

@@ -93,6 +92,7 @@ public static function provideGenerateTestFiles(): iterable
9392
public function testGenerateTestWithEmptyClassName(): void
9493
{
9594
$expectedFile = ROOTPATH . 'tests/FooTest.php';
95+
CLI::reset();
9696

9797
try {
9898
$io = new MockInputOutput();
@@ -106,7 +106,7 @@ public function testGenerateTestWithEmptyClassName(): void
106106
$expectedOutput .= 'The "Test class name" field is required.' . PHP_EOL;
107107
$expectedOutput .= 'Test class name : Foo' . PHP_EOL . PHP_EOL;
108108
$expectedOutput .= 'File created: ROOTPATH/tests/FooTest.php' . PHP_EOL . PHP_EOL;
109-
$this->assertSame($expectedOutput, $io->getOutput());
109+
$this->assertSame($expectedOutput, preg_replace('/\e\[[^m]+m/', '', $io->getOutput()));
110110
$this->assertFileExists($expectedFile);
111111
} finally {
112112
if (is_file($expectedFile)) {

tests/system/Commands/Housekeeping/ClearDebugbarTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace CodeIgniter\Commands\Housekeeping;
1515

16+
use CodeIgniter\CLI\CLI;
1617
use CodeIgniter\Test\CIUnitTestCase;
1718
use CodeIgniter\Test\StreamFilterTrait;
1819
use PHPUnit\Framework\Attributes\Group;
@@ -35,6 +36,8 @@ protected function setUp(): void
3536
command('debugbar:clear');
3637
$this->resetStreamFilterBuffer();
3738

39+
CLI::reset();
40+
3841
$this->time = time();
3942
$this->createDummyDebugbarJson();
4043
}
@@ -44,6 +47,8 @@ protected function tearDown(): void
4447
command('debugbar:clear');
4548
$this->resetStreamFilterBuffer();
4649

50+
CLI::reset();
51+
4752
parent::tearDown();
4853
}
4954

@@ -70,7 +75,7 @@ public function testClearDebugbarWorks(): void
7075
$this->assertFileDoesNotExist(WRITEPATH . 'debugbar' . DIRECTORY_SEPARATOR . "debugbar_{$this->time}.json");
7176
$this->assertFileExists(WRITEPATH . 'debugbar' . DIRECTORY_SEPARATOR . 'index.html');
7277
$this->assertSame(
73-
"Debugbar cleared.\n",
78+
"\nDebugbar cleared.\n",
7479
preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()),
7580
);
7681
}
@@ -111,7 +116,7 @@ public function testClearDebugbarWithError(): void
111116

112117
$this->assertFileExists($path);
113118
$this->assertSame(
114-
"Error deleting the debugbar JSON files.\n",
119+
"\nError deleting the debugbar JSON files.\n",
115120
preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()),
116121
);
117122
}

tests/system/Commands/Housekeeping/ClearLogsTest.php

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ protected function setUp(): void
4141
command('logs:clear --force');
4242
$this->resetStreamFilterBuffer();
4343

44+
CLI::reset();
45+
4446
$this->createDummyLogFiles();
4547
}
4648

@@ -78,7 +80,7 @@ public function testClearLogsUsingForce(): void
7880

7981
$this->assertFileDoesNotExist(WRITEPATH . 'logs' . DIRECTORY_SEPARATOR . "log-{$this->date}.log");
8082
$this->assertFileExists(WRITEPATH . 'logs' . DIRECTORY_SEPARATOR . 'index.html');
81-
$this->assertSame("Logs cleared.\n", preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()));
83+
$this->assertSame("\nLogs cleared.\n", preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()));
8284
}
8385

8486
public function testClearLogsAbortsClearWithoutForce(): void
@@ -94,11 +96,12 @@ public function testClearLogsAbortsClearWithoutForce(): void
9496
$this->assertFileExists(WRITEPATH . 'logs' . DIRECTORY_SEPARATOR . "log-{$this->date}.log");
9597
$this->assertSame(
9698
<<<'EOT'
99+
Are you sure you want to delete the logs? [n, y]: n
97100
Deleting logs aborted.
98101
If you want, use the "--force" option to force delete all log files.
99102

100103
EOT,
101-
preg_replace('/\e\[[^m]+m/', '', $io->getOutput(2) . $io->getOutput(3)),
104+
preg_replace('/\e\[[^m]+m/', '', $io->getOutput()),
102105
);
103106
}
104107

@@ -110,16 +113,19 @@ public function testClearLogsAbortsClearWithoutForceWithDefaultAnswer(): void
110113
$io->setInputs(['']);
111114
CLI::setInputOutput($io);
112115

116+
$space = ' ';
117+
113118
command('logs:clear');
114119

115120
$this->assertFileExists(WRITEPATH . 'logs' . DIRECTORY_SEPARATOR . "log-{$this->date}.log");
116121
$this->assertSame(
117-
<<<'EOT'
122+
<<<EOT
123+
Are you sure you want to delete the logs? [n, y]:{$space}
118124
Deleting logs aborted.
119125
If you want, use the "--force" option to force delete all log files.
120126
121127
EOT,
122-
preg_replace('/\e\[[^m]+m/', '', $io->getOutput(2) . $io->getOutput(3)),
128+
preg_replace('/\e\[[^m]+m/', '', $io->getOutput()),
123129
);
124130
}
125131

@@ -134,7 +140,13 @@ public function testClearLogsWithoutForceButWithConfirmation(): void
134140
command('logs:clear');
135141

136142
$this->assertFileDoesNotExist(WRITEPATH . 'logs' . DIRECTORY_SEPARATOR . "log-{$this->date}.log");
137-
$this->assertSame("Logs cleared.\n", preg_replace('/\e\[[^m]+m/', '', $io->getOutput(2)));
143+
$this->assertSame(
144+
<<<EOT
145+
Are you sure you want to delete the logs? [n, y]: y
146+
Logs cleared.
147+
148+
EOT,
149+
preg_replace('/\e\[[^m]+m/', '', $io->getOutput()));
138150
}
139151

140152
#[RequiresOperatingSystem('Darwin|Linux')]
@@ -173,6 +185,9 @@ public function testClearLogsFailsOnChmodFailure(): void
173185
}
174186

175187
$this->assertFileExists($path);
176-
$this->assertSame("Error in deleting the logs files.\n", preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()));
188+
$this->assertSame(
189+
"\nError in deleting the logs files.\n",
190+
preg_replace('/\e\[[^m]+m/', '', $this->getStreamFilterBuffer()),
191+
);
177192
}
178193
}

0 commit comments

Comments
 (0)