Skip to content

Commit

Permalink
Added more steps and Gherkin lint.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexSkrypnyk committed Jan 17, 2025
1 parent 95031fa commit 9dc0230
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 86 deletions.
58 changes: 40 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,54 @@ using following JSON format:
]
```

The `ApiServerContext` provides a step definition to make it easier to queue up
API responses:
The `ApiServerContext` provides several step definitions to make it easier to
work with the API server:

```gherkin
# Check if the API server is running.
Given the API server is running
# Queue up a single API response.
Given API will respond with:
"""
{
"code": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"Id": "test-id-1",
"Slug": "test-slug-1"
"""
{
"code": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"Id": "test-id-1",
"Slug": "test-slug-1"
}
}
}
"""
"""
# Queue up a single API response with minimal configuration.
Given API will respond with:
"""
{
"code": 200
}
"""
"""
{
"code": 200
}
"""
# Queue up a single API response with JSON body.
Given API will respond with JSON:
"""
{
"Id": "test-id-1",
"Slug": "test-slug-1"
}
"""
# Queue up a single API response with JSON body and expected code.
Given API will respond with JSON and 201 code:
"""
{
"Id": "test-id-2",
"Slug": "test-slug-2"
}
"""
```

See this [test feature](tests/behat/features/apiserver.feature) for more
Expand Down
24 changes: 23 additions & 1 deletion apiserver/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,16 @@ final public function __construct(
public array $headers = [],
mixed $body = '',
) {
$this->body = is_scalar($body) ? strval($body) : (string) json_encode($body);
if (is_scalar($body)) {
$this->body = strval($body);
if (static::isJson($this->body)) {
$this->headers['Content-Type'] = 'application/json';
}
}
else {
$this->body = (string) json_encode($body);
$this->headers['Content-Type'] = 'application/json';
}
// Set Content-Length header if a body is provided.
if ($this->body !== '') {
$this->headers['Content-Length'] = (string) strlen($this->body);
Expand Down Expand Up @@ -325,6 +334,19 @@ public static function fromArray(array $data): static {
return new static($data['code'], $data['reason'], $data['headers'], $data['body']);
}

/**
* Check if the string is a JSON.
*
* @param string $string
* The string to check.
*
* @return bool
* TRUE if the string is a JSON, FALSE otherwise.
*/
protected static function isJson(string $string): bool {
return json_decode($string) !== NULL || json_last_error() === JSON_ERROR_NONE;
}

}

// Allow to skip the script run.
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
},
"require-dev": {
"behat/mink-browserkit-driver": "^2.2",
"dantleech/gherkin-lint": "^0.2.3",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"drupal/coder": "^8.3",
"dvdoug/behat-code-coverage": "^5.3",
Expand Down Expand Up @@ -63,7 +64,8 @@
"lint": [
"phpcs",
"phpstan",
"rector --clear-cache --dry-run"
"rector --clear-cache --dry-run",
"gherkinlint lint tests/behat/features"
],
"lint-fix": [
"rector --clear-cache",
Expand Down
20 changes: 20 additions & 0 deletions gherkinlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"rules": {
"indentation": {
"width": 2,
"literalBlock": 3
},
"keyword-order": {
"enabled": false
},
"no-background-with-single-scenario": {
"enabled": false
},
"no-homogenous-tags": {
"enabled": false
},
"scenario-size": {
"enabled": false
}
}
}
62 changes: 58 additions & 4 deletions src/DrevOps/BehatPhpServer/ApiServerContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ class ApiServerContext extends PhpServerContext {
*/
const DEFAULT_WEBROOT = __DIR__ . '/../../../apiserver';

/**
* Check if the API server is running.
*
* @Given (the )API server is running
*/
public function apiIsRunning(): void {
$client = new Client([
'base_uri' => $this->getServerUrl(),
'http_errors' => FALSE,
]);

$response = $client->request('GET', '/admin/status');

if ($response->getStatusCode() !== 200) {
throw new \Exception('API server is not up');
}
}

/**
* Put expected response data to the API server.
*
Expand All @@ -51,10 +69,10 @@ class ApiServerContext extends PhpServerContext {
* @endcode
*/
public function apiWillRespondWith(PyStringNode $data): void {
$data = $this->prepareData($data->getRaw());
$data = $this->prepareResponse($data->getRaw());

$client = new Client([
'base_uri' => 'http://' . $this->host . ':' . $this->port,
'base_uri' => $this->getServerUrl(),
'http_errors' => FALSE,
]);

Expand All @@ -67,6 +85,43 @@ public function apiWillRespondWith(PyStringNode $data): void {
}
}

/**
* Put expected JSON response data to the API server.
*
* Shorthand for the API response with JSON body.
*
* @Given (the )API will respond with JSON:
* @Given (the )API will respond with JSON and :code code:
*
* @code
* Given API will respond with JSON:
* """
* {
* "Id": "test-id-1",
* "Slug": "test-slug-1"
* }
* """
* @endcode
*
* @code
* Given API will respond with JSON and 200 code:
* """
* {
* "Id": "test-id-1",
* "Slug": "test-slug-1"
* }
* """
* @endcode
*/
public function apiWillRespondWithJson(PyStringNode $json, ?string $code = NULL): void {
$data = json_encode([
'code' => $code ?? 200,
'body' => json_decode($json->getRaw()),
]);

$this->apiWillRespondWith(new PyStringNode([$data], $json->getLine()));
}

/**
* Process the response data.
*
Expand All @@ -76,8 +131,7 @@ public function apiWillRespondWith(PyStringNode $data): void {
* @return array<int, array<string, mixed>>
* The response data.
*/
protected function prepareData(string $data): array {
// Validate the JSON.
protected function prepareResponse(string $data): array {
$data = json_decode($data, TRUE);
if ($data === NULL || !is_array($data)) {
throw new \InvalidArgumentException('Request data is not a valid JSON.');
Expand Down
Loading

0 comments on commit 9dc0230

Please sign in to comment.