Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kill mutants #67

Merged
merged 4 commits into from
Nov 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"logs": {
"text": "infection.log"
},
"minMsi": 84.54,
"minCoveredMsi": 85.42
"minMsi": 100,
"minCoveredMsi": 100
}
2 changes: 1 addition & 1 deletion src/Routing/CreateAndFetchEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class CreateAndFetchEndpoint extends Endpoint
public ?string $query;
public ?string $redirectTo;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>, command?: string, query?: string, redirectTo?: string} $values */
public function __construct(array $values)
{
parent::__construct($values);
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/CreateEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class CreateEndpoint extends Endpoint
public ?string $redirectTo;
public bool $async;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>, command?: string, redirectTo?: string, async?: bool} $values */
public function __construct(array $values)
{
parent::__construct($values);
Expand Down
6 changes: 3 additions & 3 deletions src/Routing/Endpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ abstract class Endpoint implements Annotation
public ?string $name;
public ?string $app;

/** @var string[] */
/** @var list<string> */
public array $methods;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>} $values */
public function __construct(array $values)
{
$this->path = $values['path'] ?? $values['value'] ?? null;
Expand All @@ -41,6 +41,6 @@ public function validate(string $context): void
/** @throws AnnotationException */
abstract protected function validateAdditionalData(Validator $validator): void;

/** @return string[] */
/** @return list<string> */
abstract protected function defaultMethods(): array;
}
2 changes: 1 addition & 1 deletion src/Routing/ExecuteAndFetchEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class ExecuteAndFetchEndpoint extends Endpoint
public ?string $command;
public ?string $query;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>, command?: string, query?: string} $values */
public function __construct(array $values)
{
parent::__construct($values);
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/ExecuteEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class ExecuteEndpoint extends Endpoint
public ?string $command;
public bool $async;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>, command?: string, async?: bool} $values */
public function __construct(array $values)
{
parent::__construct($values);
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/FetchEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class FetchEndpoint extends Endpoint
{
public ?string $query;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, methods?: list<string>, query?: string} $values */
public function __construct(array $values)
{
parent::__construct($values);
Expand Down
2 changes: 1 addition & 1 deletion src/Routing/Middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class Middleware implements AnnotationInterface
public int $priority;
public ?string $app;

/** @param mixed[] $values */
/** @param array{path?: string, value?: string, name?: string, app?: string, priority?: int} $values */
public function __construct(array $values)
{
$this->path = $values['path'] ?? $values['value'] ?? '/';
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceBus/CommandHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class CommandHandler implements AnnotationInterface
{
public ?string $handles;

/** @param mixed[] $values */
/** @param array{handles?: string, value?: string} $values */
public function __construct(array $values)
{
$this->handles = $values['handles'] ?? $values['value'] ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceBus/Middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class Middleware implements AnnotationInterface
public ?string $bus;
public int $priority;

/** @param mixed[] $values */
/** @param array{bus?: string, value?: string, priority?: int} $values */
public function __construct(array $values)
{
$this->bus = $values['bus'] ?? $values['value'] ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceBus/QueryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class QueryHandler implements AnnotationInterface
{
public ?string $handles;

/** @param mixed[] $values */
/** @param array{handles?: string, value?: string} $values */
public function __construct(array $values)
{
$this->handles = $values['handles'] ?? $values['value'] ?? null;
Expand Down
36 changes: 17 additions & 19 deletions src/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
use Doctrine\Common\Annotations\AnnotationException;

use function array_intersect;
use function gettype;
use function implode;
use function trim;

/** @internal */
final class Validator
Expand All @@ -32,7 +32,7 @@ public function requiredScalar(string $attribute, string $type, $value): void
throw AnnotationException::requiredError($attribute, $this->annotation, $this->context, $type);
}

$this->verifyType($attribute, $type, $value);
$this->requireNonEmptyString($attribute, $type, $value);
}

/**
Expand All @@ -46,7 +46,21 @@ public function nonRequiredScalar(string $attribute, string $type, $value): void
return;
}

$this->verifyType($attribute, $type, $value);
$this->requireNonEmptyString($attribute, $type, $value);
}

/**
* @param mixed $value
*
* @throws AnnotationException
*/
private function requireNonEmptyString(string $attribute, string $type, $value): void
{
if ($type !== 'string' || trim($value) !== '') {
return;
}

throw AnnotationException::requiredError($attribute, $this->annotation, $this->context, $type);
}

/**
Expand All @@ -61,8 +75,6 @@ public function enumArray(string $attribute, array $allowedValues, $value): void
throw AnnotationException::requiredError($attribute, $this->annotation, $this->context, 'array');
}

$this->verifyType($attribute, 'array', $value);

if (array_intersect($value, $allowedValues) === []) {
// @phpstan-ignore-next-line
throw AnnotationException::enumeratorError(
Expand All @@ -74,18 +86,4 @@ public function enumArray(string $attribute, array $allowedValues, $value): void
);
}
}

/**
* @param mixed $value
*
* @throws AnnotationException
*/
private function verifyType(string $attribute, string $type, $value): void
{
$actualType = gettype($value);

if ($actualType !== $type) {
throw AnnotationException::attributeTypeError($attribute, $this->annotation, $this->context, $type, $value);
}
}
}
2 changes: 1 addition & 1 deletion tests/Unit/ReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public function getClassAnnotationShouldReturnMatchedAnnotation(): void
$annotation = $this->createMock(Annotation::class);
$class = new ReflectionClass(self::class);

$annotation->expects(self::exactly(1))
$annotation->expects(self::once())
->method('validate')
->with('class ' . self::class);

Expand Down
42 changes: 34 additions & 8 deletions tests/Unit/Routing/CreateAndFetchEndpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,49 @@ public function validateShouldNotRaiseExceptionsWhenStateIsValid(): void
* @covers \Chimera\Mapping\Validator
* @covers \Chimera\Mapping\Routing\Endpoint
*
* @param mixed[] $values
* @param array{query?: string, command?: string, redirectTo?: string} $values
*/
public function validateShouldRaiseExceptionWhenInvalidDataWasProvided(array $values): void
public function validateShouldRaiseExceptionWhenInvalidDataWasProvided(array $values, string $expectedMessage): void
{
$annotation = new CreateAndFetchEndpoint(self::ENDPOINT_DATA + $values);

$this->expectException(AnnotationException::class);
$this->expectExceptionMessage($expectedMessage);

$annotation->validate('class A');
}

/** @return mixed[][] */
public function invalidScenarios(): array
/** @return iterable<string, array{0: array{query?: string, command?: string, redirectTo?: string}, 1: string}> */
public function invalidScenarios(): iterable
{
return [
'empty command' => [['query' => 'test', 'redirectTo' => 'test3']],
'empty query' => [['command' => 'test', 'redirectTo' => 'test3']],
'empty redirectTo' => [['command' => 'test', 'query' => 'test']],
yield 'missing command' => [
['query' => 'test', 'redirectTo' => 'test3'],
'"command" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];

yield 'empty command' => [
['command' => ' ', 'query' => 'test', 'redirectTo' => 'test3'],
'"command" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];

yield 'missing query' => [
['command' => 'test', 'redirectTo' => 'test3'],
'"query" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];

yield 'empty query' => [
['command' => 'test', 'query' => '', 'redirectTo' => 'test3'],
'"query" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];

yield 'missing redirectTo' => [
['command' => 'test', 'query' => 'test'],
'"redirectTo" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];

yield 'empty redirectTo' => [
['command' => 'test', 'query' => 'test', 'redirectTo' => ''],
'"redirectTo" of @Chimera\Mapping\Routing\CreateAndFetchEndpoint declared on class A expects string.',
];
}
}
31 changes: 24 additions & 7 deletions tests/Unit/Routing/CreateEndpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,39 @@ public function validateShouldNotRaiseExceptionsWhenAsyncNotIsProvided(): void
* @covers \Chimera\Mapping\Validator
* @covers \Chimera\Mapping\Routing\Endpoint
*
* @param mixed[] $values
* @param array{command?: string, redirectTo?: string} $values
*/
public function validateShouldRaiseExceptionWhenInvalidDataWasProvided(array $values): void
public function validateShouldRaiseExceptionWhenInvalidDataWasProvided(array $values, string $expectedMessage): void
{
$annotation = new CreateEndpoint(self::ENDPOINT_DATA + $values);

$this->expectException(AnnotationException::class);
$this->expectExceptionMessage($expectedMessage);

$annotation->validate('class A');
}

/** @return mixed[][] */
public function invalidScenarios(): array
/** @return iterable<string, array{0: array{command?: string, redirectTo?: string}, 1: string}> */
public function invalidScenarios(): iterable
{
return [
'empty command' => [['redirectTo' => 'test']],
'empty redirectTo' => [['command' => 'test']],
yield 'missing command' => [
['redirectTo' => 'test'],
'"command" of @Chimera\Mapping\Routing\CreateEndpoint declared on class A expects string.',
];

yield 'empty command' => [
['command' => '', 'redirectTo' => 'test'],
'"command" of @Chimera\Mapping\Routing\CreateEndpoint declared on class A expects string.',
];

yield 'missing redirectTo' => [
['command' => 'test'],
'"redirectTo" of @Chimera\Mapping\Routing\CreateEndpoint declared on class A expects string.',
];

yield 'empty redirectTo' => [
['command' => 'test', 'redirectTo' => ''],
'"redirectTo" of @Chimera\Mapping\Routing\CreateEndpoint declared on class A expects string.',
];
}
}
Loading