From fef74e755298cc17a357e009d8cb5ec1eeb7c654 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 19 Oct 2021 16:26:21 +0200 Subject: [PATCH 1/2] add some more steps --- .../features/apiSpaces/ListSpaces.feature | 5 + .../features/bootstrap/GraphApiContext.php | 103 +++++++++++++++++- 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/tests/acceptance/features/apiSpaces/ListSpaces.feature b/tests/acceptance/features/apiSpaces/ListSpaces.feature index d4dbdeb8fb..38ce8aabc1 100644 --- a/tests/acceptance/features/apiSpaces/ListSpaces.feature +++ b/tests/acceptance/features/apiSpaces/ListSpaces.feature @@ -12,3 +12,8 @@ Feature: List and create spaces Then the HTTP status code should be "200" And user "Alice" lists the content of the personal space root using the WebDav Api And the HTTP status code should be "207" + And user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi + Then the HTTP status code should be "401" + And the administrator gives "Alice" the role "Admin" using the settings api + And user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi + Then the HTTP status code should be "201" diff --git a/tests/acceptance/features/bootstrap/GraphApiContext.php b/tests/acceptance/features/bootstrap/GraphApiContext.php index dcff78a261..fde3989c0c 100644 --- a/tests/acceptance/features/bootstrap/GraphApiContext.php +++ b/tests/acceptance/features/bootstrap/GraphApiContext.php @@ -97,7 +97,7 @@ class GraphApiContext implements Context { * @param $baseUrl * @param $user * @param $password - * @param string $spaceName + * @param string $body * @param string $xRequestId * @param array $headers * @return ResponseInterface @@ -106,7 +106,7 @@ class GraphApiContext implements Context { $baseUrl, $user, $password, - string $spaceName, + string $body, string $xRequestId = '', array $headers = [] ): ResponseInterface @@ -115,9 +115,9 @@ class GraphApiContext implements Context { if (!str_ends_with($fullUrl, '/')) { $fullUrl .= '/'; } - $fullUrl .= "drives/" . $spaceName; + $fullUrl .= "graph/v1.0/drives/"; - return HttpRequestHelper::sendRequest($fullUrl, $xRequestId, 'POST', $user, $password, $headers); + return HttpRequestHelper::post($fullUrl, $xRequestId, $user, $password, $headers, $body); } /** @@ -161,7 +161,100 @@ class GraphApiContext implements Context { } /** - * Get the webDavUrl of the personal space has been found + * @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with the default quota using the GraphApi$/ + * + * @param $user string + * @param $spaceName string + * @param $spaceType string + * + * @return void + */ + public function theUserCreatesASpaceUsingTheGraphApi($user, $spaceName, $spaceType): void + { + $space = ["Name" => $spaceName, "driveType" => $spaceType]; + $body = json_encode($space); + $this->featureContext->setResponse( + $this->sendCreateSpaceRequest( + $this->featureContext->getBaseUrl(), + $user, + $this->featureContext->getPasswordForUser($user), + $body, + "" + ) + ); + } + + /** + * @When /^the administrator gives "([^"]*)" the role "([^"]*)" using the settings api$/ + * + * @param $user string + * @param $role string + * + * @return void + */ + public function theAdministratorGivesUserTheRole($user, $role): void + { + $admin = $this->featureContext->getAdminUsername(); + $password = $this->featureContext->getAdminPassword(); + $headers = []; + + $baseUrl = $this->featureContext->getBaseUrl(); + if (!str_ends_with($baseUrl, '/')) { + $baseUrl .= '/'; + } + // get the roles list first + $fullUrl = $baseUrl . "api/v0/settings/roles-list"; + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + $bundles = []; + if (isset(\json_decode($rawBody, true)["bundles"])) { + $bundles = \json_decode($rawBody, true)["bundles"]; + } + $roleToAssign = ""; + foreach($bundles as $bundle => $value) { + // find the selected role + if ($value["displayName"] === $role) { + $roleToAssign = $value; + } + } + Assert::assertNotEmpty($roleToAssign, "The selected role $role could not be found"); + + // get the accounts list first + $fullUrl = $baseUrl . "api/v0/accounts/accounts-list"; + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + $accounts = []; + if (isset(\json_decode($rawBody, true)["accounts"])) { + $accounts = \json_decode($rawBody, true)["accounts"]; + } + $accountToChange = ""; + foreach($accounts as $account) { + // find the selected user + if ($account["preferredName"] === $user) { + $accountToChange = $account; + } + } + Assert::assertNotEmpty($accountToChange, "The seleted account $user does not exist"); + + // set the new role + $fullUrl = $baseUrl . "api/v0/settings/assignments-add"; + $body = json_encode(["account_uuid" => $accountToChange["id"], "role_id" => $roleToAssign["id"]]); + + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, $body)); + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + + $assignment = []; + if (isset(\json_decode($rawBody, true)["assignment"])) { + $assignment = \json_decode($rawBody, true)["assignment"]; + } + + Assert::assertEquals($accountToChange["id"], $assignment["accountUuid"]); + Assert::assertEquals($roleToAssign["id"], $assignment["roleId"]); + } + + + /** + * Get the webDavUrl of the personal space * * @return void */ From c1ef23a76191d3ac2d32eec0748141e4c214f0d5 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 20 Oct 2021 17:25:09 +0200 Subject: [PATCH 2/2] add also propfind steps --- tests/acceptance/config/behat.yml | 2 +- .../features/apiSpaces/ListSpaces.feature | 21 +- .../features/bootstrap/GraphApiContext.php | 306 ---------- .../features/bootstrap/SpacesContext.php | 536 ++++++++++++++++++ 4 files changed, 552 insertions(+), 313 deletions(-) delete mode 100644 tests/acceptance/features/bootstrap/GraphApiContext.php create mode 100644 tests/acceptance/features/bootstrap/SpacesContext.php diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 6455830408..e3ba6e95a1 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -32,7 +32,7 @@ default: paths: - '%paths.base%/../features/apiSpaces' contexts: - - GraphApiContext: + - SpacesContext: - OccContext: - FeatureContext: &common_feature_context_params baseUrl: http://localhost:8080 diff --git a/tests/acceptance/features/apiSpaces/ListSpaces.feature b/tests/acceptance/features/apiSpaces/ListSpaces.feature index 38ce8aabc1..ab7e5eb786 100644 --- a/tests/acceptance/features/apiSpaces/ListSpaces.feature +++ b/tests/acceptance/features/apiSpaces/ListSpaces.feature @@ -8,12 +8,21 @@ Feature: List and create spaces Scenario: list own spaces Given user "Alice" has been created with default attributes and without skeleton files - And user "Alice" lists all available spaces via the GraphApi + When user "Alice" lists all available spaces via the GraphApi Then the HTTP status code should be "200" - And user "Alice" lists the content of the personal space root using the WebDav Api - And the HTTP status code should be "207" - And user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi + When user "Alice" lists the content of the space with the name "Alice Hansen" using the WebDav Api + Then the HTTP status code should be "207" + #Then the propfind result of the space should contain these entries: + #| .space/ | + Then the propfind result of the space should not contain these entries: + | file | + When user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi Then the HTTP status code should be "401" - And the administrator gives "Alice" the role "Admin" using the settings api - And user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi + When the administrator gives "Alice" the role "Admin" using the settings api + When user "Alice" creates a space "Project Mars" of type "project" with the default quota using the GraphApi Then the HTTP status code should be "201" + Then the json responded should contain these key and value pairs + | key | value | + | driveType | project | + | name | Project Mars | + When user "Alice" creates a space "Project Venus" of type "project" with quota "2000" using the GraphApi diff --git a/tests/acceptance/features/bootstrap/GraphApiContext.php b/tests/acceptance/features/bootstrap/GraphApiContext.php deleted file mode 100644 index fde3989c0c..0000000000 --- a/tests/acceptance/features/bootstrap/GraphApiContext.php +++ /dev/null @@ -1,306 +0,0 @@ -personalDriveWebDavUrl; - } - - /** - * @param string $personalDriveWebDavUrl - */ - public function setPersonalDriveWebDavUrl(string $personalDriveWebDavUrl): void - { - $this->personalDriveWebDavUrl = $personalDriveWebDavUrl; - } - /** - * @BeforeScenario - * - * @param BeforeScenarioScope $scope - * - * @return void - * @throws Exception - */ - public function setUpScenario(BeforeScenarioScope $scope): void - { - // Get the environment - $environment = $scope->getEnvironment(); - // Get all the contexts you need in this context - $this->featureContext = $environment->getContext('FeatureContext'); - SetupHelper::init( - $this->featureContext->getAdminUsername(), - $this->featureContext->getAdminPassword(), - $this->featureContext->getBaseUrl(), - $this->featureContext->getOcPath() - ); - } - - /** - * Send Graph List Drives Request - * - * @param $baseUrl - * @param $user - * @param $password - * @param $arguments - * @param string $xRequestId - * @param array $body - * @param array $headers - * @return ResponseInterface - */ - public function listSpacesRequest( - $baseUrl, - $user, - $password, - $arguments, - string $xRequestId = '', - array $body = [], - array $headers = [] - ) { - $fullUrl = $baseUrl; - if (!str_ends_with($fullUrl, '/')) { - $fullUrl .= '/'; - } - $fullUrl .= "graph/v1.0/me/drives/" . $arguments; - - return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); - } - - /** - * Send Graph List Drives Request - * - * @param $baseUrl - * @param $user - * @param $password - * @param string $body - * @param string $xRequestId - * @param array $headers - * @return ResponseInterface - */ - public function sendCreateSpaceRequest( - $baseUrl, - $user, - $password, - string $body, - string $xRequestId = '', - array $headers = [] - ): ResponseInterface - { - $fullUrl = $baseUrl; - if (!str_ends_with($fullUrl, '/')) { - $fullUrl .= '/'; - } - $fullUrl .= "graph/v1.0/drives/"; - - return HttpRequestHelper::post($fullUrl, $xRequestId, $user, $password, $headers, $body); - } - - /** - * Send Propfind Request to Url - * - * @param $fullUrl - * @param $user - * @param $password - * @param string $xRequestId - * @param array $headers - * @return ResponseInterface - */ - public function sendPropfindRequestToUrl( - $fullUrl, - $user, - $password, - string $xRequestId = '', - array $headers = [] - ): ResponseInterface - { - return HttpRequestHelper::sendRequest($fullUrl, $xRequestId, 'PROPFIND', $user, $password, $headers); - } - - /** - * @When /^user "([^"]*)" lists all available spaces via the GraphApi$/ - * - * @param $user - * @return void - */ - public function theUserListsAllHisAvailableSpacesUsingTheGraphApi($user): void - { - $this->featureContext->setResponse( - $this->listSpacesRequest( - $this->featureContext->getBaseUrl(), - $user, - $this->featureContext->getPasswordForUser($user), - "", - "" - ) - ); - } - - /** - * @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with the default quota using the GraphApi$/ - * - * @param $user string - * @param $spaceName string - * @param $spaceType string - * - * @return void - */ - public function theUserCreatesASpaceUsingTheGraphApi($user, $spaceName, $spaceType): void - { - $space = ["Name" => $spaceName, "driveType" => $spaceType]; - $body = json_encode($space); - $this->featureContext->setResponse( - $this->sendCreateSpaceRequest( - $this->featureContext->getBaseUrl(), - $user, - $this->featureContext->getPasswordForUser($user), - $body, - "" - ) - ); - } - - /** - * @When /^the administrator gives "([^"]*)" the role "([^"]*)" using the settings api$/ - * - * @param $user string - * @param $role string - * - * @return void - */ - public function theAdministratorGivesUserTheRole($user, $role): void - { - $admin = $this->featureContext->getAdminUsername(); - $password = $this->featureContext->getAdminPassword(); - $headers = []; - - $baseUrl = $this->featureContext->getBaseUrl(); - if (!str_ends_with($baseUrl, '/')) { - $baseUrl .= '/'; - } - // get the roles list first - $fullUrl = $baseUrl . "api/v0/settings/roles-list"; - $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); - $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); - $bundles = []; - if (isset(\json_decode($rawBody, true)["bundles"])) { - $bundles = \json_decode($rawBody, true)["bundles"]; - } - $roleToAssign = ""; - foreach($bundles as $bundle => $value) { - // find the selected role - if ($value["displayName"] === $role) { - $roleToAssign = $value; - } - } - Assert::assertNotEmpty($roleToAssign, "The selected role $role could not be found"); - - // get the accounts list first - $fullUrl = $baseUrl . "api/v0/accounts/accounts-list"; - $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); - $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); - $accounts = []; - if (isset(\json_decode($rawBody, true)["accounts"])) { - $accounts = \json_decode($rawBody, true)["accounts"]; - } - $accountToChange = ""; - foreach($accounts as $account) { - // find the selected user - if ($account["preferredName"] === $user) { - $accountToChange = $account; - } - } - Assert::assertNotEmpty($accountToChange, "The seleted account $user does not exist"); - - // set the new role - $fullUrl = $baseUrl . "api/v0/settings/assignments-add"; - $body = json_encode(["account_uuid" => $accountToChange["id"], "role_id" => $roleToAssign["id"]]); - - $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, $body)); - $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); - - $assignment = []; - if (isset(\json_decode($rawBody, true)["assignment"])) { - $assignment = \json_decode($rawBody, true)["assignment"]; - } - - Assert::assertEquals($accountToChange["id"], $assignment["accountUuid"]); - Assert::assertEquals($roleToAssign["id"], $assignment["roleId"]); - } - - - /** - * Get the webDavUrl of the personal space - * - * @return void - */ - public function theWebDavUrlOfThePersonalSpaceHasBeenFound(): void - { - $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); - $drives = []; - if (isset(\json_decode($rawBody, true)["value"])) { - $drives = \json_decode($rawBody, true)["value"]; - } - - Assert::assertArrayHasKey(0, $drives, "No drives were found on that endpoint"); - - foreach($drives as $drive) { - if (isset($drive["driveType"]) && $drive["driveType"] === "personal") { - $this->setPersonalDriveWebDavUrl($drive["root"]["webDavUrl"]); - - Assert::assertNotEmpty( - $drive["root"]["webDavUrl"], - "The personal space attributes contain no webDavUrl" - ); - } - } - } - - /** - * @When /^user "([^"]*)" lists the content of the personal space root using the WebDav Api$/ - * - * @param $user - * - * @return void - */ - public function theUserListsTheContentOfAPersonalSpaceRootUsingTheWebDAvApi($user): void - { - $this->theUserListsAllHisAvailableSpacesUsingTheGraphApi($user); - $this->theWebDavUrlOfThePersonalSpaceHasBeenFound(); - $this->featureContext->setResponse( - $this->sendPropfindRequestToUrl( - $this->getPersonalDriveWebDavUrl(), - $user, - $this->featureContext->getPasswordForUser($user), - "", - [], - [], - [] - ) - ); - } -} diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php new file mode 100644 index 0000000000..990126918d --- /dev/null +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -0,0 +1,536 @@ +availableSpaces; + } + + /** + * @param array $availableSpaces + */ + public function setAvailableSpaces(array $availableSpaces): void + { + $this->availableSpaces = $availableSpaces; + } + + /** + * response content parsed from XML to an array + * + * @var array + */ + private array $responseXml = []; + + /** + * @return array + */ + public function getResponseXml(): array + { + return $this->responseXml; + } + + /** + * @param array $responseXml + */ + public function setResponseXml(array $responseXml): void + { + $this->responseXml = $responseXml; + } + + /** + * space id from last propfind request + * + * @var string + */ + private $responseSpaceId; + + /** + * @param string $responseSpaceId + */ + public function setResponseSpaceId(string $responseSpaceId): void + { + $this->responseSpaceId = $responseSpaceId; + } + + /** + * @return string + */ + public function getResponseSpaceId(): string + { + return $this->responseSpaceId; + } + + /** + * @BeforeScenario + * + * @param BeforeScenarioScope $scope + * + * @return void + * @throws Exception + */ + public function setUpScenario(BeforeScenarioScope $scope): void + { + // Get the environment + $environment = $scope->getEnvironment(); + // Get all the contexts you need in this context + $this->featureContext = $environment->getContext('FeatureContext'); + SetupHelper::init( + $this->featureContext->getAdminUsername(), + $this->featureContext->getAdminPassword(), + $this->featureContext->getBaseUrl(), + $this->featureContext->getOcPath() + ); + } + + /** + * Send Graph List Spaces Request + * + * @param $baseUrl + * @param $user + * @param $password + * @param $arguments + * @param string $xRequestId + * @param array $body + * @param array $headers + * @return ResponseInterface + */ + public function listSpacesRequest( + $baseUrl, + $user, + $password, + $arguments, + string $xRequestId = '', + array $body = [], + array $headers = [] + ) { + $fullUrl = $baseUrl; + if (!str_ends_with($fullUrl, '/')) { + $fullUrl .= '/'; + } + $fullUrl .= "graph/v1.0/me/drives/" . $arguments; + + return HttpRequestHelper::get($fullUrl, $xRequestId, $user, $password, $headers, $body); + } + + /** + * Send Graph Create Space Request + * + * @param $baseUrl + * @param $user + * @param $password + * @param string $body + * @param string $xRequestId + * @param array $headers + * @return ResponseInterface + */ + public function sendCreateSpaceRequest( + $baseUrl, + $user, + $password, + string $body, + string $xRequestId = '', + array $headers = [] + ): ResponseInterface + { + $fullUrl = $baseUrl; + if (!str_ends_with($fullUrl, '/')) { + $fullUrl .= '/'; + } + $fullUrl .= "graph/v1.0/drives/"; + + return HttpRequestHelper::post($fullUrl, $xRequestId, $user, $password, $headers, $body); + } + + /** + * Send Propfind Request to Url + * + * @param $fullUrl + * @param $user + * @param $password + * @param string $xRequestId + * @param array $headers + * @return ResponseInterface + */ + public function sendPropfindRequestToUrl( + $fullUrl, + $user, + $password, + string $xRequestId = '', + array $headers = [] + ): ResponseInterface + { + return HttpRequestHelper::sendRequest($fullUrl, $xRequestId, 'PROPFIND', $user, $password, $headers); + } + + /** + * @When /^user "([^"]*)" lists all available spaces via the GraphApi$/ + * + * @param $user + * @return void + */ + public function theUserListsAllHisAvailableSpacesUsingTheGraphApi($user): void + { + $this->featureContext->setResponse( + $this->listSpacesRequest( + $this->featureContext->getBaseUrl(), + $user, + $this->featureContext->getPasswordForUser($user), + "", + "" + ) + ); + $this->rememberTheAvailableSpaces(); + } + + /** + * @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with the default quota using the GraphApi$/ + * + * @param $user string + * @param $spaceName string + * @param $spaceType string + * + * @return void + */ + public function theUserCreatesASpaceUsingTheGraphApi($user, $spaceName, $spaceType): void + { + $space = ["Name" => $spaceName, "driveType" => $spaceType]; + $body = json_encode($space); + $this->featureContext->setResponse( + $this->sendCreateSpaceRequest( + $this->featureContext->getBaseUrl(), + $user, + $this->featureContext->getPasswordForUser($user), + $body, + "" + ) + ); + } + + /** + * @When /^user "([^"]*)" creates a space "([^"]*)" of type "([^"]*)" with quota "([^"]*)" using the GraphApi$/ + * + * @param $user string + * @param $spaceName string + * @param $spaceType string + * @param $quota int + * + * @return void + * @throws JsonException + */ + public function theUserCreatesASpaceWithQuotaUsingTheGraphApi($user, $spaceName, $spaceType, $quota): void + { + $space = ["Name" => $spaceName, "driveType" => $spaceType, "quota" => ["total" => (int) $quota]]; + $body = json_encode($space); + $this->featureContext->setResponse( + $this->sendCreateSpaceRequest( + $this->featureContext->getBaseUrl(), + $user, + $this->featureContext->getPasswordForUser($user), + $body, + "" + ) + ); + } + + /** + * @When /^the administrator gives "([^"]*)" the role "([^"]*)" using the settings api$/ + * + * @param $user string + * @param $role string + * + * @return void + */ + public function theAdministratorGivesUserTheRole(string $user, string $role): void + { + $admin = $this->featureContext->getAdminUsername(); + $password = $this->featureContext->getAdminPassword(); + $headers = []; + + $baseUrl = $this->featureContext->getBaseUrl(); + if (!str_ends_with($baseUrl, '/')) { + $baseUrl .= '/'; + } + // get the roles list first + $fullUrl = $baseUrl . "api/v0/settings/roles-list"; + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); + if ($this->featureContext->getResponse()) { + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + } + $bundles = []; + if (isset(\json_decode($rawBody, true)["bundles"])) { + $bundles = \json_decode($rawBody, true)["bundles"]; + } + $roleToAssign = ""; + foreach($bundles as $bundle => $value) { + // find the selected role + if ($value["displayName"] === $role) { + $roleToAssign = $value; + } + } + Assert::assertNotEmpty($roleToAssign, "The selected role $role could not be found"); + + // get the accounts list first + $fullUrl = $baseUrl . "api/v0/accounts/accounts-list"; + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, "{}")); + if ($this->featureContext->getResponse()) { + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + } + $accounts = []; + if (isset(\json_decode($rawBody, true)["accounts"])) { + $accounts = \json_decode($rawBody, true)["accounts"]; + } + $accountToChange = ""; + foreach($accounts as $account) { + // find the selected user + if ($account["preferredName"] === $user) { + $accountToChange = $account; + } + } + Assert::assertNotEmpty($accountToChange, "The seleted account $user does not exist"); + + // set the new role + $fullUrl = $baseUrl . "api/v0/settings/assignments-add"; + $body = json_encode(["account_uuid" => $accountToChange["id"], "role_id" => $roleToAssign["id"]]); + + $this->featureContext->setResponse(HttpRequestHelper::post($fullUrl, "", $admin, $password, $headers, $body)); + if ($this->featureContext->getResponse()) { + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + } + + $assignment = []; + if (isset(\json_decode($rawBody, true)["assignment"])) { + $assignment = \json_decode($rawBody, true)["assignment"]; + } + + Assert::assertEquals($accountToChange["id"], $assignment["accountUuid"]); + Assert::assertEquals($roleToAssign["id"], $assignment["roleId"]); + } + + + /** + * Remember the available Spaces + * + * @return void + */ + public function rememberTheAvailableSpaces(): void + { + $rawBody = $this->featureContext->getResponse()->getBody()->getContents(); + $drives = json_decode($rawBody, true); + if (isset($drives["value"])) { + $drives = $drives["value"]; + } + + Assert::assertArrayHasKey(0, $drives, "No drives were found on that endpoint"); + $spaces = []; + foreach($drives as $drive) { + $spaces[$drive["name"]] = $drive; + } + $this->setAvailableSpaces($spaces); + Assert::assertNotEmpty($spaces, "No spaces have been found"); + } + + /** + * @When /^user "([^"]*)" lists the content of the space with the name "([^"]*)" using the WebDav Api$/ + * + * @param $user + * @param $name + * @return void + */ + public function theUserListsTheContentOfAPersonalSpaceRootUsingTheWebDAvApi($user, $name): void + { + $spaceId = $this->getAvailableSpaces()[$name]["id"]; + $spaceWebDavUrl = $this->getAvailableSpaces()[$name]["root"]["webDavUrl"]; + $this->featureContext->setResponse( + $this->sendPropfindRequestToUrl( + $spaceWebDavUrl, + $user, + $this->featureContext->getPasswordForUser($user), + "", + [], + [], + [] + ) + ); + $this->setResponseSpaceId($spaceId); + $this->setResponseXml(HttpRequestHelper::parseResponseAsXml($this->featureContext->getResponse()) + ); + } + + /** + * @Then /^the (?:propfind|search) result of the space should (not|)\s?contain these (?:files|entries):$/ + * + * @param string $user + * @param string $shouldOrNot (not|) + * @param TableNode $expectedFiles + * + * @return void + * @throws Exception + */ + public function thePropfindResultShouldContainEntries( + $shouldOrNot, + TableNode $expectedFiles + ) { + $this->propfindResultShouldContainEntries( + $shouldOrNot, + $expectedFiles, + ); + } + + /** + * @Then the json responded should contain these key and value pairs + * + * @param TableNode $table + * + * @return void + */ + public function jsonRespondedShouldContain(TableNode $table) { + $this->featureContext->verifyTableNodeColumns($table, ['key', 'value']); + $responseJson = json_decode($this->featureContext->getResponse()->getBody(), true); + foreach ($table->getHash() as $row) { + $expected = [$row["key"] => $row["value"]]; + Assert::assertEquals($row["value"], $responseJson[$row["key"]]); + } + } + + /** + * @param string $shouldOrNot (not|) + * @param TableNode $expectedFiles + * @param string|null $user + * + * @return void + * @throws Exception + */ + public function propfindResultShouldContainEntries( + $shouldOrNot, + TableNode $expectedFiles + ) { + $this->verifyTableNodeColumnsCount($expectedFiles, 1); + $elementRows = $expectedFiles->getRows(); + $should = ($shouldOrNot !== "not"); + + foreach ($elementRows as $expectedFile) { + $fileFound = $this->findEntryFromPropfindResponse( + $expectedFile[0] + ); + if ($should) { + Assert::assertNotEmpty( + $fileFound, + "response does not contain the entry '$expectedFile[0]'" + ); + } else { + Assert::assertFalse( + $fileFound, + "response does contain the entry '$expectedFile[0]' but should not" + ); + } + } + } + /** + * Verify that the tableNode contains expected number of columns + * + * @param TableNode $table + * @param int $count + * + * @return void + * @throws Exception + */ + public function verifyTableNodeColumnsCount($table, $count) { + if (!($table instanceof TableNode)) { + throw new Exception("TableNode expected but got " . \gettype($table)); + } + if (\count($table->getRows()) < 1) { + throw new Exception("Table should have at least one row."); + } + $rowCount = \count($table->getRows()[0]); + if ($count !== $rowCount) { + throw new Exception("Table expected to have $count rows but found $rowCount"); + } + } + + /** + * parses a PROPFIND response from $this->response into xml + * and returns found search results if found else returns false + * + * @param string|null $entryNameToSearch + * @return string|array|boolean + * string if $entryNameToSearch is given and is found + * array if $entryNameToSearch is not given + * boolean false if $entryNameToSearch is given and is not found + */ + public function findEntryFromPropfindResponse( + string $entryNameToSearch = null + ) { + $spaceId = $this->getResponseSpaceId(); + //if we are using that step the second time in a scenario e.g. 'But ... should not' + //then don't parse the result again, because the result in a ResponseInterface + if (empty($this->getResponseXml())) { + $this->setResponseXml( + HttpRequestHelper::parseResponseAsXml($this->featureContext->getResponse()) + ); + } + Assert::assertNotEmpty($this->getResponseXml(), __METHOD__ . ' Response is empty'); + Assert::assertNotEmpty($spaceId, __METHOD__ . ' SpaceId is empty'); + + // trim any leading "/" passed by the caller, we can just match the "raw" name + $trimmedEntryNameToSearch = \trim($entryNameToSearch, "/"); + + // topWebDavPath should be something like /remote.php/webdav/ or + // /remote.php/dav/files/alice/ + $topWebDavPath = "/" . "dav/spaces/" . $spaceId . "/"; + + Assert::assertIsArray( + $this->responseXml, + __METHOD__ . " responseXml for space $spaceId is not an array" + ); + Assert::assertArrayHasKey( + "value", + $this->responseXml, + __METHOD__ . " responseXml for space $spaceId does not have key 'value'" + ); + $multistatusResults = $this->responseXml["value"]; + $results = []; + if ($multistatusResults !== null) { + foreach ($multistatusResults as $multistatusResult) { + $entryPath = $multistatusResult['value'][0]['value']; + $entryName = \str_replace($topWebDavPath, "", $entryPath); + $entryName = \rawurldecode($entryName); + $entryName = \trim($entryName, "/"); + if ($trimmedEntryNameToSearch === $entryName) { + return $multistatusResult; + } + $results[] = $entryName; + } + } + if ($entryNameToSearch === null) { + return $results; + } + return false; + } +}