testLineTruncationBasedOnTerminalSize()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
nc 1
nop 0
dl 0
loc 17
rs 9.8666
c 2
b 0
f 0
1
<?php
2
/**
3
 * This file is part of graze/console-diff-renderer.
4
 *
5
 * Copyright (c) 2017 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/console-diff-renderer/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/console-diff-renderer
12
 */
13
14
namespace Graze\DiffRenderer\Test\Unit;
15
16
use Graze\DiffRenderer\DiffConsoleOutput;
17
use Graze\DiffRenderer\Terminal\DimensionsInterface;
18
use Graze\DiffRenderer\Terminal\Terminal;
19
use Graze\DiffRenderer\Test\TestCase;
20
use Graze\DiffRenderer\Wrap\Wrapper;
21
use Mockery;
22
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
23
use Symfony\Component\Console\Output\OutputInterface;
24
25
class DiffConsoleOutputTest extends TestCase
26
{
27
    const DEFAULT_OPTIONS = 34;
28
29
    /** @var DiffConsoleOutput */
30
    private $console;
31
    /** @var mixed */
32
    private $output;
33
    /** @var Terminal */
34
    private $terminal;
35
    /** @var mixed */
36
    private $wrapper;
37
    /** @var mixed */
38
    private $dimensions;
39
    /** @var mixed */
40
    private $formatter;
41
    /** @var string[] */
42
    private $replacements;
43
44
    public function setUp()
45
    {
46
        $this->formatter = Mockery::mock(OutputFormatterInterface::class);
47
        $auto = '';
48
        $this->formatter->shouldReceive('format')
49
                        ->with(Mockery::on(function ($string) use (&$auto) {
50
                            $auto = $string;
51
                            return true;
52
                        }))
53
                        ->andReturnUsing(function () use (&$auto) {
0 ignored issues
show
Bug introduced by
The method andReturnUsing() does not exist on Mockery\ExpectationInterface. Did you maybe mean andReturn()? ( Ignorable by Annotation )

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

53
                        ->/** @scrutinizer ignore-call */ andReturnUsing(function () use (&$auto) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
54
                            if (isset($this->replacements[$auto])) {
55
                                return $this->replacements[$auto];
56
                            }
57
                            return $auto;
58
                        });
59
        $this->output = Mockery::mock(OutputInterface::class);
60
        $this->output->shouldReceive('getFormatter')
61
                     ->andReturn($this->formatter);
62
        $this->wrapper = Mockery::mock(Wrapper::class)->makePartial();
63
        $this->dimensions = Mockery::mock(DimensionsInterface::class);
64
        $this->terminal = new Terminal(null, $this->dimensions);
0 ignored issues
show
Bug introduced by
$this->dimensions of type Mockery\MockInterface is incompatible with the type Graze\DiffRenderer\Termi...imensionsInterface|null expected by parameter $dimensions of Graze\DiffRenderer\Termi...Terminal::__construct(). ( Ignorable by Annotation )

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

64
        $this->terminal = new Terminal(null, /** @scrutinizer ignore-type */ $this->dimensions);
Loading history...
65
        $this->console = new DiffConsoleOutput($this->output, $this->terminal, $this->wrapper);
0 ignored issues
show
Bug introduced by
$this->output of type Mockery\MockInterface is incompatible with the type Symfony\Component\Console\Output\OutputInterface expected by parameter $output of Graze\DiffRenderer\DiffC...leOutput::__construct(). ( Ignorable by Annotation )

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

65
        $this->console = new DiffConsoleOutput(/** @scrutinizer ignore-type */ $this->output, $this->terminal, $this->wrapper);
Loading history...
Bug introduced by
$this->wrapper of type Mockery\Mock is incompatible with the type Graze\DiffRenderer\Wrap\Wrapper|null expected by parameter $wrapper of Graze\DiffRenderer\DiffC...leOutput::__construct(). ( Ignorable by Annotation )

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

65
        $this->console = new DiffConsoleOutput($this->output, $this->terminal, /** @scrutinizer ignore-type */ $this->wrapper);
Loading history...
66
    }
67
68
    /**
69
     * @param int $width
70
     * @param int $height
71
     */
72
    private function setUpDimensions($width = 80, $height = 50)
73
    {
74
        $this->dimensions->shouldReceive('getWidth')
75
                         ->andReturn($width);
76
        $this->wrapper->shouldReceive('getWidth')
77
                      ->andReturn($width);
78
        $this->dimensions->shouldReceive('getHeight')
79
                         ->andReturn($height);
80
    }
81
82
    /**
83
     * @param array $lines
84
     * @param int   $options
85
     */
86
    private function expectWrite(array $lines, $options = self::DEFAULT_OPTIONS)
87
    {
88
        $i = 0;
89
        foreach ($lines as $line) {
90
            $this->output->shouldReceive('write')
91
                         ->with($line, ++$i < count($lines), $options)
92
                         ->once();
93
        }
94
    }
95
96
    public function testGetTerminal()
97
    {
98
        $this->assertSame($this->terminal, $this->console->getTerminal());
99
    }
100
101
    public function testTrim()
102
    {
103
        $this->assertFalse($this->console->isTrim());
104
105
        $this->console->setTrim(true);
106
107
        $this->assertTrue($this->console->isTrim());
108
    }
109
110
    public function testSingleWrite()
111
    {
112
        $this->setUpDimensions();
113
        $this->output->shouldReceive('write')
114
                     ->with('sample text', false, 0)
115
                     ->once();
116
117
        $this->console->write('sample text');
118
    }
119
120
    public function testVerbosityIsHandledBeforeOutput()
121
    {
122
        $this->setUpDimensions();
123
        $this->output->shouldReceive('getVerbosity')
124
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
125
126
        $this->output->shouldNotReceive('write');
127
128
        $this->console->reWrite('no write', false, OutputInterface::VERBOSITY_VERBOSE | OutputInterface::OUTPUT_NORMAL);
129
    }
130
131
    public function testVerbosityUsesOutputVerbosity()
132
    {
133
        $this->setUpDimensions();
134
        $this->output->shouldReceive('getVerbosity')
135
                     ->andReturn(OutputInterface::VERBOSITY_VERBOSE);
136
137
        $this->output->shouldReceive('write')
138
                     ->with('test', false, OutputInterface::VERBOSITY_VERBOSE | OutputInterface::OUTPUT_RAW)
139
                     ->once();
140
141
        $this->console->reWrite('test');
142
    }
143
144
    public function testMultipleWrite()
145
    {
146
        $this->setUpDimensions();
147
148
        $this->output->shouldReceive('write')
149
                     ->with(['first', 'second'], true, 0)
150
                     ->once();
151
152
        $this->console->writeln(['first', 'second']);
153
    }
154
155
    public function testReWrite()
156
    {
157
        $this->setUpDimensions();
158
        $this->output->shouldReceive('getVerbosity')
159
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
160
161
        $this->expectWrite(['first', 'second']);
162
        $this->console->reWrite(['first', 'second']);
163
    }
164
165
    public function testUpdateOverwrite()
166
    {
167
        $this->setUpDimensions();
168
        $this->output->shouldReceive('getVerbosity')
169
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
170
171
        $this->expectWrite(['first', 'second']);
172
        $this->console->reWrite(['first', 'second']);
173
174
        $this->output->shouldReceive('write')
175
                     ->with("\e[?25l\e[1A\r\e[5C\e[K thing\n\r\e[?25h", false, static::DEFAULT_OPTIONS)
176
                     ->once();
177
        $this->console->reWrite(['first thing', 'second']);
178
    }
179
180
    public function testUpdateWithFormatting()
181
    {
182
        $this->setUpDimensions();
183
        $this->output->shouldReceive('getVerbosity')
184
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
185
186
        $this->replacements['<info>first</info>'] = 'INFO[first]';
187
        $this->replacements['<error>second</error>'] = 'ERROR[second]';
188
189
        $this->expectWrite(["INFO[first]", "ERROR[second]"]);
190
        $this->console->reWrite(['<info>first</info>', '<error>second</error>']);
191
192
        $this->replacements['<info>first</info> thing'] = 'INFO[first] thing';
193
194
        $this->output->shouldReceive('write')
195
                     ->with("\e[?25l\e[1A\r\e[11C\e[K thing\n\r\e[?25h", false, static::DEFAULT_OPTIONS)
196
                     ->once();
197
        $this->console->reWrite(['<info>first</info> thing', '<error>second</error>']);
198
199
        $this->replacements['<info>first thing</info>'] = 'INFO[first thing]';
200
201
        $this->output->shouldReceive('write')
202
                     ->with("\e[?25l\e[1A\r\e[10C\e[K thing]\n\r\e[?25h", false, static::DEFAULT_OPTIONS)
203
                     ->once();
204
        $this->console->reWrite(['<info>first thing</info>', '<error>second</error>']);
205
    }
206
207
    public function testUpdateWithNewLine()
208
    {
209
        $this->setUpDimensions();
210
        $this->output->shouldReceive('getVerbosity')
211
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
212
213
        $this->output->shouldReceive('write')
214
                     ->with(['first', 'second'], true, static::DEFAULT_OPTIONS)
215
                     ->once();
216
        $this->console->reWrite(['first', 'second'], true);
217
218
        $this->output->shouldReceive('write')
219
                     ->with("\e[?25l\e[2A\r\e[5C\e[K thing\n\r\e[?25h", true, static::DEFAULT_OPTIONS)
220
                     ->once();
221
        $this->console->reWrite(['first thing', 'second'], true);
222
    }
223
224
    public function testBlankLines()
225
    {
226
        $this->setUpDimensions();
227
        $this->output->shouldReceive('getVerbosity')
228
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
229
230
        $this->expectWrite(['first', 'second', 'third', 'fourth']);
231
        $this->console->reWrite(['first', 'second', 'third', 'fourth']);
232
233
        $this->output->shouldReceive('write')
234
                     ->with("\e[?25l\e[3A\r\e[Knew\n\r\n\r\n\r\e[?25h", false, static::DEFAULT_OPTIONS)
235
                     ->once();
236
        $this->console->reWrite(['new', 'second', 'third', 'fourth']);
237
    }
238
239
    public function testWrappedLines()
240
    {
241
        $this->setUpDimensions();
242
        $this->output->shouldReceive('getVerbosity')
243
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
244
245
        $this->wrapper->shouldReceive('wrap')
246
                      ->with(['123456789012345'])
247
                      ->once()
248
                      ->andReturn(['1234567890', '12345']);
249
250
        $this->expectWrite(['1234567890', '12345']);
251
        $this->console->reWrite(['123456789012345']);
252
253
        $this->wrapper->shouldReceive('wrap')
254
                      ->with(['123cake   12345'])
255
                      ->once()
256
                      ->andReturn(['123cake   ', '12345']);
257
258
        $this->output->shouldReceive('write')
259
                     ->with("\e[?25l\e[1A\r\e[3C\e[Kcake   \n\r\e[?25h", false, static::DEFAULT_OPTIONS)
260
                     ->once();
261
        $this->console->reWrite(['123cake   12345']);
262
    }
263
264
    public function testNewlyWrappingLines()
265
    {
266
        $this->setUpDimensions();
267
        $this->output->shouldReceive('getVerbosity')
268
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
269
270
        $this->wrapper->shouldReceive('wrap')
271
                      ->with(['1234567890', '1234567890'])
272
                      ->once()
273
                      ->andReturn(['1234567890', '1234567890']);
274
        $this->expectWrite(['1234567890', '1234567890']);
275
        $this->console->reWrite(['1234567890', '1234567890']);
276
277
        $this->wrapper->shouldReceive('wrap')
278
                      ->with(['123456789012345', '123456789012345'])
279
                      ->once()
280
                      ->andReturn(['1234567890', '12345', '1234567890', '12345']);
281
        $this->output->shouldReceive('write')
282
                    ->with(
283
                        "\e[?25l\e[1A\r\n\r\e[5C\e[K\n\r\e[K1234567890\n\r\e[K12345\e[?25h",
284
                        false,
285
                        static::DEFAULT_OPTIONS
286
                    )
287
                     ->once();
288
        $this->console->reWrite(['123456789012345', '123456789012345']);
289
    }
290
291
    public function testTrimmedLines()
292
    {
293
        $this->setUpDimensions();
294
        $this->output->shouldReceive('getVerbosity')
295
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
296
297
        $this->console->setTrim(true);
298
299
        $this->wrapper->shouldReceive('trim')
300
                      ->with(['123456789012345'])
301
                      ->once()
302
                      ->andReturn(['1234567890']);
303
304
        $this->output->shouldReceive('write')
305
                     ->with('1234567890', false, static::DEFAULT_OPTIONS)
306
                     ->once();
307
        $this->console->reWrite(['123456789012345']);
308
309
        $this->wrapper->shouldReceive('trim')
310
                      ->with(['123cake   12345'])
311
                      ->once()
312
                      ->andReturn(['123cake   ']);
313
314
        $this->output->shouldReceive('write')
315
                     ->with("\e[?25l\r\e[3C\e[Kcake   \e[?25h", false, static::DEFAULT_OPTIONS)
316
                     ->once();
317
        $this->console->reWrite(['123cake   12345']);
318
    }
319
320
    public function testLineTruncationBasedOnTerminalSize()
321
    {
322
        $this->setUpDimensions(80, 5);
323
        $this->output->shouldReceive('getVerbosity')
324
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
325
326
        $this->expectWrite(['first', 'second', 'third', 'fourth', 'fifth']);
327
        $this->console->reWrite(['first', 'second', 'third', 'fourth', 'fifth']);
328
329
        $this->output->shouldReceive('write')
330
                    ->with(
331
                        "\e[?25l\e[4A\r\e[Ksecond\n\r\e[Kthird\n\r\e[Kfourth\n\r\e[1C\e[Kifth\n\r\e[Ksixth\e[?25h",
332
                        false,
333
                        static::DEFAULT_OPTIONS
334
                    )
335
                     ->once();
336
        $this->console->reWrite(['first', 'second', 'third', 'fourth', 'fifth', 'sixth']);
337
    }
338
339
    public function testLineTruncationWithNewLine()
340
    {
341
        $this->setUpDimensions(80, 6);
342
        $this->output->shouldReceive('getVerbosity')
343
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
344
345
        $this->output->shouldReceive('write')
346
                     ->with(['first', 'second', 'third', 'fourth', 'fifth'], true, static::DEFAULT_OPTIONS)
347
                     ->once();
348
        $this->console->reWrite(['first', 'second', 'third', 'fourth', 'fifth'], true);
349
350
        $this->output->shouldReceive('write')
351
                    ->with(
352
                        "\e[?25l\e[5A\r\e[Ksecond\n\r\e[Kthird\n\r\e[Kfourth\n\r\e[1C\e[Kifth\n\r\e[Ksixth\e[?25h",
353
                        true,
354
                        static::DEFAULT_OPTIONS
355
                    )
356
                     ->once();
357
        $this->console->reWrite(['first', 'second', 'third', 'fourth', 'fifth', 'sixth'], true);
358
    }
359
360
    public function testSplitNewLines()
361
    {
362
        $this->setUpDimensions();
363
        $this->output->shouldReceive('getVerbosity')
364
                     ->andReturn(OutputInterface::VERBOSITY_NORMAL);
365
366
        $this->expectWrite(['first', 'second']);
367
        $this->console->reWrite("first\nsecond");
368
    }
369
}
370