/**
* Tests if a fixer fixes a given string to match the expected result.
*
* It is used both if you want to test if something is fixed or if it is not touched by the fixer.
* It also makes sure that the expected output does not change when run through the fixer. That means that you
* do not need two test cases like [$expected] and [$expected, $input] (where $expected is the same in both cases)
* as the latter covers both of them.
* This method throws an exception if $expected and $input are equal to prevent test cases that accidentally do
* not test anything.
*
* @param string $expected The expected fixer output
* @param string|null $input The fixer input, or null if it should intentionally be equal to the output
* @param \SplFileInfo|null $file The file to fix, or null if unneeded
*/
protected function doTest($expected, $input = null, \SplFileInfo $file = null)
{
if ($expected === $input) {
throw new \InvalidArgumentException('Input parameter must not be equal to expected parameter.');
}
$file = $file ?: $this->getTestFile();
$fileIsSupported = $this->fixer->supports($file);
if (null !== $input) {
$this->assertNull($this->lintSource($input));
Tokens::clearCache();
$tokens = Tokens::fromCode($input);
if ($fileIsSupported) {
$this->assertTrue($this->fixer->isCandidate($tokens), 'Fixer must be a candidate for input code.');
$fixResult = $this->fixer->fix($file, $tokens);
$this->assertNull($fixResult, '->fix method must return null.');
}
$this->assertThat($tokens->generateCode(), new SameStringsConstraint($expected), 'Code build on input code must match expected code.');
$this->assertTrue($tokens->isChanged(), 'Tokens collection built on input code must be marked as changed after fixing.');
$tokens->clearEmptyTokens();
$this->assertSame(count($tokens), count(array_unique(array_map(function (Token $token) {
return spl_object_hash($token);
}, $tokens->toArray()))), 'Token items inside Tokens collection must be unique.');
Tokens::clearCache();
$expectedTokens = Tokens::fromCode($expected);
$this->assertTokens($expectedTokens, $tokens);
}
$this->assertNull($this->lintSource($expected));
Tokens::clearCache();
$tokens = Tokens::fromCode($expected);
$isCandidate = $this->fixer->isCandidate($tokens);
$this->assertFalse($tokens->isChanged(), 'Fixer should not touch Tokens on candidate check.');
if (!$isCandidate) {
return;
}
if ($fileIsSupported) {
$fixResult = $this->fixer->fix($file, $tokens);
$this->assertNull($fixResult, '->fix method must return null.');
}
$this->assertThat($tokens->generateCode(), new SameStringsConstraint($expected), 'Code build on expected code must not change.');
$this->assertFalse($tokens->isChanged(), 'Tokens collection built on expected code must not be marked as changed after fixing.');
}