bump tests to phpstan level 5 (#1922)

This commit is contained in:
Kevin Papst
2020-09-05 16:48:19 +02:00
committed by GitHub
parent b69ea0648c
commit ed528eb19a
35 changed files with 128 additions and 93 deletions

View File

@@ -24,5 +24,5 @@ jobs:
- run: composer validate --no-check-all --strict
- run: vendor/bin/php-cs-fixer fix --dry-run --verbose --config=.php_cs.dist --using-cache=no --show-progress=none --format=checkstyle | cs2pr
- run: vendor/bin/phpstan analyse src -c phpstan.neon --level=5 --no-progress --error-format=checkstyle | cs2pr
- run: vendor/bin/phpstan analyse tests -c tests/phpstan.neon --level=4 --no-progress --error-format=checkstyle | cs2pr
- run: vendor/bin/phpstan analyse tests -c tests/phpstan.neon --level=5 --no-progress --error-format=checkstyle | cs2pr
- run: composer kimai:code-lint

View File

@@ -170,7 +170,7 @@
"kimai:phpstan": "@phpstan",
"phpstan": [
"vendor/bin/phpstan analyse src -c phpstan.neon --level=5",
"vendor/bin/phpstan analyse tests -c tests/phpstan.neon --level=4"
"vendor/bin/phpstan analyse tests -c tests/phpstan.neon --level=5"
],
"kimai:codestyle": "@codestyle",
"codestyle": "vendor/bin/php-cs-fixer fix --dry-run --verbose --show-progress=none",

View File

@@ -42,8 +42,8 @@ final class AnnotationExtractor implements ExtractorInterface
*/
public function extract($value): array
{
if (!\is_string($value)) {
throw new ExtractorException('AnnotationExtractor needs a class name (string) for work');
if (!\is_string($value) || empty($value)) {
throw new ExtractorException('AnnotationExtractor needs a non-empty class name for work');
}
try {

View File

@@ -23,7 +23,7 @@ class SearchTermTransformer implements DataTransformerInterface
*/
public function transform($searchTerm)
{
if (empty($searchTerm) || !$searchTerm instanceof SearchTerm) {
if (empty($searchTerm) || !($searchTerm instanceof SearchTerm)) {
return '';
}
@@ -33,7 +33,7 @@ class SearchTermTransformer implements DataTransformerInterface
/**
* Transforms a string to a SearchTerm object.
*
* @param string $searchTerm
* @param string|null $searchTerm
* @return SearchTerm|null
* @throws TransformationFailedException if object (issue) is not found
*/

View File

@@ -48,7 +48,7 @@ class TagArrayToStringTransformer implements DataTransformerInterface
/**
* Transforms a string to an array of tags.
*
* @param string $stringOfTags
* @param string|null $stringOfTags
*
* @return Tag[]
* @throws TransformationFailedException if object (issue) is not found

View File

@@ -25,11 +25,11 @@ class TimesheetStatistic
*/
protected $durationTotal = 0;
/**
* @var int
* @var float
*/
protected $amountThisMonth = 0;
/**
* @var int
* @var float
*/
protected $amountTotal = 0;
/**
@@ -54,17 +54,24 @@ class TimesheetStatistic
$this->durationThisMonth = (int) $durationThisMonth;
}
public function getAmountTotal(): int
/**
* This is actually the rate, wrong wording...
*
* @return float
*/
public function getAmountTotal(): float
{
return $this->amountTotal;
}
/**
* @param int $amountTotal
* This is actually the rate, wrong wording...
*
* @param float|int $amountTotal
*/
public function setAmountTotal($amountTotal)
{
$this->amountTotal = (int) $amountTotal;
$this->amountTotal = (float) $amountTotal;
}
public function getDurationTotal(): int
@@ -80,17 +87,24 @@ class TimesheetStatistic
$this->durationTotal = (int) $durationTotal;
}
public function getAmountThisMonth(): int
/**
* This is actually the rate, wrong wording...
*
* @return float
*/
public function getAmountThisMonth(): float
{
return $this->amountThisMonth;
}
/**
* @param int $amountThisMonth
* This is actually the rate, wrong wording...
*
* @param float|int $amountThisMonth
*/
public function setAmountThisMonth($amountThisMonth)
{
$this->amountThisMonth = (int) $amountThisMonth;
$this->amountThisMonth = (float) $amountThisMonth;
}
public function getFirstEntry(): ?\DateTime

View File

@@ -78,10 +78,10 @@ final class MarkdownExtension extends AbstractExtension
/**
* Transforms the timesheet description content into HTML.
*
* @param string $content
* @param string|null $content
* @return string
*/
public function timesheetContent($content): string
public function timesheetContent(?string $content): string
{
if (empty($content)) {
return '';

View File

@@ -19,12 +19,12 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
final class TimesheetValidator extends ConstraintValidator
{
/**
* @var TimesheetConstraint[]
* @var Constraint[]
*/
private $constraints;
/**
* @param TimesheetConstraint[] $constraints
* @param Constraint[] $constraints
*/
public function __construct(iterable $constraints)
{

View File

@@ -9,8 +9,8 @@
namespace App\Tests\Event;
use App\Entity\Configuration;
use App\Event\SystemConfigurationEvent;
use App\Form\Model\Configuration;
use App\Form\Model\SystemConfiguration;
use PHPUnit\Framework\TestCase;

View File

@@ -75,11 +75,22 @@ class AnnotationExtractorTest extends TestCase
$sut = new AnnotationExtractor(new AnnotationReader());
$this->expectException(ExtractorException::class);
$this->expectExceptionMessage('AnnotationExtractor needs a class name (string) for work');
$this->expectExceptionMessage('AnnotationExtractor needs a non-empty class name for work');
/* @phpstan-ignore-next-line */
$sut->extract(new \stdClass());
}
public function testExceptionOnEmptyString()
{
$sut = new AnnotationExtractor(new AnnotationReader());
$this->expectException(ExtractorException::class);
$this->expectExceptionMessage('AnnotationExtractor needs a non-empty class name for work');
$sut->extract('');
}
public function testExceptionOnMissingExpression()
{
$sut = new AnnotationExtractor(new AnnotationReader());

View File

@@ -61,6 +61,7 @@ class MetaFieldExtractorTest extends TestCase
$this->expectException(ExtractorException::class);
$this->expectExceptionMessage('MetaFieldExtractor needs a MetaDisplayEventInterface instance for work');
/* @phpstan-ignore-next-line */
$sut->extract(new \stdClass());
}
}

View File

@@ -60,6 +60,7 @@ class UserPreferenceExtractorTest extends TestCase
$this->expectException(ExtractorException::class);
$this->expectExceptionMessage('UserPreferenceExtractor needs a UserPreferenceDisplayEvent instance for work');
/* @phpstan-ignore-next-line */
$sut->extract(new \stdClass());
}
}

View File

@@ -22,8 +22,10 @@ class SearchTermTransformerTest extends TestCase
{
$sut = new SearchTermTransformer();
/* @phpstan-ignore-next-line */
self::assertEquals('', $sut->transform(''));
self::assertEquals('', $sut->transform(null));
/* @phpstan-ignore-next-line */
self::assertEquals('', $sut->transform(new \stdClass()));
self::assertEquals(

View File

@@ -9,6 +9,11 @@
namespace App\Tests\Form\MultiUpdate;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Tag;
use App\Entity\Timesheet;
use App\Form\MultiUpdate\MultiUpdateTableDTO;
use PHPUnit\Framework\TestCase;
@@ -45,7 +50,13 @@ class MultiUpdateTableDTOTest extends TestCase
self::assertInstanceOf(MultiUpdateTableDTO::class, $sut->setAction('sdfsdfsdf'));
self::assertEquals('sdfsdfsdf', $sut->getAction());
self::assertInstanceOf(MultiUpdateTableDTO::class, $sut->setEntities([1, 2, 3, 4, 5, 6, 7, 8, 9, '0815']));
self::assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9, '0815'], $sut->getEntities());
$activity = new Activity();
$project = new Project();
$customer = new Customer();
$timesheet = new Timesheet();
$tag = new Tag();
self::assertInstanceOf(MultiUpdateTableDTO::class, $sut->setEntities([$tag, $timesheet, $activity, $customer, $project]));
self::assertEquals([$tag, $timesheet, $activity, $customer, $project], $sut->getEntities());
}
}

View File

@@ -12,6 +12,7 @@ namespace App\Tests\Form\MultiUpdate;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Form\MultiUpdate\TimesheetMultiUpdateDTO;
use PHPUnit\Framework\TestCase;
@@ -59,8 +60,10 @@ class TimesheetMultiUpdateDTOTest extends TestCase
self::assertInstanceOf(TimesheetMultiUpdateDTO::class, $sut->setAction('sdfsdfsdf'));
self::assertEquals('sdfsdfsdf', $sut->getAction());
self::assertInstanceOf(TimesheetMultiUpdateDTO::class, $sut->setEntities([1, 2, 3, 4, 5, 6, 7, 8, 9, '0815']));
self::assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9, '0815'], $sut->getEntities());
$entities = [new Timesheet(), new Timesheet(), new Timesheet(), new Timesheet()];
self::assertInstanceOf(TimesheetMultiUpdateDTO::class, $sut->setEntities($entities));
self::assertEquals($entities, $sut->getEntities());
self::assertInstanceOf(TimesheetMultiUpdateDTO::class, $sut->setExported(true));
self::assertTrue($sut->isExported());

View File

@@ -76,8 +76,10 @@ class SamlAuthFactory extends AbstractMockFactory
];
}
$request = $this->getMockBuilder(Request::class)->getMock();
$request->method('isFromTrustedProxy')->willReturn($fromTrustedProxy);
$mock = $this->getMockBuilder(Request::class)->getMock();
$mock->method('isFromTrustedProxy')->willReturn($fromTrustedProxy);
/** @var Request $request */
$request = $mock;
$requestStack = new RequestStack();
$requestStack->push($request);

View File

@@ -34,10 +34,16 @@ class CurrentUserFactory extends AbstractMockFactory
$user->addPreference($pref);
}
$repository = $this->getMockBuilder(UserRepository::class)->onlyMethods(['getUserById'])->disableOriginalConstructor()->getMock();
$repository->expects(TestCase::atMost(1))->method('getUserById')->willReturn($user);
$token = $this->getMockBuilder(UsernamePasswordToken::class)->onlyMethods(['getUser'])->disableOriginalConstructor()->getMock();
$token->method('getUser')->willReturn($user);
$mock = $this->getMockBuilder(UserRepository::class)->onlyMethods(['getUserById'])->disableOriginalConstructor()->getMock();
$mock->expects(TestCase::atMost(1))->method('getUserById')->willReturn($user);
/** @var UserRepository $repository */
$repository = $mock;
$mock = $this->getMockBuilder(UsernamePasswordToken::class)->onlyMethods(['getUser'])->disableOriginalConstructor()->getMock();
$mock->method('getUser')->willReturn($user);
/** @var UsernamePasswordToken $token */
$token = $mock;
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);

View File

@@ -18,7 +18,7 @@ use App\Tests\Mocks\AbstractMockFactory;
class RoleServiceFactory extends AbstractMockFactory
{
/**
* @param string[]|null $roles
* @param array<string, array<string>>|null $roles
* @param Role[]|null $repositoryRoles
* @return RoleService
*/
@@ -33,10 +33,12 @@ class RoleServiceFactory extends AbstractMockFactory
];
}
$repository = $this->getMockBuilder(RoleRepository::class)->onlyMethods(['findAll'])->disableOriginalConstructor()->getMock();
$repository->method('findAll')->willReturn($repositoryRoles);
$mock = $this->getMockBuilder(RoleRepository::class)->onlyMethods(['findAll'])->disableOriginalConstructor()->getMock();
$mock->method('findAll')->willReturn($repositoryRoles);
/** @var RoleRepository $repository */
$repository = $mock;
/* @var RoleRepository $repository */
return new RoleService($repository, $roles);
}
}

View File

@@ -27,8 +27,8 @@ class ActivityStatisticTest extends TestCase
public function testSetter()
{
$sut = new ActivityStatistic();
$sut->setRecordAmount(7654.298);
$sut->setRecordDuration(826.10);
$sut->setRecordAmount(7654);
$sut->setRecordDuration(826);
$this->assertEquals(7654, $sut->getRecordAmount());
$this->assertEquals(826, $sut->getRecordDuration());

View File

@@ -29,8 +29,8 @@ class CustomerStatisticTest extends TestCase
public function testSetter()
{
$sut = new CustomerStatistic();
$sut->setRecordAmount(7654.298);
$sut->setRecordDuration(826.10);
$sut->setRecordAmount(7654);
$sut->setRecordDuration(826);
$sut->setActivityAmount(13);
$sut->setProjectAmount(2);

View File

@@ -30,8 +30,8 @@ class ProjectStatisticTest extends TestCase
{
$project = new Project();
$sut = new ProjectStatistic($project);
$sut->setRecordAmount(7654.298);
$sut->setRecordDuration(826.10);
$sut->setRecordAmount(7654);
$sut->setRecordDuration(826);
$sut->setActivityAmount(13);
self::assertEquals(13, $sut->getActivityAmount());

View File

@@ -34,7 +34,7 @@ class DayTest extends TestCase
$date = new DateTime('-8 hours');
$sut = new Day($date, 12340, 197.25956);
$sut->setTotalDuration(999.27);
$sut->setTotalDuration(999);
$sut->setTotalRate(0.123456789);
$this->assertEquals(999, $sut->getTotalDuration());

View File

@@ -58,7 +58,7 @@ class MonthTest extends TestCase
public function testSetter()
{
$sut = new Month('01');
$sut->setTotalDuration(999.27);
$sut->setTotalDuration(999);
$sut->setTotalRate(0.123456789);
$this->assertEquals(999, $sut->getTotalDuration());

View File

@@ -21,7 +21,7 @@ class YearTest extends TestCase
public function testDefaultValues()
{
$sut = new Year('1999');
$this->assertNull($sut->getMonth('01'));
$this->assertNull($sut->getMonth(1));
$this->assertEmpty($sut->getMonths());
$this->assertIsArray($sut->getMonths());
$this->assertEquals('1999', $sut->getYear());

View File

@@ -41,8 +41,8 @@ class TimesheetStatisticTest extends TestCase
$sut->setFirstEntry($date);
$this->assertEquals(2, $sut->getRecordsTotal());
$this->assertEquals(7654, $sut->getAmountTotal());
$this->assertEquals(826, $sut->getAmountThisMonth());
$this->assertEquals(7654.298, $sut->getAmountTotal());
$this->assertEquals(826.10, $sut->getAmountThisMonth());
$this->assertEquals(13, $sut->getDurationTotal());
$this->assertEquals(200, $sut->getDurationThisMonth());
$this->assertSame($date, $sut->getFirstEntry());

View File

@@ -128,7 +128,7 @@ class TimesheetQueryTest extends BaseQueryTest
$sut->setExported(TimesheetQuery::STATE_ALL);
self::assertEquals(TimesheetQuery::STATE_ALL, $sut->getExported());
$sut->setExported('02');
$sut->setExported(2);
self::assertEquals(TimesheetQuery::STATE_ALL, $sut->getExported());
}

View File

@@ -29,15 +29,18 @@ class VisibilityQueryTest extends TestCase
self::assertFalse($sut->isShowHidden());
self::assertFalse($sut->isShowBoth());
/* @phpstan-ignore-next-line */
$sut->setVisibility('foo-bar');
$this->assertEquals(VisibilityQuery::SHOW_VISIBLE, $sut->getVisibility());
$sut->setVisibility('2');
/* @phpstan-ignore-next-line */
$sut->setVisibility('2'); // cast to integer
$this->assertEquals(VisibilityQuery::SHOW_HIDDEN, $sut->getVisibility());
self::assertFalse($sut->isShowVisible());
self::assertTrue($sut->isShowHidden());
self::assertFalse($sut->isShowBoth());
/* @phpstan-ignore-next-line */
$sut->setVisibility('0'); // keep the value that was previously set
$this->assertEquals(VisibilityQuery::SHOW_HIDDEN, $sut->getVisibility());
@@ -63,15 +66,18 @@ class VisibilityQueryTest extends TestCase
self::assertFalse($sut->isShowHidden());
self::assertFalse($sut->isShowBoth());
/* @phpstan-ignore-next-line */
$sut->setVisibility('foo-bar');
$this->assertEquals(VisibilityInterface::SHOW_VISIBLE, $sut->getVisibility());
/* @phpstan-ignore-next-line */
$sut->setVisibility('2');
$this->assertEquals(VisibilityInterface::SHOW_HIDDEN, $sut->getVisibility());
self::assertFalse($sut->isShowVisible());
self::assertTrue($sut->isShowHidden());
self::assertFalse($sut->isShowBoth());
/* @phpstan-ignore-next-line */
$sut->setVisibility('0'); // keep the value that was previously set
$this->assertEquals(VisibilityInterface::SHOW_HIDDEN, $sut->getVisibility());

View File

@@ -21,9 +21,9 @@ class RoleServiceTest extends TestCase
public function testWithEmptyRepository()
{
$real = [
'ROLE_TEAMLEAD' => [0 => 'ROLE_USER'],
'ROLE_ADMIN' => [0 => 'ROLE_TEAMLEAD'],
'ROLE_SUPER_ADMIN' => [0 => 'ROLE_ADMIN']
'ROLE_TEAMLEAD' => ['ROLE_USER'],
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN']
];
$sut = (new RoleServiceFactory($this))->create($real);

View File

@@ -171,6 +171,9 @@ class DateExtensionsTest extends TestCase
$sut = $this->getSut('en', []);
$this->assertEquals('2010-01-07T17:43:21+01:00', $sut->dateFormat($date, 'c'));
$this->assertStringStartsWith('2010-01-07T17:43:21', $sut->dateFormat('7 January 2010 17:43:21', 'c'));
// next test checks the fallback for errors while converting the date
/* @phpstan-ignore-next-line */
$this->assertEquals(2010.0107, $sut->dateFormat(2010.0107, 'c'));
}
@@ -209,6 +212,9 @@ class DateExtensionsTest extends TestCase
$this->assertEquals('2019-08-17 12:29:47', $sut->dateTimeFull($dateTime));
$this->assertEquals('2019-08-17 12:29:47', $sut->dateTimeFull('2019-08-17 12:29:47'));
// next test checks the fallback for errors while converting the date
/* @phpstan-ignore-next-line */
$this->assertEquals(189.45, $sut->dateTimeFull(189.45));
}
}

View File

@@ -77,7 +77,9 @@ class ExtensionsTest extends TestCase
$sut = $this->getSut();
$this->assertEquals('DateTime', $sut->getClassName(new \DateTime()));
$this->assertEquals('stdClass', $sut->getClassName(new \stdClass()));
/* @phpstan-ignore-next-line */
$this->assertNull($sut->getClassName(''));
/* @phpstan-ignore-next-line */
$this->assertNull($sut->getClassName(null));
$this->assertEquals('App\Entity\User', $sut->getClassName(new User()));
}

View File

@@ -268,11 +268,11 @@ class LocaleExtensionsTest extends TestCase
// test negative duration
$sut = $this->getSut($this->localeEn, 'en');
$this->assertEquals('?', $sut->duration('-1'));
$this->assertEquals('?', $sut->duration(-1));
// test zero duration
$sut = $this->getSut($this->localeEn, 'en');
$this->assertEquals('00:00 h', $sut->duration('0'));
$this->assertEquals('00:00 h', $sut->duration(0));
$sut = $this->getSut($this->localeEn, 'en');
@@ -296,11 +296,11 @@ class LocaleExtensionsTest extends TestCase
// test negative duration
$sut = $this->getSut($this->localeEn, 'en');
$this->assertEquals('0', $sut->durationDecimal('-1'));
$this->assertEquals('0', $sut->durationDecimal(-1));
// test zero duration
$sut = $this->getSut($this->localeEn, 'en');
$this->assertEquals('0', $sut->durationDecimal('0'));
$this->assertEquals('0', $sut->durationDecimal(0));
$sut = $this->getSut($this->localeEn, 'en');

View File

@@ -58,6 +58,7 @@ class WidgetExtensionTest extends TestCase
$this->expectExceptionMessage('Widget must either implement WidgetInterface or be a string');
$sut = $this->getSut();
/* @phpstan-ignore-next-line */
$sut->renderWidget(true);
}

View File

@@ -201,11 +201,11 @@ class LocaleHelperTest extends TestCase
// test negative duration
$sut = $this->getSut('en');
$this->assertEquals('0', $sut->durationDecimal('-1'));
$this->assertEquals('0', $sut->durationDecimal(-1));
// test zero duration
$sut = $this->getSut('en');
$this->assertEquals('0', $sut->durationDecimal('0'));
$this->assertEquals('0', $sut->durationDecimal(0));
}
protected function getTimesheet($seconds)

View File

@@ -9,21 +9,13 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\TimesheetConfiguration;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Repository\TimesheetRepository;
use App\Tests\Mocks\TrackingModeServiceFactory;
use App\Validator\Constraints\Timesheet as TimesheetConstraint;
use App\Validator\Constraints\TimesheetFutureTimesValidator;
use App\Validator\Constraints\TimesheetLockdownValidator;
use App\Validator\Constraints\TimesheetOverlappingValidator;
use App\Validator\Constraints\TimesheetRestartValidator;
use App\Validator\Constraints\TimesheetFutureTimes;
use App\Validator\Constraints\TimesheetValidator;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
@@ -41,32 +33,7 @@ class TimesheetValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator(bool $isGranted = true)
{
$auth = $this->createMock(AuthorizationCheckerInterface::class);
$auth->method('isGranted')->willReturn($isGranted);
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new TimesheetConfiguration($loader, [
'rules' => [
'allow_future_times' => false,
'allow_overlapping_records' => true,
],
'rounding' => [
'default' => [
'begin' => 1
]
]
]);
$service = (new TrackingModeServiceFactory($this))->create('default');
$repository = $this->createMock(TimesheetRepository::class);
$constraints = [
new TimesheetFutureTimesValidator($config),
new TimesheetLockdownValidator($auth, $config),
new TimesheetOverlappingValidator($config, $repository),
new TimesheetRestartValidator($service, $auth),
];
return new TimesheetValidator($constraints);
return new TimesheetValidator([]);
}
public function testConstraintIsInvalid()

View File

@@ -41,7 +41,7 @@ class TimesheetVoterTest extends AbstractVoterTest
public function getTestData()
{
$user0 = $this->getUser(0, null);
$user0 = $this->getUser(0, 'unknown');
$user1 = $this->getUser(1, User::ROLE_USER);
$user2 = $this->getUser(2, User::ROLE_TEAMLEAD);
$user3 = $this->getUser(3, User::ROLE_ADMIN);