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

Implement jq expression #53

Merged
merged 3 commits into from
Mar 9, 2024
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
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,26 @@ When sending "post" to ocs "/apps/libresign/api/v1/request-signature"
| file | {"base64":""} |
```

By this way you will receive on your controller method 2 values, status as integer and file as array.
## Parse response using jq

You can use [jq](https://jqlang.github.io/jq/manual/) expression casting to check a value in a json response body of a request. To do this you will need to install the jq command.

Example:

```gherkin
When set the response to:
"""
{
"Foo": {
"Bar": "33"
}
}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| key | value |
| Foo | (jq).Bar == "33" |
```

## Parse initial state
If you need to parse the initial state to use placeholder or get any value from current initial state, implement a method `parseText` like this:
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"psalm": "psalm --threads=1",
"psalm:update-baseline": "psalm --threads=1 --update-baseline --set-baseline=tests/psalm-baseline.xml",
"psalm:update-baseline": "psalm --threads=1 --update-baseline --set-baseline=psalm-baseline.xml",
"psalm:clear": "psalm --clear-cache && psalm --clear-global-cache",
"post-install-cmd": [
"@composer bin all install --ansi",
Expand All @@ -36,7 +36,8 @@
"guzzlehttp/guzzle": "^7.8",
"phpunit/phpunit": "^9.6",
"behat/behat": "^3.13",
"libresign/behat-builtin-extension": "^0.6.1"
"libresign/behat-builtin-extension": "^0.6.1",
"estahn/json-query-wrapper": "*"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
Expand Down
41 changes: 10 additions & 31 deletions features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,45 +78,24 @@ public function sendRequest(string $verb, string $url, $body = null, array $head
}

/**
* @inheritDoc
* @when set the response to:
*/
public function theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues(TableNode $table): void {
$lastRequest = $this->getLastRequest();
public function setTheResponseTo(PyStringNode $response): void {
// Mock response to be equal to body of request
$this->mockServer->setDefaultResponse(new MockWebServerResponse(
json_encode($lastRequest->getParsedInput())
(string) $response
));
parent::theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues($table);
}

/**
* @inheritDoc
*/
public function theResponseShouldContainTheInitialStateWithTheFollowingValues(string $name, PyStringNode $expected): void {
switch ($name) {
case 'appid-string':
$value = base64_encode((string) $expected);
break;
case 'appid-json-object':
$value = base64_encode(json_encode(['fruit' => 'orange']));
break;
case 'appid-json-array':
$value = base64_encode(json_encode(['orange']));
break;
default:
$value = '';
}
$this->response = new Response(
200,
[],
<<<HTML
<html>
<body>
<input type="hidden" id="initial-state-{$name}" value="{$value}">
</body>
</html>
HTML
);
parent::theResponseShouldContainTheInitialStateWithTheFollowingValues($name, $expected);
public function theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues(TableNode $table): void {
$lastRequest = $this->getLastRequest();
// Mock response to be equal to body of request
$this->mockServer->setDefaultResponse(new MockWebServerResponse(
json_encode($lastRequest->getParsedInput())
));
parent::theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues($table);
}
}
115 changes: 104 additions & 11 deletions features/test.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,143 @@ Feature: Test this extension
| status | 1 |

Scenario: Test response of POST is numeric
When sending "POST" to "/"
| status | 1 |
When set the response to:
"""
{"status":1}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| status | 1 |
| key | value |
| status | 1 |

Scenario: Test response of POST is string
When sending "POST" to "/"
| status | "string" |
When set the response to:
"""
{"status":"string"}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| status | "string" |
| key | value |
| status | string |

Scenario: Test response of POST is boolean
When sending "POST" to "/"
| status | true |
When set the response to:
"""
{"status":true}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| status | true |
| key | value |
| status | true |

Scenario: Test response of POST is json
When sending "POST" to "/"
| status | (string){"string": "test"} |
When set the response to:
"""
{"status":{"string": "test"}}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| key | value |
| status | {"string": "test"} |

Scenario: Test response of POST is json that match using jq
When set the response to:
"""
{
"Foo": {
"Bar": "33"
}
}
"""
And sending "POST" to "/"
Then the response should be a JSON array with the following mandatory values
| key | value |
| Foo | (jq).Bar == "33" |

Scenario: Test initial state with string
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-string" value="ZGVmYXVsdA==">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-string" with the following values:
"""
default
"""

Scenario: Test initial state with string
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-string" value="InRleHQgYXMganNvbiBzdHJpbmci">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-string" with the following values:
"""
"text as json string"
"""

Scenario: Test initial state with boolean
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-string" value="dHJ1ZQ==">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-string" with the following values:
"""
true
"""

Scenario: Test initial state with null
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-string" value="bnVsbA==">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-string" with the following values:
"""
null
"""

Scenario: Test initial state with empty
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-string" value="">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-string" with the following values:
"""
"""

Scenario: Test initial state with json
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-json-object" value="eyJmcnVpdCI6ICJvcmFuZ2UifQ==">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-json-object" with the following values:
"""
{
Expand All @@ -69,6 +153,15 @@ Feature: Test this extension
"""

Scenario: Test initial state with array
When set the response to:
"""
<html>
<body>
<input type="hidden" id="initial-state-appid-json-array" value="WyJvcmFuZ2UiXQ==">
</body>
</html>
"""
And sending "POST" to "/"
Then the response should contain the initial state "appid-json-array" with the following values:
"""
[
Expand Down
8 changes: 8 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
<file src="src/NextcloudApiContext.php">
<ForbiddenCode>
<code><![CDATA[`which jq`]]></code>
</ForbiddenCode>
</file>
</files>
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="features/bootstrap" />
Expand Down
20 changes: 17 additions & 3 deletions src/NextcloudApiContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,20 +254,34 @@ public function theResponseShouldBeAJsonArrayWithTheFollowingMandatoryValues(Tab
$realResponseArray,
'Not found: "' . $value['key'] . '" at array: ' . json_encode($realResponseArray)
);
$actual = $realResponseArray[$value['key']];
if (str_starts_with($value['value'], '(jq)')) {
$expected = substr($value['value'], 4);
$this->validateAsJsonQuery($expected, json_encode($actual));
continue;
}
if (is_bool($realResponseArray[$value['key']])
|| is_iterable($realResponseArray[$value['key']])
|| is_numeric($realResponseArray[$value['key']])
|| (is_string($realResponseArray[$value['key']]) && $this->isJson($realResponseArray[$value['key']]))
) {
$actualJson = json_encode($realResponseArray[$value['key']]);
Assert::assertJsonStringEqualsJsonString($value['value'], $actualJson, 'Key: ' . $value['key']);
$actual = json_encode($actual);
Assert::assertJsonStringEqualsJsonString($value['value'], $actual, 'Key: ' . $value['key']);
continue;
}
$actual = $realResponseArray[$value['key']];
Assert::assertEquals($value['value'], $actual, 'Key: ' . $value['key']);
}
}

private function validateAsJsonQuery(string $expected, string $actual): void {
if (!`which jq`) {
throw new \InvalidArgumentException('Is necessary install the jq command to use jq');
}
$jq = \JsonQueryWrapper\JsonQueryFactory::createWith($actual);
$result = $jq->run($expected);
Assert::assertTrue($result, 'The jq "' . $expected . '" do not match with: ' . $actual);
}

/**
* @When the response should contain the initial state :name with the following values:
*/
Expand Down