Skip to content

Commit 74625b8

Browse files
committed
feat: run command
These steps make possible run occ and bash commands as steps. Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 622be19 commit 74625b8

3 files changed

Lines changed: 104 additions & 0 deletions

File tree

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ vendor/bin/behat -dl
5151
Given as user :user
5252
Given user :user exists
5353
Given sending :verb to :url
54+
Given set the response to:
5455
Given the response should be a JSON array with the following mandatory values
5556
Given /^set the display name of user "([^"]*)" to "([^"]*)"$/
5657
Given /^set the email of user "([^"]*)" to "([^"]*)"$/
@@ -60,6 +61,9 @@ Given fetch field :path from previous JSON response
6061
Given the response should contain the initial state :name with the following values:
6162
Given the response should contain the initial state :name json that match with:
6263
Given the following :appId app config is set
64+
Given /^run the command "(?P<command>(?:[^"]|\\")*)"$/
65+
Given /^run the command "(?P<command>(?:[^"]|\\")*)" with result code (\d+)$/
66+
Given /^run the bash command "(?P<command>(?:[^"]|\\")*)" with result code (\d+)$/
6367
```
6468

6569
## Tips
@@ -83,6 +87,15 @@ Given sending "post" to ocs "/apps/libresign/api/v1/request-signature"
8387
| file | {"base64":""} |
8488
```
8589

90+
### Step: all steps that run commands
91+
92+
Before the command be executd, will replace the follow placeholders:
93+
94+
| Placeholder | Value |
95+
| -------------------- | ---------------------- |
96+
| `<appRootDir>` | your app root dir |
97+
| `<nextcloudRootDir>` | The Nextcloud root dir |
98+
8699
### Step: `fetch field :path from previous JSON response`
87100

88101
If the json response is an array, you can fetch specific values using this step. The fetched values is stored to be used by other steps.

features/test.feature

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,21 @@ Feature: Test this extension
227227
Then the response should contain the initial state "appid-json-array" json that match with:
228228
| key | value |
229229
| (jq).[0] | orange |
230+
231+
Scenario: Test list app directory with success
232+
When run the bash command "ls <appRootDir>" with result code 0
233+
234+
Scenario: Test list Nextcloud directory with success
235+
When run the bash command "ls <nextcloudRootDir>" with result code 0
236+
237+
Scenario: Test run bash command with success
238+
When run the bash command "true" with result code 0
239+
240+
Scenario: Test run bash command with error
241+
When run the bash command "false" with result code 1
242+
243+
Scenario: Run occ command with success
244+
When run the command "status" with result code 0
245+
246+
Scenario: Run occ command with success
247+
When run the command "invalid-command" with result code 1

src/NextcloudApiContext.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,79 @@ protected function parseText(string $text): string {
448448
return $text;
449449
}
450450

451+
#[Given('/^run the command "(?P<command>(?:[^"]|\\")*)"$/')]
452+
public static function runCommand(string $command): array {
453+
$console = self::findParentDirContainingFile('console.php');
454+
$console .= '/console.php';
455+
$fileOwnerUid = fileowner($console);
456+
if (!is_int($fileOwnerUid)) {
457+
throw new \Exception('The console file owner of ' . $console . ' is not an integer UID.');
458+
}
459+
$owner = posix_getpwuid($fileOwnerUid);
460+
if ($owner === false) {
461+
throw new \Exception('Could not retrieve owner information for UID ' . $fileOwnerUid);
462+
}
463+
$fullCommand = 'php ' . $console . ' ' . $command;
464+
if (posix_getuid() !== $owner['uid']) {
465+
$fullCommand = 'runuser -u ' . $owner['name'] . ' -- ' . $fullCommand;
466+
}
467+
$fullCommand .= ' 2>&1';
468+
return self::runBashCommand($fullCommand);
469+
}
470+
471+
public static function findParentDirContainingFile(string $filename): string {
472+
$dir = getcwd();
473+
if (is_bool($dir)) {
474+
throw new \Exception('Could not get current working directory (getcwd() returned false)');
475+
}
476+
477+
while ($dir !== dirname($dir)) {
478+
if (file_exists($dir . DIRECTORY_SEPARATOR . $filename)) {
479+
return $dir;
480+
}
481+
$dir = dirname($dir);
482+
}
483+
484+
throw new \Exception('The file ' . $filename . ' was not found in the parent directories of ' . $dir);
485+
}
486+
487+
private static function runBashCommand(string $command): array {
488+
$command = str_replace('\"', '"', $command);
489+
$patterns = [];
490+
$replacements = [];
491+
$fields = [
492+
'appRootDir' => self::findParentDirContainingFile('appinfo'),
493+
'nextcloudRootDir' => self::findParentDirContainingFile('console.php'),
494+
];
495+
foreach ($fields as $key => $value) {
496+
$patterns[] = '/<' . $key . '>/';
497+
$replacements[] = $value;
498+
}
499+
$command = preg_replace($patterns, $replacements, $command);
500+
if (!is_string($command)) {
501+
throw new \Exception('The command is not a string after preg_replace: ' . print_r($command, true));
502+
}
503+
504+
exec($command, $output, $resultCode);
505+
return [
506+
'command' => $command,
507+
'output' => $output,
508+
'resultCode' => $resultCode,
509+
];
510+
}
511+
512+
#[Given('/^run the command "(?P<command>(?:[^"]|\\")*)" with result code (\d+)$/')]
513+
public static function runCommandWithResultCode(string $command, int $resultCode = 0): void {
514+
$return = self::runCommand($command);
515+
Assert::assertEquals($resultCode, $return['resultCode'], print_r($return, true));
516+
}
517+
518+
#[Given('/^run the bash command "(?P<command>(?:[^"]|\\")*)" with result code (\d+)$/')]
519+
public static function runBashCommandWithResultCode(string $command, int $resultCode = 0): void {
520+
$return = self::runBashCommand($command);
521+
Assert::assertEquals($resultCode, $return['resultCode'], print_r($return, true));
522+
}
523+
451524
#[AfterScenario()]
452525
public function tearDown(): void {
453526
foreach ($this->createdUsers as $user) {

0 commit comments

Comments
 (0)