Skip to content
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
61 changes: 61 additions & 0 deletions src/Codeception/Module/REST.php
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,67 @@ public function seeResponseJsonMatchesXpath(string $xPath): void
);
}

/**
* Checks if applying xpath to json structure in response matches the expected result.
* JSON is not supposed to be checked against XPath, yet it can be converted to xml and used with XPath.
* This assertion allows you to check the structure of response json.
* *
* ```json
* { "store": {
* "book": [
* { "category": "reference",
* "author": "Nigel Rees",
* "title": "Sayings of the Century",
* "price": 8.95
* },
* { "category": "fiction",
* "author": "Evelyn Waugh",
* "title": "Sword of Honour",
* "price": 12.99
* }
* ],
* "bicycle": {
* "color": "red",
* "price": 19.95
* }
* }
* }
* ```
*
* ```php
* <?php
* // at least one book in store has author
* $I->seeResponseJsonXpathEvaluatesTo('count(//store/book/author) > 0', true);
* // count the number of books written by given author is 5
* $I->seeResponseJsonMatchesXpath("//author[text() = 'Nigel Rees']", 1.0);
* ```
* @part json
*/
public function seeResponseJsonXpathEvaluatesTo(string $xPath, $expected): void
{
$response = $this->connectionModule->_getResponseContent();
$this->assertEquals(
$expected,
(new JsonArray($response))->evaluateXPath($xPath),
"Received JSON did not evualated XPath `{$xPath}` as expected.\nJson Response: \n" . $response
);
}

/**
* Opposite to seeResponseJsonXpathEvaluatesTo
*
* @part json
*/
public function dontSeeResponseJsonXpathEvaluatesTo(string $xPath, $expected): void
{
$response = $this->connectionModule->_getResponseContent();
$this->assertNotEquals(
$expected,
(new JsonArray($response))->evaluateXPath($xPath),
"Received JSON did not evualated XPath `{$xPath}` as expected.\nJson Response: \n" . $response
);
}

/**
* Opposite to seeResponseJsonMatchesXpath
*
Expand Down
6 changes: 6 additions & 0 deletions src/Codeception/Util/JsonArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ public function filterByXPath(string $xPath): DOMNodeList|false
$path = new DOMXPath($this->toXml());
return $path->query($xPath);
}

public function evaluateXPath(string $xPath): mixed
{
$path = new DOMXPath($this->toXml());
return $path->evaluate($xPath);
}

public function filterByJsonPath(string $jsonPath): array
{
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/Codeception/Module/RestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,31 @@ public function testSeeResponseJsonMatchesXpathCanHandleResponseWithOneSubArray(
$this->module->seeResponseJsonMatchesXpath('//array/success');
}


public function testSeeResponseJsonXpathEvaluatesToBoolean()
{
$this->setStubResponse('{"success": 1}');
$this->module->seeResponseJsonXpathEvaluatesTo('count(//success) > 0', true);
}

public function testSeeResponseJsonXpathEvaluatesToNumber()
{
$this->setStubResponse('{"success": 1}');
$this->module->seeResponseJsonXpathEvaluatesTo('count(//success)', 1.0);
}

public function testDontSeeResponseJsonXpathEvaluatesToBoolean()
{
$this->setStubResponse('{"success": 1}');
$this->module->dontSeeResponseJsonXpathEvaluatesTo('count(//success) > 0', false);
}

public function testDontSeeResponseJsonXpathEvaluatesToNumber()
{
$this->setStubResponse('{"success": 1}');
$this->module->dontSeeResponseJsonXpathEvaluatesTo('count(//success)', 0.0);
}

public function testSeeBinaryResponseEquals()
{
$data = base64_decode('/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=');
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/Codeception/Util/JsonArrayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public function testXmlArrayConversion2()
$this->assertSame(2, $jsonArray->filterByXPath('//user')->length);
}

public function testXPathEvaluation()
{
$this->assertSame(true, $this->jsonArray->evaluateXPath('count(//ticket/title)>0'));
$this->assertEquals(1.0 , $this->jsonArray->evaluateXPath('count(//ticket/user/name)'));
$this->assertSame(true, $this->jsonArray->evaluateXPath("count(//user/name[text() = 'Davert']) > 0"));
}

public function testXPathLocation()
{
$this->assertGreaterThan(0, $this->jsonArray->filterByXPath('//ticket/title')->length);
Expand Down