fileProvider = Mockery::mock(FileProvider::class); } public function testLoadShouldParseXmlBaselineToPhpArray(): void { $baselineFilePath = 'baseline.xml'; $this->fileProvider->allows()->fileExists($baselineFilePath)->andReturns(true); $this->fileProvider->allows()->getContents($baselineFilePath)->andReturns( ' foo bar foo bar ', ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['foo', 'bar']], 'InvalidReturnStatement' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'PossiblyUnusedMethod' => ['o' => 2, 's' => ['foo', 'bar']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider, $baselineFilePath), ); } public function testLoadShouldIgnoreLineEndingsInIssueSnippet(): void { $baselineFilePath = 'baseline.xml'; $this->fileProvider->allows()->fileExists($baselineFilePath)->andReturns(true); $this->fileProvider->allows()->getContents($baselineFilePath)->andReturns( " foo\r ", ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 1, 's' => ['foo']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider, $baselineFilePath), ); } public function testLoadShouldThrowExceptionWhenFilesAreNotDefinedInBaselineFile(): void { $this->expectException(ConfigException::class); $baselineFile = 'baseline.xml'; $this->fileProvider->allows()->fileExists($baselineFile)->andReturns(true); $this->fileProvider->allows()->getContents($baselineFile)->andReturns( ' ', ); ErrorBaseline::read($this->fileProvider, $baselineFile); } public function testLoadShouldThrowExceptionWhenBaselineFileDoesNotExist(): void { $this->expectException(ConfigException::class); $baselineFile = 'baseline.xml'; $this->fileProvider->expects()->fileExists($baselineFile)->andReturns(false); ErrorBaseline::read($this->fileProvider, $baselineFile); } public function testCountTotalIssuesShouldReturnCorrectNumber(): void { $existingIssues = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['bar']], 'MixedOperand' => ['o' => 2, 's' => []], ], 'sample/sample-file2.php' => [ 'TypeCoercion' => ['o' => 1, 's' => []], ], ]; $totalIssues = ErrorBaseline::countTotalIssues($existingIssues); $this->assertSame($totalIssues, 5); } public function testCreateShouldAggregateIssuesPerFile(): void { $baselineFile = 'baseline.xml'; $this->fileProvider = Mockery::spy(FileProvider::class); ErrorBaseline::create( $this->fileProvider, $baselineFile, [ 'sample/sample-file.php' => [ new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'foo', 'foo', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bar', 'bar', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bat', 'bat', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bing', 'bing', 0, 0, 0, 0, 0, 0, ), new IssueData( 'info', 0, 0, 'AssignmentToVoid', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bong', 'bong', 0, 0, 0, 0, 0, 0, ), ], 'sample/sample-file2.php' => [ new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'boardy', 'boardy', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'bardy', 'bardy', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'TypeCoercion', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'hardy' . "\n", 'hardy' . "\n", 0, 0, 0, 0, 0, 0, ), ], ], false, ); $this->fileProvider->shouldHaveReceived() ->setContents( $baselineFile, Mockery::on(function (string $document): bool { $baselineDocument = new DOMDocument(); $baselineDocument->loadXML($document, LIBXML_NOBLANKS); /** @var DOMElement[] $files */ $files = $baselineDocument->getElementsByTagName('files')[0]->childNodes; [$file1, $file2] = $files; $this->assertSame('sample/sample-file.php', $file1->getAttribute('src')); $this->assertSame('sample/sample-file2.php', $file2->getAttribute('src')); /** @var DOMElement[] $file1Issues */ $file1Issues = $file1->childNodes; /** @var DOMElement[] $file2Issues */ $file2Issues = $file2->childNodes; $this->assertSame('MixedAssignment', $file1Issues[0]->tagName); $this->assertSame( 3, count($file1Issues[0]->getElementsByTagName('code')), 'MixedAssignment should have occured 3 times', ); $this->assertSame('MixedOperand', $file1Issues[1]->tagName); $this->assertSame( 1, count($file1Issues[1]->getElementsByTagName('code')), 'MixedOperand should have occured 1 time', ); $this->assertSame('MixedAssignment', $file2Issues[0]->tagName); $this->assertSame( 2, count($file2Issues[0]->getElementsByTagName('code')), 'MixedAssignment should have occured 2 times', ); $this->assertSame('TypeCoercion', $file2Issues[1]->tagName); $this->assertSame( 1, count($file2Issues[1]->getElementsByTagName('code')), 'TypeCoercion should have occured 1 time', ); return true; }), ); } public function testUpdateShouldRemoveExistingIssuesWithoutAddingNewOnes(): void { $baselineFile = 'baseline.xml'; $this->fileProvider->allows()->fileExists($baselineFile)->andReturns(true); $this->fileProvider->allows()->getContents($baselineFile)->andReturns( ' bar bat ', ); $this->fileProvider->allows()->setContents(Mockery::andAnyOtherArgs()); $newIssues = [ 'sample/sample-file.php' => [ new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'foo', 'foo', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bar', 'bar', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bat', 'bat', 0, 0, 0, 0, 0, 0, ), new IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bam', 'bam', 0, 0, 0, 0, 0, 0, ), ], 'sample/sample-file2.php' => [ new IssueData( 'error', 0, 0, 'TypeCoercion', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'tar', 'tar', 0, 0, 0, 0, 0, 0, ), ], ]; $remainingBaseline = ErrorBaseline::update( $this->fileProvider, $baselineFile, $newIssues, false, ); $this->assertSame([ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['bar']], 'MixedOperand' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'TypeCoercion' => ['o' => 1, 's' => []], ], ], $remainingBaseline); } public function testAddingACommentInBaselineDoesntTriggerNotice(): void { $baselineFilePath = 'baseline.xml'; $this->fileProvider->allows()->fileExists($baselineFilePath)->andReturns(true); $this->fileProvider->allows()->getContents($baselineFilePath)->andReturns( ' foo bar foo bar ', ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['foo', 'bar']], 'InvalidReturnStatement' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'PossiblyUnusedMethod' => ['o' => 2, 's' => ['foo', 'bar']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider, $baselineFilePath), ); } }