Skip to content

Commit

Permalink
Allow the object asserter to inspect the object keys
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosV2 committed Jun 22, 2017
1 parent d3abe6d commit a7e1a3b
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
19 changes: 19 additions & 0 deletions docs/PrimitiveTypesExtension/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,22 @@ In order to refine the validation, the following functions are available:
This function checks if the given object is or has the given type.

You can use this function as `To::beObject()->withType($type)`.

### withKey

This function registers the given key for future inspection. This function does nothing by itself. It needs to be
combined with `expected` or `withNoOtherKeys` functions.

### expected

This function checks if the given key contains data that matches the given asserter. This function needs a
previous call to `withKey` in order to know which key it needs to apply the asserter to.

You can use this function as `To::beObject()->withKey($key)->expected(To::be*())`.

### withNoOtherKeys

This function checks if the given object contains other non-registered keys. This function needs a previous
call to `withKey` in order to know which keys it needs to check.

You can use this function as `To::beObject()->withKey($key)->withNoOtherKeys()`.
47 changes: 47 additions & 0 deletions spec/Extension/PrimitiveTypesExtension/ObjectAsserterSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace spec\carlosV2\Can\Extension\PrimitiveTypesExtension;

use carlosV2\Can\AsserterInterface;
use PhpSpec\ObjectBehavior;

class ObjectAsserterSpec extends ObjectBehavior
Expand All @@ -26,6 +27,52 @@ function it_returns_false_for_anything_but_object()
$this->check(true)->shouldReturn(false);
}

function it_ensures_it_only_contains_accepted_keys()
{
$this->withKey('k1')->shouldReturn($this);
$this->withKey('k2')->shouldReturn($this);
$this->withNoOtherKeys()->shouldReturn($this);

$object1 = new \stdClass();
$object1->k1 = 'val1';

$object2 = new \stdClass();
$object2->k1 = 'val1';
$object2->k2 = 'val2';

$object3 = new \stdClass();
$object3->k1 = 'val1';
$object3->k2 = 'val2';
$object3->k3 = 'val3';

$this->check($object1)->shouldReturn(true);
$this->check($object2)->shouldReturn(true);
$this->check($object3)->shouldReturn(false);
}

function it_ensures_the_keys_types(AsserterInterface $asserterK1, AsserterInterface $asserterK2)
{
$asserterK1->check('val1')->willReturn(true);
$asserterK1->check(1)->willReturn(false);
$asserterK2->check('val2')->willReturn(true);

$this->withKey('k1')->shouldReturn($this);
$this->expected($asserterK1)->shouldReturn($this);
$this->withKey('k2')->shouldReturn($this);
$this->expected($asserterK2)->shouldReturn($this);

$object1 = new \stdClass();
$object1->k1 = 'val1';
$object1->k2 = 'val2';

$object2 = new \stdClass();
$object2->k1 = 1;
$object2->k2 = 'val2';

$this->check($object1)->shouldReturn(true);
$this->check($object2)->shouldReturn(false);
}

function it_ensures_the_object_is_of_an_specific_type()
{
$this->withType('\DateTime')->shouldReturn($this);
Expand Down
74 changes: 74 additions & 0 deletions src/Extension/PrimitiveTypesExtension/ObjectAsserter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@ class ObjectAsserter implements AsserterInterface
*/
private $requiredType;

/**
* @var AsserterInterface[]
*/
private $keys;

/**
* @var string
*/
private $lastKey;

/**
* @var bool
*/
private $otherKeysAllowed;

public function __construct()
{
$this->keys = [];
$this->otherKeysAllowed = true;
}

/**
* @param string $type
*
Expand All @@ -23,6 +44,45 @@ public function withType($type)
return $this;
}

/**
* @param string $key
*
* @return ObjectAsserter
*/
public function withKey($key)
{
$this->lastKey = $key;
$this->keys[$key] = null;

return $this;
}

/**
* @param AsserterInterface $asserter
*
* @return ObjectAsserter
*/
public function expected(AsserterInterface $asserter)
{
if (is_null($this->lastKey)) {
throw new \BadMethodCallException();
}

$this->keys[$this->lastKey] = $asserter;

return $this;
}

/**
* @return ObjectAsserter
*/
public function withNoOtherKeys()
{
$this->otherKeysAllowed = false;

return $this;
}

/**
* @inheritdoc
*/
Expand All @@ -38,6 +98,20 @@ public function check($data)
}
}

foreach ($this->keys as $key => $asserter) {
if (!is_null($asserter)) {
if (!$asserter->check($data->{$key})) {
return false;
}
}
}

if (!$this->otherKeysAllowed) {
if (count(array_diff(array_keys(get_object_vars($data)), array_keys($this->keys))) > 0) {
return false;
}
}

return true;
}
}

0 comments on commit a7e1a3b

Please sign in to comment.