[tests-only] add tests for etag propagation on copy operation using spaces DAV (#4174)

* Transferred spaces etag propagation tests on copy operation from oC10

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Added implementation for copy request operation

* Upto store etag in given

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Fix remaining steps

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Style fix

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Updated feature name

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Address reviews

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

* Address reviews

Signed-off-by: Kiran Parajuli <kiranparajuli589@gmail.com>

Co-authored-by: sagargurung1001@gmail.com <sagargurung1001@gmail.com>
This commit is contained in:
PKiran
2022-07-14 16:59:36 +05:45
committed by GitHub
co-authored by sagargurung1001@gmail.com <sagargurung1001@gmail.com>
parent 930ccbffb3
commit 30809a7b37
2 changed files with 351 additions and 1 deletions
@@ -74,6 +74,29 @@ class SpacesContext implements Context {
*/
private string $davSpacesUrl = '/remote.php/dav/spaces/';
/**
* @var array map with user as key, spaces and file etags as value
* @example
* [
* "user1" => [
* "Personal" => [
* "file1.txt": "etag1",
* ],
* "Shares Jail" => []
* ],
* "user2" => [
* ...
* ]
* ]
*/
private $storedEtags = [];
private $etagPropfindBody = '<?xml version="1.0"?>'
. '<d:propfind xmlns:d="DAV:" '
. 'xmlns:oc="http://owncloud.org/ns" '
. 'xmlns:ocs="http://open-collaboration-services.org/ns">'
.'<d:prop><d:getetag/></d:prop></d:propfind>';
/**
* @param string $spaceName
*
@@ -215,8 +238,10 @@ class SpacesContext implements Context {
* @throws GuzzleException
*/
public function getSpaceByName(string $user, string $spaceName): array {
if ($spaceName === "Personal") {
$spaceName = $this->featureContext->getUserDisplayName($user);
}
$this->theUserListsAllHisAvailableSpacesUsingTheGraphApi($user);
$spaces = $this->getAvailableSpaces();
Assert::assertIsArray($spaces[$spaceName], "Space with name $spaceName for user $user not found");
Assert::assertNotEmpty($spaces[$spaceName]["root"]["webDavUrl"], "WebDavUrl for space with name $spaceName for user $user not found");
@@ -1660,6 +1685,97 @@ class SpacesContext implements Context {
);
}
/**
* @When /^user "([^"]*)" copies (?:file|folder) "([^"]*)" to "([^"]*)" inside space "([^"]*)" using the WebDAV API$/
*
* @param string $user
* @param string $fileSource
* @param string $fileDestination
* @param string $spaceName
*
* @return void
* @throws GuzzleException
*/
public function userCopiesFileWithinSpaceUsingTheWebDAVAPI(
string $user,
string $fileSource,
string $fileDestination,
string $spaceName
):void {
$space = $this->getSpaceByName($user, $spaceName);
$headers['Destination'] = $this->destinationHeaderValueWithSpaceName(
$user,
$fileDestination,
$spaceName
);
$fullUrl = $space["root"]["webDavUrl"] . '/' . ltrim($fileSource, "/");
$this->copyFilesAndFoldersRequest($user, $fullUrl, $headers);
}
/**
* @When /^user "([^"]*)" copies (?:file|folder) "([^"]*)" from space "([^"]*)" to "([^"]*)" inside space "([^"]*)" using the WebDAV API$/
*
* @param string $user
* @param string $fileSource
* @param string $fromSpaceName
* @param string $fileDestination
* @param string $toSpaceName
*
* @return void
* @throws GuzzleException
*/
public function userCopiesFileFromAndToSpaceBetweenSpaces(
string $user,
string $fileSource,
string $fromSpaceName,
string $fileDestination,
string $toSpaceName
):void {
$space = $this->getSpaceByName($user, $fromSpaceName);
$headers['Destination'] = $this->destinationHeaderValueWithSpaceName($user, $fileDestination, $toSpaceName);
$fullUrl = $space["root"]["webDavUrl"] . '/' . ltrim($fileSource, "/");
$this->copyFilesAndFoldersRequest($user, $fullUrl, $headers);
}
/**
* returns a url for destination with spacename
*
* @param string $user
* @param string $fileDestination
* @param string $spaceName
*
* @return string
* @throws GuzzleException
*/
public function destinationHeaderValueWithSpaceName(string $user, string $fileDestination, string $spaceName):string {
$space = $this->getSpaceByName($user, $spaceName);
return $space["root"]["webDavUrl"] . '/' . \ltrim($fileDestination, '/');
}
/**
* COPY request for files|folders
*
* @param string $user
* @param string $fullUrl
* @param array $headers
*
* @return void
* @throws GuzzleException
*/
public function copyFilesAndFoldersRequest(string $user, string $fullUrl, array $headers):void {
$this->featureContext->setResponse(
HttpRequestHelper::sendRequest(
$fullUrl,
$this->featureContext->getStepLineRef(),
'COPY',
$user,
$this->featureContext->getPasswordForUser($user),
$headers,
)
);
}
/**
* @Given /^user "([^"]*)" has uploaded a file inside space "([^"]*)" with content "([^"]*)" to "([^"]*)"$/
*
@@ -2366,4 +2482,174 @@ class SpacesContext implements Context {
$responseXml = HttpRequestHelper::getResponseXml($this->featureContext->getResponse());
return $responseXml->xpath("//d:response/d:href");
}
/**
* return the etag for an element inside a space
*
* @param string $user requestor
* @param string $space space name
* @param string $path path to the file
*
* @return string
* @throws GuzzleException
*/
public function userGetsEtagOfElementInASpace(string $user, string $space, string $path) {
$user = $this->featureContext->getActualUsername($user);
$space = $this->getSpaceByName($user, $space);
$fullUrl = $space['root']['webDavUrl'] . '/' . ltrim($path, '/');
$response = HttpRequestHelper::sendRequest(
$fullUrl,
$this->featureContext->getStepLineRef(),
'PROPFIND',
$user,
$this->featureContext->getPasswordForUser($user),
[],
$this->etagPropfindBody
);
$responseXml = HttpRequestHelper::getResponseXml($response);
$this->featureContext->setResponseXmlObject($responseXml);
return $this->featureContext->getEtagFromResponseXmlObject();
}
/**
* saves the etag of an element in a space
*
* @param string $user requestor
* @param string $space space name
* @param string $path path to the file
* @param ?string $storePath path to the file in the store
*
* @return void
* @throws GuzzleException
*/
public function storeEtagOfElementInSpaceForUser(string $user, string $space, string $path, ?string $storePath = ""): void {
if ($storePath === "") {
$storePath = $path;
}
$this->storedEtags[$user][$space][$storePath]
= $this->userGetsEtagOfElementInASpace(
$user,
$space,
$path,
);
}
/**
* returns stored etag for an element if present
*
* @param string $user
* @param string $space
* @param string $path
*
* @return string
*/
public function getStoredEtagForPathInSpaceOfAUser(string $user, string $space, string $path): string {
Assert::assertArrayHasKey(
$user,
$this->storedEtags,
__METHOD__ . " No stored etags for user '$user' found"
. "\nFound: " . print_r($this->storedEtags, true)
);
Assert::assertArrayHasKey(
$space,
$this->storedEtags[$user],
__METHOD__ . " No stored etags for user '$user' with space '$space' found"
. "\nFound: " . implode(', ', array_keys($this->storedEtags[$user]))
);
Assert::assertArrayHasKey(
$path,
$this->storedEtags[$user][$space],
__METHOD__ . " No stored etags for user '$user' with space '$space' with path '$path' found"
. '\nFound: ' . print_r($this->storedEtags[$user][$space], true)
);
return $this->storedEtags[$user][$space][$path];
}
/**
* @Then /^these etags should have changed$/
*
* @throws GuzzleException
*/
public function theseEtagsShouldHaveChanged(TableNode $table): void {
$this->featureContext->verifyTableNodeColumns($table, ["user", "path", "space"]);
$this->featureContext->verifyTableNodeColumnsCount($table, 3);
$unchangedEtagCount = 0;
$unchangedEtagMessage = __METHOD__;
foreach ($table->getColumnsHash() as $row) {
$user = $row['user'];
$path = $row['path'];
$space = $row['space'];
$etag = $this->userGetsEtagOfElementInASpace($user, $space, $path);
$storedEtag = $this->getStoredEtagForPathInSpaceOfAUser($user, $space, $path);
if ($etag === $storedEtag) {
$unchangedEtagCount++;
$unchangedEtagMessage .= "\nExpected etag of element '$path' for user '$user' in space '$space' to change, but it did not.";
}
}
Assert::assertEquals(0, $unchangedEtagCount, $unchangedEtagMessage);
}
/**
* @Then /^these etags should not have changed$/
*
* @param TableNode $table
*
* @throws GuzzleException
*/
public function theseEtagsShouldNotHaveChanged(TableNode $table): void {
$this->featureContext->verifyTableNodeColumns($table, ["user", "path", "space"]);
$this->featureContext->verifyTableNodeColumnsCount($table, 3);
$changedEtagCount = 0;
$changedEtagMessage = __METHOD__;
foreach ($table->getColumnsHash() as $row) {
$user = $row['user'];
$path = $row['path'];
$space = $row['space'];
$actualEtag = $this->userGetsEtagOfElementInASpace($user, $space, $path);
$storedEtag = $this->getStoredEtagForPathInSpaceOfAUser($user, $space, $path);
if ($actualEtag !== $storedEtag) {
$changedEtagCount++;
$changedEtagMessage .= "\nExpected etag of element '$path' for user '$user' in space '$space' not to change, but it did.";
}
}
Assert::assertEquals(0, $changedEtagCount, $changedEtagMessage);
}
/**
* @Given /^user "([^"]*)" has stored etag of element "([^"]*)" inside space "([^"]*)"$/
*
* @throws GuzzleException | Exception
*/
public function userHasStoredEtagOfElementFromSpace(string $user, string $path, string $space):void {
$user = $this->featureContext->getActualUsername($user);
$this->storeEtagOfElementInSpaceForUser(
$user,
$space,
$path,
);
if ($this->storedEtags[$user][$space][$path] === "" || $this->storedEtags[$user][$space][$path] === null) {
throw new Exception("Expected stored etag to be some string but found null!");
}
}
/**
* @Given /^user "([^"]*)" has stored etag of element "([^"]*)" on path "([^"]*)" inside space "([^"]*)"$/
*
* @throws Exception | GuzzleException
*/
public function userHasStoredEtagOfElementOnPathFromSpace($user, $path, $storePath, $space) {
$user = $this->featureContext->getActualUsername($user);
$this->storeEtagOfElementInSpaceForUser(
$user,
$space,
$path,
$storePath
);
if ($this->storedEtags[$user][$space][$storePath] === "" || $this->storedEtags[$user][$space][$storePath] === null) {
throw new Exception("Expected stored etag to be some string but found null!");
}
}
}