diff --git a/src/Matcher/ArrayMatcher.php b/src/Matcher/ArrayMatcher.php index c811ffbd..f1de7f1d 100644 --- a/src/Matcher/ArrayMatcher.php +++ b/src/Matcher/ArrayMatcher.php @@ -144,6 +144,15 @@ private function iterateMatch(array $values, array $patterns, $parentPath = "") private function isPatternValid(array $pattern, array $values, $parentPath) { if (is_array($pattern)) { + $skipPattern = static::UNBOUNDED_PATTERN; + + $pattern = array_filter( + $pattern, + function ($item) use ($skipPattern) { + return $item !== $skipPattern; + } + ); + $notExistingKeys = array_diff_key($pattern, $values); if (count($notExistingKeys) > 0) { diff --git a/tests/Matcher/ArrayMatcherTest.php b/tests/Matcher/ArrayMatcherTest.php index eb009740..4a02e480 100644 --- a/tests/Matcher/ArrayMatcherTest.php +++ b/tests/Matcher/ArrayMatcherTest.php @@ -147,7 +147,7 @@ public static function positiveMatchData() 'firstName' => '@string@', 'lastName' => '@string@' ), - '@...@' + Matcher\ArrayMatcher::UNBOUNDED_PATTERN ), true, false, @@ -163,7 +163,25 @@ public static function positiveMatchData() array(array('foo' => null), array('foo' => "@null@")), array(array('key' => 'val'), array('key' => 'val')), array(array(1), array(1)), - array(array('roles' => array('ROLE_ADMIN', 'ROLE_DEVELOPER')), array('roles' => '@wildcard@')) + array( + array('roles' => array('ROLE_ADMIN', 'ROLE_DEVELOPER')), + array('roles' => '@wildcard@'), + ), + 'unbound array should match one or none elements' => array( + array( + 'users' => array( + array( + 'firstName' => 'Norbert', + 'lastName' => 'Foobar', + ), + ), + true, + false, + 1, + 6.66, + ), + $simpleArrPattern, + ), ); } @@ -210,7 +228,22 @@ public static function negativeMatchData() array(array('key' => 'val'), array('key' => 'val2')), array(array(1), array(2)), array(array('foo', 1, 3), array('foo', 2, 3)), - array(array(), array('foo' => 'bar')) + array(array(), array('foo' => 'bar')), + 'unbound array should match one or none elements' => array( + array( + 'users' => array( + array( + 'firstName' => 'Norbert', + 'lastName' => 'Foobar', + ), + ), + true, + false, + 1, + 6.66, + ), + $simpleDiff, + ), ); } } diff --git a/tests/MatcherTest.php b/tests/MatcherTest.php index dc7db940..4021b6a9 100644 --- a/tests/MatcherTest.php +++ b/tests/MatcherTest.php @@ -4,7 +4,6 @@ use Coduo\PHPMatcher\Factory\SimpleFactory; use Coduo\PHPMatcher\Matcher; -use Coduo\PHPMatcher\Parser; use Coduo\PHPMatcher\PHPMatcher; class MatcherTest extends \PHPUnit_Framework_TestCase @@ -28,14 +27,14 @@ public function test_matcher_with_array_value() 'id' => 1, 'firstName' => 'Norbert', 'lastName' => 'Orzechowicz', - 'enabled' => true + 'enabled' => true, ), array( 'id' => 2, 'firstName' => 'Michał', 'lastName' => 'Dąbrowski', 'enabled' => true, - ) + ), ), 'readyToUse' => true, 'data' => new \stdClass(), @@ -47,14 +46,14 @@ public function test_matcher_with_array_value() 'id' => '@integer@', 'firstName' => '@string@', 'lastName' => 'Orzechowicz', - 'enabled' => '@boolean@' + 'enabled' => '@boolean@', ), array( 'id' => '@integer@', 'firstName' => '@string@', 'lastName' => 'Dąbrowski', 'enabled' => '@boolean@', - ) + ), ), 'readyToUse' => true, 'data' => '@wildcard@', @@ -73,55 +72,112 @@ public function test_matcher_with_scalar_values($value, $pattern) $this->assertTrue(PHPMatcher::match($value, $pattern)); } - public function test_matcher_with_json() + /** + * @dataProvider jsonDataProvider + */ + public function test_matcher_with_json($json, $jsonPattern) { - $json = ' - { - "users":[ - { - "id": 131, - "firstName": "Norbert", - "lastName": "Orzechowicz", - "enabled": true, - "roles": ["ROLE_DEVELOPER"] - }, - { - "id": 132, - "firstName": "Michał", - "lastName": "Dąbrowski", - "enabled": false, - "roles": ["ROLE_DEVELOPER"] - } - ], - "prevPage": "http:\/\/example.com\/api\/users\/1?limit=2", - "nextPage": "http:\/\/example.com\/api\/users\/3?limit=2" - }'; - $jsonPattern = ' - { - "users":[ - { - "id": "@integer@", - "firstName":"Norbert", - "lastName":"Orzechowicz", - "enabled": "@boolean@", - "roles": "@array@" - }, - { - "id": "@integer@", - "firstName": "Michał", - "lastName": "Dąbrowski", - "enabled": "expr(value == false)", - "roles": "@array@" - } - ], - "prevPage": "@string@", - "nextPage": "@string@" - }'; - $this->assertTrue($this->matcher->match($json, $jsonPattern)); $this->assertTrue(PHPMatcher::match($json, $jsonPattern)); } + public function jsonDataProvider() + { + return array( + 'matches exactly' => array( + /** @lang JSON */ + '{ + "users":[ + { + "id": 131, + "firstName": "Norbert", + "lastName": "Orzechowicz", + "enabled": true, + "roles": ["ROLE_DEVELOPER"] + }, + { + "id": 132, + "firstName": "Michał", + "lastName": "Dąbrowski", + "enabled": false, + "roles": ["ROLE_DEVELOPER"] + } + ], + "prevPage": "http:\/\/example.com\/api\/users\/1?limit=2", + "nextPage": "http:\/\/example.com\/api\/users\/3?limit=2" + }', + /** @lang JSON */ + '{ + "users":[ + { + "id": "@integer@", + "firstName":"Norbert", + "lastName":"Orzechowicz", + "enabled": "@boolean@", + "roles": "@array@" + }, + { + "id": "@integer@", + "firstName": "Michał", + "lastName": "Dąbrowski", + "enabled": "expr(value == false)", + "roles": "@array@" + } + ], + "prevPage": "@string@", + "nextPage": "@string@" + }', + ), + 'matches none elements - empty array' => array( + /** @lang JSON */ + '{ + "users":[], + "prevPage": "http:\/\/example.com\/api\/users\/1?limit=2", + "nextPage": "http:\/\/example.com\/api\/users\/3?limit=2" + }', + /** @lang JSON */ + '{ + "users":[ + "@...@" + ], + "prevPage": "@string@", + "nextPage": "@string@" + }', + ), + 'matches one element' => array( + /** @lang JSON */ + '{ + "users":[ + { + "id": 131, + "firstName": "Norbert", + "lastName": "Orzechowicz", + "enabled": true, + "roles": ["ROLE_DEVELOPER"] + } + ], + "prevPage": "http:\/\/example.com\/api\/users\/1?limit=2", + "nextPage": "http:\/\/example.com\/api\/users\/3?limit=2" + }', + /** @lang JSON */ + '{ + "users":[ + { + "id": "@integer@", + "firstName":"Norbert", + "lastName":"Orzechowicz", + "enabled": "@boolean@", + "roles": "@array@" + }, + "@...@" + ], + "prevPage": "@string@", + "nextPage": "@string@" + }', + ), + ); + } + public function test_matcher_with_xml() { $xml = <<