Giter Site home page Giter Site logo

coduo / php-matcher Goto Github PK

View Code? Open in Web Editor NEW
813.0 813.0 83.0 7.98 MB

The easiest way to match data structures like JSON/PlainText/XML against readable patterns. Sandbox:

Home Page: https://php-matcher.norbert.tech/

License: MIT License

PHP 100.00%

php-matcher's Introduction

PHP Matcher

Type Coverage

Library created for testing all kinds of JSON/XML/TXT/Scalar values against patterns.

API:

PHPMatcher::match($value = '{"foo": "bar"}', $pattern = '{"foo": "@string@"}') : bool;
PHPMatcher::backtrace() : Backtrace;
PHPMatcher::error() : ?string;

It was built to simplify API's functional testing.

Latest Stable Version Total Downloads Latest Unstable Version License

We Stand Against Terror

Stand With Ukraine Stand With Us
Flag of Ukraine Flag of Israel

On Feb. 24, 2022, Russia declared an unprovoked war on Ukraine and launched a full-scale invasion. Russia is currently bombing peaceful Ukrainian cities, including schools and hospitals and attacking civilians who are fleeing conflict zones.

On Oct. 7, 2023, the national holiday of Simchat Torah, Hamas terrorists initiated an attack on Israel in the early hours, targeting civilians. They unleashed violence that resulted in at least 1,400 casualties and abducted at least 200 individuals, not limited to Israelis.

Sandbox

Feel free to play first with Sandbox

Installation

Require new dev dependency using composer:

composer require --dev "coduo/php-matcher"

Basic usage

Direct PHPMatcher usage

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();
$match = $matcher->match("lorem ipsum dolor", "@string@");

if (!$match) {
    echo "Error: " . $matcher->error();
    echo "Backtrace: \n";
    echo (string) $matcher->backtrace();
}

PHPUnit extending PHPMatcherTestCase

<?php

use Coduo\PHPMatcher\PHPUnit\PHPMatcherTestCase;

class MatcherTest extends PHPMatcherTestCase
{
    public function test_matcher_that_value_matches_pattern()
    {
        $this->assertMatchesPattern('{"name": "@string@"}', '{"name": "Norbert"}');
    }
}

PHPUnit using PHPMatcherAssertions trait

<?php

use Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions;
use PHPUnit\Framework\TestCase;

class MatcherTest extends TestCase
{
    use PHPMatcherAssertions;

    public function test_matcher_that_value_matches_pattern()
    {
        $this->assertMatchesPattern('{"name": "@string@"}', '{"name": "Norbert"}');
    }
}

Available patterns

  • @string@
  • @integer@
  • @number@
  • @double@
  • @boolean@
  • @time@
  • @date@
  • @datetime@
  • @timezone@ || @tz
  • @array@
  • @array_previous@ - match next array element using pattern from previous element
  • @array_previous_repeat@ - match all remaining array elements using pattern from previous element
  • @...@ - unbounded array, once used matcher will skip any further array elements
  • @null@
  • @*@ || @wildcard@
  • expr(expression) - optional, requires symfony/expression-language: ^2.3|^3.0|^4.0|^5.0 to be present
  • @uuid@
  • @ulid@
  • @json@
  • @string@||@integer@ - string OR integer

Available pattern expanders

  • startsWith($stringBeginning, $ignoreCase = false)
  • endsWith($stringEnding, $ignoreCase = false)
  • contains($string, $ignoreCase = false)
  • notContains($string, $ignoreCase = false)
  • isDateTime()
  • isInDateFormat($format) - example "@[email protected]('Y-m-d H:i:s')
  • before(string $date) - example "@[email protected]().before(\"2020-01-01 00:00:00\")"
  • after(string $date) - example "@[email protected]().after(\"2020-01-01 00:00:00\")"
  • isTzOffset()
  • isTzIdentifier()
  • isTzAbbreviation()
  • isEmail()
  • isUrl()
  • isIp()
  • isEmpty()
  • isNotEmpty()
  • lowerThan($boundry)
  • greaterThan($boundry)
  • inArray($value) - example "@[email protected](\"ROLE_USER\")"
  • hasProperty($propertyName) - example "@[email protected](\"property_name\")"
  • oneOf(...$expanders) - example "@[email protected](contains('foo'), contains('bar'), contains('baz'))"
  • matchRegex($regex) - example "@[email protected]('/^lorem.+/')"
  • optional() - work's only with ArrayMatcher, JsonMatcher and XmlMatcher
  • count() - work's only with ArrayMatcher - example "@[email protected](5)"
  • repeat($pattern, $isStrict = true) - example '@[email protected]({"name": "foe"})' or "@[email protected]('@string@')"
  • match($pattern) - example {"image":"@[email protected]({\"url\":\"@[email protected]()\"})"}

Example usage

Scalar matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(1, 1);
$matcher->match('string', 'string');

String matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('Norbert', '@string@');
$matcher->match("lorem ipsum dolor", "@[email protected]('lorem').contains('ipsum').endsWith('dolor')");

Time matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('00:00:00', '@time@');
$matcher->match('00:01:00.000000', '@time@');
$matcher->match('00:01:00', '@[email protected]("00:00:00")');
$matcher->match('00:00:00', '@[email protected]("01:00:00")');

Date matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('2014-08-19', '@date@');
$matcher->match('2020-01-11', '@date@');
$matcher->match('2014-08-19', '@[email protected]("2016-08-19")');
$matcher->match('2014-08-19', '@[email protected]("today").after("+ 100year")');

DateTime matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('2014-08-19', '@datetime@');
$matcher->match('2020-01-11 00:00:00', '@datetime@');
$matcher->match('2014-08-19', '@[email protected]("2016-08-19")');
$matcher->match('2014-08-19', '@[email protected]("today").after("+ 100year")');

TimeZone matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('Europe/Warsaw', '@timezone@');
$matcher->match('Europe/Warsaw', '@tz@');
$matcher->match('GMT', '@tz@');
$matcher->match('01:00', '@tz@');
$matcher->match('01:00', '@[email protected]()');
$matcher->match('GMT', '@[email protected]()');
$matcher->match('Europe/Warsaw', '@[email protected]()');

Integer matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(100, '@integer@');
$matcher->match(100, '@[email protected](200).greaterThan(10)');

Number matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(100, '@number@');
$matcher->match('200', '@number@');
$matcher->match(1.25, '@number@');
$matcher->match('1.25', '@number@');
$matcher->match(0b10100111001, '@number@');

Double matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(10.1, "@double@");
$matcher->match(10.1, "@[email protected](50.12).greaterThan(10)");

Boolean matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(true, "@boolean@");
$matcher->match(false, "@boolean@");

Wildcard matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match("@integer@", "@*@");
$matcher->match("foobar", "@*@");
$matcher->match(true, "@*@");
$matcher->match(6.66, "@*@");
$matcher->match(array("bar"), "@wildcard@");
$matcher->match(new \stdClass, "@wildcard@");

Expression matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(new \DateTime('2014-04-01'), "expr(value.format('Y-m-d') == '2014-04-01'");
$matcher->match("Norbert", "expr(value === 'Norbert')");

UUID matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('9f4db639-0e87-4367-9beb-d64e3f42ae18', '@uuid@');

ULID matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match('01BX5ZZKBKACTAV9WEVGEMMVS0', '@ulid@');

Array matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(
   array(
      'users' => array(
          array(
              'id' => 1,
              'firstName' => 'Norbert',
              'lastName' => 'Orzechowicz',
              'roles' => array('ROLE_USER'),
              'position' => 'Developer',
          ),
          array(
              'id' => 2,
              'firstName' => 'Michał',
              'lastName' => 'Dąbrowski',
              'roles' => array('ROLE_USER')
          ),
          array(
              'id' => 3,
              'firstName' => 'Johnny',
              'lastName' => 'DąbrowsBravoki',
              'roles' => array('ROLE_HANDSOME_GUY')
          )
      ),
      true,
      6.66
  ),
   array(
      'users' => array(
          array(
              'id' => '@[email protected](0)',
              'firstName' => '@string@',
              'lastName' => 'Orzechowicz',
              'roles' => '@array@',
              'position' => '@[email protected]()'
          ),
          array(
              'id' => '@integer@',
              'firstName' => '@string@',
              'lastName' => 'Dąbrowski',
              'roles' => '@array@'
          ),
          '@...@'
      ),
      '@boolean@',
      '@double@'
  )
);

Array Previous

@array_previous@ can also be used when matching JSON's and XML's

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(
   array(
      'users' => array(
          array(
              'id' => 1,
              'firstName' => 'Norbert',
              'lastName' => 'Orzechowicz',
              'roles' => array('ROLE_USER'),
              'position' => 'Developer',
          ),
          array(
              'id' => 2,
              'firstName' => 'Michał',
              'lastName' => 'Dąbrowski',
              'roles' => array('ROLE_USER')
          ),
          array(
              'id' => 3,
              'firstName' => 'Johnny',
              'lastName' => 'DąbrowsBravoki',
              'roles' => array('ROLE_HANDSOME_GUY')
          )
      ),
      true,
      6.66
  ),
   array(
      'users' => array(
          array(
              'id' => '@[email protected](0)',
              'firstName' => '@string@',
              'lastName' => 'Orzechowicz',
              'roles' => '@array@',
              'position' => '@[email protected]()'
          ),
          '@array_previous@',
          '@array_previous@'
      ),
      '@boolean@',
      '@double@'
  )
);

Array Previous Repeat

@array_previous_repeat@ can also be used when matching JSON's and XML's

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(
   array(
      'users' => array(
          array(
              'id' => 1,
              'firstName' => 'Norbert',
              'lastName' => 'Orzechowicz',
              'roles' => array('ROLE_USER'),
              'position' => 'Developer',
          ),
          array(
              'id' => 2,
              'firstName' => 'Michał',
              'lastName' => 'Dąbrowski',
              'roles' => array('ROLE_USER')
          ),
          array(
              'id' => 3,
              'firstName' => 'Johnny',
              'lastName' => 'DąbrowsBravoki',
              'roles' => array('ROLE_HANDSOME_GUY')
          )
      ),
      true,
      6.66
  ),
   array(
      'users' => array(
          array(
              'id' => '@[email protected](0)',
              'firstName' => '@string@',
              'lastName' => 'Orzechowicz',
              'roles' => '@array@',
              'position' => '@[email protected]()'
          ),
          '@array_previous_repeat@'
      ),
      '@boolean@',
      '@double@'
  )
);

Json matching

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(
  '{
    "users":[
      {
        "firstName": "Norbert",
        "lastName": "Orzechowicz",
        "created": "2014-01-01",
        "roles":["ROLE_USER", "ROLE_DEVELOPER"]
      }
    ]
  }',
  '{
    "users":[
      {
        "firstName": "@string@",
        "lastName": "@string@",
        "created": "@[email protected]()",
        "roles": "@array@",
        "position": "@[email protected]()"
      }
    ]
  }'
);

Json matching with unbounded arrays and objects

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(
  '{
    "users":[
      {
        "firstName": "Norbert",
        "lastName": "Orzechowicz",
        "created": "2014-01-01",
        "roles":["ROLE_USER", "ROLE_DEVELOPER"],
        "attributes": {
          "isAdmin": false,
          "dateOfBirth": null,
          "hasEmailVerified": true
        },
        "avatar": {
          "url": "http://avatar-image.com/avatar.png"
        }
      },
      {
        "firstName": "Michał",
        "lastName": "Dąbrowski",
        "created": "2014-01-01",
        "roles":["ROLE_USER", "ROLE_DEVELOPER", "ROLE_ADMIN"],
        "attributes": {
          "isAdmin": true,
          "dateOfBirth": null,
          "hasEmailVerified": true
        },
        "avatar": null
      }
    ]
  }',
  '{
    "users":[
      {
        "firstName": "@string@",
        "lastName": "@string@",
        "created": "@[email protected]()",
        "roles": [
            "ROLE_USER",
            "@...@"
        ],
        "attributes": {
          "isAdmin": @boolean@,
          "@*@": "@*@"
        },
        "avatar": "@[email protected]({\"url\":\"@[email protected]()\"})"
      }
      ,
      @...@
    ]
  }'
);

Xml matching

Optional - requires openlss/lib-array2xml: ^1.0 to be present.

<?php

use Coduo\PHPMatcher\PHPMatcher;

$matcher = new PHPMatcher();

$matcher->match(<<<XML
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">

<soap:Body xmlns:m="http://www.example.org/stock">
  <m:GetStockPrice>
    <m:StockName>IBM</m:StockName>
    <m:StockValue>Any Value</m:StockValue>
  </m:GetStockPrice>
</soap:Body>

</soap:Envelope>
XML
                ,
                <<<XML
<?xml version="1.0"?>
<soap:Envelope
    xmlns:soap="@string@"
            soap:encodingStyle="@string@">

<soap:Body xmlns:m="@string@">
  <m:GetStockPrice>
    <m:StockName>@string@</m:StockName>
    <m:StockValue>@string@</m:StockValue>
    <m:StockQty>@[email protected]()</m:StockQty>
  </m:GetStockPrice>
</soap:Body>

</soap:Envelope>
XML
        );

Example scenario for api in behat using mongo.

@profile, @user
Feature: Listing user toys

  As a user
  I want to list my toys

  Background:
    Given I send and accept JSON

  Scenario: Listing toys
    Given the following users exist:
      | firstName     | lastName     |
      | Chuck         | Norris       |

    And the following toys user "Chuck Norris" exist:
      | name            |
      | Barbie          |
      | GI Joe          |
      | Optimus Prime   |

    When I set valid authorization code oauth header for user "Chuck Norris"
    And I send a GET request on "/api/toys"
    Then the response status code should be 200
    And the JSON response should match:
    """
      [
        {
          "id": "@string@",
          "name": "Barbie",
          "_links: "@*@"
        },
        {
          "id": "@string@",
          "name": "GI Joe",
          "_links": "@*@"
        },
        {
          "id": "@string@",
          "name": "Optimus Prime",
          "_links": "@*@"
        }
      ]
    """

PHPUnit integration

The assertMatchesPattern() is a handy assertion that matches values in PHPUnit tests. To use it either include the Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions trait, or extend the Coduo\PHPMatcher\PHPUnit\PHPMatcherTestCase:

namespace Coduo\PHPMatcher\Tests\PHPUnit;

use Coduo\PHPMatcher\PHPUnit\PHPMatcherAssertions;
use PHPUnit\Framework\TestCase;

class PHPMatcherAssertionsTest extends TestCase
{
    use PHPMatcherAssertions;

    public function test_it_asserts_if_a_value_matches_the_pattern()
    {
        $this->assertMatchesPattern('@string@', 'foo');
    }
}

The matchesPattern() method can be used in PHPUnit stubs or mocks:

$mock = $this->createMock(Foo::class);
$mock->method('bar')
    ->with($this->matchesPattern('@string@'))
    ->willReturn('foo');

License

This library is distributed under the MIT license. Please see the LICENSE file.

Credits

This lib was inspired by JSON Expressions gem && Behat RestExtension

php-matcher's People

Contributors

aeon-automation avatar alexander-schranz avatar bendavies avatar cakper avatar cordoval avatar defrag avatar dependabot[bot] avatar drymek avatar github-actions[bot] avatar jakzal avatar jarjak avatar k-phoen avatar kasn avatar marcospassos avatar mateuszsip avatar mmoreram avatar nclshart avatar norberttech avatar partikus avatar peter279k avatar pskt avatar raing3 avatar robinvdvleuten avatar rogervila avatar samnela avatar spartakusmd avatar teklakct avatar thomasbisignani avatar vudaltsov avatar wengerk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-matcher's Issues

Null value matching problem

Following pattern:

    {
      "username":null,
      "some_data": @string@ 
    }

does not match value

{"username":null,"some_data":"test"}

but when using @wildcard@ or @null@ instead of null in patter it works. This issue needs to be solved before 2.0.0 release described here #66

Tested with version 2.0.0-rc

Support of CSV

Hello,

I'm not sure it's realistic but well, I think it's something missing with this lib so here is the issue.

If I have serveral minutes, gonna try to make it !

[RFC] Pattern expanders

In most cases patterns are enough to create our expectations against value but sometimes there is a need to check something more. For example if we want to check if integer is lower than X or if array contain specific key/value.
Of course there is a expression pattern which is very elastic but it also make our patterns big, less readable and sometimes hard to understand.
I believe it would be nice to expand patterns with some extra critierias.
Few examples:

Following patterns will match ['foo' => 'bar'] value
@[email protected]('foo':'bar')
@[email protected]('foo')
@[email protected]('bar')

Following patterns will match "25" value:
@[email protected](23)
@[email protected](20)
@[email protected](10, 100)

Following patterns will match "Hello world" value:
@[email protected]('Hello')
@[email protected]('World')
@[email protected]('llo Wo')

I think there might be a need to use more than one expander for a pattern.

@[email protected]('Hello').contains(' ').endWith('World')

First matcher will check if pattern match value and after that value is going to be check against every single expander. The result will be positive only if every single expander return "true".

Maybe there are some more expanders we can add?

Packagist not auto-updated

Hey, would be nice if you could setup git hook to let packagist know whenever you release a new version. Currently 3.1.2 is not listed on packagist despite it's been relased on github 11 days ago.

More info can be found on https://packagist.org/about

Thanks!

Null not work correctly

I have problem with comparing null value

This works

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();
$json1 = '{"proformaInvoiceLink":null}';
$json2 = '{"proformaInvoiceLink":null}';
 $match = $matcher->match($json1, $json2);

But this not works

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();
$json1 = '{"proformaInvoiceLink":null, "test":"test"}';
$json2 = '{"proformaInvoiceLink":null, "test":"@string@"}';
 $match = $matcher->match($json1, $json2);

When I use @null@ it works

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();
$json1 = '{"proformaInvoiceLink":null, "test":"test"}';
$json2 = '{"proformaInvoiceLink":@null@, "test":"@string@"}';
 $match = $matcher->match($json1, $json2);

I think that second example should works too.

[UUID] Uuid inside string doesn't work

In the next string case the @uuid@ pattern is not supported

{
    "@context":"\/v1\/contexts\/Team",
    "@id":"\/v1\/teams\/@uuid@"
}

If change the 2 constants in the UuidMatcher it works like expected.

const UUID_PATTERN = '/@uuid@/';
const UUID_FORMAT_PATTERN = '|[\da-f]{8}-[\da-f]{4}-[1-5][\da-f]{3}-[89ab][\da-f]{3}-[\da-f]{12}|';

Lib is not compatible with PHP 7.3

Lib is not compatible with PHP 7.3

Error : Cannot call constructor
 /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherConstraint.php:19
 /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherAssertions.php:18
 /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherAssertions.php:13
 /srv/api/tests/functional/Users/RegisterTest.php:34

    public function testUsersRegisterSuccess($data)
    {
        $response = $this->request('POST', '/users/register', $data);

        $this->assertMatchesPattern('{"http_code":201,"response":{"@context":"\/contexts\/User","@id":"\/users\/424","@type":"User","email":"[email protected]","lastName":"Brawn","firstName":"John","birthDate":"1984-01-15T00:00:00+00:00","phoneNumber":"89375699565","smoker":"no","status":"not_verified","pet":["dog","fish"],"gender":"male","religion":null,"education":null,"groups":[],"profession":null,"countryOfResidence":null,"countryOfBirth":null,"id":424}}', $response);
    }
final class PHPMatcherConstraint extends Constraint
{
    private $pattern;

    private $matcher;

    public function __construct(string $pattern)
    {
        parent::__construct();

        $this->pattern = $pattern;
        $this->matcher = $this->createMatcher();
    }

parent in __construct does not work


Error: Cannot call constructor in /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherConstraint.php on line 19

Call Stack:
    0.0549     399416   1. {main}() /srv/api/vendor/phpunit/phpunit/phpunit:0
    0.0634    1204704   2. PHPUnit\TextUI\Command::main(???) /srv/api/vendor/phpunit/phpunit/phpunit:61
    0.0635    1204816   3. PHPUnit\TextUI\Command->run(???, ???) /srv/api/vendor/phpunit/phpunit/src/TextUI/Command.php:160
    0.1108    3450504   4. PHPUnit\TextUI\TestRunner->doRun(???, ???, ???) /srv/api/vendor/phpunit/phpunit/src/TextUI/Command.php:201
    0.1209    4036992   5. PHPUnit\Framework\TestSuite->run(???) /srv/api/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:619
    0.1292    4039080   6. PHPUnit\Framework\DataProviderTestSuite->run(???) /srv/api/vendor/phpunit/phpunit/src/Framework/TestSuite.php:568
    0.1305    4039640   7. App\Tests\Functional\Users\RegisterTest->run(???) /srv/api/vendor/phpunit/phpunit/src/Framework/TestSuite.php:568
    0.1308    4039640   8. PHPUnit\Framework\TestResult->run(???) /srv/api/vendor/phpunit/phpunit/src/Framework/TestCase.php:823
    0.1319    4051656   9. App\Tests\Functional\Users\RegisterTest->runBare() /srv/api/vendor/phpunit/phpunit/src/Framework/TestResult.php:680
    2.5206   36902456  10. App\Tests\Functional\Users\RegisterTest->runTest() /srv/api/vendor/phpunit/phpunit/src/Framework/TestCase.php:869
    2.5207   36902832  11. App\Tests\Functional\Users\RegisterTest->testUsersRegisterSuccess(???) /srv/api/vendor/phpunit/phpunit/src/Framework/TestCase.php:1192
    5.0228   40668832  12. App\Tests\Functional\Users\RegisterTest->assertMatchesPattern(???, ???, ???) /srv/api/tests/functional/Users/RegisterTest.php:34
    6.6382   40668832  13. App\Functional\AbstractWebTestCase::matchesPattern(???) /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherAssertions.php:13
   11.8812   40692808  14. Coduo\PHPMatcher\PHPUnit\PHPMatcherConstraint->__construct(???) /srv/api/vendor/coduo/php-matcher/src/PHPUnit/PHPMatcherAssertions.php:18

Unexpected error - (does not match)

I don't understand why I'm getting error below for the code. Anyone reason?

Composer has "coduo/php-matcher": "~1.1" package.

It passes when I remove @string@ but what's the point!

_CODE_

use Coduo\PHPMatcher\Factory\SimpleFactory;

class FeatureContext extends WebApiContext implements KernelAwareInterface
{
    /**
     * Checks that response body contains JSON from PyString.
     *
     * @param PyStringNode $jsonString
     *
     * @Then /^(?:the )?response should contain dynamic json:$/
     */
    public function theResponseShouldContainDynamicJson(PyStringNode $jsonString)
    {
        $factory = new SimpleFactory();
        $matcher = $factory->createMatcher();

        $matcher->match(
        '{
            "users":[
              {
                "firstName": "Norbert",
                "lastName": "Orzechowicz",
                "created": "2014-01-01",
                "roles":["ROLE_USER", "ROLE_DEVELOPER"]}
              ]
          }',
        '{
            "users":[
              {
                "firstName": @string@,
                "lastName": "Orzechowicz",
                "created": "2014-01-01",
                "roles":["ROLE_USER", "ROLE_DEVELOPER"]}
              ]
          }'
        );

        echo $matcher->getError();
    }
}

_ERROR_

"{
            "users":[
              {
                "firstName": "Norbert",
                "lastName": "Orzechowicz",
                "created": "2014-01-01",
                "roles":["ROLE_USER", "ROLE_DEVELOPER"]}
              ]
          }" does not match "{
            "users":[
              {
                "firstName": @string@,
                "lastName": "Orzechowicz",
                "created": "2014-01-01",
                "roles":["ROLE_USER", "ROLE_DEVELOPER"]}
              ]
          }".

Example code fail

I've issue with the code in the example. I create this very simple script.

#!/usr/bin/env php
<?php
// application.php

use Coduo\PHPMatcher\Factory\SimpleFactory;

require __DIR__.'/vendor/autoload.php';

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$matcher->match($value = '{"foo": "bar"}', $pattern = '{"foo": "@string@"}');
echo $matcher->getError();

but I get : Any matcher from chain can't match value "{"foo": "bar"}" to pattern "{"foo": "@string@"}"

I'm using latest version of this library and version 7.3.7 of PHP

Can't understand where I go wrong.

Use matchers for keys instead of values

Hi,

Thanks for your work on this package, it's really nice!

In my test cases I am in need to use matchers for keys too, I saw this is currently not possible. In my case the key is an ID which is different in every test run. So I just want to test it like this:

{
    "@integer@": 9.95
}

Would something like this be a good feature to have in this library?

2.0.0 Release cycle

Version 2.0.0-alpha1 was just released. From now on, every monday I will release next version in order to finish with stable release 2.0.0

  • 2.0.0-alpha1 - 25.01.2016
  • 2.0.0-alpha2 - (will be skipped in case of no changes) - 01.02.2015
  • 2.0.0-beta - 08.02.2016 (beta1 and beta2 are merged to beta)
  • 2.0.0-rc - 15.02.2016
  • 2.0.0-rc1 - 03.03.2016 - solved #71
  • 2.0.0-rc2 - 18.03.2016 - finally solved #71
  • 2.0.0 - 25.03.2016

So in the worse scenario I will release stable version 2.0.0 on 29.02.2015. But in case of no problems with 2.0.0-alpha1 I will skip to beta1 and then to rc1 so 2.0.0 can be possibly released on 22.02.2015

Also from version we are going to follow semantic versioning guidelines.
changelog and upgrade documents should be from now updated after each PR that require it.

Match specific fields in a JSON (ignoring the others)

Hello! Given a JSON like this:

{
    "id": "@string@",
    "title": "My Title",
    "short_description": "@string@",
    "campaign_start": "@string@",
    "campaign_end": "@string@",
    "status": "@integer@",
    "_links": "@wildcard@",
    "_embedded": {
        "account": {
            "id": "@string@",
            "name": "@string@",
            "society_name": "@string@",
            "_links": "@wildcard@"
        }
    }
}

I would like to check that title equals to "My Title", but I don't care about the other fields. There is any way to ignore them?
I want to do that because the structure of the expected JSON is already tested before, so if I could write something like following would make my features cleaner and focused on what I'm testing each scenario.

What I'm figuring out would be like this:

{
    "title": "My title",
    "@whatever@"
}

nullable subjson

Hi,

Is there a way to match that json property can be an object matching my matcher AND can also be null:

{
  "id": "@integer@",
  "title": "@string@",
  "image": {
    "title": "@string@",
    "alt": "@string@",
    "url": "@[email protected]()"
  },
  "content": "@string@",
  "description": "@string@",
  "cookTime": "@integer@",
  "preparationTime": "@integer@",
  "coverNumber": "@integer@",
  "ingredients": "@string@",
  "type": "recipe"
}

But my image object can be null like this:

{
  "id": "@integer@",
  "title": "@string@",
  "image": null,
  "content": "@string@",
  "description": "@string@",
  "cookTime": "@integer@",
  "preparationTime": "@integer@",
  "coverNumber": "@integer@",
  "ingredients": "@string@",
  "type": "recipe"
}

Thanks for your help

Allow Date comparaison

Hello,

I've been in the need of testing timestamp of token, if it was prior or after a certain datetime. I've looked at how symfomy constraint allow to validate date.

They let us use two main objects :

I think it would be nice if we add the same kind of functionality. It would only require to write or adapt a few expanders.

I'll try to PR something today or this week, in the mean time what do you think about it ? Have you any suggestion?

Matching empty array always return true

Hi

I'm using php-matcher to match some JSONs and I found an issue.
If in $value will be empty array php-matcher always return true.

For example, as $value I have

{"status":"ok","data":[]}

And as $pattern

{
  "status": "ok",
  "data": [
      {
          "id": @integer@,
          "code": "123987",
          "name": "Anvill",
          "short_description": "ACME Anvill",
          "url": "http://test-store.example.com/p/123987",
          "image": {
          "url": "http://test-store.example.com/i/123987-0.jpg",
          "description": "ACME Anvill"
          },
          "price": 95,
          "promotion_description": "Anvills sale"
      },
      {
          "id": @integer@,
          "code": "123988",
          "name": "Red Anvill",
          "short_description": "Red ACME Anvill",
          "url": "http://test-store.example.com/p/123988",
          "image": {
          "url": "http://test-store.example.com/i/123988-0.jpg",
          "description": "ACME Anvill"
          },
          "price": 44.99,
          "promotion_description": "Red is cheap"
      }
  ]
}

And matcher return true.

v2.3.1?

Any chance we could get a 2.3.1 version which includes the repeat expander? As much as I would love to be on PHP7 we are stuck on 5.6, and I'd like to be using a non-dev version of the library.

Multiple elements JSON matching

Given I have a JSON response witch returns an array of 10 elements, like:

[
      {
        "id": 1,
        "name": "Posiłek @integer@",
        "date": @string@
      },
      {
        "id": 2,
        "name": "Posiłek @integer@",
        "date": @string@
      },
      {
        "id": 3,
        "name": "Posiłek @integer@",
        "date": @string@
      },
      @repeat@
]

I'd like to point somehow that there's one unique pattern which should be matched 10 times in JSON response, becouse array has 10 items. Are you thinking about such feature?

Can't make array Repeat expander working in JSON context

Or maybe I am using it wrong way?

First I've tried:

"@[email protected]({"name": "@string@", "value": "@array@"})"

Which gives confusing error: RuntimeException: Type pattern "@array@" is not supported by TextMatcher.

Then I've tried:

"@[email protected]({\"name\": \"@string@\", \"value\": \"@array@\"})"

But that one also gives an error:

      Behat\Testwork\Call\Exception\FatalThrowableError: Type error: Argument 1 passed to Coduo\PHPMatcher\Matcher\Pattern\Expander\Repeat::__construct() must be of the type string, array given in vendor/coduo/php-matcher/src/Matcher/Pattern/Expander/Repeat.php:29
      Stack trace:
      #0 [internal function]: Coduo\PHPMatcher\Matcher\Pattern\Expander\Repeat->__construct(Array)
      #1 vendor/coduo/php-matcher/src/Parser/ExpanderInitializer.php(79): ReflectionClass->newInstanceArgs(Array)

Repeat matcher expects argument to be json encoded string but ExpanderInitializer gives to it already decoded json array. It can be fixed by allowing Repeat expander to accept arrays too.

Composer install problem

@norzechowicz
The lib will lead to the problem when run composer. The error below
You must set up the project dependencies, run the following commands: curl -s http://getcomposer.org/installer | php php composer.phar install

Fatal error on version 3.0: Argument 1 passed to Parser::unexpectedSyntaxError() must be of the type array, null given

Hi, I'm using PHP Matcher 3.0 on PHP 7.2.

The following script:

<?php

require 'vendor/autoload.php';

use Coduo\PHPMatcher\Factory\SimpleFactory;

$matcher = (new SimpleFactory)->createMatcher();

$a = '{"foo": "","bar": "baz"}';
$b = '{"foo": "","bar": "bazz"}';

$match = $matcher->match($a, $b);

results in the following exception:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to Coduo\PHPMatcher\Parser::unexpectedSyntaxError() must be of the type array, null given, called in vendor/coduo/php-matcher/src/Parser.php on line 62 and defined in vendor/coduo/php-matcher/src/Parser.php:248
Stack trace:
#0 vendor/coduo/php-matcher/src/Parser.php(62): Coduo\PHPMatcher\Parser->unexpectedSyntaxError(NULL, '@type@ pattern')
#1 vendor/coduo/php-matcher/src/Parser.php(50): Coduo\PHPMatcher\Parser->getPattern()
#2 vendor/coduo/php-matcher/src/Parser.php(29): Coduo\PHPMatcher\Parser->getAST('')
#3 vendor/coduo/php-matcher/src/Matcher/StringMatcher.php(43): Coduo\PHPMatcher\Parser->hasValidSyntax('')
#4 vendor/coduo/php-matcher/src/Matcher/ChainMatcher.php(32): Coduo\PHPMatcher\Matcher\StringMatcher->canMatch('')
#5  in vendor/coduo/php-matcher/src/Parser.php on line 248

With PHP Matcher 2.4 works as expected, returning false.

Array format with trailing comma weird behavior

Hello,

I noticed a weird behavior when the matching pattern contains an array with a trailing comma after the final element as seen in the example and it's output below.

I'd expect the trailing comma to be ignored in the "First" test below and not throw an error.
But take a look at the "Second" test, where the error is incorrectly about the @null@ formatter.

<?php
use Coduo\PHPMatcher\Factory\SimpleFactory;

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();

$match = $matcher->match(
    '{"ids": [1, 2]}',
    '{"ids": [@integer@, @integer@,]}'
);

if (!$match) {
    echo "First: " . $matcher->getError() . "\n";
}

$match = $matcher->match(
    '{"value": null, "ids": [1, 2]}',
    '{"value": @null@, "ids": [@integer@, @integer@,]}'
);

if (!$match) {
    echo "Second: " . $matcher->getError() . "\n";
}

Output:
First: "{"ids": [1, 2]}" does not match "{"ids": [@integer@, @integer@,]}" pattern
Second: Type pattern "@null@" is not supported by TextMatcher.

"OR" operator

It will be very useful to have simple "OR" operator.
Ex: check whether value is string or null @string@||@null@ or @[email protected](@null@)
Is there any way to implement it?

And yes, I know I can extend expression language and add my own functions but native implementation is more descriptive, imho

Using @string@ in JSON response

Hi,

Since batch1064 always differs I would like to replace it with @string@ but when I do that tests still fail.

I'm using Symfony2 and have run composer require --dev "coduo/php-matcher" and all went fine. Apart from replacing batch1064 with @string@, what else should I do? E.g. I'm seeing two lines below as standard but where do I put them? Somewhere in FeatureContext.php, maybe?

@Then /^(?:the )?response should contain json:$/ is a build-in method in WebApiContext.php of Behat.

$factory = new SimpleFactory();
$matcher = $factory->createMatcher();

MY EXAMPLE

  Scenario: Whatever whatever
    When I send a GET request to "/1/products?id=1"
    Then the response should contain json:
    """
    {
      "products": [
        {
          "name": "Aaaa",
          "images": [
            {
              "type": "url",
              "value": "http:\/\/www.abc.com\/imagegallery\/batch1064\/image.JPG"
            }
          ]
        }
      ]
    }
    """

How to use pattern extenders in behat

I am quite confused how to do anything dynamic with JSON at the moment. I've looked at the docs and issue queue but I'm running into limitations.

I want to test for the following where the result items can be infinite:

{
          "result": [{
            "id": 2,
            "displayName": "Company Name",
            "dataType": "string",
            "length": 255,
            "rest": {
              "name": "company",
              "readOnly": false
            }
          },
          {
            "id": 3,
            "displayName": "Billing Address",
            "dataType": "text",
            "rest": {
              "name": "billingStreet",
              "readOnly": false
            }
          }],
          "success": true
}

I want to do something like so in Behat feature code:

Then the response should contain json:
    """
    {
      "result": @[email protected](
        {
          "id": @integer@,
          "displayName": @string@,
          "dataType": @string@,
          "rest": {
            "name": @string@,
            "readOnly": @string@
          }
        }, 1, INF
      ),
      "success": true
    }
    """

I get the error for most extenders:

Type pattern "@array@" is not supported by TextMatcher.

How do we do the following in Behat using this library? #21 Thanks.

Version 2.3 is not compatible with php 5.3.0

Expander\Contains::NAME => Expander\Contains::class,
Expander\Count::NAME => Expander\Count::class,
Expander\EndsWith::NAME => Expander\EndsWith::class,
Expander\GreaterThan::NAME => Expander\GreaterThan::class,
Expander\InArray::NAME => Expander\InArray::class,
Expander\IsDateTime::NAME => Expander\IsDateTime::class,
Expander\IsEmail::NAME => Expander\IsEmail::class,
Expander\IsEmpty::NAME => Expander\IsEmpty::class,
Expander\IsNotEmpty::NAME => Expander\IsNotEmpty::class,
Expander\IsUrl::NAME => Expander\IsUrl::class,
Expander\LowerThan::NAME => Expander\LowerThan::class,
Expander\MatchRegex::NAME => Expander\MatchRegex::class,
Expander\OneOf::NAME => Expander\OneOf::class,
Expander\Optional::NAME => Expander\Optional::class,
Expander\StartsWith::NAME => Expander\StartsWith::class,

The following code is not compatible with php version 5.3, because ::class is available in PHP 5.5.0

The special ::class constant are available as of PHP 5.5.0, and allows for fully qualified class name resolution at compile, this is useful for namespaced classes:

Execute this code in lower PHP versions gives the following error:

Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) in ../vendor/coduo/php-matcher/src/Parser/ExpanderInitializer.php on line 19

Cannot mock Matcher

I need to mock the main Matcher class which is marked as final.

In order to do it I have made a fork and create an interface for matcher.

@uuid@ not working as @integer@

Hi,

I am validating url containing id as integer, and I used to do it like this (the following code print match.

if (!PHPMatcher::match("/test/0", "/test/@integer@", $error)) { 
    echo $error; // in case of error message is set on $error variable via reference
}
else
{
	echo "match\n";
}

I am switching to UUID and the same test case is not working. The following code print Type pattern "@uuid@" is not supported by TextMatcher.:

if (!PHPMatcher::match("/test/00200000-0000-4000-a000-000000000000", "/test/@uuid@", $error)) { 
    echo $error."\n"; // in case of error message is set on $error variable via reference
}
else
{
	echo "match\n";
}```


JSON matcher is not working as expected with pattern expanders

In project I'm currently working on, we had a following scenario step:

    And json response should match:
    """
    {
      "limit": 10,
      "offset": 0,
      "count": 1,
      "wins": @[email protected](1)
    }
    """

and it was throwing me a very weird error: Type pattern "@array@" is not supported by TextMatcher. (RuntimeException).
After investigation it turned out that php-matcher/src/Matcher/Pattern/Assert/Json.php:33 can't recognize this pattern as a valid json value (because of @[email protected](1)) and thats why JSONExpander is being ignored.
The same problem seems to be found here: #83

Perfect solution would be to update Json::transformPattern($pattern) method, to transform patterns with expanders into native strings:

before transformation:
@[email protected](1)

after transformation:
"@[email protected](1)"

Of course currently this issue can be solved by making sure that all patterns with expanders are stored just like in following example:

    And json response should match:
    """
    {
      "limit": 10,
      "offset": 0,
      "count": 1,
      "wins": "@[email protected](1)"
    }
    """

Add @include

I know that this package is about matching but would be nice to have something like @include 'url' to be able reuse part of my json.

Do you think it will be implemented ? Or maybe you can point me out how to do it

Matching sub-json

When trying to match {'id': 1, 'name': 'name1'} to array of json objects there is no match.

[
{'id': 1, 'name': 'name1'},
{'id': 2, 'name': 'name2'},
{'id': 3, 'name': 'name3'}
]

I think that comparison should result with match.

The ArrayMatcher does not match inside an existing string

Hello,

The ArrayMatcher does not match inside an existing string.
Examples with this following code :

$value = [
     'foo' => "http://foo.com/bar"
 ];

if (!PHPMatcher::match($value, $pattern, $error)) {
    echo $error;
} else {
    echo "Matched.";
}

This pattern works :

$pattern = [
    'foo' =>  '@string@'
];

Result:
Matched.

This pattern does not work :

$pattern = [
    'foo' =>  'http://foo.com/@string@'
];

Result:
"http://foo.com/bar" does not match "http://foo.com/@string@".

I want "ExpressionMatcher" to return the exception

I'm not good at much English.

Time it took to resolve the "ExpressionMatcher" of use.
It was a small thing.

// Bad
$matcher->match(new \DateTime('2014-04-01'), "expr(value.format('Y-m-d') == '2014-04-01'");
// Good
$matcher->match(new \DateTime('2014-04-01'), "expr(value.format('Y-m-d') == '2014-04-01')");

I want you to return an exception for typing error.

Issue with TextMatcher registration.

Hey there,

Think I've encounter an issue with the default matcher chain where this doesn't work:

<?php

declare(strict_types=1);

use Coduo\PHPMatcher\PHPMatcher;

include_once 'vendor/autoload.php';

$value = '{"foo" : "/accounts/9a7dae2d-d135-4bd7-b202-b3e7e91aaecd"}';
$pattern = '{"foo" : "/accounts/@uuid@"}';
$error = '';

var_dump(PHPMatcher::match($value, $pattern, $error));
var_dump($error);

This should work if i'm not missing something obvious!
I can't see exactly how to fix it, sorry.
Cheers!

PHPUnit 6 Support

Is there currently a plan in place to update the PHPUnit assertions to use the new namespaces in PHPUnit 6?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.