TableTest::setUp()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * This file is part of graze/parallel-process.
4
 *
5
 * Copyright © 2018 Nature Delivered Ltd. <https://www.graze.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
 * @license https://github.com/graze/parallel-process/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/parallel-process
12
 */
13
14
namespace Graze\ParallelProcess\Test\Unit\Display;
15
16
use Graze\ParallelProcess\Display\Table;
17
use Graze\ParallelProcess\Event\PoolRunEvent;
18
use Graze\ParallelProcess\PoolInterface;
19
use Graze\ParallelProcess\PriorityPool;
20
use Graze\ParallelProcess\ProcessRun;
21
use Graze\ParallelProcess\Test\BufferDiffOutput;
22
use Graze\ParallelProcess\Test\TestCase;
23
use Mockery;
24
use Symfony\Component\Console\Output\ConsoleOutputInterface;
25
use Symfony\Component\Console\Output\OutputInterface;
26
use Symfony\Component\Process\Exception\ProcessFailedException;
27
use Symfony\Component\Process\Process;
28
29
class TableTest extends TestCase
30
{
31
    /** @var BufferDiffOutput */
32
    private $bufferOutput;
33
    /** @var mixed */
34
    private $pool;
35
    /** @var Table */
36
    private $table;
37
38
    public function setUp()
39
    {
40
        mb_internal_encoding("UTF-8");
41
        $this->bufferOutput = new BufferDiffOutput();
42
        $this->pool = new PriorityPool();
43
        $this->table = new Table($this->bufferOutput, $this->pool);
44
    }
45
46
    public function testConstructWithNonBufferedOutput()
47
    {
48
        $output = Mockery::mock(ConsoleOutputInterface::class);
49
        $table = new Table($output);
0 ignored issues
show
Bug introduced by
$output of type Mockery\MockInterface is incompatible with the type Symfony\Component\Console\Output\OutputInterface expected by parameter $output of Graze\ParallelProcess\Display\Table::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

49
        $table = new Table(/** @scrutinizer ignore-type */ $output);
Loading history...
50
51
        $this->assertInstanceOf(Table::class, $table);
52
    }
53
54
    public function testShowOutput()
55
    {
56
        $output = Mockery::mock(ConsoleOutputInterface::class);
57
        $table = new Table($output);
0 ignored issues
show
Bug introduced by
$output of type Mockery\MockInterface is incompatible with the type Symfony\Component\Console\Output\OutputInterface expected by parameter $output of Graze\ParallelProcess\Display\Table::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
        $table = new Table(/** @scrutinizer ignore-type */ $output);
Loading history...
58
59
        $this->assertTrue($table->isShowOutput());
60
61
        $this->assertSame($table, $table->setShowOutput(false));
62
63
        $this->assertFalse($table->isShowOutput());
64
    }
65
66
    public function testShowSummary()
67
    {
68
        $output = Mockery::mock(ConsoleOutputInterface::class);
69
        $table = new Table($output);
0 ignored issues
show
Bug introduced by
$output of type Mockery\MockInterface is incompatible with the type Symfony\Component\Console\Output\OutputInterface expected by parameter $output of Graze\ParallelProcess\Display\Table::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
        $table = new Table(/** @scrutinizer ignore-type */ $output);
Loading history...
70
71
        $this->assertTrue($table->isShowSummary());
72
73
        $this->assertSame($table, $table->setShowSummary(false));
74
75
        $this->assertFalse($table->isShowSummary());
76
    }
77
78
    public function testSpinnerLoop()
79
    {
80
        $this->table->setShowSummary(false);
81
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
82
83
        $process = Mockery::mock(Process::class);
84
        $process->shouldReceive('stop');
85
        $process->shouldReceive('start')->once();
86
        $process->shouldReceive('isStarted')->andReturn(false, false, false, true); //add, add2, start, run
87
        $process->shouldReceive('isRunning')->andReturn(
88
            false, // add
89
            false, // add2
90
            true,  // check
91
            true,  // ...
92
            true,
93
            true,
94
            true,
95
            true,
96
            true,
97
            true,
98
            true,
99
            true,
100
            true,
101
            false // complete
102
        );
103
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
104
105
        $this->pool->add($process, ['key' => 'value']);
106
107
        $this->table->run(0);
108
109
        $expected = [
110
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %'],
111
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
112
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠙%'],
113
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠹%'],
114
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠸%'],
115
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠼%'],
116
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠴%'],
117
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠦%'],
118
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠧%'],
119
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠇%'],
120
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠏%'],
121
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
122
            ['%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
123
        ];
124
125
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
126
    }
127
128
    public function testProgressBar()
129
    {
130
        $this->table->setShowSummary(false);
131
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
132
133
        $process = Mockery::mock(Process::class);
134
        $process->shouldReceive('stop');
135
        $process->shouldReceive('start')->once();
136
        $process->shouldReceive('isStarted')->andReturn(false, false, false, true); // add, add2, start, run
137
        $process->shouldReceive('isRunning')->andReturn(
138
            false, // add
139
            false, // add
140
            true,  // check
141
            true,  // ...
142
            true,
143
            true,
144
            true,
145
            true,
146
            true,
147
            true,
148
            true,
149
            true,
150
            true,
151
            true,
152
            true,
153
            true,
154
            true,
155
            true,
156
            true,
157
            true,
158
            true,
159
            true,
160
            false // complete
161
        );
162
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
163
164
        $run = Mockery::mock(ProcessRun::class, [$process, ['key' => 'value']])->makePartial();
165
        $this->pool->add($run);
166
167
        $run->allows()
168
            ->getProgress()
169
            ->andReturns(
170
                [0, 100, 0],
171
                [5, 100, 0.05],
172
                [10, 100, 0.1],
173
                [15, 100, 0.15],
174
                [20, 100, 0.2],
175
                [25, 100, 0.25],
176
                [30, 100, 0.3],
177
                [35, 100, 0.35],
178
                [40, 100, 0.4],
179
                [45, 100, 0.45],
180
                [50, 100, 0.5],
181
                [55, 100, 0.55],
182
                [60, 100, 0.6],
183
                [65, 100, 0.65],
184
                [70, 100, 0.7],
185
                [75, 100, 0.75],
186
                [80, 100, 0.8],
187
                [85, 100, 0.85],
188
                [90, 100, 0.9],
189
                [95, 100, 0.95],
190
                [100, 100, 1]
191
            );
192
        $run->allows()
193
            ->getDuration()
194
            ->andReturns(
195
                0,
196
                0.05,
197
                0.1,
198
                0.15,
199
                0.2,
200
                0.25,
201
                0.3,
202
                0.35,
203
                0.4,
204
                0.45,
205
                0.5,
206
                0.55,
207
                0.6,
208
                0.65,
209
                0.7,
210
                0.75,
211
                0.8,
212
                0.85,
213
                0.9,
214
                0.95,
215
                1
216
            );
217
218
        $this->table->run(0);
219
220
        $expected = [
221
            ['/<info>key<\/info>: value \(<comment>  0.00s<\/comment>\) /'],
222
            ['/<info>key<\/info>: value \(<comment>  0.00s<\/comment>\) ▕<comment>  <\/comment>▏<info>  0%<\/info>/'],
223
            ['/<info>key<\/info>: value \(<comment>  0.05s<\/comment>\) ▕<comment>▏ <\/comment>▏<info>  5%<\/info>/'],
224
            ['/<info>key<\/info>: value \(<comment>  0.10s<\/comment>\) ▕<comment>▎ <\/comment>▏<info> 10%<\/info>/'],
225
            ['/<info>key<\/info>: value \(<comment>  0.15s<\/comment>\) ▕<comment>▍ <\/comment>▏<info> 15%<\/info>/'],
226
            ['/<info>key<\/info>: value \(<comment>  0.20s<\/comment>\) ▕<comment>▍ <\/comment>▏<info> 20%<\/info>/'],
227
            ['/<info>key<\/info>: value \(<comment>  0.25s<\/comment>\) ▕<comment>▌ <\/comment>▏<info> 25%<\/info>/'],
228
            ['/<info>key<\/info>: value \(<comment>  0.30s<\/comment>\) ▕<comment>▋ <\/comment>▏<info> 30%<\/info>/'],
229
            ['/<info>key<\/info>: value \(<comment>  0.35s<\/comment>\) ▕<comment>▋ <\/comment>▏<info> 35%<\/info>/'],
230
            ['/<info>key<\/info>: value \(<comment>  0.40s<\/comment>\) ▕<comment>▊ <\/comment>▏<info> 40%<\/info>/'],
231
            ['/<info>key<\/info>: value \(<comment>  0.45s<\/comment>\) ▕<comment>▉ <\/comment>▏<info> 45%<\/info>/'],
232
            ['/<info>key<\/info>: value \(<comment>  0.50s<\/comment>\) ▕<comment>█ <\/comment>▏<info> 50%<\/info>/'],
233
            ['/<info>key<\/info>: value \(<comment>  0.55s<\/comment>\) ▕<comment>█▏<\/comment>▏<info> 55%<\/info>/'],
234
            ['/<info>key<\/info>: value \(<comment>  0.60s<\/comment>\) ▕<comment>█▎<\/comment>▏<info> 60%<\/info>/'],
235
            ['/<info>key<\/info>: value \(<comment>  0.65s<\/comment>\) ▕<comment>█▍<\/comment>▏<info> 65%<\/info>/'],
236
            ['/<info>key<\/info>: value \(<comment>  0.70s<\/comment>\) ▕<comment>█▍<\/comment>▏<info> 70%<\/info>/'],
237
            ['/<info>key<\/info>: value \(<comment>  0.75s<\/comment>\) ▕<comment>█▌<\/comment>▏<info> 75%<\/info>/'],
238
            ['/<info>key<\/info>: value \(<comment>  0.80s<\/comment>\) ▕<comment>█▋<\/comment>▏<info> 80%<\/info>/'],
239
            ['/<info>key<\/info>: value \(<comment>  0.85s<\/comment>\) ▕<comment>█▋<\/comment>▏<info> 85%<\/info>/'],
240
            ['/<info>key<\/info>: value \(<comment>  0.90s<\/comment>\) ▕<comment>█▊<\/comment>▏<info> 90%<\/info>/'],
241
            ['/<info>key<\/info>: value \(<comment>  0.95s<\/comment>\) ▕<comment>█▉<\/comment>▏<info> 95%<\/info>/'],
242
            ['/<info>key<\/info>: value \(<comment>  1.00s<\/comment>\) <info>✓<\/info>/'],
243
        ];
244
245
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
246
    }
247
248
    public function testValueDataArrayDoesNotShowTheKey()
249
    {
250
        $this->table->setShowSummary(false);
251
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
252
253
        $process = Mockery::mock(Process::class);
254
        $process->shouldReceive('stop');
255
        $process->shouldReceive('start')->once();
256
        $process->shouldReceive('isStarted')->andReturn(false, false, false, true); // add, start, run
257
        $process->shouldReceive('isRunning')->andReturn(
258
            false, // add
259
            false, // add2
260
            true,  // check
261
            false // complete
262
        );
263
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
264
265
        $this->pool->add($process, ['value', 'value2']);
266
267
        $this->table->run(0);
268
269
        $expected = [
270
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) %'],
271
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) ⠋%'],
272
            ['%value value2 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
273
        ];
274
275
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
276
    }
277
278
    public function testSummaryIsWaitingBeforeTheProcessStarts()
279
    {
280
        $this->bufferOutput->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
281
        $this->table->setShowOutput(true);
282
        $this->table->setShowSummary(true);
283
284
        $oneFails = false;
285
286
        $process = Mockery::mock(Process::class);
287
        $process->shouldReceive('stop');
288
        $process->shouldReceive('start')->with(Mockery::on(function ($closure) {
289
            call_user_func($closure, Process::OUT, 'some text');
290
            return true;
291
        }))->once();
292
        $process->shouldReceive('isStarted')
293
                ->andReturn(false, false, false, false, true); // add, add2, summary, start, run
294
        $process->shouldReceive('isRunning')->andReturn(false, false, true, false); // add, add2, check, check
295
        $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn(true);
296
        $process->shouldReceive('getOutput')->andReturn('some text');
297
298
        $this->pool->add($process, ['key' => 'value']);
299
300
        try {
301
            $this->table->run(0);
302
        } catch (\Exception $e) {
303
            if (!$oneFails || !$e instanceof ProcessFailedException) {
0 ignored issues
show
introduced by
The condition $oneFails is always false.
Loading history...
304
                throw $e;
305
            }
306
        }
307
308
        $expected = [
309
            [
310
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %',
311
                '%waiting...%',
312
            ],
313
            [
314
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) %',
315
                '%<comment>Total</comment>:  1, <comment>Running</comment>:  1, <comment>Waiting</comment>:  0%',
316
            ],
317
            [
318
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
319
                '%<comment>Total</comment>:  1, <comment>Running</comment>:  1, <comment>Waiting</comment>:  0%',
320
            ],
321
            [
322
                '%<info>key</info>: value \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
323
                '%^$%',
324
            ],
325
        ];
326
327
        $this->compareOutputs($expected, $this->bufferOutput->getWritten());
328
    }
329
330
    /**
331
     * Runs a series of processes, each doing initial state, single on progress run, single complete entry
332
     *
333
     * @dataProvider outputData
334
     *
335
     * @param int        $verbosity     OutputInterface::VERBOSITY_*
336
     * @param bool       $showOutput    Should it display some output text
337
     * @param bool       $showSummary   Should we show a summary
338
     * @param bool[]     $processStates an entry for each process to run, true = success, false = failure
339
     * @param string[][] $outputs       Regex patterns for the output string
340
     *
341
     * @throws \Exception
342
     */
343
    public function testOutput($verbosity, $showOutput, $showSummary, array $processStates, array $outputs)
344
    {
345
        $this->bufferOutput->setVerbosity($verbosity);
346
        $this->table->setShowOutput($showOutput);
347
        $this->table->setShowSummary($showSummary);
348
349
        $oneFails = false;
350
351
        for ($i = 0; $i < count($processStates); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
352
            $process = Mockery::mock(Process::class);
353
            $process->shouldReceive('stop');
354
            $process->shouldReceive('start')->with(Mockery::on(function ($closure) {
355
                call_user_func($closure, Process::OUT, 'some text');
356
                return true;
357
            }))->once();
358
            if ($showSummary) {
359
                $process->shouldReceive('isStarted')
360
                        ->andReturn(false, false, false, false, true); // add, add2, summary, start, run
361
            } else {
362
                $process->shouldReceive('isStarted')->andReturn(false, false, false, true); // add, add2, start, run
363
            }
364
            $process->shouldReceive('isRunning')->andReturn(false, false, true, false); // add, add2, check, check
365
            $process->shouldReceive('isSuccessful')->atLeast()->once()->andReturn($processStates[$i]);
366
            $process->shouldReceive('getOutput')->andReturn('some text');
367
368
            if (!$processStates[$i]) {
369
                $process->shouldReceive('getCommandLine')->andReturn('test');
370
                $process->shouldReceive('getExitCode')->andReturn(1);
371
                $process->shouldReceive('getExitCodeText')->andReturn('failed');
372
                $process->shouldReceive('getWorkingDirectory')->andReturn('/tmp');
373
                $process->shouldReceive('isOutputDisabled')->andReturn(false);
374
                $process->shouldReceive('getErrorOutput')->andReturn('some error text');
375
                $oneFails = true;
376
            }
377
378
            $this->pool->add($process, ['key' => 'value', 'run' => $i]);
379
        }
380
381
        try {
382
            $this->table->run(0);
383
        } catch (\Exception $e) {
384
            if (!$oneFails || !$e instanceof ProcessFailedException) {
385
                throw $e;
386
            }
387
        }
388
389
        $this->compareOutputs($outputs, $this->bufferOutput->getWritten());
390
    }
391
392
    /**
393
     * @return array
394
     */
395
    public function outputData()
396
    {
397
        return [
398
            [ // verbose with single valid run
399
              OutputInterface::VERBOSITY_VERBOSE,
400
              false,
401
              false,
402
              [true],
403
              [
404
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
405
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%'],
406
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
407
              ],
408
            ],
409
            [ // normal verbosity only writes a single line
410
              OutputInterface::VERBOSITY_NORMAL,
411
              false,
412
              false,
413
              [true],
414
              [
415
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
416
              ],
417
            ],
418
            [
419
                OutputInterface::VERBOSITY_NORMAL,
420
                false,
421
                false,
422
                [true, true],
423
                [
424
                    ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
425
                    ['%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%'],
426
                ],
427
            ],
428
            [ // multiple runs with verbosity will update each item one at a time
429
              OutputInterface::VERBOSITY_VERBOSE,
430
              false,
431
              false,
432
              [true, true],
433
              [
434
                  [
435
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
436
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
437
                  ],
438
                  [
439
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
440
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
441
                  ],
442
                  [
443
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
444
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
445
                  ],
446
                  [
447
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
448
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
449
                  ],
450
                  [
451
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
452
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
453
                  ],
454
              ],
455
            ],
456
            [ // errors will display an error
457
              OutputInterface::VERBOSITY_VERBOSE,
458
              false,
459
              false,
460
              [false],
461
              [
462
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
463
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%'],
464
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%'],
465
                  [
466
                      <<<DOC
467
%The command "test" failed.
468
469
Exit Code: 1\(failed\)
470
471
Working directory: /tmp
472
473
Output:
474
================
475
some text
476
477
Error Output:
478
================
479
some error text%
480
DOC
481
                      ,
482
                  ],
483
              ],
484
            ],
485
            [ // errors will display an error
486
              OutputInterface::VERBOSITY_NORMAL,
487
              false,
488
              false,
489
              [false],
490
              [
491
                  ['%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%'],
492
                  [
493
                      <<<DOC
494
%The command "test" failed.
495
496
Exit Code: 1\(failed\)
497
498
Working directory: /tmp
499
500
Output:
501
================
502
some text
503
504
Error Output:
505
================
506
some error text%
507
DOC
508
                      ,
509
                  ],
510
              ],
511
            ],
512
            [ // multiple runs with verbosity will update each item one at a time
513
              OutputInterface::VERBOSITY_VERBOSE,
514
              false,
515
              false,
516
              [true, false],
517
              [
518
                  [
519
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
520
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
521
                  ],
522
                  [
523
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
524
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
525
                  ],
526
                  [
527
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
528
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
529
                  ],
530
                  [
531
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
532
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
533
                  ],
534
                  [
535
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
536
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <error>x</error>%',
537
                  ],
538
                  [
539
                      <<<DOC
540
%The command "test" failed.
541
542
Exit Code: 1\(failed\)
543
544
Working directory: /tmp
545
546
Output:
547
================
548
some text
549
550
Error Output:
551
================
552
some error text%
553
DOC
554
                      ,
555
                  ],
556
              ],
557
            ],
558
            [ // include output
559
              OutputInterface::VERBOSITY_VERBOSE,
560
              true,
561
              false,
562
              [true],
563
              [
564
                  ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %'],
565
                  ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]  some text%'],
566
                  ['%(*UTF8)<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>  some text%'],
567
              ],
568
            ],
569
            [ // include a summary
570
              OutputInterface::VERBOSITY_VERBOSE,
571
              false,
572
              true,
573
              [true, true],
574
              [
575
                  [
576
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) %',
577
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
578
                      '%^waiting...$%',
579
                  ],
580
                  [
581
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
582
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) %',
583
                      '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
584
                  ],
585
                  [
586
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
587
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
588
                      '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
589
                  ],
590
                  [
591
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
592
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) [⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]%',
593
                      '%<comment>Total</comment>:  2, <comment>Running</comment>:  2, <comment>Waiting</comment>:  0%',
594
                  ],
595
                  [
596
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
597
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
598
                      '%<comment>Total</comment>:  2, <comment>Running</comment>:  1, <comment>Waiting</comment>:  0%',
599
                  ],
600
                  [
601
                      '%<info>key</info>: value <info>run</info>: 0 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
602
                      '%<info>key</info>: value <info>run</info>: 1 \(<comment>[ 0-9\.s]+</comment>\) <info>✓</info>%',
603
                      '%^$%',
604
                  ],
605
              ],
606
            ],
607
        ];
608
    }
609
}
610