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

Added require annotation propery to the spec example #21

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,28 @@ Skips all the spec example if the class or interface is not available
```php
/**
* @require Vendor\Builder\ToolInterface
*
* All examples will be skipped if the ToolInterface does not exist
*/
class BridgeBuilderSpec extends ObjectBehavior
class LondonBridgeBuilderSpec extends ObjectBehavior
{
// Will be skipped if the Vendor\Builder\ToolInterface interface does not exist
function it_builds_a_brige()
/**
* @require Vendor\Manufacturer\StoneFactory
* @require Vendor\Manufacturer\BrickFactory
*
* Will be skipped if the ToolInterface OR StoneFactory OR BrickFacroty does not exist
*/
function it_builds_a_stone_brige()
{
}

// Will be skipped if the Vendor\Builder\ToolInterface interface does not exist
function it_builds_the_road()
/**
* @require Vendor\Manufacturer\WoodFactory
* @require Vendor\Manufacturer\ClayFactory
*
* Will be skipped if the ToolInterface OR WoodFactory OR ClayFactory does not exist
*/
function it_builds_a_wooden_bridge()
{
}

Expand Down
132 changes: 124 additions & 8 deletions spec/Akeneo/Runner/Maintainer/SkipExampleMaintainerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
*/
final class SkipExampleMaintainerSpec extends ObjectBehavior
{
const MISSING_REQUIRE = "/**\n * @require Foo\\Bar\n */";
const EXISTING_CLASS = "/**\n * @require Akeneo\Runner\Maintainer\SkipExampleMaintainer\n */";
const EXISTING_INTERFACE = "/**\n * @require PhpSpec\Runner\Maintainer\Maintainer\n */";

function it_is_a_maintainer(): void
{
$this->shouldImplement(Maintainer::class);
Expand All @@ -29,26 +33,51 @@ function its_priority_is_75(): void
$this->getPriority()->shouldBe(75);
}

function it_supports_specification_that_has_require_doc_comment(
function it_supports_specification_that_has_require_class_doc_comment(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass
\ReflectionClass $refClass,
\ReflectionFunction $refMethod
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn("/**\n * @require Foo\\Bar\n */");

$refClass->getDocComment()->willReturn(self::MISSING_REQUIRE);
$refMethod->getDocComment()->willReturn(false);

$this->supports($example)->shouldBe(true);
}

function it_does_not_support_specification_that_does_not_have_doc_comment(
function it_supports_example_node_that_has_require_method_doc_comment(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass
\ReflectionClass $refClass,
\ReflectionFunction $refMethod
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);

$refClass->getDocComment()->willReturn(false);
$refMethod->getDocComment()->willReturn(self::MISSING_REQUIRE);

$this->supports($example)->shouldBe(true);
}

function it_does_not_support_specification_that_does_not_have_any_doc_comment(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);

$specification->getClassReflection()->willReturn($refClass);

$refClass->getDocComment()->willReturn(false);
$refMethod->getDocComment()->willReturn(false);

$this->supports($example)->shouldBe(false);
}
Expand All @@ -57,13 +86,16 @@ function its_prepare_method_throws_skipping_exception_when_specification_require
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn("/**\n * @require Foo\\Bar\n */");
$refClass->getDocComment()->willReturn(self::MISSING_REQUIRE);
$refMethod->getDocComment()->willReturn(self::EXISTING_INTERFACE);

$exception = new SkippingException('"Foo\\Bar" is not available');
$this->shouldThrow($exception)->duringPrepare($example, $context, $matchers, $collaborators);
Expand All @@ -73,13 +105,36 @@ function its_prepare_method_does_not_throw_exception_when_specification_requires
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn("/**\n * @require Akeneo\Runner\Maintainer\SkipExampleMaintainer\n */");

$refClass->getDocComment()->willReturn(self::EXISTING_CLASS);
$refMethod->getDocComment()->willReturn(false);

$this->shouldNotThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}

function its_prepare_method_does_not_throw_exception_when_example_node_requires_an_existing_class(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);

$refClass->getDocComment()->willReturn(false);
$refMethod->getDocComment()->willReturn(self::EXISTING_CLASS);

$this->shouldNotThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}
Expand All @@ -88,28 +143,89 @@ function its_prepare_method_does_not_throw_exception_when_specification_requires
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn("/**\n * @require PhpSpec\Runner\Maintainer\Maintainer\n */");
$refClass->getDocComment()->willReturn(self::EXISTING_INTERFACE);
$refMethod->getDocComment()->willReturn(false);

$this->shouldNotThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}

function its_prepare_method_does_not_throw_exception_when_example_node_requires_an_existing_interface(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);

$refClass->getDocComment()->willReturn(false);
$refMethod->getDocComment()->willReturn(self::EXISTING_INTERFACE);

$this->shouldNotThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}

function its_prepare_method_throw_exception_when_specification_requires_an_existing_class_but_example_node_requires_an_missing_class(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn(self::EXISTING_CLASS);
$refMethod->getDocComment()->willReturn(self::MISSING_REQUIRE);

$this->shouldThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}

function its_prepare_method_throw_exception_when_specification_requires_an_missing_class_but_example_node_requires_an_existing_class(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn(self::MISSING_REQUIRE);
$refMethod->getDocComment()->willReturn(self::EXISTING_CLASS);

$this->shouldThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}

function its_prepare_method_ignores_other_annotation(
ExampleNode $example,
SpecificationNode $specification,
\ReflectionClass $refClass,
\ReflectionFunction $refMethod,
Specification $context,
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
$example->getSpecification()->willReturn($specification);
$example->getFunctionReflection()->willReturn($refMethod);
$specification->getClassReflection()->willReturn($refClass);
$refClass->getDocComment()->willReturn("/**\n * @author [email protected] \n */");
$refMethod->getDocComment()->willReturn("/**\n * @author [email protected] \n */");

$this->shouldNotThrow(SkippingException::class)->duringPrepare($example, $context, $matchers, $collaborators);
}
Expand Down
29 changes: 26 additions & 3 deletions src/Akeneo/Runner/Maintainer/SkipExampleMaintainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ final class SkipExampleMaintainer implements Maintainer
*/
public function supports(ExampleNode $example): bool
{
return count($this->getRequirements($this->getDocComment($example))) > 0;
$specDocComments = $this->getSpecDocComment($example);
$exampleDocCommnts = $this->getExampleDocComment($example);

return count($this->getRequirements($specDocComments . $exampleDocCommnts)) > 0;
}

/**
Expand All @@ -30,7 +33,15 @@ public function prepare(
MatcherManager $matchers,
CollaboratorManager $collaborators
): void {
foreach ($this->getRequirements($this->getDocComment($example)) as $requirement) {

$specRequirements = $this->getRequirements($this->getSpecDocComment($example));
$exampleRequirements = $this->getRequirements($this->getExampleDocComment($example));

// Push example node requirement to the end of check list,
// if any spec class requirements are missing, all example node will not be executed as well.
$requirements = \array_merge($specRequirements, $exampleRequirements);

foreach ($requirements as $requirement) {
if (!class_exists($requirement) && !interface_exists($requirement)) {
throw new SkippingException(
sprintf('"%s" is not available', $requirement)
Expand Down Expand Up @@ -100,8 +111,20 @@ function($docline) {
*
* @return string
*/
private function getDocComment(ExampleNode $example): string
private function getSpecDocComment(ExampleNode $example): string
{
return $example->getSpecification()->getClassReflection()->getDocComment() ?: '';
}

/**
* Get example node doc comment
*
* @param ExampleNode $example
*
* @return string
*/
private function getExampleDocComment(ExampleNode $example): string
{
return $example->getFunctionReflection()->getDocComment() ?: '';
}
}