From 0526d97363609bd4999a0f97e7b8862ed2d1a010 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:24:05 -0300 Subject: [PATCH 1/4] feat: add response header and body assertion steps Add three new composable step definitions to NextcloudApiContext: - 'the response header :header should contain :value' Asserts that the given response header contains the expected substring (case-insensitive). - 'the response body should not be empty' Asserts that the response body is non-empty. - 'the response body should match the regular expression :pattern' Asserts that the response body matches the given regex pattern. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/NextcloudApiContext.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index 5fb310a..126d732 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -359,6 +359,25 @@ public function theResponseShouldHaveStatusCode(string $code): void { Assert::assertEquals($code, $currentCode, $this->response->getBody()->getContents()); } + #[Given('the response header :header should contain :value')] + public function theResponseHeaderShouldContain(string $header, string $value): void { + $actual = strtolower((string)$this->response->getHeaderLine($header)); + Assert::assertStringContainsString(strtolower($value), $actual, sprintf('Response header "%s" does not contain "%s"', $header, $value)); + } + + #[Given('the response body should not be empty')] + public function theResponseBodyShouldNotBeEmpty(): void { + $this->response->getBody()->rewind(); + Assert::assertNotSame('', $this->response->getBody()->getContents(), 'Response body is empty'); + } + + #[Given('the response body should match the regular expression :pattern')] + public function theResponseBodyShouldMatchTheRegularExpression(string $pattern): void { + $this->response->getBody()->rewind(); + $content = $this->response->getBody()->getContents(); + Assert::assertMatchesRegularExpression('#' . $pattern . '#', $content, sprintf('Response body does not match pattern "%s"', $pattern)); + } + /** * @throws \InvalidArgumentException */ From 82dea2ec588a609ff6b47ae60e1f23af315694be Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:24:05 -0300 Subject: [PATCH 2/4] test: add step to set mock response with explicit header Add 'set the response with :header header :value to:' step to the test FeatureContext so scenarios can control the Content-Type (or any other header) of the mock server response, making header assertion scenarios deterministic. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- features/bootstrap/FeatureContext.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 74fa641..3b34859 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -139,6 +139,14 @@ public function setTheResponseTo(PyStringNode $response): void { )); } + #[Given('set the response with :header header :value to:')] + public function setTheResponseWithHeaderTo(string $header, string $value, PyStringNode $response): void { + $this->mockServer->setDefaultResponse(new MockWebServerResponse( + (string) $response, + [$header => $value] + )); + } + /** * @inheritDoc */ From b7f0f075daf36f6396e14d53d67f360b7be831e2 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:24:05 -0300 Subject: [PATCH 3/4] test: cover new response header and body assertion steps Add three scenarios to features/test.feature: - Response header assertion with explicit Content-Type - Response body is not empty - Response body matches a regular expression Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- features/test.feature | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/features/test.feature b/features/test.feature index 8c1d86f..ea21f48 100644 --- a/features/test.feature +++ b/features/test.feature @@ -315,3 +315,27 @@ Feature: Test this extension Scenario: Wait for seconds When wait for 1 seconds When past 1 second since wait step + + Scenario: Test response header assertion matches expected value + When set the response with "Content-Type" header "application/json" to: + """ + {"ok":true} + """ + And sending "POST" to "/" + Then the response header "Content-Type" should contain "application/json" + + Scenario: Test response body is not empty + When set the response to: + """ + hello + """ + And sending "POST" to "/" + Then the response body should not be empty + + Scenario: Test response body matches a regular expression + When set the response to: + """ + %PDF-1.4 binary content here + """ + And sending "POST" to "/" + Then the response body should match the regular expression "^%PDF" From 4e0dc02094f11bb2352e45aedbbfd59166946f9b Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:27:20 -0300 Subject: [PATCH 4/4] fix: remove redundant string cast on getHeaderLine return value getHeaderLine() already returns string per PSR-7; Psalm flags the (string) cast as RedundantCast. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/NextcloudApiContext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index 126d732..2b0cddb 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -361,7 +361,7 @@ public function theResponseShouldHaveStatusCode(string $code): void { #[Given('the response header :header should contain :value')] public function theResponseHeaderShouldContain(string $header, string $value): void { - $actual = strtolower((string)$this->response->getHeaderLine($header)); + $actual = strtolower($this->response->getHeaderLine($header)); Assert::assertStringContainsString(strtolower($value), $actual, sprintf('Response header "%s" does not contain "%s"', $header, $value)); }