ProgressBarTest.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Console\Tests\Helper;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Console\Helper\ProgressBar;
  13. use Symfony\Component\Console\Helper\Helper;
  14. use Symfony\Component\Console\Output\StreamOutput;
  15. /**
  16. * @group time-sensitive
  17. */
  18. class ProgressBarTest extends TestCase
  19. {
  20. public function testMultipleStart()
  21. {
  22. $bar = new ProgressBar($output = $this->getOutputStream());
  23. $bar->start();
  24. $bar->advance();
  25. $bar->start();
  26. rewind($output->getStream());
  27. $this->assertEquals(
  28. ' 0 [>---------------------------]'.
  29. $this->generateOutput(' 1 [->--------------------------]').
  30. $this->generateOutput(' 0 [>---------------------------]'),
  31. stream_get_contents($output->getStream())
  32. );
  33. }
  34. public function testAdvance()
  35. {
  36. $bar = new ProgressBar($output = $this->getOutputStream());
  37. $bar->start();
  38. $bar->advance();
  39. rewind($output->getStream());
  40. $this->assertEquals(
  41. ' 0 [>---------------------------]'.
  42. $this->generateOutput(' 1 [->--------------------------]'),
  43. stream_get_contents($output->getStream())
  44. );
  45. }
  46. public function testAdvanceWithStep()
  47. {
  48. $bar = new ProgressBar($output = $this->getOutputStream());
  49. $bar->start();
  50. $bar->advance(5);
  51. rewind($output->getStream());
  52. $this->assertEquals(
  53. ' 0 [>---------------------------]'.
  54. $this->generateOutput(' 5 [----->----------------------]'),
  55. stream_get_contents($output->getStream())
  56. );
  57. }
  58. public function testAdvanceMultipleTimes()
  59. {
  60. $bar = new ProgressBar($output = $this->getOutputStream());
  61. $bar->start();
  62. $bar->advance(3);
  63. $bar->advance(2);
  64. rewind($output->getStream());
  65. $this->assertEquals(
  66. ' 0 [>---------------------------]'.
  67. $this->generateOutput(' 3 [--->------------------------]').
  68. $this->generateOutput(' 5 [----->----------------------]'),
  69. stream_get_contents($output->getStream())
  70. );
  71. }
  72. public function testAdvanceOverMax()
  73. {
  74. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  75. $bar->setProgress(9);
  76. $bar->advance();
  77. $bar->advance();
  78. rewind($output->getStream());
  79. $this->assertEquals(
  80. ' 9/10 [=========================>--] 90%'.
  81. $this->generateOutput(' 10/10 [============================] 100%').
  82. $this->generateOutput(' 11/11 [============================] 100%'),
  83. stream_get_contents($output->getStream())
  84. );
  85. }
  86. public function testRegress()
  87. {
  88. $bar = new ProgressBar($output = $this->getOutputStream());
  89. $bar->start();
  90. $bar->advance();
  91. $bar->advance();
  92. $bar->advance(-1);
  93. rewind($output->getStream());
  94. $this->assertEquals(
  95. ' 0 [>---------------------------]'.
  96. $this->generateOutput(' 1 [->--------------------------]').
  97. $this->generateOutput(' 2 [-->-------------------------]').
  98. $this->generateOutput(' 1 [->--------------------------]'),
  99. stream_get_contents($output->getStream())
  100. );
  101. }
  102. public function testRegressWithStep()
  103. {
  104. $bar = new ProgressBar($output = $this->getOutputStream());
  105. $bar->start();
  106. $bar->advance(4);
  107. $bar->advance(4);
  108. $bar->advance(-2);
  109. rewind($output->getStream());
  110. $this->assertEquals(
  111. ' 0 [>---------------------------]'.
  112. $this->generateOutput(' 4 [---->-----------------------]').
  113. $this->generateOutput(' 8 [-------->-------------------]').
  114. $this->generateOutput(' 6 [------>---------------------]'),
  115. stream_get_contents($output->getStream())
  116. );
  117. }
  118. public function testRegressMultipleTimes()
  119. {
  120. $bar = new ProgressBar($output = $this->getOutputStream());
  121. $bar->start();
  122. $bar->advance(3);
  123. $bar->advance(3);
  124. $bar->advance(-1);
  125. $bar->advance(-2);
  126. rewind($output->getStream());
  127. $this->assertEquals(
  128. ' 0 [>---------------------------]'.
  129. $this->generateOutput(' 3 [--->------------------------]').
  130. $this->generateOutput(' 6 [------>---------------------]').
  131. $this->generateOutput(' 5 [----->----------------------]').
  132. $this->generateOutput(' 3 [--->------------------------]'),
  133. stream_get_contents($output->getStream())
  134. );
  135. }
  136. public function testRegressBelowMin()
  137. {
  138. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  139. $bar->setProgress(1);
  140. $bar->advance(-1);
  141. $bar->advance(-1);
  142. rewind($output->getStream());
  143. $this->assertEquals(
  144. ' 1/10 [==>-------------------------] 10%'.
  145. $this->generateOutput(' 0/10 [>---------------------------] 0%'),
  146. stream_get_contents($output->getStream())
  147. );
  148. }
  149. public function testFormat()
  150. {
  151. $expected =
  152. ' 0/10 [>---------------------------] 0%'.
  153. $this->generateOutput(' 10/10 [============================] 100%').
  154. $this->generateOutput(' 10/10 [============================] 100%')
  155. ;
  156. // max in construct, no format
  157. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  158. $bar->start();
  159. $bar->advance(10);
  160. $bar->finish();
  161. rewind($output->getStream());
  162. $this->assertEquals($expected, stream_get_contents($output->getStream()));
  163. // max in start, no format
  164. $bar = new ProgressBar($output = $this->getOutputStream());
  165. $bar->start(10);
  166. $bar->advance(10);
  167. $bar->finish();
  168. rewind($output->getStream());
  169. $this->assertEquals($expected, stream_get_contents($output->getStream()));
  170. // max in construct, explicit format before
  171. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  172. $bar->setFormat('normal');
  173. $bar->start();
  174. $bar->advance(10);
  175. $bar->finish();
  176. rewind($output->getStream());
  177. $this->assertEquals($expected, stream_get_contents($output->getStream()));
  178. // max in start, explicit format before
  179. $bar = new ProgressBar($output = $this->getOutputStream());
  180. $bar->setFormat('normal');
  181. $bar->start(10);
  182. $bar->advance(10);
  183. $bar->finish();
  184. rewind($output->getStream());
  185. $this->assertEquals($expected, stream_get_contents($output->getStream()));
  186. }
  187. public function testCustomizations()
  188. {
  189. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  190. $bar->setBarWidth(10);
  191. $bar->setBarCharacter('_');
  192. $bar->setEmptyBarCharacter(' ');
  193. $bar->setProgressCharacter('/');
  194. $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
  195. $bar->start();
  196. $bar->advance();
  197. rewind($output->getStream());
  198. $this->assertEquals(
  199. ' 0/10 [/ ] 0%'.
  200. $this->generateOutput(' 1/10 [_/ ] 10%'),
  201. stream_get_contents($output->getStream())
  202. );
  203. }
  204. public function testDisplayWithoutStart()
  205. {
  206. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  207. $bar->display();
  208. rewind($output->getStream());
  209. $this->assertEquals(
  210. ' 0/50 [>---------------------------] 0%',
  211. stream_get_contents($output->getStream())
  212. );
  213. }
  214. public function testDisplayWithQuietVerbosity()
  215. {
  216. $bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50);
  217. $bar->display();
  218. rewind($output->getStream());
  219. $this->assertEquals(
  220. '',
  221. stream_get_contents($output->getStream())
  222. );
  223. }
  224. public function testFinishWithoutStart()
  225. {
  226. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  227. $bar->finish();
  228. rewind($output->getStream());
  229. $this->assertEquals(
  230. ' 50/50 [============================] 100%',
  231. stream_get_contents($output->getStream())
  232. );
  233. }
  234. public function testPercent()
  235. {
  236. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  237. $bar->start();
  238. $bar->display();
  239. $bar->advance();
  240. $bar->advance();
  241. rewind($output->getStream());
  242. $this->assertEquals(
  243. ' 0/50 [>---------------------------] 0%'.
  244. $this->generateOutput(' 0/50 [>---------------------------] 0%').
  245. $this->generateOutput(' 1/50 [>---------------------------] 2%').
  246. $this->generateOutput(' 2/50 [=>--------------------------] 4%'),
  247. stream_get_contents($output->getStream())
  248. );
  249. }
  250. public function testOverwriteWithShorterLine()
  251. {
  252. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  253. $bar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
  254. $bar->start();
  255. $bar->display();
  256. $bar->advance();
  257. // set shorter format
  258. $bar->setFormat(' %current%/%max% [%bar%]');
  259. $bar->advance();
  260. rewind($output->getStream());
  261. $this->assertEquals(
  262. ' 0/50 [>---------------------------] 0%'.
  263. $this->generateOutput(' 0/50 [>---------------------------] 0%').
  264. $this->generateOutput(' 1/50 [>---------------------------] 2%').
  265. $this->generateOutput(' 2/50 [=>--------------------------]'),
  266. stream_get_contents($output->getStream())
  267. );
  268. }
  269. public function testStartWithMax()
  270. {
  271. $bar = new ProgressBar($output = $this->getOutputStream());
  272. $bar->setFormat('%current%/%max% [%bar%]');
  273. $bar->start(50);
  274. $bar->advance();
  275. rewind($output->getStream());
  276. $this->assertEquals(
  277. ' 0/50 [>---------------------------]'.
  278. $this->generateOutput(' 1/50 [>---------------------------]'),
  279. stream_get_contents($output->getStream())
  280. );
  281. }
  282. public function testSetCurrentProgress()
  283. {
  284. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  285. $bar->start();
  286. $bar->display();
  287. $bar->advance();
  288. $bar->setProgress(15);
  289. $bar->setProgress(25);
  290. rewind($output->getStream());
  291. $this->assertEquals(
  292. ' 0/50 [>---------------------------] 0%'.
  293. $this->generateOutput(' 0/50 [>---------------------------] 0%').
  294. $this->generateOutput(' 1/50 [>---------------------------] 2%').
  295. $this->generateOutput(' 15/50 [========>-------------------] 30%').
  296. $this->generateOutput(' 25/50 [==============>-------------] 50%'),
  297. stream_get_contents($output->getStream())
  298. );
  299. }
  300. public function testSetCurrentBeforeStarting()
  301. {
  302. $bar = new ProgressBar($this->getOutputStream());
  303. $bar->setProgress(15);
  304. $this->assertNotNull($bar->getStartTime());
  305. }
  306. public function testRedrawFrequency()
  307. {
  308. $bar = new ProgressBar($output = $this->getOutputStream(), 6);
  309. $bar->setRedrawFrequency(2);
  310. $bar->start();
  311. $bar->setProgress(1);
  312. $bar->advance(2);
  313. $bar->advance(2);
  314. $bar->advance(1);
  315. rewind($output->getStream());
  316. $this->assertEquals(
  317. ' 0/6 [>---------------------------] 0%'.
  318. $this->generateOutput(' 3/6 [==============>-------------] 50%').
  319. $this->generateOutput(' 5/6 [=======================>----] 83%').
  320. $this->generateOutput(' 6/6 [============================] 100%'),
  321. stream_get_contents($output->getStream())
  322. );
  323. }
  324. public function testRedrawFrequencyIsAtLeastOneIfZeroGiven()
  325. {
  326. $bar = new ProgressBar($output = $this->getOutputStream());
  327. $bar->setRedrawFrequency(0);
  328. $bar->start();
  329. $bar->advance();
  330. rewind($output->getStream());
  331. $this->assertEquals(
  332. ' 0 [>---------------------------]'.
  333. $this->generateOutput(' 1 [->--------------------------]'),
  334. stream_get_contents($output->getStream())
  335. );
  336. }
  337. public function testRedrawFrequencyIsAtLeastOneIfSmallerOneGiven()
  338. {
  339. $bar = new ProgressBar($output = $this->getOutputStream());
  340. $bar->setRedrawFrequency(0.9);
  341. $bar->start();
  342. $bar->advance();
  343. rewind($output->getStream());
  344. $this->assertEquals(
  345. ' 0 [>---------------------------]'.
  346. $this->generateOutput(' 1 [->--------------------------]'),
  347. stream_get_contents($output->getStream())
  348. );
  349. }
  350. public function testMultiByteSupport()
  351. {
  352. $bar = new ProgressBar($output = $this->getOutputStream());
  353. $bar->start();
  354. $bar->setBarCharacter('■');
  355. $bar->advance(3);
  356. rewind($output->getStream());
  357. $this->assertEquals(
  358. ' 0 [>---------------------------]'.
  359. $this->generateOutput(' 3 [■■■>------------------------]'),
  360. stream_get_contents($output->getStream())
  361. );
  362. }
  363. public function testClear()
  364. {
  365. $bar = new ProgressBar($output = $this->getOutputStream(), 50);
  366. $bar->start();
  367. $bar->setProgress(25);
  368. $bar->clear();
  369. rewind($output->getStream());
  370. $this->assertEquals(
  371. ' 0/50 [>---------------------------] 0%'.
  372. $this->generateOutput(' 25/50 [==============>-------------] 50%').
  373. $this->generateOutput(''),
  374. stream_get_contents($output->getStream())
  375. );
  376. }
  377. public function testPercentNotHundredBeforeComplete()
  378. {
  379. $bar = new ProgressBar($output = $this->getOutputStream(), 200);
  380. $bar->start();
  381. $bar->display();
  382. $bar->advance(199);
  383. $bar->advance();
  384. rewind($output->getStream());
  385. $this->assertEquals(
  386. ' 0/200 [>---------------------------] 0%'.
  387. $this->generateOutput(' 0/200 [>---------------------------] 0%').
  388. $this->generateOutput(' 199/200 [===========================>] 99%').
  389. $this->generateOutput(' 200/200 [============================] 100%'),
  390. stream_get_contents($output->getStream())
  391. );
  392. }
  393. public function testNonDecoratedOutput()
  394. {
  395. $bar = new ProgressBar($output = $this->getOutputStream(false), 200);
  396. $bar->start();
  397. for ($i = 0; $i < 200; ++$i) {
  398. $bar->advance();
  399. }
  400. $bar->finish();
  401. rewind($output->getStream());
  402. $this->assertEquals(
  403. ' 0/200 [>---------------------------] 0%'.PHP_EOL.
  404. ' 20/200 [==>-------------------------] 10%'.PHP_EOL.
  405. ' 40/200 [=====>----------------------] 20%'.PHP_EOL.
  406. ' 60/200 [========>-------------------] 30%'.PHP_EOL.
  407. ' 80/200 [===========>----------------] 40%'.PHP_EOL.
  408. ' 100/200 [==============>-------------] 50%'.PHP_EOL.
  409. ' 120/200 [================>-----------] 60%'.PHP_EOL.
  410. ' 140/200 [===================>--------] 70%'.PHP_EOL.
  411. ' 160/200 [======================>-----] 80%'.PHP_EOL.
  412. ' 180/200 [=========================>--] 90%'.PHP_EOL.
  413. ' 200/200 [============================] 100%',
  414. stream_get_contents($output->getStream())
  415. );
  416. }
  417. public function testNonDecoratedOutputWithClear()
  418. {
  419. $bar = new ProgressBar($output = $this->getOutputStream(false), 50);
  420. $bar->start();
  421. $bar->setProgress(25);
  422. $bar->clear();
  423. $bar->setProgress(50);
  424. $bar->finish();
  425. rewind($output->getStream());
  426. $this->assertEquals(
  427. ' 0/50 [>---------------------------] 0%'.PHP_EOL.
  428. ' 25/50 [==============>-------------] 50%'.PHP_EOL.
  429. ' 50/50 [============================] 100%',
  430. stream_get_contents($output->getStream())
  431. );
  432. }
  433. public function testNonDecoratedOutputWithoutMax()
  434. {
  435. $bar = new ProgressBar($output = $this->getOutputStream(false));
  436. $bar->start();
  437. $bar->advance();
  438. rewind($output->getStream());
  439. $this->assertEquals(
  440. ' 0 [>---------------------------]'.PHP_EOL.
  441. ' 1 [->--------------------------]',
  442. stream_get_contents($output->getStream())
  443. );
  444. }
  445. public function testParallelBars()
  446. {
  447. $output = $this->getOutputStream();
  448. $bar1 = new ProgressBar($output, 2);
  449. $bar2 = new ProgressBar($output, 3);
  450. $bar2->setProgressCharacter('#');
  451. $bar3 = new ProgressBar($output);
  452. $bar1->start();
  453. $output->write("\n");
  454. $bar2->start();
  455. $output->write("\n");
  456. $bar3->start();
  457. for ($i = 1; $i <= 3; ++$i) {
  458. // up two lines
  459. $output->write("\033[2A");
  460. if ($i <= 2) {
  461. $bar1->advance();
  462. }
  463. $output->write("\n");
  464. $bar2->advance();
  465. $output->write("\n");
  466. $bar3->advance();
  467. }
  468. $output->write("\033[2A");
  469. $output->write("\n");
  470. $output->write("\n");
  471. $bar3->finish();
  472. rewind($output->getStream());
  473. $this->assertEquals(
  474. ' 0/2 [>---------------------------] 0%'."\n".
  475. ' 0/3 [#---------------------------] 0%'."\n".
  476. rtrim(' 0 [>---------------------------]').
  477. "\033[2A".
  478. $this->generateOutput(' 1/2 [==============>-------------] 50%')."\n".
  479. $this->generateOutput(' 1/3 [=========#------------------] 33%')."\n".
  480. rtrim($this->generateOutput(' 1 [->--------------------------]')).
  481. "\033[2A".
  482. $this->generateOutput(' 2/2 [============================] 100%')."\n".
  483. $this->generateOutput(' 2/3 [==================#---------] 66%')."\n".
  484. rtrim($this->generateOutput(' 2 [-->-------------------------]')).
  485. "\033[2A".
  486. "\n".
  487. $this->generateOutput(' 3/3 [============================] 100%')."\n".
  488. rtrim($this->generateOutput(' 3 [--->------------------------]')).
  489. "\033[2A".
  490. "\n".
  491. "\n".
  492. rtrim($this->generateOutput(' 3 [============================]')),
  493. stream_get_contents($output->getStream())
  494. );
  495. }
  496. public function testWithoutMax()
  497. {
  498. $output = $this->getOutputStream();
  499. $bar = new ProgressBar($output);
  500. $bar->start();
  501. $bar->advance();
  502. $bar->advance();
  503. $bar->advance();
  504. $bar->finish();
  505. rewind($output->getStream());
  506. $this->assertEquals(
  507. rtrim(' 0 [>---------------------------]').
  508. rtrim($this->generateOutput(' 1 [->--------------------------]')).
  509. rtrim($this->generateOutput(' 2 [-->-------------------------]')).
  510. rtrim($this->generateOutput(' 3 [--->------------------------]')).
  511. rtrim($this->generateOutput(' 3 [============================]')),
  512. stream_get_contents($output->getStream())
  513. );
  514. }
  515. public function testWithSmallScreen()
  516. {
  517. $output = $this->getOutputStream();
  518. $bar = new ProgressBar($output);
  519. putenv('COLUMNS=12');
  520. $bar->start();
  521. $bar->advance();
  522. putenv('COLUMNS=120');
  523. rewind($output->getStream());
  524. $this->assertEquals(
  525. ' 0 [>---]'.
  526. $this->generateOutput(' 1 [->--]'),
  527. stream_get_contents($output->getStream())
  528. );
  529. }
  530. public function testAddingPlaceholderFormatter()
  531. {
  532. ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
  533. return $bar->getMaxSteps() - $bar->getProgress();
  534. });
  535. $bar = new ProgressBar($output = $this->getOutputStream(), 3);
  536. $bar->setFormat(' %remaining_steps% [%bar%]');
  537. $bar->start();
  538. $bar->advance();
  539. $bar->finish();
  540. rewind($output->getStream());
  541. $this->assertEquals(
  542. ' 3 [>---------------------------]'.
  543. $this->generateOutput(' 2 [=========>------------------]').
  544. $this->generateOutput(' 0 [============================]'),
  545. stream_get_contents($output->getStream())
  546. );
  547. }
  548. public function testMultilineFormat()
  549. {
  550. $bar = new ProgressBar($output = $this->getOutputStream(), 3);
  551. $bar->setFormat("%bar%\nfoobar");
  552. $bar->start();
  553. $bar->advance();
  554. $bar->clear();
  555. $bar->finish();
  556. rewind($output->getStream());
  557. $this->assertEquals(
  558. ">---------------------------\nfoobar".
  559. $this->generateOutput("=========>------------------\nfoobar").
  560. "\x0D\x1B[2K\x1B[1A\x1B[2K".
  561. $this->generateOutput("============================\nfoobar"),
  562. stream_get_contents($output->getStream())
  563. );
  564. }
  565. public function testAnsiColorsAndEmojis()
  566. {
  567. putenv('COLUMNS=156');
  568. $bar = new ProgressBar($output = $this->getOutputStream(), 15);
  569. ProgressBar::setPlaceholderFormatterDefinition('memory', function (ProgressBar $bar) {
  570. static $i = 0;
  571. $mem = 100000 * $i;
  572. $colors = $i++ ? '41;37' : '44;37';
  573. return "\033[".$colors.'m '.Helper::formatMemory($mem)." \033[0m";
  574. });
  575. $bar->setFormat(" \033[44;37m %title:-37s% \033[0m\n %current%/%max% %bar% %percent:3s%%\n 🏁 %remaining:-10s% %memory:37s%");
  576. $bar->setBarCharacter($done = "\033[32m●\033[0m");
  577. $bar->setEmptyBarCharacter($empty = "\033[31m●\033[0m");
  578. $bar->setProgressCharacter($progress = "\033[32m➤ \033[0m");
  579. $bar->setMessage('Starting the demo... fingers crossed', 'title');
  580. $bar->start();
  581. rewind($output->getStream());
  582. $this->assertEquals(
  583. " \033[44;37m Starting the demo... fingers crossed \033[0m\n".
  584. ' 0/15 '.$progress.str_repeat($empty, 26)." 0%\n".
  585. " \xf0\x9f\x8f\x81 < 1 sec \033[44;37m 0 B \033[0m",
  586. stream_get_contents($output->getStream())
  587. );
  588. ftruncate($output->getStream(), 0);
  589. rewind($output->getStream());
  590. $bar->setMessage('Looks good to me...', 'title');
  591. $bar->advance(4);
  592. rewind($output->getStream());
  593. $this->assertEquals(
  594. $this->generateOutput(
  595. " \033[44;37m Looks good to me... \033[0m\n".
  596. ' 4/15 '.str_repeat($done, 7).$progress.str_repeat($empty, 19)." 26%\n".
  597. " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 97 KiB \033[0m"
  598. ),
  599. stream_get_contents($output->getStream())
  600. );
  601. ftruncate($output->getStream(), 0);
  602. rewind($output->getStream());
  603. $bar->setMessage('Thanks, bye', 'title');
  604. $bar->finish();
  605. rewind($output->getStream());
  606. $this->assertEquals(
  607. $this->generateOutput(
  608. " \033[44;37m Thanks, bye \033[0m\n".
  609. ' 15/15 '.str_repeat($done, 28)." 100%\n".
  610. " \xf0\x9f\x8f\x81 < 1 sec \033[41;37m 195 KiB \033[0m"
  611. ),
  612. stream_get_contents($output->getStream())
  613. );
  614. putenv('COLUMNS=120');
  615. }
  616. public function testSetFormat()
  617. {
  618. $bar = new ProgressBar($output = $this->getOutputStream());
  619. $bar->setFormat('normal');
  620. $bar->start();
  621. rewind($output->getStream());
  622. $this->assertEquals(
  623. ' 0 [>---------------------------]',
  624. stream_get_contents($output->getStream())
  625. );
  626. $bar = new ProgressBar($output = $this->getOutputStream(), 10);
  627. $bar->setFormat('normal');
  628. $bar->start();
  629. rewind($output->getStream());
  630. $this->assertEquals(
  631. ' 0/10 [>---------------------------] 0%',
  632. stream_get_contents($output->getStream())
  633. );
  634. }
  635. /**
  636. * @dataProvider provideFormat
  637. */
  638. public function testFormatsWithoutMax($format)
  639. {
  640. $bar = new ProgressBar($output = $this->getOutputStream());
  641. $bar->setFormat($format);
  642. $bar->start();
  643. rewind($output->getStream());
  644. $this->assertNotEmpty(stream_get_contents($output->getStream()));
  645. }
  646. /**
  647. * Provides each defined format.
  648. *
  649. * @return array
  650. */
  651. public function provideFormat()
  652. {
  653. return array(
  654. array('normal'),
  655. array('verbose'),
  656. array('very_verbose'),
  657. array('debug'),
  658. );
  659. }
  660. protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
  661. {
  662. return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
  663. }
  664. protected function generateOutput($expected)
  665. {
  666. $count = substr_count($expected, "\n");
  667. return "\x0D\x1B[2K".($count ? str_repeat("\x1B[1A\x1B[2K", $count) : '').$expected;
  668. }
  669. public function testBarWidthWithMultilineFormat()
  670. {
  671. putenv('COLUMNS=10');
  672. $bar = new ProgressBar($output = $this->getOutputStream());
  673. $bar->setFormat("%bar%\n0123456789");
  674. // before starting
  675. $bar->setBarWidth(5);
  676. $this->assertEquals(5, $bar->getBarWidth());
  677. // after starting
  678. $bar->start();
  679. rewind($output->getStream());
  680. $this->assertEquals(5, $bar->getBarWidth(), stream_get_contents($output->getStream()));
  681. putenv('COLUMNS=120');
  682. }
  683. }