Completed
Push — master ( 27667a...b36312 )
by Dave
15s queued 12s
created

RemoveBaseLineCommandTest::testCleanUpOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 19
rs 9.8666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DaveLiddament\StaticAnalysisResultsBaseliner\Tests\Unit\Framework\Command;
6
7
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\AbsoluteFileName;
8
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\BaseLine;
9
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\LineNumber;
10
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\Location;
11
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\ProjectRoot;
12
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\Type;
13
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\OutputFormatter\OutputFormatter;
14
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Pruner\PrunedResults;
15
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\RandomResultsPicker\RandomResultsPicker;
16
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\ResultsParser\AnalysisResult;
17
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\ResultsParser\AnalysisResults;
18
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\ResultsParser\AnalysisResultsBuilder;
19
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Utils\RandomNumberGenerator;
20
use DaveLiddament\StaticAnalysisResultsBaseliner\Framework\Command\RemoveBaseLineFromResultsCommand;
21
use DaveLiddament\StaticAnalysisResultsBaseliner\Framework\Container\OutputFormatterRegistry;
22
use DaveLiddament\StaticAnalysisResultsBaseliner\Plugins\GitDiffHistoryAnalyser\GitCommit;
23
use DaveLiddament\StaticAnalysisResultsBaseliner\Plugins\OutputFormatters\TableOutputFormatter;
24
use DaveLiddament\StaticAnalysisResultsBaseliner\Plugins\ResultsParsers\SarbJsonResultsParser\SarbJsonResultsParser;
25
use DaveLiddament\StaticAnalysisResultsBaseliner\Tests\Helpers\BaseLineResultsBuilder;
26
use DaveLiddament\StaticAnalysisResultsBaseliner\Tests\TestDoubles\HistoryFactoryStub;
27
use DaveLiddament\StaticAnalysisResultsBaseliner\Tests\TestDoubles\MockResultsPruner;
28
use DaveLiddament\StaticAnalysisResultsBaseliner\Tests\TestDoubles\OutputFormatterStub;
29
use Exception;
30
use PHPUnit\Framework\TestCase;
31
use Symfony\Component\Console\Tester\CommandTester;
32
use Throwable;
33
34
class RemoveBaseLineCommandTest extends TestCase
35
{
36
    private const INPUT_STRING_1 = <<<EOF
37
This is
38
a multiline
39
string
40
EOF;
41
    public const BASELINE_FILENAME = 'baseline1.sarb';
42
    public const BASELINE_FILE_ARGUMENT = 'baseline-file';
43
    public const OUTPUT_FORMAT_OPTION = '--output-format';
44
    public const PROJECT_ROOT = '--project-root';
45
    public const CLEAN_UP = '--clean-up';
46
47
    /**
48
     * @var ProjectRoot
49
     */
50
    private $projectRoot;
51
52
    /**
53
     * @var OutputFormatterRegistry
54
     */
55
    private $outputFormatterRegistry;
56
    /**
57
     * @var OutputFormatter
58
     */
59
    private $defaultOutputFormater;
60
    /**
61
     * @var OutputFormatter
62
     */
63
    private $stubOutputFormatter;
64
65
    protected function setUp(): void
66
    {
67
        $this->defaultOutputFormater = new TableOutputFormatter();
68
        $this->stubOutputFormatter = new OutputFormatterStub();
69
70
        $this->outputFormatterRegistry = new OutputFormatterRegistry([
71
            $this->defaultOutputFormater,
72
            $this->stubOutputFormatter,
73
        ]);
74
75
        $this->projectRoot = ProjectRoot::fromProjectRoot('/tmp', '/tmp/foo/bar');
76
    }
77
78
    public function testNoNewIssues(): void
79
    {
80
        $commandTester = $this->createCommandTester(
81
            $this->getAnalysisResultsWithXResults(0),
82
            null,
83
            null
84
        );
85
86
        $commandTester->execute([
87
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
88
        ]);
89
90
        $this->assertReturnCode(0, $commandTester);
91
        $this->assertResponseContains('Latest analysis issue count: 2', $commandTester);
92
        $this->assertResponseContains('Baseline issue count: 4', $commandTester);
93
        $this->assertResponseContains('Issue count with baseline removed: 0', $commandTester);
94
    }
95
96
    public function test1NewIssues(): void
97
    {
98
        $commandTester = $this->createCommandTester(
99
            $this->getAnalysisResultsWithXResults(1),
100
            null,
101
            null
102
        );
103
104
        $commandTester->execute([
105
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
106
        ]);
107
108
        $this->assertReturnCode(1, $commandTester);
109
        $this->assertResponseContains('Issue count with baseline removed: 1', $commandTester);
110
    }
111
112
    public function testPickNonDefaultOutputFormatter(): void
113
    {
114
        $commandTester = $this->createCommandTester(
115
            $this->getAnalysisResultsWithXResults(0),
116
            null,
117
            null
118
        );
119
120
        $commandTester->execute([
121
            self::OUTPUT_FORMAT_OPTION => OutputFormatterStub::CODE,
122
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
123
        ]);
124
125
        $this->assertReturnCode(0, $commandTester);
126
        $this->assertResponseContains(
127
            '[stub output formatter: Issues since baseline 0]',
128
            $commandTester
129
        );
130
    }
131
132
    public function testPickNonDefaultOutputFormatterWithIssues(): void
133
    {
134
        $commandTester = $this->createCommandTester(
135
            $this->getAnalysisResultsWithXResults(8),
136
            null,
137
            null
138
        );
139
140
        $commandTester->execute([
141
            self::OUTPUT_FORMAT_OPTION => OutputFormatterStub::CODE,
142
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
143
        ]);
144
145
        $this->assertReturnCode(1, $commandTester);
146
        $this->assertResponseContains(
147
            '[stub output formatter: Issues since baseline 8]',
148
            $commandTester
149
        );
150
    }
151
152
    public function testInvalidResultsParser(): void
153
    {
154
        $commandTester = $this->createCommandTester(
155
            $this->getAnalysisResultsWithXResults(0),
156
            null,
157
            null
158
        );
159
160
        $commandTester->execute([
161
            self::OUTPUT_FORMAT_OPTION => 'rubbish',
162
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
163
        ]);
164
165
        $this->assertReturnCode(11, $commandTester);
166
        $this->assertResponseContains(
167
            'Invalid value [rubbish] for option [output-format]. Pick one of: table|stub',
168
            $commandTester
169
        );
170
    }
171
172
    public function testSpecifyProjectRoot(): void
173
    {
174
        $commandTester = $this->createCommandTester(
175
            $this->getAnalysisResultsWithXResults(0),
176
            $this->projectRoot,
177
            null
178
        );
179
180
        $commandTester->execute([
181
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
182
            self::PROJECT_ROOT => '/tmp',
183
        ]);
184
185
        $this->assertReturnCode(0, $commandTester);
186
    }
187
188
    public function testException(): void
189
    {
190
        $commandTester = $this->createCommandTester(
191
            $this->getAnalysisResultsWithXResults(1),
192
            null,
193
            new Exception()
194
        );
195
196
        $commandTester->execute([
197
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
198
        ]);
199
200
        $this->assertReturnCode(100, $commandTester);
201
    }
202
203
    public function testCleanUpOptions(): void
204
    {
205
        $commandTester = $this->createCommandTester(
206
            $this->getAnalysisResultsWithXResults(0),
207
            null,
208
            null
209
        );
210
211
        $commandTester->execute([
212
            self::BASELINE_FILE_ARGUMENT => self::BASELINE_FILENAME,
213
            self::CLEAN_UP => true,
214
        ]);
215
216
        $this->assertReturnCode(0, $commandTester);
217
218
        $this->assertResponseContains('Random 2 issues in the baseline to fix...', $commandTester);
219
        $this->assertResponseContains('FILE: /FILE_2', $commandTester);
220
        $this->assertResponseContains('| 2    | MESSAGE_1   |', $commandTester);
221
        $this->assertResponseContains('| 2    | MESSAGE_0   |', $commandTester);
222
    }
223
224
    private function createCommandTester(
225
        AnalysisResults $expectedAnalysisResults,
226
        ?ProjectRoot $projectRoot,
227
        ?Throwable $exception
228
    ): CommandTester {
229
        $baseLineResultsBuilder = new BaseLineResultsBuilder();
230
        $baseLineResultsBuilder->add('file1', 1, 'type1');
231
        $baseLineResultsBuilder->add('file2', 2, 'type2');
232
        $baseLineResultsBuilder->add('file3', 3, 'type3');
233
        $baseLineResultsBuilder->add('file4', 4, 'type4');
234
235
        $baseLine = new BaseLine(
236
            new HistoryFactoryStub(),
237
            $baseLineResultsBuilder->build(),
238
            new SarbJsonResultsParser(),
239
            new GitCommit('fae40b3d596780ffd746dbd2300d05dcfbd09033')
240
        );
241
242
        $prunedResults = new PrunedResults(
243
            $baseLine,
244
            $expectedAnalysisResults,
245
            $this->getAnalysisResultsWithXResults(2)
246
        );
247
248
        $mockResultsPruner = new MockResultsPruner(
249
            self::INPUT_STRING_1,
250
            $prunedResults,
251
            $projectRoot,
252
            $exception
253
        );
254
255
        $command = new RemoveBaseLineFromResultsCommand(
256
            $mockResultsPruner,
257
            $this->outputFormatterRegistry,
258
            new TableOutputFormatter(),
259
            new RandomResultsPicker(new RandomNumberGenerator())
260
        );
261
262
        $commandTester = new CommandTester($command);
263
        $commandTester->setInputs([self::INPUT_STRING_1]);
264
265
        return $commandTester;
266
    }
267
268
    private function assertReturnCode(int $expectedReturnCode, CommandTester $commandTester): void
269
    {
270
        $this->assertSame($expectedReturnCode, $commandTester->getStatusCode(), $commandTester->getDisplay());
271
    }
272
273
    private function assertResponseContains(string $expectedMessage, CommandTester $commandTester): void
274
    {
275
        $output = $commandTester->getDisplay();
276
        $position = strpos($output, $expectedMessage);
277
        $this->assertNotFalse($position, "Can't find message [$expectedMessage] in [$output]");
278
    }
279
280
    private function getAnalysisResultsWithXResults(int $count): AnalysisResults
281
    {
282
        $projectRoot = ProjectRoot::fromCurrentWorkingDirectory('/');
283
284
        $analysisResultsBuilder = new AnalysisResultsBuilder();
285
        for ($i = 0; $i < $count; ++$i) {
286
            $analysisResult = new AnalysisResult(
287
                Location::fromAbsoluteFileName(
288
                    new AbsoluteFileName("/FILE_$count"),
289
                    $projectRoot,
290
                    new LineNumber($count)
291
                ),
292
                new Type("TYPE_$i"),
293
                "MESSAGE_$i",
294
                []
295
            );
296
            $analysisResultsBuilder->addAnalysisResult($analysisResult);
297
        }
298
299
        return $analysisResultsBuilder->build();
300
    }
301
}
302