From 18af63a7e01c975676e5a7e4261df62426f03856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 00:52:51 +0000 Subject: [PATCH 1/6] build(deps): update behat/behat requirement from ^3.29 to ^3.29 || ^4.0 Updates the requirements on [behat/behat](https://github.com/Behat/Behat) to permit the latest version. - [Release notes](https://github.com/Behat/Behat/releases) - [Changelog](https://github.com/Behat/Behat/blob/3.x/CHANGELOG.md) - [Commits](https://github.com/Behat/Behat/compare/v3.29.0...v4.0.0) --- updated-dependencies: - dependency-name: behat/behat dependency-version: 4.0.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 214190a..9c83530 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "php": ">=8.2", "guzzlehttp/guzzle": "^7.10 || ^8.0", "phpunit/phpunit": "*", - "behat/behat": "^3.29", + "behat/behat": "^3.29 || ^4.0", "libresign/behat-builtin-extension": "^0.7.1", "estahn/json-query-wrapper": "*" }, From dc0a2af1830a5d63f88902f0722fff107a1d674d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:50:07 +0000 Subject: [PATCH 2/6] fix(behat): initialize built-in server when first needed Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/NextcloudApiContext.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index e2dd98a..d4d005f 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -47,8 +47,6 @@ class NextcloudApiContext implements Context { protected array $requestOptions = []; public function __construct(?array $parameters = []) { - $this->server = RunServerListener::getInstance(); - $this->baseUrl = RunServerListener::getServerRoot(); $this->response = new Response(); $this->cookieJars = []; if (isset($parameters['test_password'])) { @@ -223,6 +221,11 @@ public function sendRequest(string $verb, string $url, $body = null, array $head if (strpos($url, '/ocs/v2.php') === false) { $url = '/index.php' . $url; } + if (!isset($this->baseUrl)) { + // Behat 4 may instantiate contexts before the server listener exists. + $this->server = RunServerListener::getInstance(); + $this->baseUrl = RunServerListener::getServerRoot(); + } if (str_ends_with($this->baseUrl, '/')) { $this->baseUrl = rtrim($this->baseUrl, '/'); } From 81a3b396b041e2dd4cc5e3a89b2a96784d4979ac Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:56:46 +0000 Subject: [PATCH 3/6] fix(behat): use noncapturing alternatives for time steps Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/NextcloudApiContext.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index d4d005f..f654032 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -685,13 +685,13 @@ public static function createAnEnvironmentWithValueToBeUsedByOccCommand(string $ self::$environments[$name] = $value; } - #[Given('/^wait for ([0-9]+) (second|seconds)$/')] + #[Given('/^wait for ([0-9]+) seconds?$/')] public function waitForXSecond(int $seconds): void { $this->startWaitFor = $seconds; sleep($seconds); } - #[Given('/^past ([0-9]+) (second|seconds) since wait step$/')] + #[Given('/^past ([0-9]+) seconds? since wait step$/')] public function pastXSecondsSinceWaitStep(int $seconds): void { $currentTime = time(); $startTime = $currentTime - $this->startWaitFor; From 2cdea9f7e677b57668beba1f19dbc787701eec53 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:04:01 +0000 Subject: [PATCH 4/6] fix(behat): run jq without deprecated process factory Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/NextcloudApiContext.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index f654032..f2cb5f0 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -16,9 +16,11 @@ use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Psr7\Response; +use JsonQueryWrapper\DataTypeMapper; use PhpBuiltin\RunServerListener; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; +use Symfony\Component\Process\Process; /** * Defines application features from the specific context. @@ -447,14 +449,18 @@ private function testAndGetActualValue(array $value, string $json): string { */ private function evalJsonQuery(string $jsonQuery, string $target) { Assert::assertNotEmpty(`which jq`, 'Is necessary install the jq command to use jq'); - $jq = \JsonQueryWrapper\JsonQueryFactory::createWith($target); - return $jq->run($jsonQuery); + return $this->runJsonQuery($target, $jsonQuery); + } + + private function runJsonQuery(string $json, string $filter): mixed { + $process = new Process(['jq', '-M', $filter], null, null, $json); + $process->mustRun(); + return (new DataTypeMapper())->map(trim($process->getOutput())); } private function validateAsJsonQuery(string $expected, string $actual): void { Assert::assertNotEmpty(`which jq`, 'Is necessary install the jq command to use jq'); - $jq = \JsonQueryWrapper\JsonQueryFactory::createWith($actual); - $result = $jq->run($expected); + $result = $this->runJsonQuery($actual, $expected); Assert::assertTrue($result, 'The jq "' . $expected . '" do not match with: ' . $actual); } From 4a4311adc61ad1d52127fb7016dd3c3df611b9ee Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:08:59 +0000 Subject: [PATCH 5/6] build(deps): declare Symfony Process used by Behat contexts Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9c83530..58ebe8c 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ "phpunit/phpunit": "*", "behat/behat": "^3.29 || ^4.0", "libresign/behat-builtin-extension": "^0.7.1", - "estahn/json-query-wrapper": "*" + "estahn/json-query-wrapper": "*", + "symfony/process": "^6.4 || ^7.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.9", From 8e01eeea2094f3bf7b48b183c3cc6c606200bd51 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:31:02 +0000 Subject: [PATCH 6/6] fix(behat): replace legacy JSON query dependency with Symfony Process Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- composer.json | 1 - psalm-baseline.xml | 6 ------ src/NextcloudApiContext.php | 15 ++++++++------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 58ebe8c..8e2514c 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,6 @@ "phpunit/phpunit": "*", "behat/behat": "^3.29 || ^4.0", "libresign/behat-builtin-extension": "^0.7.1", - "estahn/json-query-wrapper": "*", "symfony/process": "^6.4 || ^7.0" }, "require-dev": { diff --git a/psalm-baseline.xml b/psalm-baseline.xml index b6fd750..2ca56b7 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,9 +1,3 @@ - - - - - - diff --git a/src/NextcloudApiContext.php b/src/NextcloudApiContext.php index f2cb5f0..64efc99 100644 --- a/src/NextcloudApiContext.php +++ b/src/NextcloudApiContext.php @@ -16,10 +16,10 @@ use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Exception\ClientException; use GuzzleHttp\Psr7\Response; -use JsonQueryWrapper\DataTypeMapper; use PhpBuiltin\RunServerListener; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; +use Symfony\Component\Process\ExecutableFinder; use Symfony\Component\Process\Process; /** @@ -28,8 +28,8 @@ class NextcloudApiContext implements Context { protected string $testPassword = '123456'; protected string $adminPassword = 'admin'; - protected string $baseUrl; - protected RunServerListener $server; + protected string $baseUrl = ''; + protected ?RunServerListener $server = null; protected string $currentUser = ''; protected array $fields = []; protected static array $environments = []; @@ -223,7 +223,7 @@ public function sendRequest(string $verb, string $url, $body = null, array $head if (strpos($url, '/ocs/v2.php') === false) { $url = '/index.php' . $url; } - if (!isset($this->baseUrl)) { + if ($this->baseUrl === '') { // Behat 4 may instantiate contexts before the server listener exists. $this->server = RunServerListener::getInstance(); $this->baseUrl = RunServerListener::getServerRoot(); @@ -448,18 +448,19 @@ private function testAndGetActualValue(array $value, string $json): string { * @return mixed */ private function evalJsonQuery(string $jsonQuery, string $target) { - Assert::assertNotEmpty(`which jq`, 'Is necessary install the jq command to use jq'); return $this->runJsonQuery($target, $jsonQuery); } private function runJsonQuery(string $json, string $filter): mixed { + Assert::assertNotEmpty((new ExecutableFinder())->find('jq'), 'Is necessary install the jq command to use jq'); $process = new Process(['jq', '-M', $filter], null, null, $json); $process->mustRun(); - return (new DataTypeMapper())->map(trim($process->getOutput())); + $output = trim($process->getOutput()); + $decoded = json_decode($output, true); + return json_last_error() === JSON_ERROR_NONE ? $decoded : $output; } private function validateAsJsonQuery(string $expected, string $actual): void { - Assert::assertNotEmpty(`which jq`, 'Is necessary install the jq command to use jq'); $result = $this->runJsonQuery($actual, $expected); Assert::assertTrue($result, 'The jq "' . $expected . '" do not match with: ' . $actual); }