Merge pull request #9924 from owncloud/reorganize-test-folders
[tests-only][full-ci] reorganize test folders within the acceptance directory
This commit is contained in:
@@ -1,309 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2021 Artur Neumann artur@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use TestHelpers\SetupHelper;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use splitbrain\PHPArchive\Tar;
|
||||
use splitbrain\PHPArchive\Zip;
|
||||
use splitbrain\PHPArchive\Archive;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Context for Archiver specific steps
|
||||
*/
|
||||
class ArchiverContext implements Context {
|
||||
/**
|
||||
* @var FeatureContext
|
||||
*/
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @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()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*
|
||||
* @return Archive
|
||||
*/
|
||||
public function getArchiveClass(string $type): Archive {
|
||||
if ($type === 'zip') {
|
||||
return new Zip();
|
||||
} elseif ($type === 'tar') {
|
||||
return new Tar();
|
||||
} else {
|
||||
throw new Exception('Unknown archive type: ' . $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeDir(string $dir): void {
|
||||
$items = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($items as $item) {
|
||||
$itemPath = $dir . DIRECTORY_SEPARATOR . $item;
|
||||
if (\is_dir($itemPath)) {
|
||||
$this->removeDir($itemPath);
|
||||
} else {
|
||||
\unlink($itemPath);
|
||||
}
|
||||
}
|
||||
\rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $resource
|
||||
* @param string $addressType id|ids|path|paths
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getArchiverQueryString(
|
||||
string $user,
|
||||
string $resource,
|
||||
string $addressType
|
||||
): string {
|
||||
switch ($addressType) {
|
||||
case 'id':
|
||||
case 'ids':
|
||||
return 'id=' . $this->featureContext->getFileIdForPath($user, $resource);
|
||||
case 'path':
|
||||
case 'paths':
|
||||
return 'path=' . $resource;
|
||||
default:
|
||||
throw new Exception(
|
||||
'"' . $addressType .
|
||||
'" is not a legal value for $addressType, must be id|ids|path|paths'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" downloads the (zip|tar) archive of "([^"]*)" using the resource (id|ids|path|paths) and setting these headers:$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $archiveType
|
||||
* @param string $resource
|
||||
* @param string $addressType id|path
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userDownloadsTheZipOrTarArchiveOfResourceUsingResourceIdOrPathAndSettingTheseHeaders(
|
||||
string $user,
|
||||
string $archiveType,
|
||||
string $resource,
|
||||
string $addressType,
|
||||
TableNode $headersTable
|
||||
): void {
|
||||
$this->featureContext->verifyTableNodeColumns(
|
||||
$headersTable,
|
||||
['header', 'value']
|
||||
);
|
||||
$headers = [];
|
||||
foreach ($headersTable as $row) {
|
||||
$headers[$row['header']] = $row ['value'];
|
||||
}
|
||||
$this->featureContext->setResponse($this->downloadArchive($user, $resource, $addressType, $archiveType, null, $headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :downloader downloads the archive of :item of user :owner using the resource :addressType
|
||||
*
|
||||
* @param string $downloader Who sends the request
|
||||
* @param string $resource
|
||||
* @param string $owner Who is the real owner of the file
|
||||
* @param string $addressType id|path
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userDownloadsTheArchiveOfItemOfUser(
|
||||
string $downloader,
|
||||
string $resource,
|
||||
string $owner,
|
||||
string $addressType
|
||||
): void {
|
||||
$this->featureContext->setResponse($this->downloadArchive($downloader, $resource, $addressType, null, $owner));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $downloader
|
||||
* @param string $resource
|
||||
* @param string $addressType
|
||||
* @param string|null $archiveType
|
||||
* @param string|null $owner
|
||||
* @param array|null $headers
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function downloadArchive(
|
||||
string $downloader,
|
||||
string $resource,
|
||||
string $addressType,
|
||||
?string $archiveType = null,
|
||||
?string $owner = null,
|
||||
?array $headers = null
|
||||
): ResponseInterface {
|
||||
$owner = $owner ?? $downloader;
|
||||
$downloader = $this->featureContext->getActualUsername($downloader);
|
||||
$queryString = $this->getArchiverQueryString($owner, $resource, $addressType);
|
||||
if ($archiveType !== null) {
|
||||
$queryString .= '&output-format=' . $archiveType;
|
||||
}
|
||||
return HttpRequestHelper::get(
|
||||
$this->featureContext->getBaseUrl() . '/archiver?' . $queryString,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$downloader,
|
||||
$this->featureContext->getPasswordForUser($downloader),
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user downloads the archive of these items using the resource :addressType
|
||||
*
|
||||
* @param string $user
|
||||
* @param TableNode $items
|
||||
* @param string $addressType ids|paths
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException|Exception
|
||||
*/
|
||||
public function userDownloadsTheArchiveOfTheseItems(
|
||||
string $user,
|
||||
TableNode $items,
|
||||
string $addressType
|
||||
): void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$queryString = '';
|
||||
foreach ($items->getRows() as $item) {
|
||||
$queryString .= $this->getArchiverQueryString($user, $item[0], $addressType) . '&';
|
||||
}
|
||||
|
||||
$queryString = \rtrim($queryString, '&');
|
||||
$this->featureContext->setResponse(
|
||||
HttpRequestHelper::get(
|
||||
$this->featureContext->getBaseUrl() . '/archiver?' . $queryString,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the downloaded :type archive should contain these files:
|
||||
*
|
||||
* @param string $type
|
||||
* @param TableNode $expectedFiles
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theDownloadedArchiveShouldContainTheseFiles(string $type, TableNode $expectedFiles):void {
|
||||
$this->featureContext->verifyTableNodeColumns($expectedFiles, ['name', 'content']);
|
||||
$contents = $this->featureContext->getResponse()->getBody()->getContents();
|
||||
$tempFile = \tempnam(\sys_get_temp_dir(), 'OcAcceptanceTests_');
|
||||
$tempExtractFolder = $tempFile;
|
||||
\unlink($tempFile); // we only need the name
|
||||
$tempFile = $tempFile . '.' . $type; // it needs the extension
|
||||
\file_put_contents($tempFile, $contents);
|
||||
|
||||
// open the archive
|
||||
$tar = $this->getArchiveClass($type);
|
||||
$tar->open($tempFile);
|
||||
$archiveData = $tar->contents();
|
||||
|
||||
// extract the archive
|
||||
$tar->open($tempFile);
|
||||
$tar->extract($tempExtractFolder);
|
||||
$tar->close();
|
||||
|
||||
foreach ($expectedFiles->getHash() as $expectedItem) {
|
||||
$expectedPath = trim($expectedItem['name'], "/");
|
||||
$found = false;
|
||||
foreach ($archiveData as $info) {
|
||||
// get only the parent folder path for the given item
|
||||
$actualPath = $info->getPath();
|
||||
|
||||
if ($expectedPath === $actualPath) {
|
||||
if (!$info->getIsdir()) {
|
||||
$fileContent = \file_get_contents("$tempExtractFolder/$actualPath");
|
||||
Assert::assertEquals(
|
||||
$expectedItem['content'],
|
||||
$fileContent,
|
||||
__METHOD__ .
|
||||
" content of '" . $expectedPath . "' not as expected"
|
||||
);
|
||||
}
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
Assert::fail("Resource '" . $expectedPath . "' is not in the downloaded archive.");
|
||||
}
|
||||
}
|
||||
\unlink($tempFile);
|
||||
$this->removeDir($tempExtractFolder);
|
||||
}
|
||||
}
|
||||
@@ -1,648 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* @author Christoph Wurst <christoph@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2018, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use Behat\Behat\Context\Context;
|
||||
use TestHelpers\SetupHelper;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\WebDavHelper;
|
||||
|
||||
/**
|
||||
* Authentication functions
|
||||
*/
|
||||
class AuthContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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');
|
||||
|
||||
// Reset ResponseXml
|
||||
$this->featureContext->setResponseXml([]);
|
||||
|
||||
// Initialize SetupHelper class
|
||||
SetupHelper::init(
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$this->featureContext->getAdminPassword(),
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getOcPath()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createBasicAuthHeader(string $user, string $password): array {
|
||||
$header = [];
|
||||
$authString = \base64_encode("$user:$password");
|
||||
$header["Authorization"] = "basic $authString";
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
* @param string|null $body
|
||||
* @param array|null $headers
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function sendRequest(
|
||||
string $url,
|
||||
string $method,
|
||||
?string $body = null,
|
||||
?array $headers = []
|
||||
): ResponseInterface {
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $url;
|
||||
|
||||
return HttpRequestHelper::sendRequest(
|
||||
$fullUrl,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$method,
|
||||
null,
|
||||
null,
|
||||
$headers,
|
||||
$body,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
* @param string|null $body
|
||||
* @param array|null $headers
|
||||
* @param string|null $property
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function requestUrlWithBasicAuth(
|
||||
string $user,
|
||||
string $url,
|
||||
string $method,
|
||||
?string $body = null,
|
||||
?array $headers = null,
|
||||
?string $property = null
|
||||
): ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$url = $this->featureContext->substituteInLineCodes(
|
||||
$url,
|
||||
$user
|
||||
);
|
||||
$authHeader = $this->createBasicAuthHeader($user, $this->featureContext->getPasswordForUser($user));
|
||||
$headers = \array_merge($headers ?? [], $authHeader);
|
||||
|
||||
if ($property !== null) {
|
||||
$body = $this->featureContext->getBodyForOCSRequest($method, $property);
|
||||
}
|
||||
|
||||
return $this->sendRequest(
|
||||
$url,
|
||||
$method,
|
||||
$body,
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When a user requests :url with :method and no authentication
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userRequestsURLWithNoAuth(string $url, string $method):void {
|
||||
$this->featureContext->setResponse($this->sendRequest($url, $method));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When a user requests these endpoints with :method with body :body and no authentication about user :user
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $body
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userRequestsEndpointsWithBodyAndNoAuthThenStatusCodeAboutUser(string $method, string $body, string $ofUser, TableNode $table): void {
|
||||
$ofUser = \strtolower($this->featureContext->getActualUsername($ofUser));
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->sendRequest($row['endpoint'], $method, $body);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When a user requests these endpoints with :method with no authentication about user :user
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsEndpointsWithoutBodyAndNoAuthAboutUser(string $method, string $ofUser, TableNode $table): void {
|
||||
$ofUser = \strtolower($this->featureContext->getActualUsername($ofUser));
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->sendRequest($row['endpoint'], $method);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When a user requests these endpoints with :method and no authentication
|
||||
*
|
||||
* @param string $method
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsEndpointsWithNoAuthentication(string $method, TableNode $table):void {
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
foreach ($table->getHash() as $row) {
|
||||
$this->featureContext->setResponse($this->sendRequest($row['endpoint'], $method));
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the user :user requests these endpoints with :method with basic auth
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsEndpointsWithBasicAuth(string $user, string $method, TableNode $table):void {
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
foreach ($table->getHash() as $row) {
|
||||
$response = $this->requestUrlWithBasicAuth($user, $row['endpoint'], $method);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" requests these endpoints with "([^"]*)" to (?:get|set) property "([^"]*)" about user "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $property
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theUserRequestsTheseEndpointsToGetOrSetPropertyAboutUser(
|
||||
string $user,
|
||||
string $method,
|
||||
string $property,
|
||||
string $ofUser,
|
||||
TableNode $table
|
||||
):void {
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->requestUrlWithBasicAuth($user, $row['endpoint'], $method, null, null, $property);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator requests these endpoints with :method
|
||||
*
|
||||
* @param string $method
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theAdminRequestsTheseEndpointsWithMethod(string $method, TableNode $table):void {
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
foreach ($table->getHash() as $row) {
|
||||
$response = $this->requestUrlWithBasicAuth(
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$row['endpoint'],
|
||||
$method
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests :url with :method using basic auth
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userRequestsURLUsingBasicAuth(
|
||||
string $user,
|
||||
string $url,
|
||||
string $method
|
||||
):void {
|
||||
$response = $this->requestUrlWithBasicAuth($user, $url, $method);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests :url with :method using basic auth and with headers
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $url
|
||||
* @param string $method
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsURLWithUsingBasicAuthAndDepthHeader(string $user, string $url, string $method, TableNode $headersTable):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$url = $this->featureContext->substituteInLineCodes(
|
||||
$url,
|
||||
$user
|
||||
);
|
||||
$this->featureContext->verifyTableNodeColumns(
|
||||
$headersTable,
|
||||
['header', 'value']
|
||||
);
|
||||
$headers = [];
|
||||
foreach ($headersTable as $row) {
|
||||
$headers[$row['header']] = $row ['value'];
|
||||
}
|
||||
$this->featureContext->setResponse(
|
||||
$this->requestUrlWithBasicAuth(
|
||||
$user,
|
||||
$url,
|
||||
$method,
|
||||
null,
|
||||
$headers
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests these endpoints with :method using password :password
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $password
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsWithPassword(
|
||||
string $user,
|
||||
string $method,
|
||||
string $password,
|
||||
TableNode $table
|
||||
): void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
|
||||
$authHeader = $this->createBasicAuthHeader($user, $this->featureContext->getActualPassword($password));
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$response = $this->sendRequest($row['endpoint'], $method, null, $authHeader);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests these endpoints with :method using password :password about user :ofUser
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $password
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsUsingPasswordAboutUser(
|
||||
string $user,
|
||||
string $method,
|
||||
string $password,
|
||||
string $ofUser,
|
||||
TableNode $table
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$ofUser = $this->featureContext->getActualUsername($ofUser);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint'], ['destination']);
|
||||
|
||||
$headers = $this->createBasicAuthHeader($user, $this->featureContext->getActualPassword($password));
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
if (isset($row['destination'])) {
|
||||
$headers['Destination'] = $this->featureContext->substituteInLineCodes(
|
||||
$this->featureContext->getBaseUrl() . $row['destination'],
|
||||
$ofUser
|
||||
);
|
||||
}
|
||||
$response = $this->sendRequest(
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
null,
|
||||
$headers
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests these endpoints with :method including body :body using password :password about user :ofUser
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $body
|
||||
* @param string $password
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsWithBodyUsingPasswordAboutUser(
|
||||
string $user,
|
||||
string $method,
|
||||
string $body,
|
||||
string $password,
|
||||
string $ofUser,
|
||||
TableNode $table
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$ofUser = $this->featureContext->getActualUsername($ofUser);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint'], ['destination']);
|
||||
|
||||
$headers = $this->createBasicAuthHeader($user, $this->featureContext->getActualPassword($password));
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
if (isset($row['destination'])) {
|
||||
$headers['Destination'] = $this->featureContext->substituteInLineCodes(
|
||||
$this->featureContext->getBaseUrl() . $row['destination'],
|
||||
$ofUser
|
||||
);
|
||||
}
|
||||
$response = $this->sendRequest(
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
$body,
|
||||
$headers
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests these endpoints with :method including body :body about user :ofUser
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $body
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsIncludingBodyAboutUser(string $user, string $method, string $body, string $ofUser, TableNode $table):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$ofUser = $this->featureContext->getActualUsername($ofUser);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
|
||||
$headers = [];
|
||||
if ($method === 'MOVE' || $method === 'COPY') {
|
||||
$headers['Destination'] = '/path/to/destination';
|
||||
}
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->requestUrlWithBasicAuth(
|
||||
$user,
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
$body,
|
||||
$headers
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :asUser requests these endpoints with :method using the password of user :ofUser
|
||||
*
|
||||
* @param string $asUser
|
||||
* @param string $method
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsWithoutBodyUsingThePasswordOfUser(string $asUser, string $method, string $ofUser, TableNode $table):void {
|
||||
$asUser = $this->featureContext->getActualUsername($asUser);
|
||||
$ofUser = $this->featureContext->getActualUsername($ofUser);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
|
||||
// do request as $asUser using password of $ofUser
|
||||
$authHeader = $this->createBasicAuthHeader($asUser, $this->featureContext->getPasswordForUser($ofUser));
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->sendRequest(
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
null,
|
||||
$authHeader
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :asUser requests these endpoints with :method including body :body using the password of user :user
|
||||
*
|
||||
* @param string $asUser
|
||||
* @param string $method
|
||||
* @param string|null $body
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userRequestsTheseEndpointsIncludingBodyUsingPasswordOfUser(string $asUser, string $method, ?string $body, string $ofUser, TableNode $table):void {
|
||||
$asUser = $this->featureContext->getActualUsername($asUser);
|
||||
$ofUser = $this->featureContext->getActualUsername($ofUser);
|
||||
$this->featureContext->verifyTableNodeColumns($table, ['endpoint']);
|
||||
|
||||
// do request as $asUser using password of $ofUser
|
||||
$authHeader = $this->createBasicAuthHeader($asUser, $this->featureContext->getPasswordForUser($ofUser));
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->sendRequest(
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
$body,
|
||||
$authHeader
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests these endpoints with :method about user :ofUser
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $method
|
||||
* @param string $ofUser
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRequestsTheseEndpointsAboutUser(string $user, string $method, string $ofUser, TableNode $table):void {
|
||||
$headers = [];
|
||||
if ($method === 'MOVE' || $method === 'COPY') {
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
$suffix = "";
|
||||
if ($this->featureContext->getDavPathVersion() === WebDavHelper::DAV_VERSION_SPACES) {
|
||||
$suffix = $this->featureContext->spacesContext->getSpaceIdByName($user, "Personal") . "/";
|
||||
}
|
||||
$davPath = WebDavHelper::getDavPath($user, $this->featureContext->getDavPathVersion());
|
||||
$headers['Destination'] = "{$baseUrl}/{$davPath}{$suffix}moved";
|
||||
}
|
||||
|
||||
foreach ($table->getHash() as $row) {
|
||||
$row['endpoint'] = $this->featureContext->substituteInLineCodes(
|
||||
$row['endpoint'],
|
||||
$ofUser
|
||||
);
|
||||
$response = $this->requestUrlWithBasicAuth(
|
||||
$user,
|
||||
$row['endpoint'],
|
||||
$method,
|
||||
null,
|
||||
$headers
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastStatusCodesArrays();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests :endpoint with :method without retrying
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $endpoint
|
||||
* @param string $method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userRequestsURLWithoutRetry(
|
||||
string $user,
|
||||
string $endpoint,
|
||||
string $method
|
||||
):void {
|
||||
$username = $this->featureContext->getActualUsername($user);
|
||||
$endpoint = $this->featureContext->substituteInLineCodes(
|
||||
$endpoint,
|
||||
$username
|
||||
);
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $endpoint;
|
||||
$response = HttpRequestHelper::sendRequestOnce(
|
||||
$fullUrl,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$method,
|
||||
$username,
|
||||
$this->featureContext->getPasswordForUser($user)
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
* @author Sergio Bertolin <sbertolin@owncloud.com>
|
||||
* @author Phillip Davis <phil@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018, ownCloud GmbH
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\PyStringNode;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\OcsApiHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Capabilities context.
|
||||
*/
|
||||
class CapabilitiesContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $username
|
||||
* @param boolean $formatJson // if true then formats the response in json
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userGetsCapabilities(string $username, ?bool $formatJson = false): ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($username);
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
return OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$password,
|
||||
'GET',
|
||||
'/cloud/capabilities' . ($formatJson ? '?format=json' : ''),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
[],
|
||||
$this->featureContext->getOcsApiVersion()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function getAdminUsernameForCapabilitiesCheck(): string {
|
||||
if (\TestHelpers\OcisHelper::isTestingOnReva()) {
|
||||
// When testing on reva we don't have a user called "admin" to use
|
||||
// to access the capabilities. So create an ordinary user on-the-fly
|
||||
// with a default password. That user should be able to get a
|
||||
// capabilities response that the test can process.
|
||||
$adminUsername = "PseudoAdminForRevaTest";
|
||||
$createdUsers = $this->featureContext->getCreatedUsers();
|
||||
if (!\array_key_exists($adminUsername, $createdUsers)) {
|
||||
$this->featureContext->userHasBeenCreated(["userName" => $adminUsername]);
|
||||
}
|
||||
} else {
|
||||
$adminUsername = $this->featureContext->getAdminUsername();
|
||||
}
|
||||
return $adminUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SimpleXMLElement $xml of the capabilities
|
||||
* @param string $capabilitiesApp the "app" name in the capabilities response
|
||||
* @param string $capabilitiesPath the path to the element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getParameterValueFromXml(
|
||||
SimpleXMLElement $xml,
|
||||
string $capabilitiesApp,
|
||||
string $capabilitiesPath
|
||||
): string {
|
||||
$path_to_element = \explode('@@@', $capabilitiesPath);
|
||||
$answeredValue = $xml->{$capabilitiesApp};
|
||||
foreach ($path_to_element as $element) {
|
||||
$nameIndexParts = \explode('[', $element);
|
||||
if (isset($nameIndexParts[1])) {
|
||||
// This part of the path should be something like "some_element[1]"
|
||||
// Separately extract the name and the index
|
||||
$name = $nameIndexParts[0];
|
||||
$index = (int) \explode(']', $nameIndexParts[1])[0];
|
||||
// and use those to construct the reference into the next XML level
|
||||
$answeredValue = $answeredValue->{$name}[$index];
|
||||
} else {
|
||||
if ($element !== "") {
|
||||
$answeredValue = $answeredValue->{$element};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (string) $answeredValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :username retrieves the capabilities using the capabilities API
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userRetrievesCapabilities(string $username): void {
|
||||
$user = $this->featureContext->getActualUsername($username);
|
||||
$this->featureContext->setResponse($this->userGetsCapabilities($user, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator retrieves the capabilities using the capabilities API
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorGetsCapabilities(): void {
|
||||
$user = $this->getAdminUsernameForCapabilitiesCheck();
|
||||
$this->featureContext->setResponse($this->userGetsCapabilities($user, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the major-minor-micro version data in the response should match the version string
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function checkVersionMajorMinorMicroResponse():void {
|
||||
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent();
|
||||
$versionData = $jsonResponse->ocs->data->version;
|
||||
$versionString = (string) $versionData->string;
|
||||
// We expect that versionString will be in a format like "10.9.2 beta" or "10.9.2-alpha" or "10.9.2"
|
||||
$result = \preg_match('/^[0-9]+\.[0-9]+\.[0-9]+/', $versionString, $matches);
|
||||
Assert::assertSame(
|
||||
1,
|
||||
$result,
|
||||
__METHOD__ . " version string '$versionString' does not start with a semver version"
|
||||
);
|
||||
// semVerParts should have an array with the 3 semver components of the version, e.g. "1", "9" and "2".
|
||||
$semVerParts = \explode('.', $matches[0]);
|
||||
$expectedMajor = $semVerParts[0];
|
||||
$expectedMinor = $semVerParts[1];
|
||||
$expectedMicro = $semVerParts[2];
|
||||
$actualMajor = (string) $versionData->major;
|
||||
$actualMinor = (string) $versionData->minor;
|
||||
$actualMicro = (string) $versionData->micro;
|
||||
Assert::assertSame(
|
||||
$expectedMajor,
|
||||
$actualMajor,
|
||||
__METHOD__ . "'major' data item does not match with major version in string '$versionString'"
|
||||
);
|
||||
Assert::assertSame(
|
||||
$expectedMinor,
|
||||
$actualMinor,
|
||||
__METHOD__ . "'minor' data item does not match with minor version in string '$versionString'"
|
||||
);
|
||||
Assert::assertSame(
|
||||
$expectedMicro,
|
||||
$actualMicro,
|
||||
__METHOD__ . "'micro' data item does not match with micro (patch) version in string '$versionString'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the status.php response should include
|
||||
*
|
||||
* @param PyStringNode $jsonExpected
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function statusPhpRespondedShouldMatch(PyStringNode $jsonExpected): void {
|
||||
$jsonExpectedDecoded = \json_decode($jsonExpected->getRaw(), true);
|
||||
$jsonRespondedDecoded = $this->featureContext->getJsonDecodedResponse();
|
||||
|
||||
$response = $this->userGetsCapabilities($this->getAdminUsernameForCapabilitiesCheck());
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
$responseXml = $this->featureContext->getResponseXml($response)->data->capabilities;
|
||||
$edition = $this->getParameterValueFromXml(
|
||||
$responseXml,
|
||||
'core',
|
||||
'status@@@edition'
|
||||
);
|
||||
|
||||
if (!\strlen($edition)) {
|
||||
Assert::fail(
|
||||
"Cannot get edition from core capabilities"
|
||||
);
|
||||
}
|
||||
|
||||
$product = $this->getParameterValueFromXml(
|
||||
$responseXml,
|
||||
'core',
|
||||
'status@@@product'
|
||||
);
|
||||
if (!\strlen($product)) {
|
||||
Assert::fail(
|
||||
"Cannot get product from core capabilities"
|
||||
);
|
||||
}
|
||||
|
||||
$productName = $this->getParameterValueFromXml(
|
||||
$responseXml,
|
||||
'core',
|
||||
'status@@@productname'
|
||||
);
|
||||
|
||||
if (!\strlen($productName)) {
|
||||
Assert::fail(
|
||||
"Cannot get productname from core capabilities"
|
||||
);
|
||||
}
|
||||
|
||||
$jsonExpectedDecoded['edition'] = $edition;
|
||||
$jsonExpectedDecoded['product'] = $product;
|
||||
$jsonExpectedDecoded['productname'] = $productName;
|
||||
|
||||
// We are on oCIS or reva or some other implementation. We cannot do "occ status".
|
||||
// So get the expected version values by looking in the capabilities response.
|
||||
$version = $this->getParameterValueFromXml(
|
||||
$responseXml,
|
||||
'core',
|
||||
'status@@@version'
|
||||
);
|
||||
|
||||
if (!\strlen($version)) {
|
||||
Assert::fail(
|
||||
"Cannot get version from core capabilities"
|
||||
);
|
||||
}
|
||||
|
||||
$versionString = $this->getParameterValueFromXml(
|
||||
$responseXml,
|
||||
'core',
|
||||
'status@@@versionstring'
|
||||
);
|
||||
|
||||
if (!\strlen($versionString)) {
|
||||
Assert::fail(
|
||||
"Cannot get versionstring from core capabilities"
|
||||
);
|
||||
}
|
||||
|
||||
$jsonExpectedDecoded['version'] = $version;
|
||||
$jsonExpectedDecoded['versionstring'] = $versionString;
|
||||
$errorMessage = "";
|
||||
$errorFound = false;
|
||||
foreach ($jsonExpectedDecoded as $key => $expectedValue) {
|
||||
if (\array_key_exists($key, $jsonRespondedDecoded)) {
|
||||
$actualValue = $jsonRespondedDecoded[$key];
|
||||
if ($actualValue !== $expectedValue) {
|
||||
$errorMessage .= "$key expected value was $expectedValue but actual value was $actualValue\n";
|
||||
$errorFound = true;
|
||||
}
|
||||
} else {
|
||||
$errorMessage .= "$key was not found in the status response\n";
|
||||
$errorFound = true;
|
||||
}
|
||||
}
|
||||
Assert::assertFalse($errorFound, $errorMessage);
|
||||
// We have checked that the status.php response has data that matches up with
|
||||
// data found in the capabilities response and/or the "occ status" command output.
|
||||
// But the output might be reported wrongly in all of these in the same way.
|
||||
// So check that the values also seem "reasonable".
|
||||
$version = $jsonExpectedDecoded['version'];
|
||||
$versionString = $jsonExpectedDecoded['versionstring'];
|
||||
Assert::assertMatchesRegularExpression(
|
||||
"/^\d+\.\d+\.\d+\.\d+$/",
|
||||
$version,
|
||||
"version should be in a form like 10.9.8.1 but is $version"
|
||||
);
|
||||
if (\preg_match("/^(\d+\.\d+\.\d+)\.\d+(-[0-9A-Za-z-]+)?(\+[0-9A-Za-z-]+)?$/", $version, $matches)) {
|
||||
// We should have matched something like 10.9.8 - the first 3 numbers in the version.
|
||||
// Ignore pre-releases and meta information
|
||||
Assert::assertArrayHasKey(
|
||||
1,
|
||||
$matches,
|
||||
"version $version could not match the pattern Major.Minor.Patch"
|
||||
);
|
||||
$majorMinorPatchVersion = $matches[1];
|
||||
} else {
|
||||
Assert::fail("version '$version' does not start in a form like 10.9.8");
|
||||
}
|
||||
Assert::assertStringStartsWith(
|
||||
$majorMinorPatchVersion,
|
||||
$versionString,
|
||||
"versionstring should start with $majorMinorPatchVersion but is $versionString"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,488 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* @author Roeland Jago Douma <rullzer@owncloud.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2018, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\WebDavHelper;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Checksum functions
|
||||
*/
|
||||
class ChecksumContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function uploadFileToWithChecksumUsingTheAPI(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $checksum
|
||||
):ResponseInterface {
|
||||
$file = \file_get_contents(
|
||||
$this->featureContext->acceptanceTestsDirLocation() . $source
|
||||
);
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
'PUT',
|
||||
$destination,
|
||||
['OC-Checksum' => $checksum],
|
||||
$file
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file :source to :destination with checksum :checksum using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUploadsFileToWithChecksumUsingTheAPI(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $checksum
|
||||
):void {
|
||||
$this->featureContext->setResponse($this->uploadFileToWithChecksumUsingTheAPI($user, $source, $destination, $checksum));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has uploaded file :source to :destination with checksum :checksum
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasUploadedFileToWithChecksumUsingTheAPI(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $checksum
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$response = $this->uploadFileToWithChecksumUsingTheAPI(
|
||||
$user,
|
||||
$source,
|
||||
$destination,
|
||||
$checksum
|
||||
);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe([201,204], '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $checksum
|
||||
* @param string $destination
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function uploadFileWithContentAndChecksumToUsingTheAPI(
|
||||
string $user,
|
||||
string $content,
|
||||
string $checksum,
|
||||
string $destination
|
||||
):ResponseInterface {
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
'PUT',
|
||||
$destination,
|
||||
['OC-Checksum' => $checksum],
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has uploaded file with content :content and checksum :checksum to :destination
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $checksum
|
||||
* @param string $destination
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasUploadedFileWithContentAndChecksumToUsingTheAPI(
|
||||
string $user,
|
||||
string $content,
|
||||
string $checksum,
|
||||
string $destination
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$response = $this->uploadFileWithContentAndChecksumToUsingTheAPI($user, $content, $checksum, $destination);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(201, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user requests the checksum of :path via propfind
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userRequestsTheChecksumOfViaPropfind(string $user, string $path):void {
|
||||
$this->featureContext->setResponse($this->propfindResourceChecksum($user, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function propfindResourceChecksum(string $user, string $path) : ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$body = '<?xml version="1.0"?>
|
||||
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||
<d:prop>
|
||||
<oc:checksums />
|
||||
</d:prop>
|
||||
</d:propfind>';
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
return WebDavHelper::makeDavRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$password,
|
||||
'PROPFIND',
|
||||
$path,
|
||||
null,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the webdav checksum should match :expectedChecksum
|
||||
*
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theWebdavChecksumShouldMatch(string $expectedChecksum):void {
|
||||
$bodyContents = $this->featureContext->getResponse()->getBody()->getContents();
|
||||
$this->validateChecksum($bodyContents, $expectedChecksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then as user :user the webdav checksum of :path via propfind should match :expectedChecksum
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function asUserTheWebdavChecksumOfPathViaPropfindShouldMatch(string $user, string $path, string $expectedChecksum):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$resource = $this->propfindResourceChecksum($user, $path);
|
||||
$bodyContents = $resource->getBody()->getContents();
|
||||
$this->validateChecksum($bodyContents, $expectedChecksum);
|
||||
}
|
||||
/**
|
||||
* @param string $bodyContents
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validateChecksum(string $bodyContents, string $expectedChecksum):void {
|
||||
$service = new Sabre\Xml\Service();
|
||||
$parsed = $service->parse($bodyContents);
|
||||
|
||||
/*
|
||||
* Fetch the checksum array
|
||||
* The checksums are way down in the array:
|
||||
* $checksums = $parsed[0]['value'][1]['value'][0]['value'][0];
|
||||
* And inside is the actual checksum string:
|
||||
* $checksums['value'][0]['value']
|
||||
* The Asserts below check the existence of the expected key at every level
|
||||
* of the nested array. This helps to see what happened if a test fails
|
||||
* because the response structure is not as expected.
|
||||
*/
|
||||
|
||||
Assert::assertIsArray(
|
||||
$parsed,
|
||||
__METHOD__ . " could not parse response as XML. Expected parsed XML to be an array but found " . $bodyContents
|
||||
);
|
||||
Assert::assertArrayHasKey(
|
||||
0,
|
||||
$parsed,
|
||||
__METHOD__ . " parsed XML does not have key 0"
|
||||
);
|
||||
$parsed0 = $parsed[0];
|
||||
Assert::assertArrayHasKey(
|
||||
'value',
|
||||
$parsed0,
|
||||
__METHOD__ . " parsed XML parsed0 does not have key value"
|
||||
);
|
||||
$parsed0Value = $parsed0['value'];
|
||||
Assert::assertArrayHasKey(
|
||||
1,
|
||||
$parsed0Value,
|
||||
__METHOD__ . " parsed XML parsed0Value does not have key 1"
|
||||
);
|
||||
$parsed0Value1 = $parsed0Value[1];
|
||||
Assert::assertArrayHasKey(
|
||||
'value',
|
||||
$parsed0Value1,
|
||||
__METHOD__ . " parsed XML parsed0Value1 does not have key value after key 1"
|
||||
);
|
||||
$parsed0Value1Value = $parsed0Value1['value'];
|
||||
Assert::assertArrayHasKey(
|
||||
0,
|
||||
$parsed0Value1Value,
|
||||
__METHOD__ . " parsed XML parsed0Value1Value does not have key 0"
|
||||
);
|
||||
$parsed0Value1Value0 = $parsed0Value1Value[0];
|
||||
Assert::assertArrayHasKey(
|
||||
'value',
|
||||
$parsed0Value1Value0,
|
||||
__METHOD__ . " parsed XML parsed0Value1Value0 does not have key value"
|
||||
);
|
||||
$parsed0Value1Value0Value = $parsed0Value1Value0['value'];
|
||||
Assert::assertArrayHasKey(
|
||||
0,
|
||||
$parsed0Value1Value0Value,
|
||||
__METHOD__ . " parsed XML parsed0Value1Value0Value does not have key 0"
|
||||
);
|
||||
$checksums = $parsed0Value1Value0Value[0];
|
||||
Assert::assertArrayHasKey(
|
||||
'value',
|
||||
$checksums,
|
||||
__METHOD__ . " parsed XML checksums does not have key value"
|
||||
);
|
||||
$checksumsValue = $checksums['value'];
|
||||
Assert::assertArrayHasKey(
|
||||
0,
|
||||
$checksumsValue,
|
||||
__METHOD__ . " parsed XML checksumsValue does not have key 0"
|
||||
);
|
||||
$checksumsValue0 = $checksumsValue[0];
|
||||
Assert::assertArrayHasKey(
|
||||
'value',
|
||||
$checksumsValue0,
|
||||
__METHOD__ . " parsed XML checksumsValue0 does not have key value"
|
||||
);
|
||||
$actualChecksum = $checksumsValue0['value'];
|
||||
Assert::assertEquals(
|
||||
$expectedChecksum,
|
||||
$actualChecksum,
|
||||
"Expected: webDav checksum should be $expectedChecksum but got $actualChecksum"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the header checksum should match :expectedChecksum
|
||||
*
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theHeaderChecksumShouldMatch(string $expectedChecksum):void {
|
||||
$headerChecksums
|
||||
= $this->featureContext->getResponse()->getHeader('OC-Checksum');
|
||||
|
||||
Assert::assertIsArray(
|
||||
$headerChecksums,
|
||||
__METHOD__ . " getHeader('OC-Checksum') did not return an array"
|
||||
);
|
||||
|
||||
Assert::assertNotEmpty(
|
||||
$headerChecksums,
|
||||
__METHOD__ . " getHeader('OC-Checksum') returned an empty array. No checksum header was found."
|
||||
);
|
||||
|
||||
$checksumCount = \count($headerChecksums);
|
||||
|
||||
Assert::assertTrue(
|
||||
$checksumCount === 1,
|
||||
__METHOD__ . " Expected 1 checksum in the header but found $checksumCount checksums"
|
||||
);
|
||||
|
||||
$headerChecksum
|
||||
= $headerChecksums[0];
|
||||
Assert::assertEquals(
|
||||
$expectedChecksum,
|
||||
$headerChecksum,
|
||||
"Expected: header checksum should match $expectedChecksum but got $headerChecksum"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the header checksum when user :arg1 downloads file :arg2 using the WebDAV API should match :arg3
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileName
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theHeaderChecksumWhenUserDownloadsFileUsingTheWebdavApiShouldMatch(string $user, string $fileName, string $expectedChecksum):void {
|
||||
$response = $this->featureContext->downloadFileAsUserUsingPassword($user, $fileName);
|
||||
$headerChecksums = $response->getHeader('OC-Checksum');
|
||||
|
||||
Assert::assertIsArray(
|
||||
$headerChecksums,
|
||||
__METHOD__ . " getHeader('OC-Checksum') did not return an array"
|
||||
);
|
||||
|
||||
Assert::assertNotEmpty(
|
||||
$headerChecksums,
|
||||
__METHOD__ . " getHeader('OC-Checksum') returned an empty array. No checksum header was found."
|
||||
);
|
||||
|
||||
$checksumCount = \count($headerChecksums);
|
||||
|
||||
Assert::assertTrue(
|
||||
$checksumCount === 1,
|
||||
__METHOD__ . " Expected 1 checksum in the header but found $checksumCount checksums"
|
||||
);
|
||||
|
||||
$headerChecksum
|
||||
= $headerChecksums[0];
|
||||
Assert::assertEquals(
|
||||
$expectedChecksum,
|
||||
$headerChecksum,
|
||||
"Expected: header checksum should match $expectedChecksum but got $headerChecksum"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param int $num
|
||||
* @param int $total
|
||||
* @param string $data
|
||||
* @param string $destination
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function uploadChunkFileOfWithToWithChecksum(
|
||||
string $user,
|
||||
int $num,
|
||||
int $total,
|
||||
string $data,
|
||||
string $destination,
|
||||
string $expectedChecksum
|
||||
):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$num -= 1;
|
||||
$file = "$destination-chunking-42-$total-$num";
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
'PUT',
|
||||
$file,
|
||||
['OC-Checksum' => $expectedChecksum, 'OC-Chunked' => '1'],
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads chunk file :num of :total with :data to :destination with checksum :expectedChecksum using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $num
|
||||
* @param int $total
|
||||
* @param string $data
|
||||
* @param string $destination
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUploadsChunkFileOfWithToWithChecksum(
|
||||
string $user,
|
||||
int $num,
|
||||
int $total,
|
||||
string $data,
|
||||
string $destination,
|
||||
string $expectedChecksum
|
||||
):void {
|
||||
$response = $this->uploadChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination, $expectedChecksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has uploaded chunk file :num of :total with :data to :destination with checksum :expectedChecksum
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $num
|
||||
* @param int $total
|
||||
* @param string $data
|
||||
* @param string $destination
|
||||
* @param string $expectedChecksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasUploadedChunkFileOfWithToWithChecksum(
|
||||
string $user,
|
||||
int $num,
|
||||
int $total,
|
||||
string $data,
|
||||
string $destination,
|
||||
string $expectedChecksum
|
||||
):void {
|
||||
$response = $this->uploadChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination, $expectedChecksum);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(
|
||||
[201, 206],
|
||||
'',
|
||||
$response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Sajan Gurung <sajan@jankaritech.com>
|
||||
* @copyright Copyright (c) 2024 Sajan Gurung sajan@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Behat\Context\Context;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\CliHelper;
|
||||
use TestHelpers\OcisConfigHelper;
|
||||
|
||||
/**
|
||||
* CLI context
|
||||
*/
|
||||
class CliContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private SpacesContext $spacesContext;
|
||||
|
||||
/**
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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');
|
||||
$this->spacesContext = $environment->getContext('SpacesContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the administrator has stopped the server
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorHasStoppedTheServer(): void {
|
||||
$response = OcisConfigHelper::stopOcis();
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^the administrator (?:starts|has started) the server$/
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorHasStartedTheServer(): void {
|
||||
$response = OcisConfigHelper::startOcis();
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the administrator resets the password of (non-existing|existing) user "([^"]*)" to "([^"]*)" using the CLI$/
|
||||
*
|
||||
* @param string $status
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorResetsThePasswordOfUserUsingTheCLI(string $status, string $user, string $password): void {
|
||||
$command = "idm resetpassword -u $user";
|
||||
$body = [
|
||||
"command" => $command,
|
||||
"inputs" => [$password, $password]
|
||||
];
|
||||
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
if ($status === "non-existing") {
|
||||
return;
|
||||
}
|
||||
$this->featureContext->updateUserPassword($user, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator deletes the empty trashbin folders using the CLI
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorDeletesEmptyTrashbinFoldersUsingTheCli():void {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "trash purge-empty-dirs -p $path --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator checks the backup consistency using the CLI
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorChecksTheBackupConsistencyUsingTheCli():void {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "backup consistency -p $path";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator removes all the file versions using the CLI
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorRemovesAllVersionsOfResources() {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$command = "revisions purge -p $path --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator removes the versions of file :file of user :user from space :space using the CLI
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $user
|
||||
* @param string $space
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorRemovesTheVersionsOfFileUsingFileId($file, $user, $space) {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$fileId = $this->spacesContext->getFileId($user, $space, $file);
|
||||
$command = "revisions purge -p $path -r $fileId --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the administrator reindexes all spaces using the CLI$/
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorReindexesAllSpacesUsingTheCli(): void {
|
||||
$command = "search index --all-spaces";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the administrator reindexes a space "([^"]*)" using the CLI$/
|
||||
*
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorReindexesASpaceUsingTheCli(string $spaceName): void {
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($this->featureContext->getAdminUsername(), $spaceName);
|
||||
$command = "search index --space $spaceId";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator removes the file versions of space :space using the CLI
|
||||
*
|
||||
* @param string $space
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorRemovesTheVersionsOfFilesInSpaceUsingSpaceId(string $space):void {
|
||||
$path = $this->featureContext->getStorageUsersRoot();
|
||||
$adminUsername = $this->featureContext->getAdminUsername();
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($adminUsername, $space);
|
||||
$command = "revisions purge -p $path -r $spaceId --dry-run=false";
|
||||
$body = [
|
||||
"command" => $command
|
||||
];
|
||||
$this->featureContext->setResponse(CliHelper::runCommand($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the command should be successful
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theCommandShouldBeSuccessful(): void {
|
||||
$response = $this->featureContext->getResponse();
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
|
||||
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
||||
|
||||
Assert::assertSame("OK", $jsonResponse["status"]);
|
||||
Assert::assertSame(0, $jsonResponse["exitCode"], "Expected exit code to be 0, but got " . $jsonResponse["exitCode"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the command output (should|should not) contain "([^"]*)"$/
|
||||
*
|
||||
* @param string $shouldOrNot
|
||||
* @param string $output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theCommandOutputShouldContain(string $shouldOrNot, string $output): void {
|
||||
$response = $this->featureContext->getResponse();
|
||||
$jsonResponse = $this->featureContext->getJsonDecodedResponse($response);
|
||||
$output = $this->featureContext->substituteInLineCodes($output);
|
||||
|
||||
if ($shouldOrNot === "should") {
|
||||
Assert::assertStringContainsString($output, $jsonResponse["message"]);
|
||||
} else {
|
||||
Assert::assertStringNotContainsString($output, $jsonResponse["message"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018 Artur Neumann artur@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\WebDavHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* context containing favorites related API steps
|
||||
*/
|
||||
class FavoritesContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private WebDavPropertiesContext $webDavPropertiesContext;
|
||||
|
||||
/**
|
||||
* @param string$user
|
||||
* @param string $path
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function userFavoritesElement(string $user, string $path):ResponseInterface {
|
||||
return $this->changeFavStateOfAnElement(
|
||||
$user,
|
||||
$path,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user favorites element :path using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userFavoritesElementUsingWebDavApi(string $user, string $path):void {
|
||||
$this->featureContext->setResponse($this->userFavoritesElement($user, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has favorited element :path
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasFavoritedElementUsingWebDavApi(string $user, string $path):void {
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(207, '', $this->userFavoritesElement($user, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function userUnfavoritesElement(string $user, string $path):ResponseInterface {
|
||||
return $this->changeFavStateOfAnElement(
|
||||
$user,
|
||||
$path,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unfavorites element :path using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUnfavoritesElementUsingWebDavApi(string $user, string $path):void {
|
||||
$this->featureContext->setResponse($this->userUnfavoritesElement($user, $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^user "([^"]*)" should (not|)\s?have the following favorited items$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $shouldOrNot (not|)
|
||||
* @param TableNode $expectedElements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function checkFavoritedElements(
|
||||
string $user,
|
||||
string $shouldOrNot,
|
||||
TableNode $expectedElements
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->userListsFavorites($user);
|
||||
$this->featureContext->propfindResultShouldContainEntries(
|
||||
$shouldOrNot,
|
||||
$expectedElements,
|
||||
$user
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" lists the favorites and limits the result to ([\d*]) elements using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param int|null $limit
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userListsFavorites(string $user, ?int $limit = null):void {
|
||||
$renamedUser = $this->featureContext->getActualUsername($user);
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
$body
|
||||
= "<?xml version='1.0' encoding='utf-8' ?>\n" .
|
||||
" <oc:filter-files xmlns:a='DAV:' xmlns:oc='http://owncloud.org/ns' >\n" .
|
||||
" <a:prop><oc:favorite/></a:prop>\n" .
|
||||
" <oc:filter-rules><oc:favorite>1</oc:favorite></oc:filter-rules>\n";
|
||||
|
||||
if ($limit !== null) {
|
||||
$body .= " <oc:search>\n" .
|
||||
" <oc:limit>$limit</oc:limit>\n" .
|
||||
" </oc:search>\n";
|
||||
}
|
||||
|
||||
$body .= " </oc:filter-files>";
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$renamedUser,
|
||||
$password,
|
||||
"REPORT",
|
||||
"/",
|
||||
null,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion()
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^as user "([^"]*)" (?:file|folder|entry) "([^"]*)" should be favorited$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
* @param integer $expectedValue 0|1
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function asUserFileOrFolderShouldBeFavorited(string $user, string $path, int $expectedValue = 1):void {
|
||||
$property = "oc:favorite";
|
||||
$this->webDavPropertiesContext->checkPropertyOfAFolder(
|
||||
$user,
|
||||
$path,
|
||||
$property,
|
||||
(string)$expectedValue
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^as user "([^"]*)" (?:file|folder|entry) "([^"]*)" should not be favorited$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function asUserFileShouldNotBeFavorited(string $user, string $path):void {
|
||||
$this->asUserFileOrFolderShouldBeFavorited($user, $path, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the elements of a proppatch
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
* @param int|null $favOrUnfav 1 = favorite, 0 = unfavorite
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function changeFavStateOfAnElement(
|
||||
string $user,
|
||||
string $path,
|
||||
?int $favOrUnfav
|
||||
):ResponseInterface {
|
||||
$renamedUser = $this->featureContext->getActualUsername($user);
|
||||
return WebDavHelper::proppatch(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$renamedUser,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$path,
|
||||
'favorite',
|
||||
(string)$favOrUnfav,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
"oc='http://owncloud.org/ns'",
|
||||
$this->featureContext->getDavPathVersion()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->webDavPropertiesContext = $environment->getContext(
|
||||
'WebDavPropertiesContext'
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,541 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018, ownCloud GmbH
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use TestHelpers\WebDavHelper;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Steps that relate to files_versions app
|
||||
*/
|
||||
class FilesVersionsContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @param string $fileId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getVersionsPathForFileId(string $fileId):string {
|
||||
return "/meta/$fileId/v";
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user tries to get versions of file :file from :fileOwner
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $fileOwner
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userTriesToGetFileVersions(string $user, string $file, string $fileOwner):void {
|
||||
$this->featureContext->setResponse($this->getFileVersions($user, $file, $fileOwner));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user gets the number of versions of file :file
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userGetsFileVersions(string $user, string $file):void {
|
||||
$this->featureContext->setResponse($this->getFileVersions($user, $file));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string|null $fileOwner
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws JsonException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function getFileVersions(
|
||||
string $user,
|
||||
string $file,
|
||||
?string $fileOwner = null
|
||||
): ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileOwner = $fileOwner ? $this->featureContext->getActualUsername($fileOwner) : $user;
|
||||
$fileId = $this->featureContext->getFileIdForPath($fileOwner, $file);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " fileid of file $file user $fileOwner not found (the file may not exist)");
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"PROPFIND",
|
||||
$this->getVersionsPathForFileId($fileId),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'2'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user gets the number of versions of file :resource using file-id path :endpoint
|
||||
* @When user :user tries to get the number of versions of file :resource using file-id path :endpoint
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $endpoint
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userGetsTheNumberOfVersionsOfFileOfTheSpace(string $user, string $endpoint):void {
|
||||
$this->featureContext->setResponse(
|
||||
$this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"PROPFIND",
|
||||
$endpoint,
|
||||
null,
|
||||
null,
|
||||
"versions",
|
||||
(string)$this->featureContext->getDavPathVersion()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user gets the version metadata of file :file
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userGetsVersionMetadataOfFile(string $user, string $file):void {
|
||||
$response = $this->getFileVersionMetadata($user, $file);
|
||||
$this->featureContext->setResponse($response, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function getFileVersionMetadata(string $user, string $file) : ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $file);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " fileid of file $file user $user not found (the file may not exist)");
|
||||
$body = '<?xml version="1.0"?>
|
||||
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||
<d:prop>
|
||||
<oc:meta-version-edited-by />
|
||||
<oc:meta-version-edited-by-name />
|
||||
</d:prop>
|
||||
</d:propfind>';
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"PROPFIND",
|
||||
$this->getVersionsPathForFileId($fileId),
|
||||
null,
|
||||
$body,
|
||||
null,
|
||||
'2'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param int $versionIndex
|
||||
* @param string $path
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function restoreVersionIndexOfFile(string $user, int $versionIndex, string $path):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $path);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " fileid of file $path user $user not found (the file may not exist)");
|
||||
$response = $this->listVersionFolder($user, $fileId, 1);
|
||||
$responseXml = HttpRequestHelper::getResponseXml(
|
||||
$response,
|
||||
__METHOD__
|
||||
);
|
||||
$xmlPart = $responseXml->xpath("//d:response/d:href");
|
||||
//restoring the version only works with DAV path v2
|
||||
$destinationUrl = $this->featureContext->getBaseUrl() . "/" .
|
||||
WebDavHelper::getDavPath($user, 2) . \trim($path, "/");
|
||||
$fullUrl = $this->featureContext->getBaseUrlWithoutPath() .
|
||||
$xmlPart[$versionIndex];
|
||||
return HttpRequestHelper::sendRequest(
|
||||
$fullUrl,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
'COPY',
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
['Destination' => $destinationUrl]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has restored version index :versionIndex of file :path
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $versionIndex
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userHasRestoredVersionIndexOfFile(string $user, int $versionIndex, string $path):void {
|
||||
$response = $this->restoreVersionIndexOfFile($user, $versionIndex, $path);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user restores version index :versionIndex of file :path using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $versionIndex
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRestoresVersionIndexOfFile(string $user, int $versionIndex, string $path):void {
|
||||
$response = $this->restoreVersionIndexOfFile($user, $versionIndex, $path);
|
||||
$this->featureContext->setResponse($response, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* assert file versions count
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileId
|
||||
* @param int $expectedCount
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function assertFileVersionsCount(string $user, string $fileId, int $expectedCount):void {
|
||||
$response = $this->listVersionFolder($user, $fileId, 1);
|
||||
$responseXml = HttpRequestHelper::getResponseXml(
|
||||
$response,
|
||||
__METHOD__
|
||||
);
|
||||
$actualCount = \count($responseXml->xpath("//d:prop/d:getetag")) - 1;
|
||||
if ($actualCount === -1) {
|
||||
$actualCount = 0;
|
||||
}
|
||||
Assert::assertEquals(
|
||||
$expectedCount,
|
||||
$actualCount,
|
||||
"Expected $expectedCount versions but found $actualCount in \n" . $responseXml->asXML()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the version folder of file :path for user :user should contain :count element(s)
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $user
|
||||
* @param int $count
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theVersionFolderOfFileShouldContainElements(
|
||||
string $path,
|
||||
string $user,
|
||||
int $count
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $path);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " file '$path' for user '$user' not found (the file may not exist)");
|
||||
$this->assertFileVersionsCount($user, $fileId, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the version folder of fileId :fileId for user :user should contain :count element(s)
|
||||
*
|
||||
* @param string $fileId
|
||||
* @param string $user
|
||||
* @param int $count
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theVersionFolderOfFileIdShouldContainElements(
|
||||
string $fileId,
|
||||
string $user,
|
||||
int $count
|
||||
):void {
|
||||
$this->assertFileVersionsCount($user, $fileId, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the content length of file :path with version index :index for user :user in versions folder should be :length
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $index
|
||||
* @param string $user
|
||||
* @param int $length
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theContentLengthOfFileForUserInVersionsFolderIs(
|
||||
string $path,
|
||||
int $index,
|
||||
string $user,
|
||||
int $length
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $path);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " fileid of file $path user $user not found (the file may not exist)");
|
||||
$response = $this->listVersionFolder($user, $fileId, 1, ['d:getcontentlength']);
|
||||
$responseXml = HttpRequestHelper::getResponseXml(
|
||||
$response,
|
||||
__METHOD__
|
||||
);
|
||||
$xmlPart = $responseXml->xpath("//d:prop/d:getcontentlength");
|
||||
Assert::assertEquals(
|
||||
$length,
|
||||
(int) $xmlPart[$index],
|
||||
"The content length of file $path with version $index for user $user was
|
||||
expected to be $length but the actual content length is $xmlPart[$index]"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^as (?:users|user) "([^"]*)" the authors of the versions of file "([^"]*)" should be:$/
|
||||
*
|
||||
* @param string $users comma-separated list of usernames
|
||||
* @param string $filename
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function asUsersAuthorsOfVersionsOfFileShouldBe(
|
||||
string $users,
|
||||
string $filename,
|
||||
TableNode $table
|
||||
): void {
|
||||
$this->featureContext->verifyTableNodeColumns(
|
||||
$table,
|
||||
['index', 'author']
|
||||
);
|
||||
$requiredVersionMetadata = $table->getHash();
|
||||
$usersArray = \explode(",", $users);
|
||||
foreach ($usersArray as $username) {
|
||||
$actualUsername = $this->featureContext->getActualUsername($username);
|
||||
$this->featureContext->setResponse(
|
||||
$this->getFileVersionMetadata($actualUsername, $filename)
|
||||
);
|
||||
foreach ($requiredVersionMetadata as $versionMetadata) {
|
||||
$this->featureContext->checkAuthorOfAVersionOfFile(
|
||||
$versionMetadata['index'],
|
||||
$versionMetadata['author']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
* @param string $index
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function downloadVersion(string $user, string $path, string $index):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $path);
|
||||
Assert::assertNotNull($fileId, __METHOD__ . " fileid of file $path user $user not found (the file may not exist)");
|
||||
$index = (int)$index;
|
||||
$response = $this->listVersionFolder($user, $fileId, 1);
|
||||
if ($response->getStatusCode() === 403) {
|
||||
return $response;
|
||||
}
|
||||
$responseXml = new SimpleXMLElement($response->getBody()->getContents());
|
||||
$xmlPart = $responseXml->xpath("//d:response/d:href");
|
||||
if (!isset($xmlPart[$index])) {
|
||||
Assert::fail(
|
||||
'could not find version of path "' . $path . '" with index "' . $index . '"'
|
||||
);
|
||||
}
|
||||
// the href already contains the path
|
||||
$url = WebDavHelper::sanitizeUrl(
|
||||
$this->featureContext->getBaseUrlWithoutPath() . $xmlPart[$index]
|
||||
);
|
||||
return HttpRequestHelper::get(
|
||||
$url,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user downloads the version of file :path with the index :index
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $path
|
||||
* @param string $index
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userDownloadsVersion(string $user, string $path, string $index):void {
|
||||
$this->featureContext->setResponse($this->downloadVersion($user, $path, $index), $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the content of version index "([^"]*)" of file "([^"]*)" for user "([^"]*)" should be "([^"]*)"$/
|
||||
*
|
||||
* @param string $index
|
||||
* @param string $path
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theContentOfVersionIndexOfFileForUserShouldBe(
|
||||
string $index,
|
||||
string $path,
|
||||
string $user,
|
||||
string $content
|
||||
): void {
|
||||
$response = $this->downloadVersion($user, $path, $index);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe("200", '', $response);
|
||||
$this->featureContext->checkDownloadedContentMatches($content, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" retrieves the meta information of (file|fileId) "([^"]*)" using the meta API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileOrFileId
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userGetMetaInfo(string $user, string $fileOrFileId, string $path):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
|
||||
if ($fileOrFileId === "file") {
|
||||
$fileId = $this->featureContext->getFileIdForPath($user, $path);
|
||||
$metaPath = "/meta/$fileId/";
|
||||
} else {
|
||||
$metaPath = "/meta/$path/";
|
||||
}
|
||||
|
||||
$body = '<?xml version="1.0" encoding="utf-8"?>
|
||||
<a:propfind xmlns:a="DAV:" xmlns:oc="http://owncloud.org/ns">
|
||||
<a:prop>
|
||||
<oc:meta-path-for-user />
|
||||
</a:prop>
|
||||
</a:propfind>';
|
||||
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$user,
|
||||
$password,
|
||||
"PROPFIND",
|
||||
$metaPath,
|
||||
['Content-Type' => 'text/xml','Depth' => '0'],
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion(),
|
||||
null
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$responseXml = HttpRequestHelper::getResponseXml(
|
||||
$response,
|
||||
__METHOD__
|
||||
);
|
||||
$this->featureContext->setResponseXmlObject($responseXml);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the result parsed into a SimpleXMLElement
|
||||
* with a registered namespace with 'd' as prefix and 'DAV:' as namespace
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileId
|
||||
* @param int $folderDepth
|
||||
* @param string[]|null $properties
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listVersionFolder(
|
||||
string $user,
|
||||
string $fileId,
|
||||
int $folderDepth,
|
||||
?array $properties = null
|
||||
):ResponseInterface {
|
||||
if (!$properties) {
|
||||
$properties = [
|
||||
'd:getetag'
|
||||
];
|
||||
}
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
$response = WebDavHelper::propfind(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$password,
|
||||
$this->getVersionsPathForFileId($fileId),
|
||||
$properties,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
(string) $folderDepth,
|
||||
"versions"
|
||||
);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,656 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Viktor Scharf <vscharf@owncloud.com>
|
||||
* @copyright Copyright (c) 2023 Viktor Scharf vscharf@owncloud.com
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use TestHelpers\OcsApiHelper;
|
||||
use Behat\Gherkin\Node\PyStringNode;
|
||||
use TestHelpers\EmailHelper;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\GraphHelper;
|
||||
use TestHelpers\SettingsHelper;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Defines application features from the specific context.
|
||||
*/
|
||||
class NotificationContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private SpacesContext $spacesContext;
|
||||
private SettingsContext $settingsContext;
|
||||
private string $notificationEndpointPath = '/apps/notifications/api/v1/notifications?format=json';
|
||||
private string $globalNotificationEndpointPath = '/apps/notifications/api/v1/notifications/global';
|
||||
|
||||
private array $notificationIds;
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function getNotificationIds():array {
|
||||
return $this->notificationIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function getLastNotificationId():array {
|
||||
return \end($this->notificationIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @AfterScenario
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteDeprovisioningNotification(): void {
|
||||
$payload["ids"] = ["deprovision"];
|
||||
|
||||
OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$this->featureContext->getAdminPassword(),
|
||||
'DELETE',
|
||||
$this->globalNotificationEndpointPath,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
json_encode($payload)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $userRecipient;
|
||||
|
||||
/**
|
||||
* @param string $userRecipient
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUserRecipient(string $userRecipient): void {
|
||||
$this->userRecipient = $userRecipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUserRecipient(): string {
|
||||
return $this->userRecipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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');
|
||||
$this->spacesContext = $environment->getContext('SpacesContext');
|
||||
$this->settingsContext = $environment->getContext('SettingsContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function listAllNotifications(string $user):ResponseInterface {
|
||||
$this->setUserRecipient($user);
|
||||
$language = SettingsHelper::getLanguageSettingValue(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef()
|
||||
);
|
||||
$headers = ["accept-language" => $language];
|
||||
return OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
'GET',
|
||||
$this->notificationEndpointPath,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
[],
|
||||
2,
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" lists all notifications$/
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userListAllNotifications(string $user):void {
|
||||
$response = $this->listAllNotifications($user);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastHttpStatusCodesArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function deleteAllNotifications(string $user):ResponseInterface {
|
||||
$response = $this->listAllNotifications($user);
|
||||
if (isset($this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data)) {
|
||||
$responseBody = $this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data;
|
||||
foreach ($responseBody as $value) {
|
||||
// set notificationId
|
||||
$this->notificationIds[] = $value->notification_id;
|
||||
}
|
||||
}
|
||||
return $this->userDeletesNotification($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user deletes all notifications
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userDeletesAllNotifications(string $user):void {
|
||||
$response = $this->deleteAllNotifications($user);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has deleted all notifications
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userHasDeletedAllNotifications(string $user):void {
|
||||
$response = $this->deleteAllNotifications($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user deletes a notification related to resource :resource with subject :subject
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $resource
|
||||
* @param string $subject
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userDeletesNotificationOfResourceAndSubject(string $user, string $resource, string $subject):void {
|
||||
$response = $this->listAllNotifications($user);
|
||||
$this->filterResponseByNotificationSubjectAndResource($subject, $resource, $response);
|
||||
$this->featureContext->setResponse($this->userDeletesNotification($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes notification
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userDeletesNotification(string $user):ResponseInterface {
|
||||
$this->setUserRecipient($user);
|
||||
$payload["ids"] = $this->getNotificationIds();
|
||||
return OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
'DELETE',
|
||||
$this->notificationEndpointPath,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
\json_encode($payload),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the notifications should be empty
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theNotificationsShouldBeEmpty(): void {
|
||||
$statusCode = $this->featureContext->getResponse()->getStatusCode();
|
||||
if ($statusCode !== 200) {
|
||||
$response = $this->featureContext->getResponse()->getBody()->getContents();
|
||||
throw new \Exception(
|
||||
__METHOD__
|
||||
. " Failed to get user notification list" . $response
|
||||
);
|
||||
}
|
||||
$notifications = $this->featureContext->getJsonDecodedResponseBodyContent()->ocs->data;
|
||||
Assert::assertNull($notifications, "response should not contain any notification");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then user :user should not have any notification
|
||||
*
|
||||
* @param $user
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldNotHaveAnyNotification($user): void {
|
||||
$response = $this->listAllNotifications($user);
|
||||
$notifications = $this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data;
|
||||
Assert::assertNull($notifications, "response should not contain any notification");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^there should be "([^"]*)" notifications$/
|
||||
*
|
||||
* @param int $numberOfNotification
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldHaveNotifications(int $numberOfNotification): void {
|
||||
if (!isset($this->featureContext->getJsonDecodedResponseBodyContent()->ocs->data)) {
|
||||
throw new Exception("Notification is empty");
|
||||
}
|
||||
$responseBody = $this->featureContext->getJsonDecodedResponseBodyContent()->ocs->data;
|
||||
$actualNumber = \count($responseBody);
|
||||
Assert::assertEquals(
|
||||
$numberOfNotification,
|
||||
$actualNumber,
|
||||
"Expected number of notifications was '$numberOfNotification', but got '$actualNumber'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the JSON response should contain a notification message with the subject "([^"]*)" and the message-details should match$/
|
||||
*
|
||||
* @param string $subject
|
||||
* @param PyStringNode $schemaString
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theJsonDataFromLastResponseShouldMatch(
|
||||
string $subject,
|
||||
PyStringNode $schemaString
|
||||
): void {
|
||||
$responseBody = $this->filterResponseAccordingToNotificationSubject($subject);
|
||||
// substitute the value here
|
||||
$schemaString = $schemaString->getRaw();
|
||||
$schemaString = $this->featureContext->substituteInLineCodes(
|
||||
$schemaString,
|
||||
$this->featureContext->getCurrentUser(),
|
||||
[],
|
||||
[],
|
||||
null,
|
||||
$this->getUserRecipient(),
|
||||
);
|
||||
$this->featureContext->assertJsonDocumentMatchesSchema(
|
||||
$responseBody,
|
||||
$this->featureContext->getJSONSchema($schemaString)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* filter notification according to subject
|
||||
*
|
||||
* @param string $subject
|
||||
* @param ResponseInterface|null $response
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function filterResponseAccordingToNotificationSubject(string $subject, ?ResponseInterface $response = null): object {
|
||||
$response = $response ?? $this->featureContext->getResponse();
|
||||
if (isset($this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data)) {
|
||||
$responseBody = $this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data;
|
||||
foreach ($responseBody as $value) {
|
||||
if (isset($value->subject) && $value->subject === $subject) {
|
||||
$responseBody = $value;
|
||||
// set notificationId
|
||||
$this->notificationIds[] = $value->notification_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$responseBody = $this->featureContext->getJsonDecodedResponseBodyContent($response);
|
||||
}
|
||||
return $responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* filter notification according to subject and resource
|
||||
*
|
||||
* @param string $subject
|
||||
* @param string $resource
|
||||
* @param ResponseInterface|null $response
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filterResponseByNotificationSubjectAndResource(string $subject, string $resource, ?ResponseInterface $response = null): array {
|
||||
$responseBodyArray = [];
|
||||
$response = $response ?? $this->featureContext->getResponse();
|
||||
$statusCode = $response->getStatusCode();
|
||||
if ($statusCode !== 200) {
|
||||
$response = $response->getBody()->getContents();
|
||||
Assert::fail($response . " Response should contain status code 200");
|
||||
}
|
||||
if (isset($this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data)) {
|
||||
$responseBody = $this->featureContext->getJsonDecodedResponseBodyContent($response)->ocs->data;
|
||||
foreach ($responseBody as $value) {
|
||||
if (isset($value->subject) && $value->subject === $subject && isset($value->messageRichParameters->resource->name) && $value->messageRichParameters->resource->name === $resource) {
|
||||
$this->notificationIds[] = $value->notification_id;
|
||||
$responseBodyArray[] = $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$responseBodyArray[] = $this->featureContext->getJsonDecodedResponseBodyContent($response);
|
||||
Assert::fail("Response should contain notification but found: " . print_r($responseBodyArray, true));
|
||||
}
|
||||
return $responseBodyArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^user "([^"]*)" should (?:get|have) a notification with subject "([^"]*)" and message:$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $subject
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldGetANotificationWithMessage(string $user, string $subject, TableNode $table):void {
|
||||
$count = 0;
|
||||
// Sometimes the test might try to get the notifications before the server has created the notification.
|
||||
// To prevent the test from failing because of that, try to list the notifications again
|
||||
do {
|
||||
if ($count > 0) {
|
||||
\sleep(1);
|
||||
}
|
||||
$this->featureContext->setResponse(null);
|
||||
$response = $this->listAllNotifications($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, "", $response);
|
||||
++$count;
|
||||
} while (!isset($this->filterResponseAccordingToNotificationSubject($subject, $response)->message) && $count <= 5);
|
||||
if (isset($this->filterResponseAccordingToNotificationSubject($subject, $response)->message)) {
|
||||
$actualMessage = str_replace(["\r", "\n"], " ", $this->filterResponseAccordingToNotificationSubject($subject, $response)->message);
|
||||
} else {
|
||||
throw new \Exception("Notification was not found even after retrying for 5 seconds.");
|
||||
}
|
||||
$expectedMessage = $table->getColumnsHash()[0]['message'];
|
||||
Assert::assertSame(
|
||||
$expectedMessage,
|
||||
$actualMessage,
|
||||
__METHOD__ . "expected message to be '$expectedMessage' but found'$actualMessage'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then user :user should get a notification for resource :resource with subject :subject and message:
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $resource
|
||||
* @param string $subject
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldGetNotificationForResourceWithMessage(string $user, string $resource, string $subject, TableNode $table):void {
|
||||
$response = $this->listAllNotifications($user);
|
||||
$notification = $this->filterResponseByNotificationSubjectAndResource($subject, $resource, $response);
|
||||
|
||||
if (\count($notification) === 1) {
|
||||
$actualMessage = str_replace(["\r", "\r"], " ", $notification[0]->message);
|
||||
$expectedMessage = $table->getColumnsHash()[0]['message'];
|
||||
Assert::assertSame(
|
||||
$expectedMessage,
|
||||
$actualMessage,
|
||||
__METHOD__ . "expected message to be '$expectedMessage' but found'$actualMessage'"
|
||||
);
|
||||
$response = $this->userDeletesNotification($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
} elseif (\count($notification) === 0) {
|
||||
throw new \Exception("Response doesn't contain any notification with resource '$resource' and subject '$subject'.\n" . print_r($notification, true));
|
||||
} else {
|
||||
throw new \Exception("Response contains more than one notification with resource '$resource' and subject '$subject'.\n" . print_r($notification, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then user :user should not have a notification related to resource :resource with subject :subject
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $resource
|
||||
* @param string $subject
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userShouldNotHaveANotificationRelatedToResourceWithSubject(string $user, string $resource, string $subject):void {
|
||||
$response = $this->listAllNotifications($user);
|
||||
$filteredResponse = $this->filterResponseByNotificationSubjectAndResource($subject, $resource, $response);
|
||||
Assert::assertCount(0, $filteredResponse, "Response should not contain notification related to resource '$resource' with subject '$subject' but found" . print_r($filteredResponse, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then user :user should have received the following email from user :sender about the share of project space :spaceName
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $sender
|
||||
* @param string $spaceName
|
||||
* @param PyStringNode $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldHaveReceivedTheFollowingEmailFromUserAboutTheShareOfProjectSpace(string $user, string $sender, string $spaceName, PyStringNode $content):void {
|
||||
$rawExpectedEmailBodyContent = \str_replace("\r\n", "\n", $content->getRaw());
|
||||
$this->featureContext->setResponse(
|
||||
GraphHelper::getMySpaces(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
'',
|
||||
$this->featureContext->getStepLineRef()
|
||||
)
|
||||
);
|
||||
$expectedEmailBodyContent = $this->featureContext->substituteInLineCodes(
|
||||
$rawExpectedEmailBodyContent,
|
||||
$sender,
|
||||
[],
|
||||
[
|
||||
[
|
||||
"code" => "%space_id%",
|
||||
"function" =>
|
||||
[$this->spacesContext, "getSpaceIdByName"],
|
||||
"parameter" => [$sender, $spaceName]
|
||||
],
|
||||
]
|
||||
);
|
||||
$this->assertEmailContains($user, $expectedEmailBodyContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then user :user should have received the following email from user :sender
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $sender
|
||||
* @param PyStringNode $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldHaveReceivedTheFollowingEmailFromUser(string $user, string $sender, PyStringNode $content):void {
|
||||
$rawExpectedEmailBodyContent = \str_replace("\r\n", "\n", $content->getRaw());
|
||||
$expectedEmailBodyContent = $this->featureContext->substituteInLineCodes(
|
||||
$rawExpectedEmailBodyContent,
|
||||
$sender
|
||||
);
|
||||
$this->assertEmailContains($user, $expectedEmailBodyContent);
|
||||
}
|
||||
|
||||
/***
|
||||
* @param string $user
|
||||
* @param string $expectedEmailBodyContent
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function assertEmailContains(string $user, string $expectedEmailBodyContent):void {
|
||||
$address = $this->featureContext->getEmailAddressForUser($user);
|
||||
$this->featureContext->pushEmailRecipientAsMailBox($address);
|
||||
$actualEmailBodyContent = EmailHelper::getBodyOfLastEmail($address, $this->featureContext->getStepLineRef());
|
||||
Assert::assertStringContainsString(
|
||||
$expectedEmailBodyContent,
|
||||
$actualEmailBodyContent,
|
||||
"The email address '$address' should have received an email with the body containing $expectedEmailBodyContent
|
||||
but the received email is $actualEmailBodyContent"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the inbucket emails
|
||||
*
|
||||
* @AfterScenario @email
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clearInbucketMessages():void {
|
||||
try {
|
||||
if (!empty($this->featureContext->emailRecipients)) {
|
||||
foreach ($this->featureContext->emailRecipients as $emailRecipient) {
|
||||
EmailHelper::deleteAllEmailsForAMailbox(
|
||||
EmailHelper::getLocalEmailUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$emailRecipient
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo __METHOD__ .
|
||||
" could not delete inbucket messages, is inbucket set up?\n" .
|
||||
$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string|null $user
|
||||
* @param string|null $deprovision_date
|
||||
* @param string|null $deprovision_date_format
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userCreatesDeprovisioningNotification(
|
||||
?string $user = null,
|
||||
?string $deprovision_date = "2043-07-04T11:23:12Z",
|
||||
?string $deprovision_date_format= "2006-01-02T15:04:05Z07:00"
|
||||
):ResponseInterface {
|
||||
$payload["type"] = "deprovision";
|
||||
$payload["data"] = ["deprovision_date" => $deprovision_date, "deprovision_date_format" => $deprovision_date_format];
|
||||
return OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user ? $this->featureContext->getActualUsername($user) : $this->featureContext->getAdminUsername(),
|
||||
$user ? $this->featureContext->getPasswordForUser($user) : $this->featureContext->getAdminPassword(),
|
||||
'POST',
|
||||
$this->globalNotificationEndpointPath,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
json_encode($payload)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator creates a deprovisioning notification
|
||||
* @When user :user tries to create a deprovisioning notification
|
||||
*
|
||||
* @param string|null $user
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function theAdministratorCreatesADeprovisioningNotification(?string $user = null) {
|
||||
$response = $this->userCreatesDeprovisioningNotification($user);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastHttpStatusCodesArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator creates a deprovisioning notification for date :deprovision_date of format :deprovision_date_format
|
||||
*
|
||||
* @param $deprovision_date
|
||||
* @param $deprovision_date_format
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function theAdministratorCreatesADeprovisioningNotificationUsingDateFormat($deprovision_date, $deprovision_date_format) {
|
||||
$response = $this->userCreatesDeprovisioningNotification(null, $deprovision_date, $deprovision_date_format);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->pushToLastHttpStatusCodesArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the administrator has created a deprovisioning notification
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasCreatedDeprovisioningNotification():void {
|
||||
$response = $this->userCreatesDeprovisioningNotification();
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator deletes the deprovisioning notification
|
||||
* @When user :user tries to delete the deprovisioning notification
|
||||
*
|
||||
* @param string|null $user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userDeletesDeprovisioningNotification(?string $user = null):void {
|
||||
$payload["ids"] = ["deprovision"];
|
||||
|
||||
$response = OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user ? $this->featureContext->getActualUsername($user) : $this->featureContext->getAdminUsername(),
|
||||
$user ? $this->featureContext->getPasswordForUser($user) : $this->featureContext->getAdminPassword(),
|
||||
'DELETE',
|
||||
$this->globalNotificationEndpointPath,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
json_encode($payload)
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
}
|
||||
@@ -1,663 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2019, ownCloud GmbH
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\PyStringNode;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\OcsApiHelper;
|
||||
use TestHelpers\TranslationHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* steps needed to send requests to the OCS API
|
||||
*/
|
||||
class OCSContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @When /^the user sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)"$/
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theUserSendsToOcsApiEndpoint(string $verb, string $url):void {
|
||||
$response = $this->theUserSendsToOcsApiEndpointWithBody($verb, $url);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)"$/
|
||||
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" using password "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param string|null $password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userSendsToOcsApiEndpoint(string $user, string $verb, string $url, ?string $password = null):void {
|
||||
$response = $this->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
$verb,
|
||||
$url,
|
||||
null,
|
||||
$password
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode|null $body
|
||||
* @param string|null $password
|
||||
* @param array|null $headers
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function sendRequestToOcsEndpoint(
|
||||
string $user,
|
||||
string $verb,
|
||||
string $url,
|
||||
?TableNode $body = null,
|
||||
?string $password = null,
|
||||
?array $headers = null
|
||||
):ResponseInterface {
|
||||
/**
|
||||
* array of the data to be sent in the body.
|
||||
* contains $body data converted to an array
|
||||
*/
|
||||
$bodyArray = [];
|
||||
if ($body instanceof TableNode) {
|
||||
$bodyArray = $body->getRowsHash();
|
||||
}
|
||||
|
||||
if ($user !== 'UNAUTHORIZED_USER') {
|
||||
if ($password === null) {
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
}
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
} else {
|
||||
$user = null;
|
||||
$password = null;
|
||||
}
|
||||
return OcsApiHelper::sendRequest(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$password,
|
||||
$verb,
|
||||
$url,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$bodyArray,
|
||||
$this->featureContext->getOcsApiVersion(),
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode|null $body
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function adminSendsHttpMethodToOcsApiEndpointWithBody(
|
||||
string $verb,
|
||||
string $url,
|
||||
?TableNode $body
|
||||
):ResponseInterface {
|
||||
$admin = $this->featureContext->getAdminUsername();
|
||||
return $this->sendRequestToOcsEndpoint(
|
||||
$admin,
|
||||
$verb,
|
||||
$url,
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode|null $body
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function theUserSendsToOcsApiEndpointWithBody(string $verb, string $url, ?TableNode $body = null):ResponseInterface {
|
||||
return $this->sendRequestToOcsEndpoint(
|
||||
$this->featureContext->getCurrentUser(),
|
||||
$verb,
|
||||
$url,
|
||||
$body
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with body$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode|null $body
|
||||
* @param string|null $password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userSendHTTPMethodToOcsApiEndpointWithBody(
|
||||
string $user,
|
||||
string $verb,
|
||||
string $url,
|
||||
?TableNode $body = null,
|
||||
?string $password = null
|
||||
):void {
|
||||
$response = $this->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
$verb,
|
||||
$url,
|
||||
$body,
|
||||
$password
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator sends HTTP method :verb to OCS API endpoint :url
|
||||
* @When the administrator sends HTTP method :verb to OCS API endpoint :url using password :password
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param string|null $password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorSendsHttpMethodToOcsApiEndpoint(
|
||||
string $verb,
|
||||
string $url,
|
||||
?string $password = null
|
||||
):void {
|
||||
$this->featureContext->setResponse(
|
||||
$this->sendRequestToOcsEndpoint(
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$verb,
|
||||
$url,
|
||||
null,
|
||||
$password
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with headers$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userSendsToOcsApiEndpointWithHeaders(
|
||||
string $user,
|
||||
string $verb,
|
||||
string $url,
|
||||
TableNode $headersTable
|
||||
):void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
$this->featureContext->setResponse(
|
||||
$this->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
$verb,
|
||||
$url,
|
||||
null,
|
||||
$password,
|
||||
$headersTable->getRowsHash()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the administrator sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with headers$/
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function administratorSendsToOcsApiEndpointWithHeaders(
|
||||
string $verb,
|
||||
string $url,
|
||||
TableNode $headersTable
|
||||
):void {
|
||||
$user = $this->featureContext->getAdminUsername();
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
$this->featureContext->setResponse(
|
||||
$this->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
$verb,
|
||||
$url,
|
||||
null,
|
||||
$password,
|
||||
$headersTable->getRowsHash()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the administrator sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with headers using password "([^"]*)"$/
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param string $password
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function administratorSendsToOcsApiEndpointWithHeadersAndPassword(
|
||||
string $verb,
|
||||
string $url,
|
||||
string $password,
|
||||
TableNode $headersTable
|
||||
):void {
|
||||
$this->featureContext->setResponse(
|
||||
$this->sendRequestToOcsEndpoint(
|
||||
$this->featureContext->getAdminUsername(),
|
||||
$verb,
|
||||
$url,
|
||||
null,
|
||||
$password,
|
||||
$headersTable->getRowsHash()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator sends HTTP method :verb to OCS API endpoint :url with body
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode|null $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorSendsHttpMethodToOcsApiEndpointWithBody(
|
||||
string $verb,
|
||||
string $url,
|
||||
?TableNode $body
|
||||
):void {
|
||||
$response = $this->adminSendsHttpMethodToOcsApiEndpointWithBody(
|
||||
$verb,
|
||||
$url,
|
||||
$body
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the user sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with body$/
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theUserSendsHTTPMethodToOcsApiEndpointWithBody(string $verb, string $url, TableNode $body):void {
|
||||
$response = $this->theUserSendsToOcsApiEndpointWithBody(
|
||||
$verb,
|
||||
$url,
|
||||
$body
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the administrator sends HTTP method :verb to OCS API endpoint :url with body using password :password
|
||||
*
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param string $password
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theAdministratorSendsHttpMethodToOcsApiWithBodyAndPassword(
|
||||
string $verb,
|
||||
string $url,
|
||||
string $password,
|
||||
TableNode $body
|
||||
):void {
|
||||
$admin = $this->featureContext->getAdminUsername();
|
||||
$response = $this->sendRequestToOcsEndpoint(
|
||||
$admin,
|
||||
$verb,
|
||||
$url,
|
||||
$body,
|
||||
$password
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends HTTP method "([^"]*)" to OCS API endpoint "([^"]*)" with body using password "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $verb
|
||||
* @param string $url
|
||||
* @param string $password
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userSendsHTTPMethodToOcsApiEndpointWithBodyAndPassword(
|
||||
string $user,
|
||||
string $verb,
|
||||
string $url,
|
||||
string $password,
|
||||
TableNode $body
|
||||
):void {
|
||||
$response = $this->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
$verb,
|
||||
$url,
|
||||
$body,
|
||||
$password
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the OCS status code should be "([^"]*)"$/
|
||||
*
|
||||
* @param string $statusCode
|
||||
* @param string $message
|
||||
* @param ResponseInterface|null $response
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theOCSStatusCodeShouldBe(string $statusCode, string $message = "", ?ResponseInterface $response = null):void {
|
||||
$statusCodes = explode(",", $statusCode);
|
||||
$response = $response ?? $this->featureContext->getResponse();
|
||||
$responseStatusCode = $this->getOCSResponseStatusCode(
|
||||
$response
|
||||
);
|
||||
if (\is_array($statusCodes)) {
|
||||
if ($message === "") {
|
||||
$message = "OCS status code is not any of the expected values " . \implode(",", $statusCodes) . " got " . $responseStatusCode;
|
||||
}
|
||||
Assert::assertContainsEquals(
|
||||
$responseStatusCode,
|
||||
$statusCodes,
|
||||
$message
|
||||
);
|
||||
$this->featureContext->emptyLastOCSStatusCodesArray();
|
||||
} else {
|
||||
if ($message === "") {
|
||||
$message = "OCS status code is not the expected value " . $statusCodes . " got " . $responseStatusCode;
|
||||
}
|
||||
|
||||
Assert::assertEquals(
|
||||
$statusCodes,
|
||||
$responseStatusCode,
|
||||
$message
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the OCS status code should be "([^"]*)" or "([^"]*)"$/
|
||||
*
|
||||
* @param string $statusCode1
|
||||
* @param string $statusCode2
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theOcsStatusCodeShouldBeOr(string $statusCode1, string $statusCode2):void {
|
||||
$statusCodes = [$statusCode1,$statusCode1];
|
||||
$response = $this->featureContext->getResponse();
|
||||
$responseStatusCode = $this->getOCSResponseStatusCode(
|
||||
$response
|
||||
);
|
||||
Assert::assertContainsEquals(
|
||||
$responseStatusCode,
|
||||
$statusCodes,
|
||||
"OCS status code is not any of the expected values " . \implode(",", $statusCodes) . " got " . $responseStatusCode
|
||||
);
|
||||
$this->featureContext->emptyLastOCSStatusCodesArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the text in an OCS status message
|
||||
*
|
||||
* @Then /^the OCS status message should be "([^"]*)"$/
|
||||
* @Then /^the OCS status message should be "([^"]*)" in language "([^"]*)"$/
|
||||
*
|
||||
* @param string $statusMessage
|
||||
* @param string|null $language
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theOCSStatusMessageShouldBe(string $statusMessage, ?string $language = null):void {
|
||||
$language = TranslationHelper::getLanguage($language);
|
||||
$statusMessage = $this->getActualStatusMessage($statusMessage, $language);
|
||||
|
||||
Assert::assertEquals(
|
||||
$statusMessage,
|
||||
$this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
),
|
||||
'Unexpected OCS status message :"' . $this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
) . '" in response'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the text in an OCS status message
|
||||
*
|
||||
* @Then /^the OCS status message about user "([^"]*)" should be "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $statusMessage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theOCSStatusMessageAboutUserShouldBe(string $user, string $statusMessage):void {
|
||||
$user = \strtolower($this->featureContext->getActualUsername($user));
|
||||
$statusMessage = $this->featureContext->substituteInLineCodes(
|
||||
$statusMessage,
|
||||
$user
|
||||
);
|
||||
Assert::assertEquals(
|
||||
$statusMessage,
|
||||
$this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
),
|
||||
'Unexpected OCS status message :"' . $this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
) . '" in response'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the text in an OCS status message.
|
||||
* Use this step form if the expected text contains double quotes,
|
||||
* single quotes and other content that theOCSStatusMessageShouldBe()
|
||||
* cannot handle.
|
||||
*
|
||||
* After the step, write the expected text in PyString form like:
|
||||
*
|
||||
* """
|
||||
* File "abc.txt" can't be shared due to reason "xyz"
|
||||
* """
|
||||
*
|
||||
* @Then /^the OCS status message should be:$/
|
||||
*
|
||||
* @param PyStringNode $statusMessage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theOCSStatusMessageShouldBePyString(
|
||||
PyStringNode $statusMessage
|
||||
):void {
|
||||
Assert::assertEquals(
|
||||
$statusMessage->getRaw(),
|
||||
$this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
),
|
||||
'Unexpected OCS status message: "' . $this->getOCSResponseStatusMessage(
|
||||
$this->featureContext->getResponse()
|
||||
) . '" in response'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml answer to get ocs response which doesn't match with
|
||||
* http one in v1 of the api.
|
||||
*
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOCSResponseStatusCode(ResponseInterface $response):string {
|
||||
try {
|
||||
$jsonResponse = $this->featureContext->getJsonDecodedResponseBodyContent($response);
|
||||
} catch (JsonException $e) {
|
||||
$jsonResponse = null;
|
||||
}
|
||||
|
||||
if (\is_object($jsonResponse) && $jsonResponse->ocs->meta->statuscode) {
|
||||
return (string) $jsonResponse->ocs->meta->statuscode;
|
||||
}
|
||||
// go to xml response when json response is null (it means not formatted and get status code)
|
||||
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
|
||||
if (isset($responseXml->meta[0], $responseXml->meta[0]->statuscode)) {
|
||||
return (string) $responseXml->meta[0]->statuscode;
|
||||
}
|
||||
throw new Exception(
|
||||
"No OCS status code found in response"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml answer to return data items from ocs response
|
||||
*
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return SimpleXMLElement
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOCSResponseData(ResponseInterface $response): SimpleXMLElement {
|
||||
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
|
||||
if (isset($responseXml->data)) {
|
||||
return $responseXml->data;
|
||||
}
|
||||
throw new Exception(
|
||||
"No OCS data items found in responseXml"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the xml answer to get ocs response message which doesn't match with
|
||||
* http one in v1 of the api.
|
||||
*
|
||||
* @param ResponseInterface $response
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOCSResponseStatusMessage(ResponseInterface $response):string {
|
||||
return (string) $this->featureContext->getResponseXml($response, __METHOD__)->meta[0]->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert status message in the desired language
|
||||
*
|
||||
* @param string $statusMessage
|
||||
* @param string|null $language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getActualStatusMessage(string $statusMessage, ?string $language = null):string {
|
||||
if ($language !== null) {
|
||||
$multiLingualMessage = \json_decode(
|
||||
\file_get_contents(__DIR__ . "/../../fixtures/multiLanguageErrors.json"),
|
||||
true
|
||||
);
|
||||
|
||||
if (isset($multiLingualMessage[$statusMessage][$language])) {
|
||||
$statusMessage = $multiLingualMessage[$statusMessage][$language];
|
||||
}
|
||||
}
|
||||
return $statusMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the HTTP status code and the OCS status code indicate that the request was successful
|
||||
* this function is aware of the currently used OCS version
|
||||
*
|
||||
* @param string|null $message
|
||||
* @param ResponseInterface|null $response
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function assertOCSResponseIndicatesSuccess(?string $message = "", ?ResponseInterface $response = null):void {
|
||||
$response = $response ?? $this->featureContext->getResponse();
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe('200', $message, $response);
|
||||
if ($this->featureContext->getOcsApiVersion() === 1) {
|
||||
$this->theOCSStatusCodeShouldBe('100', $message, $response);
|
||||
} else {
|
||||
$this->theOCSStatusCodeShouldBe('200', $message, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Sajan Gurung <sajan@jankaritech.com>
|
||||
* @copyright Copyright (c) 2023 Sajan Gurung sajan@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use TestHelpers\OcisConfigHelper;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
/**
|
||||
* steps needed to re-configure oCIS server
|
||||
*/
|
||||
class OcisConfigContext implements Context {
|
||||
/**
|
||||
* @Given async upload has been enabled with post-processing delayed to :delayTime seconds
|
||||
*
|
||||
* @param string $delayTime
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function asyncUploadHasBeenEnabledWithDelayedPostProcessing(string $delayTime): void {
|
||||
$envs = [
|
||||
"OCIS_ASYNC_UPLOADS" => true,
|
||||
"OCIS_EVENTS_ENABLE_TLS" => false,
|
||||
"POSTPROCESSING_DELAY" => $delayTime . "s",
|
||||
];
|
||||
|
||||
$response = OcisConfigHelper::reConfigureOcis($envs);
|
||||
Assert::assertEquals(
|
||||
200,
|
||||
$response->getStatusCode(),
|
||||
"Failed to set async upload with delayed post processing"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the config :configVariable has been set to :configValue
|
||||
*
|
||||
* @param string $configVariable
|
||||
* @param string $configValue
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theConfigHasBeenSetTo(string $configVariable, string $configValue): void {
|
||||
$envs = [
|
||||
$configVariable => $configValue,
|
||||
];
|
||||
|
||||
$response = OcisConfigHelper::reConfigureOcis($envs);
|
||||
Assert::assertEquals(
|
||||
200,
|
||||
$response->getStatusCode(),
|
||||
"Failed to set config $configVariable=$configValue"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the config :configVariable has been set to path :path
|
||||
*
|
||||
* @param string $configVariable
|
||||
* @param string $path
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theConfigHasBeenSetPathTo(string $configVariable, string $path): void {
|
||||
$path = \dirname(__FILE__) . "/../../../" . $path;
|
||||
$response = OcisConfigHelper::reConfigureOcis(
|
||||
[
|
||||
$configVariable => $path
|
||||
]
|
||||
);
|
||||
Assert::assertEquals(
|
||||
200,
|
||||
$response->getStatusCode(),
|
||||
"Failed to set config $configVariable=$path"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the following configs have been set:
|
||||
*
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theConfigHasBeenSetToValue(TableNode $table): void {
|
||||
$envs = [];
|
||||
foreach ($table->getHash() as $row) {
|
||||
$envs[$row['config']] = $row['value'];
|
||||
}
|
||||
|
||||
$response = OcisConfigHelper::reConfigureOcis($envs);
|
||||
Assert::assertEquals(
|
||||
200,
|
||||
$response->getStatusCode(),
|
||||
"Failed to set config"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @AfterScenario @env-config
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rollbackOcis(): void {
|
||||
$response = OcisConfigHelper::rollbackOcis();
|
||||
Assert::assertEquals(
|
||||
200,
|
||||
$response->getStatusCode(),
|
||||
"Failed to rollback ocis server. Check if oCIS is started with ociswrapper."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* @author Viktor Scharf <scharf.vi@gmail.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2024, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\OcisHelper;
|
||||
use TestHelpers\OcmHelper;
|
||||
use TestHelpers\WebDavHelper;
|
||||
|
||||
/**
|
||||
* Acceptance test steps related to testing federation share(ocm) features
|
||||
*/
|
||||
class OcmContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private string $invitationToken;
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope): void {
|
||||
if (OcisHelper::isTestingOnReva()) {
|
||||
return;
|
||||
}
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context from here
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOcisDomain(): string {
|
||||
return $this->extractDomain(\getenv('TEST_SERVER_URL'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFedOcisDomain(): string {
|
||||
return $this->extractDomain(\getenv('TEST_SERVER_FED_URL'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function extractDomain($url): string {
|
||||
if (!$url) {
|
||||
return "localhost";
|
||||
}
|
||||
return parse_url($url)["host"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $email
|
||||
* @param string $description
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function createInvitation(string $user, $email = null, $description = null): ResponseInterface {
|
||||
$response = OcmHelper::createInvitation(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$email,
|
||||
$description
|
||||
);
|
||||
$responseData = \json_decode($response->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
if (isset($responseData["token"])) {
|
||||
$this->invitationToken = $responseData["token"];
|
||||
} else {
|
||||
throw new Exception(__METHOD__ . " response doesn't contain token");
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @When :user creates the federation share invitation
|
||||
* @When :user creates the federation share invitation with email :email and description :description
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $email
|
||||
* @param string $description
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userCreatesTheFederationShareInvitation(string $user, $email = null, $description = null): void {
|
||||
$this->featureContext->setResponse($this->createInvitation($user, $email, $description));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given :user has created the federation share invitation
|
||||
* @Given :user has created the federation share invitation with email :email and description :description
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $email
|
||||
* @param string $description
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasCreatedTheFederationShareInvitation(string $user, $email = null, $description = null): void {
|
||||
$response = $this->createInvitation($user, $email, $description);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $token
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function acceptInvitation(string $user, string $token = null): ResponseInterface {
|
||||
$providerDomain = ($this->featureContext->getCurrentServer() === "LOCAL") ? $this->getFedOcisDomain() : $this->getOcisDomain();
|
||||
return OcmHelper::acceptInvitation(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$token ? $token : $this->invitationToken,
|
||||
$providerDomain
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When :user accepts the last federation share invitation
|
||||
* @When :user tries to accept the last federation share invitation
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userAcceptsTheLastFederationShareInvitation(string $user): void {
|
||||
$this->featureContext->setResponse($this->acceptInvitation($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When :user tries to accept the invitation with invalid token
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userTriesToAcceptInvitationWithInvalidToken(string $user): void {
|
||||
$this->featureContext->setResponse($this->acceptInvitation($user, WebDavHelper::generateUUIDv4()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given :user has accepted invitation
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasAcceptedTheLastFederationShareInvitation(string $user): void {
|
||||
$response = $this->acceptInvitation($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function findAcceptedUsers(string $user): ResponseInterface {
|
||||
return OcmHelper::findAcceptedUsers(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When :user searches for accepted users
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userFindsAcceptedUsers(string $user): void {
|
||||
$this->featureContext->setResponse($this->findAcceptedUsers($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function listInvitations(string $user): ResponseInterface {
|
||||
return OcmHelper::listInvite(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When :user lists the created invitations
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userListsCreatedInvitations(string $user): void {
|
||||
$this->featureContext->setResponse($this->listInvitations($user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the user waits :number seconds for the token to expire
|
||||
*
|
||||
* @param int $number
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theUserWaitsForTokenToExpire(int $number): void {
|
||||
\sleep($number);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,214 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018 Artur Neumann artur@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\WebDavHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* context containing search related API steps
|
||||
*/
|
||||
class SearchContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
/**
|
||||
* @When user :user searches for :pattern using the WebDAV API
|
||||
* @When user :user searches for :pattern and limits the results to :limit items using the WebDAV API
|
||||
* @When user :user searches for :pattern using the WebDAV API requesting these properties:
|
||||
* @When user :user searches for :pattern and limits the results to :limit items using the WebDAV API requesting these properties:
|
||||
* @When user :user searches for :pattern inside folder :scope using the WebDAV API
|
||||
* @When user :user searches for :pattern inside folder :scope in space :spaceName using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $pattern
|
||||
* @param string|null $limit
|
||||
* @param string|null $scope
|
||||
* @param string|null $spaceName
|
||||
* @param TableNode|null $properties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userSearchesUsingWebDavAPI(
|
||||
string $user,
|
||||
string $pattern,
|
||||
?string $limit = null,
|
||||
?string $scope = null,
|
||||
?string $spaceName = null,
|
||||
TableNode $properties = null
|
||||
): void {
|
||||
// NOTE: because indexing of newly uploaded files or directories with ocis is decoupled and occurs asynchronously
|
||||
// short wait is necessary before searching
|
||||
sleep(5);
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
if (str_contains($pattern, '$')) {
|
||||
$date = explode("$", $pattern);
|
||||
switch ($date[1]) {
|
||||
case "today":
|
||||
$pattern = $date[0] . date('Y-m-d', strtotime('today'));
|
||||
break;
|
||||
case "yesterday":
|
||||
$pattern = $date[0] . date('Y-m-d', strtotime('yesterday'));
|
||||
break;
|
||||
default:
|
||||
throw new Exception("cannot convert the date");
|
||||
}
|
||||
}
|
||||
$body
|
||||
= "<?xml version='1.0' encoding='utf-8' ?>\n" .
|
||||
" <oc:search-files xmlns:a='DAV:' xmlns:oc='http://owncloud.org/ns' >\n" .
|
||||
" <oc:search>\n";
|
||||
if ($scope !== null) {
|
||||
$scope = \trim($scope, "/");
|
||||
$resourceID = $this->featureContext->spacesContext->getResourceId($user, $spaceName ?? "Personal", $scope);
|
||||
$pattern .= " scope:$resourceID";
|
||||
}
|
||||
$body .= "<oc:pattern>$pattern</oc:pattern>\n";
|
||||
if ($limit !== null) {
|
||||
$body .= " <oc:limit>$limit</oc:limit>\n";
|
||||
}
|
||||
|
||||
$body .= " </oc:search>\n";
|
||||
if ($properties !== null) {
|
||||
$propertiesRows = $properties->getRows();
|
||||
$body .= " <a:prop>";
|
||||
foreach ($propertiesRows as $property) {
|
||||
$body .= "<$property[0]/>";
|
||||
}
|
||||
$body .= " </a:prop>";
|
||||
}
|
||||
$body .= " </oc:search-files>";
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$user,
|
||||
$password,
|
||||
"REPORT",
|
||||
"/",
|
||||
null,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion()
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then file/folder :path in the search result of user :user should contain these properties:
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $user
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fileOrFolderInTheSearchResultShouldContainProperties(
|
||||
string $path,
|
||||
string $user,
|
||||
TableNode $properties
|
||||
): void {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->featureContext->verifyTableNodeColumns($properties, ['name', 'value']);
|
||||
$properties = $properties->getHash();
|
||||
$fileResult = $this->featureContext->findEntryFromSearchResponse(
|
||||
$path
|
||||
);
|
||||
Assert::assertNotFalse(
|
||||
$fileResult,
|
||||
"could not find file/folder '$path'"
|
||||
);
|
||||
foreach ($properties as $property) {
|
||||
$property['value'] = $this->featureContext->substituteInLineCodes(
|
||||
$property['value'],
|
||||
$user
|
||||
);
|
||||
$fileResultProperty = $fileResult->xpath("d:propstat//" . $property['name']);
|
||||
if ($fileResultProperty) {
|
||||
Assert::assertMatchesRegularExpression(
|
||||
"/" . $property['value'] . "/",
|
||||
\trim((string)$fileResultProperty[0])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
throw new Error("Could not find property '" . $property['name'] . "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope): void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the search result should contain these (?:files|entries) with highlight on keyword "([^"]*)"/
|
||||
*
|
||||
* @param TableNode $expectedFiles
|
||||
* @param string $expectedContent
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theSearchResultShouldContainEntriesWithHighlight(
|
||||
TableNode $expectedFiles,
|
||||
string $expectedContent
|
||||
): void {
|
||||
$this->featureContext->verifyTableNodeColumnsCount($expectedFiles, 1);
|
||||
$elementRows = $expectedFiles->getRows();
|
||||
$foundEntries = $this->featureContext->findEntryFromSearchResponse(
|
||||
null,
|
||||
true
|
||||
);
|
||||
foreach ($elementRows as $expectedFile) {
|
||||
$filename = $expectedFile[0];
|
||||
$content = $foundEntries[$filename];
|
||||
// Extract the content between the <mark> tags
|
||||
preg_match('/<mark>(.*?)<\/mark>/s', $content, $matches);
|
||||
$actualContent = $matches[1] ?? '';
|
||||
|
||||
// Remove any leading/trailing whitespace for comparison
|
||||
$actualContent = trim($actualContent);
|
||||
Assert::assertEquals(
|
||||
$expectedContent,
|
||||
$actualContent,
|
||||
"Expected text highlight to be '$expectedContent' but found '$actualContent'"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,491 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Viktor Scharf <v.scharf@owncloud.com>
|
||||
* @copyright Copyright (c) 2022 Viktor Scharf v.scharf@owncloud.com
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use TestHelpers\SettingsHelper;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Context for the TUS-specific steps using the Graph API
|
||||
*/
|
||||
class SettingsContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private string $baseUrl;
|
||||
private string $settingsUrl = '/api/v0/settings/';
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope): void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context from here
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->baseUrl = \trim($this->featureContext->getBaseUrl(), "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRoles(string $user): ResponseInterface {
|
||||
return SettingsHelper::getRolesList(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" tries to get all existing roles$/
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAllExistingRoles(string $user): void {
|
||||
$response = $this->getRoles($user);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $userId
|
||||
* @param string $roleId
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function assignRoleToUser(string $user, string $userId, string $roleId): ResponseInterface {
|
||||
return SettingsHelper::assignRoleToUser(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$userId,
|
||||
$roleId,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $userId
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAssignmentsList(string $user, string $userId): ResponseInterface {
|
||||
return SettingsHelper::getAssignmentsList(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$userId,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^the administrator has given "([^"]*)" the role "([^"]*)" using the settings api$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $role
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theAdministratorHasGivenUserTheRole(string $user, string $role): void {
|
||||
$admin = $this->featureContext->getAdminUserName();
|
||||
$roleId = $this->getRoleIdByRoleName($admin, $role);
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id') ?: $user;
|
||||
$response = $this->assignRoleToUser($admin, $userId, $roleId);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(
|
||||
201,
|
||||
"Expected response status code should be 201",
|
||||
$response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $role
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRoleIdByRoleName(string $user, string $role): string {
|
||||
// Sometimes the response body is not complete and results invalid json.
|
||||
// So we try again until we get a valid json.
|
||||
$retried = 0;
|
||||
do {
|
||||
$response = $this->getRoles($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(
|
||||
201,
|
||||
"Expected response status code should be 201",
|
||||
$response
|
||||
);
|
||||
|
||||
$rawBody = $response->getBody()->getContents();
|
||||
try {
|
||||
$decodedBody = \json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
|
||||
$tryAgain = false;
|
||||
} catch (Exception $e) {
|
||||
$tryAgain = $retried < HttpRequestHelper::numRetriesOnHttpTooEarly();
|
||||
|
||||
if (!$tryAgain) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tryAgain) {
|
||||
$retried += 1;
|
||||
echo "Invalid json body, retrying ($retried)...\n";
|
||||
// wait 500ms and try again
|
||||
\usleep(500 * 1000);
|
||||
}
|
||||
} while ($tryAgain);
|
||||
|
||||
Assert::assertArrayHasKey(
|
||||
'bundles',
|
||||
$decodedBody,
|
||||
__METHOD__ . " could not find bundles in body"
|
||||
);
|
||||
$bundles = $decodedBody["bundles"];
|
||||
|
||||
$roleToAssign = "";
|
||||
foreach ($bundles as $value) {
|
||||
// find the selected role
|
||||
if ($value["displayName"] === $role) {
|
||||
$roleToAssign = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert::assertNotEmpty($roleToAssign, "The selected role $role could not be found");
|
||||
return $roleToAssign["id"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" changes his own role to "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $role
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userChangeOwnRole(string $user, string $role): void {
|
||||
// we assume that the user knows uuid role.
|
||||
$roleId = $this->getRoleIdByRoleName($this->featureContext->getAdminUserName(), $role);
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
||||
$response = $this->assignRoleToUser($user, $userId, $roleId);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" changes the role "([^"]*)" for user "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $role
|
||||
* @param string $assignedUser
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userChangeRoleAnotherUser(string $user, string $role, string $assignedUser): void {
|
||||
// we assume that the user knows uuid role.
|
||||
$roleId = $this->getRoleIdByRoleName($this->featureContext->getAdminUserName(), $role);
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($assignedUser, 'id');
|
||||
$response = $this->assignRoleToUser($user, $userId, $roleId);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" tries to get list of assignment$/
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userGetAssignmentsList(string $user): void {
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
||||
$this->featureContext->setResponse($this->getAssignmentsList($user, $userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^user "([^"]*)" should have the role "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $role
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userShouldHaveRole(string $user, string $role): void {
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
||||
$response = $this->getAssignmentsList($this->featureContext->getAdminUserName(), $userId);
|
||||
$assignmentResponse = $this->featureContext->getJsonDecodedResponseBodyContent($response);
|
||||
if (isset($assignmentResponse->assignments[0]->roleId)) {
|
||||
$actualRoleId = $assignmentResponse->assignments[0]->roleId;
|
||||
Assert::assertEquals($this->getRoleIdByRoleName($this->featureContext->getAdminUserName(), $role), $actualRoleId, "user $user has no role $role");
|
||||
} else {
|
||||
Assert::fail("Response should contain user role but not found.\n" . json_encode($assignmentResponse));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the setting API response should have the role "([^"]*)"$/
|
||||
*
|
||||
* @param string $role
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theSettingApiResponseShouldHaveTheRole(string $role): void {
|
||||
$assignmentRoleId = $this->featureContext->getJsonDecodedResponse($this->featureContext->getResponse())["assignments"][0]["roleId"];
|
||||
Assert::assertEquals($this->getRoleIdByRoleName($this->featureContext->getAdminUserName(), $role), $assignmentRoleId, "user has no role $role");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendRequestGetBundlesList(string $user): ResponseInterface {
|
||||
return SettingsHelper::getBundlesList(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $bundleName
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getBundleByName(string $user, string $bundleName): array {
|
||||
return SettingsHelper::getBundleByName(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$bundleName,
|
||||
$this->featureContext->getStepLineRef()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param array $headers
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendRequestGetSettingsValuesList(string $user, array $headers = null): ResponseInterface {
|
||||
return SettingsHelper::getValuesList(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" lists values-list with headers using the Settings API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param TableNode $headersTable
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theUserListsAllValuesListWithHeadersUsingSettingsApi(string $user, TableNode $headersTable): void {
|
||||
$this->featureContext->verifyTableNodeColumns(
|
||||
$headersTable,
|
||||
['header', 'value']
|
||||
);
|
||||
$headers = [];
|
||||
foreach ($headersTable as $row) {
|
||||
$headers[$row['header']] = $row ['value'];
|
||||
}
|
||||
$this->featureContext->setResponse($this->sendRequestGetSettingsValuesList($user, $headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $language
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendRequestToSwitchSystemLanguage(string $user, string $language): ResponseInterface {
|
||||
$profileBundlesList = $this->getBundleByName($user, "Profile");
|
||||
Assert::assertNotEmpty($profileBundlesList, "bundles list is empty");
|
||||
|
||||
$settingId = '';
|
||||
foreach ($profileBundlesList["settings"] as $value) {
|
||||
if ($value["name"] === "language") {
|
||||
$settingId = $value["id"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert::assertNotEmpty($settingId, "settingId is empty");
|
||||
|
||||
$userId = $this->featureContext->getAttributeOfCreatedUser($user, 'id');
|
||||
$body = json_encode(
|
||||
[
|
||||
"value" => [
|
||||
"account_uuid" => "me",
|
||||
"bundleId" => $profileBundlesList["id"],
|
||||
"id" => $userId,
|
||||
"listValue" => [
|
||||
"values" => [
|
||||
[
|
||||
"stringValue" => $language
|
||||
]
|
||||
]
|
||||
],
|
||||
"resource" => [
|
||||
"type" => "TYPE_USER"
|
||||
],
|
||||
"settingId" => $settingId
|
||||
]
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
return SettingsHelper::updateSettings(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$body,
|
||||
$this->featureContext->getStepLineRef()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has switched the system language to "([^"]*)" using the settings API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $language
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theUserHasSwitchedSystemLanguage(string $user, string $language): void {
|
||||
$response = $this->sendRequestToSwitchSystemLanguage($user, $language);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(
|
||||
201,
|
||||
"Expected response status code should be 201",
|
||||
$response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendRequestToDisableAutoAccepting(string $user): ResponseInterface {
|
||||
$body = json_encode(
|
||||
[
|
||||
"value" => [
|
||||
"account_uuid" => "me",
|
||||
"bundleId" => "2a506de7-99bd-4f0d-994e-c38e72c28fd9",
|
||||
"settingId" => "ec3ed4a3-3946-4efc-8f9f-76d38b12d3a9",
|
||||
"resource" => [
|
||||
"type" => "TYPE_USER"
|
||||
],
|
||||
"boolValue" => false
|
||||
]
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
return SettingsHelper::updateSettings(
|
||||
$this->baseUrl,
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$body,
|
||||
$this->featureContext->getStepLineRef()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has disabled auto-accepting
|
||||
* @Given user :user has disabled the auto-sync share
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function theUserHasDisabledAutoAccepting(string $user): void {
|
||||
$response = $this->sendRequestToDisableAutoAccepting($user);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(
|
||||
201,
|
||||
"Expected response status code should be 201",
|
||||
$response
|
||||
);
|
||||
$this->featureContext->rememberUserAutoSyncSetting($user, false);
|
||||
}
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
* @author Sergio Bertolin <sbertolin@owncloud.com>
|
||||
* @author Phillip Davis <phil@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018, ownCloud GmbH
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Sharees context.
|
||||
*/
|
||||
class ShareesContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private OCSContext $ocsContext;
|
||||
|
||||
/**
|
||||
* @When /^the user gets the sharees using the sharing API with parameters$/
|
||||
*
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theUserGetsTheShareesWithParameters(TableNode $body):void {
|
||||
$this->featureContext->setResponse(
|
||||
$this->getShareesWithParameters(
|
||||
$this->featureContext->getCurrentUser(),
|
||||
$body
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" gets the sharees using the sharing API with parameters$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userGetsTheShareesWithParameters(string $user, TableNode $body):void {
|
||||
$this->featureContext->setResponse(
|
||||
$this->getShareesWithParameters(
|
||||
$user,
|
||||
$body
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the "([^"]*)" sharees returned should be$/
|
||||
*
|
||||
* @param string $shareeType
|
||||
* @param TableNode $shareesList
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theShareesReturnedShouldBe(string $shareeType, TableNode $shareesList):void {
|
||||
$this->featureContext->verifyTableNodeColumnsCount($shareesList, 4);
|
||||
$sharees = $shareesList->getRows();
|
||||
$respondedArray = $this->getArrayOfShareesResponded(
|
||||
$this->featureContext->getResponse(),
|
||||
$shareeType
|
||||
);
|
||||
Assert::assertEquals(
|
||||
$sharees,
|
||||
$respondedArray,
|
||||
"Returned sharees do not match the expected ones. See the differences below."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the "([^"]*)" sharees returned should include$/
|
||||
*
|
||||
* @param string $shareeType
|
||||
* @param TableNode $shareesList
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theShareesReturnedShouldInclude(string $shareeType, TableNode $shareesList):void {
|
||||
$this->featureContext->verifyTableNodeColumnsCount($shareesList, 3);
|
||||
$sharees = $shareesList->getRows();
|
||||
$respondedArray = $this->getArrayOfShareesResponded(
|
||||
$this->featureContext->getResponse(),
|
||||
$shareeType
|
||||
);
|
||||
foreach ($sharees as $sharee) {
|
||||
Assert::assertContains(
|
||||
$sharee,
|
||||
$respondedArray,
|
||||
"Returned sharees do not match the expected ones. See the differences below."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the "([^"]*)" sharees returned should be empty$/
|
||||
*
|
||||
* @param string $shareeType
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function theShareesReturnedShouldBeEmpty(string $shareeType):void {
|
||||
$respondedArray = $this->getArrayOfShareesResponded(
|
||||
$this->featureContext->getResponse(),
|
||||
$shareeType
|
||||
);
|
||||
if (isset($respondedArray[0])) {
|
||||
// [0] is display name and [2] is user or group id
|
||||
$firstEntry = $respondedArray[0][0] . " (" . $respondedArray[0][2] . ")";
|
||||
} else {
|
||||
$firstEntry = "";
|
||||
}
|
||||
|
||||
Assert::assertEmpty(
|
||||
$respondedArray,
|
||||
"'$shareeType' array should be empty, but it starts with $firstEntry"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ResponseInterface $response
|
||||
* @param string $shareeType
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getArrayOfShareesResponded(
|
||||
ResponseInterface $response,
|
||||
string $shareeType
|
||||
):array {
|
||||
$elements = $this->featureContext->getResponseXml($response, __METHOD__)->data;
|
||||
$elements = \json_decode(\json_encode($elements), true);
|
||||
if (\strpos($shareeType, 'exact ') === 0) {
|
||||
$elements = $elements['exact'];
|
||||
$shareeType = \substr($shareeType, 6);
|
||||
}
|
||||
|
||||
Assert::assertArrayHasKey(
|
||||
$shareeType,
|
||||
$elements,
|
||||
__METHOD__ . " The sharees response does not have key '$shareeType'"
|
||||
);
|
||||
|
||||
$sharees = [];
|
||||
foreach ($elements[$shareeType] as $element) {
|
||||
if (\is_int(\key($element))) {
|
||||
// this is a list of elements instead of just one item,
|
||||
// so return the list
|
||||
foreach ($element as $innerItem) {
|
||||
$sharees[] = [
|
||||
$innerItem['label'],
|
||||
$innerItem['value']['shareType'],
|
||||
$innerItem['value']['shareWith'],
|
||||
$innerItem['value']['shareWithAdditionalInfo']
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$sharees[] = [
|
||||
$element['label'],
|
||||
$element['value']['shareType'],
|
||||
$element['value']['shareWith'],
|
||||
$element['value']['shareWithAdditionalInfo']
|
||||
];
|
||||
}
|
||||
}
|
||||
return $sharees;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param TableNode $body
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function getShareesWithParameters(string $user, TableNode $body): ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$url = '/apps/files_sharing/api/v1/sharees';
|
||||
$this->featureContext->verifyTableNodeColumnsCount($body, 2);
|
||||
$parameters = [];
|
||||
foreach ($body->getRowsHash() as $key => $value) {
|
||||
$parameters[] = "$key=$value";
|
||||
}
|
||||
if (!empty($parameters)) {
|
||||
$url .= '?' . \implode('&', $parameters);
|
||||
}
|
||||
|
||||
return $this->ocsContext->sendRequestToOcsEndpoint(
|
||||
$user,
|
||||
'GET',
|
||||
$url
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope):void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->ocsContext = $environment->getContext('OCSContext');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,411 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Viktor Scharf <v.scharf@owncloud.com>
|
||||
* @copyright Copyright (c) 2022 Viktor Scharf v.scharf@owncloud.com
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\WebDavHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Context for the TUS-specific steps using the Graph API
|
||||
*/
|
||||
class SpacesTUSContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private TUSContext $tusContext;
|
||||
private SpacesContext $spacesContext;
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope): void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context from here
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->spacesContext = $environment->getContext('SpacesContext');
|
||||
$this->tusContext = $environment->getContext('TUSContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has uploaded a file from "([^"]*)" to "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasUploadedFileViaTusInSpace(string $user, string $source, string $destination, string $spaceName): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$this->tusContext->uploadFileUsingTus($user, $source, $destination);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" uploads a file from "([^"]*)" to "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userUploadsAFileViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$this->tusContext->uploadFileUsingTus($user, $source, $destination);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has created a new TUS resource for the space :spaceName with content :content using the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $spaceName
|
||||
* @param string $content
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasCreatedANewTusResourceForTheSpaceUsingTheWebdavApiWithTheseHeaders(
|
||||
string $user,
|
||||
string $spaceName,
|
||||
string $content,
|
||||
TableNode $headers
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$response = $this->tusContext->createNewTUSResourceWithHeaders($user, $headers, $content);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(201, "Expected response status code should be 201", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user creates a new TUS resource for the space :spaceName with content :content using the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $spaceName
|
||||
* @param string $content
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userCreatesANewTusResourceForTheSpaceUsingTheWebdavApiWithTheseHeaders(
|
||||
string $user,
|
||||
string $spaceName,
|
||||
string $content,
|
||||
TableNode $headers
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$response = $this->tusContext->createNewTUSResourceWithHeaders($user, $headers, $content);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads a file with content to the specified space using the TUS protocol via the WebDAV API.
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $resource
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
private function uploadFileViaTus(string $user, string $content, string $resource, string $spaceName): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$tmpFile = $this->tusContext->writeDataToTempFile($content);
|
||||
try {
|
||||
$this->tusContext->uploadFileUsingTus(
|
||||
$user,
|
||||
\basename($tmpFile),
|
||||
$resource
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
} catch (Exception $e) {
|
||||
Assert::assertStringContainsString('Unable to create resource', (string)$e);
|
||||
}
|
||||
\unlink($tmpFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" uploads a file with content "([^"]*)" to "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $resource
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userUploadsAFileWithContentToViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $content,
|
||||
string $resource,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->uploadFileViaTus($user, $content, $resource, $spaceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has uploaded a file with content "([^"]*)" to "([^"]*)" via TUS inside of the space "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $resource
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userHasUploadedAFileWithContentToViaTusInsideOfTheSpace(
|
||||
string $user,
|
||||
string $content,
|
||||
string $resource,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->uploadFileViaTus($user, $content, $resource, $spaceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" uploads a file "([^"]*)" to "([^"]*)" with mtime "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $mtime Time in human-readable format is taken as input which is converted into milliseconds that is used by API
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userUploadsAFileToWithMtimeViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $mtime,
|
||||
string $spaceName
|
||||
): void {
|
||||
switch ($mtime) {
|
||||
case "today":
|
||||
$mtime = date('Y-m-d', strtotime('today'));
|
||||
break;
|
||||
case "yesterday":
|
||||
$mtime = date('Y-m-d', strtotime('yesterday'));
|
||||
break;
|
||||
case "lastWeek":
|
||||
$mtime = date('Y-m-d', strtotime('-7 days'));
|
||||
break;
|
||||
case "lastMonth":
|
||||
$mtime = date('Y-m-d', strtotime('first day of previous month'));
|
||||
break;
|
||||
case "lastYear":
|
||||
$mtime = date('Y-m' . '-01', strtotime('-1 year'));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$mtime = new DateTime($mtime);
|
||||
$mtime = $mtime->format('U');
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->tusContext->uploadFileUsingTus(
|
||||
$user,
|
||||
$source,
|
||||
$destination,
|
||||
['mtime' => $mtime]
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has uploaded file with checksum "([^"]*)" to the last created TUS Location with offset "([^"]*)" and content "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $checksum
|
||||
* @param string $offset
|
||||
* @param string $content
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userHasUploadedFileWithChecksumToTheLastCreatedTusLocationWithOffsetAndContentViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $checksum,
|
||||
string $offset,
|
||||
string $content,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$response = $this->tusContext->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $content, $checksum);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" uploads file with checksum "([^"]*)" to the last created TUS Location with offset "([^"]*)" and content "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $checksum
|
||||
* @param string $offset
|
||||
* @param string $content
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userUploadsFileWithChecksumToTheLastCreatedTusLocationWithOffsetAndContentViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $checksum,
|
||||
string $offset,
|
||||
string $content,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$response = $this->tusContext->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $content, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends a chunk to the last created TUS Location with offset "([^"]*)" and data "([^"]*)" with checksum "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
* @param string $spaceName
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userSendsAChunkToTheLastCreatedTusLocationWithOffsetAndDataWithChecksumViaTusInsideOfTheSpaceUsingTheWebdavApi(
|
||||
string $user,
|
||||
string $offset,
|
||||
string $data,
|
||||
string $checksum,
|
||||
string $spaceName
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$response = $this->tusContext->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" sends a chunk to the last created TUS Location with data "([^"]*)" inside of the space "([^"]*)" with headers:$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $data
|
||||
* @param string $spaceName
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function userSendsAChunkToTheLastCreatedTusLocationWithDataInsideOfTheSpaceWithHeaders(
|
||||
string $user,
|
||||
string $data,
|
||||
string $spaceName,
|
||||
TableNode $headers
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$rows = $headers->getRowsHash();
|
||||
$response = $this->tusContext->sendsAChunkToTUSLocationWithOffsetAndData($user, $rows['Upload-Offset'], $data, $rows['Upload-Checksum'], ['Origin' => $rows['Origin']]);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" overwrites recently shared file with offset "([^"]*)" and data "([^"]*)" with checksum "([^"]*)" via TUS inside of the space "([^"]*)" using the WebDAV API with these headers:$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
* @param string $spaceName
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userOverwritesRecentlySharedFileWithOffsetAndDataWithChecksumViaTusInsideOfTheSpaceUsingTheWebdavApiWithTheseHeaders(
|
||||
string $user,
|
||||
string $offset,
|
||||
string $data,
|
||||
string $checksum,
|
||||
string $spaceName,
|
||||
TableNode $headers
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$createResponse = $this->tusContext->createNewTUSResource($user, $headers);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(201, "", $createResponse);
|
||||
$response = $this->tusContext->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^as "([^"]*)" the mtime of the file "([^"]*)" in space "([^"]*)" should be "([^"]*)"$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $resource
|
||||
* @param string $spaceName
|
||||
* @param string $mtime
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function theMtimeOfTheFileInSpaceShouldBe(
|
||||
string $user,
|
||||
string $resource,
|
||||
string $spaceName,
|
||||
string $mtime
|
||||
): void {
|
||||
$this->spacesContext->setSpaceIDByName($user, $spaceName);
|
||||
$mtime = new DateTime($mtime);
|
||||
Assert::assertEquals(
|
||||
$mtime->format('U'),
|
||||
WebDavHelper::getMtimeOfResource(
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$resource,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$this->featureContext->getDavPathVersion()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,567 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2020, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use TestHelpers\WebDavHelper;
|
||||
use TusPhp\Exception\ConnectionException;
|
||||
use TusPhp\Exception\TusException;
|
||||
use TusPhp\Tus\Client;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* TUS related test steps
|
||||
*/
|
||||
class TUSContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
|
||||
private ?string $resourceLocation = null;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTusResourceLocation(): string {
|
||||
return $this->resourceLocation ?: "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param TableNode $headers
|
||||
* @param string $content
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function createNewTUSResourceWithHeaders(string $user, TableNode $headers, string $content = ''): ResponseInterface {
|
||||
$this->featureContext->verifyTableNodeColumnsCount($headers, 2);
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$password = $this->featureContext->getUserPassword($user);
|
||||
$this->resourceLocation = null;
|
||||
|
||||
$response = $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"POST",
|
||||
null,
|
||||
$headers->getRowsHash(),
|
||||
$content,
|
||||
"files",
|
||||
null,
|
||||
false,
|
||||
$password
|
||||
);
|
||||
$locationHeader = $response->getHeader('Location');
|
||||
if (\sizeof($locationHeader) > 0) {
|
||||
$this->resourceLocation = $locationHeader[0];
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user creates a new TUS resource on the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param TableNode $headers
|
||||
* @param string $content
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userCreateNewTUSResourceWithHeaders(string $user, TableNode $headers, string $content = ''): void {
|
||||
$response = $this->createNewTUSResourceWithHeaders($user, $headers, $content);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has created a new TUS resource on the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param TableNode $headers Tus-Resumable: 1.0.0 header is added automatically
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasCreatedNewTUSResourceWithHeaders(string $user, TableNode $headers): void {
|
||||
$response = $this->createNewTUSResource($user, $headers);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(201, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function createNewTUSResource(string $user, TableNode $headers):ResponseInterface {
|
||||
$rows = $headers->getRows();
|
||||
$rows[] = ['Tus-Resumable', '1.0.0'];
|
||||
return $this->createNewTUSResourceWithHeaders($user, new TableNode($rows));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
* @param array|null $extraHeaders
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function sendsAChunkToTUSLocationWithOffsetAndData(string $user, string $offset, string $data, string $checksum = '', ?array $extraHeaders = null): ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$password = $this->featureContext->getUserPassword($user);
|
||||
$headers = [
|
||||
'Content-Type' => 'application/offset+octet-stream',
|
||||
'Tus-Resumable' => '1.0.0',
|
||||
'Upload-Checksum' => $checksum,
|
||||
'Upload-Offset' => $offset
|
||||
];
|
||||
$headers = empty($extraHeaders) ? $headers : array_merge($headers, $extraHeaders);
|
||||
|
||||
return HttpRequestHelper::sendRequest(
|
||||
$this->resourceLocation,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
'PATCH',
|
||||
$user,
|
||||
$password,
|
||||
$headers,
|
||||
$data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user sends a chunk to the last created TUS Location with offset :offset and data :data using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function userSendsAChunkToTUSLocationWithOffsetAndData(string $user, string $offset, string $data): void {
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file :source to :destination using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string|null $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param array $uploadMetadata array of metadata to be placed in the
|
||||
* `Upload-Metadata` header.
|
||||
* see https://tus.io/protocols/resumable-upload.html#upload-metadata
|
||||
* Don't Base64 encode the value.
|
||||
* @param int $noOfChunks
|
||||
* @param int|null $bytes
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
* @throws ConnectionException
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
* @throws ReflectionException
|
||||
* @throws TusException
|
||||
*/
|
||||
public function userUploadsUsingTusAFileTo(
|
||||
?string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
array $uploadMetadata = [],
|
||||
int $noOfChunks = 1,
|
||||
int $bytes = null,
|
||||
string $checksum = ''
|
||||
): void {
|
||||
$this->uploadFileUsingTus($user, $source, $destination, $uploadMetadata, $noOfChunks, $bytes, $checksum);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param array $uploadMetadata
|
||||
* @param integer $noOfChunks
|
||||
* @param integer $bytes
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function uploadFileUsingTus(
|
||||
?string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
array $uploadMetadata = [],
|
||||
int $noOfChunks = 1,
|
||||
int $bytes = null,
|
||||
string $checksum = ''
|
||||
) {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$password = $this->featureContext->getUserPassword($user);
|
||||
$headers = [
|
||||
'Authorization' => 'Basic ' . \base64_encode($user . ':' . $password)
|
||||
];
|
||||
if ($bytes !== null) {
|
||||
$creationWithUploadHeader = [
|
||||
'Content-Type' => 'application/offset+octet-stream',
|
||||
'Tus-Resumable' => '1.0.0'
|
||||
];
|
||||
$headers = \array_merge($headers, $creationWithUploadHeader);
|
||||
}
|
||||
if ($checksum != '') {
|
||||
$checksumHeader = [
|
||||
'Upload-Checksum' => $checksum
|
||||
];
|
||||
$headers = \array_merge($headers, $checksumHeader);
|
||||
}
|
||||
|
||||
$client = new Client(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
[
|
||||
'verify' => false,
|
||||
'headers' => $headers
|
||||
]
|
||||
);
|
||||
$client->setChecksumAlgorithm('sha1');
|
||||
$client->setApiPath(
|
||||
WebDavHelper::getDavPath(
|
||||
$user,
|
||||
$this->featureContext->getDavPathVersion(),
|
||||
"files",
|
||||
WebDavHelper::$SPACE_ID_FROM_OCIS
|
||||
?: $this->featureContext->getPersonalSpaceIdForUser($user)
|
||||
)
|
||||
);
|
||||
WebDavHelper::$SPACE_ID_FROM_OCIS = '';
|
||||
$client->setMetadata($uploadMetadata);
|
||||
$sourceFile = $this->featureContext->acceptanceTestsDirLocation() . $source;
|
||||
$client->setKey((string)rand())->file($sourceFile, $destination);
|
||||
$this->featureContext->pauseUploadDelete();
|
||||
|
||||
if ($bytes !== null) {
|
||||
$client->file($sourceFile, $destination)->createWithUpload($client->getKey(), $bytes);
|
||||
} elseif (\filesize($sourceFile) === 0) {
|
||||
$client->file($sourceFile, $destination)->createWithUpload($client->getKey(), 0);
|
||||
} elseif ($noOfChunks === 1) {
|
||||
$client->file($sourceFile, $destination)->upload();
|
||||
} else {
|
||||
$bytesPerChunk = (int)\ceil(\filesize($sourceFile) / $noOfChunks);
|
||||
for ($i = 0; $i < $noOfChunks; $i++) {
|
||||
$client->upload($bytesPerChunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file with content :content to :destination using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $destination
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userUploadsAFileWithContentToUsingTus(
|
||||
string $user,
|
||||
string $content,
|
||||
string $destination
|
||||
): void {
|
||||
$temporaryFileName = $this->writeDataToTempFile($content);
|
||||
try {
|
||||
$this->uploadFileUsingTus(
|
||||
$user,
|
||||
\basename($temporaryFileName),
|
||||
$destination
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
} catch (Exception $e) {
|
||||
Assert::assertStringContainsString('TusPhp\Exception\FileException: Unable to create resource', (string)$e);
|
||||
}
|
||||
\unlink($temporaryFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file with content :content in :noOfChunks chunks to :destination using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string|null $user
|
||||
* @param string $content
|
||||
* @param int|null $noOfChunks
|
||||
* @param string $destination
|
||||
*
|
||||
* @return void
|
||||
* @throws ConnectionException
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
* @throws ReflectionException
|
||||
* @throws TusException
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userUploadsAFileWithContentInChunksUsingTus(
|
||||
?string $user,
|
||||
string $content,
|
||||
?int $noOfChunks,
|
||||
string $destination
|
||||
): void {
|
||||
$temporaryFileName = $this->writeDataToTempFile($content);
|
||||
$this->uploadFileUsingTus(
|
||||
$user,
|
||||
\basename($temporaryFileName),
|
||||
$destination,
|
||||
[],
|
||||
$noOfChunks
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
\unlink($temporaryFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file :source to :destination with mtime :mtime using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $destination
|
||||
* @param string $mtime Time in human-readable format is taken as input which is converted into milliseconds that is used by API
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userUploadsFileWithContentToWithMtimeUsingTUS(
|
||||
string $user,
|
||||
string $source,
|
||||
string $destination,
|
||||
string $mtime
|
||||
): void {
|
||||
$mtime = new DateTime($mtime);
|
||||
$mtime = $mtime->format('U');
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$this->uploadFileUsingTus(
|
||||
$user,
|
||||
$source,
|
||||
$destination,
|
||||
['mtime' => $mtime]
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*
|
||||
* @return string the file name
|
||||
* @throws Exception
|
||||
*/
|
||||
public function writeDataToTempFile(string $content): string {
|
||||
$temporaryFileName = \tempnam(
|
||||
$this->featureContext->acceptanceTestsDirLocation(),
|
||||
"tus-upload-test-"
|
||||
);
|
||||
if ($temporaryFileName === false) {
|
||||
throw new \Exception("could not create a temporary filename");
|
||||
}
|
||||
$temporaryFile = \fopen($temporaryFileName, "w");
|
||||
if ($temporaryFile === false) {
|
||||
throw new \Exception("could not open " . $temporaryFileName . " for write");
|
||||
}
|
||||
\fwrite($temporaryFile, $content);
|
||||
\fclose($temporaryFile);
|
||||
return $temporaryFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user creates a new TUS resource with content :content on the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param TableNode $headers
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userCreatesWithUpload(
|
||||
string $user,
|
||||
string $content,
|
||||
TableNode $headers
|
||||
): void {
|
||||
$response = $this->createNewTUSResourceWithHeaders($user, $headers, $content);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user creates file :source and uploads content :content in the same request using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $source
|
||||
* @param string $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userUploadsWithCreatesWithUpload(
|
||||
string $user,
|
||||
string $source,
|
||||
string $content
|
||||
): void {
|
||||
$temporaryFileName = $this->writeDataToTempFile($content);
|
||||
$this->uploadFileUsingTus(
|
||||
$user,
|
||||
\basename($temporaryFileName),
|
||||
$source,
|
||||
[],
|
||||
1,
|
||||
-1
|
||||
);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
\unlink($temporaryFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user uploads file with checksum :checksum to the last created TUS Location with offset :offset and content :content using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $checksum
|
||||
* @param string $offset
|
||||
* @param string $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userUploadsFileWithChecksum(
|
||||
string $user,
|
||||
string $checksum,
|
||||
string $offset,
|
||||
string $content
|
||||
): void {
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $content, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has uploaded file with checksum :checksum to the last created TUS Location with offset :offset and content :content using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $checksum
|
||||
* @param string $offset
|
||||
* @param string $content
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userHasUploadedFileWithChecksum(
|
||||
string $user,
|
||||
string $checksum,
|
||||
string $offset,
|
||||
string $content
|
||||
): void {
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $content, $checksum);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user sends a chunk to the last created TUS Location with offset :offset and data :data with checksum :checksum using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userUploadsChunkFileWithChecksum(string $user, string $offset, string $data, string $checksum): void {
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has uploaded a chunk to the last created TUS Location with offset :offset and data :data with checksum :checksum using the TUS protocol on the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userHasUploadedChunkFileWithChecksum(string $user, string $offset, string $data, string $checksum): void {
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user overwrites recently shared file with offset :offset and data :data with checksum :checksum using the TUS protocol on the WebDAV API with these headers:
|
||||
* @When user :user overwrites existing file with offset :offset and data :data with checksum :checksum using the TUS protocol on the WebDAV API with these headers:
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $offset
|
||||
* @param string $data
|
||||
* @param string $checksum
|
||||
* @param TableNode $headers Tus-Resumable: 1.0.0 header is added automatically
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userOverwritesFileWithChecksum(string $user, string $offset, string $data, string $checksum, TableNode $headers): void {
|
||||
$createResponse = $this->createNewTUSResource($user, $headers);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(201, "", $createResponse);
|
||||
$response = $this->sendsAChunkToTUSLocationWithOffsetAndData($user, $offset, $data, $checksum);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* @author Viktor Scharf <scharf.vi@gmail.com>
|
||||
*
|
||||
* @copyright Copyright (c) 2022, ownCloud GmbH
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\GraphHelper;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* Acceptance test steps related to testing tags features
|
||||
*/
|
||||
class TagContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private SpacesContext $spacesContext;
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope): void {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context from here
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->spacesContext = $environment->getContext('SpacesContext');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createTags(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):ResponseInterface {
|
||||
$tagNameArray = [];
|
||||
foreach ($table->getRows() as $value) {
|
||||
$tagNameArray[] = $value[0];
|
||||
}
|
||||
if ($fileOrFolder === 'folder' || $fileOrFolder === 'folders') {
|
||||
$resourceId = $this->spacesContext->getResourceId($user, $space, $resource);
|
||||
} else {
|
||||
$resourceId = $this->spacesContext->getFileId($user, $space, $resource);
|
||||
}
|
||||
|
||||
return GraphHelper::createTags(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$resourceId,
|
||||
$tagNameArray
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" creates the following tags for (folder|file) "([^"]*)" of space "([^"]*)":$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theUserCreatesFollowingTags(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):void {
|
||||
$response = $this->createTags($user, $fileOrFolder, $resource, $space, $table);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has created the following tags for (folder|file)\s?"([^"]*)" of the space "([^"]*)":$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theUserHasCreatedFollowingTags(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):void {
|
||||
$response = $this->createTags($user, $fileOrFolder, $resource, $space, $table);
|
||||
$this->featureContext->theHttpStatusCodeShouldBe(200, "", $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has tagged the following (folders|files) of the space "([^"]*)":$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $filesOrFolders (files|folders)
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userHasCreatedTheFollowingTagsForFilesOfTheSpace(string $user, string $filesOrFolders, string $space, TableNode $table):void {
|
||||
$this->featureContext->verifyTableNodeColumns($table, ["path", "tagName"]);
|
||||
$rows = $table->getHash();
|
||||
foreach ($rows as $row) {
|
||||
$tags = explode(',', $row['tagName']);
|
||||
$response = $this->createTags($user, $filesOrFolders, $row['path'], $space, new TableNode([$tags]));
|
||||
$this->featureContext->theHttpStatusCodeShouldBe(200, "", $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user lists all available tag(s) via the Graph API
|
||||
*
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theUserGetsAllAvailableTags(string $user):void {
|
||||
// Note: after creating or deleting tags, in some cases tags do not appear or disappear immediately,
|
||||
// So wait is necessary before listing tags
|
||||
sleep(5);
|
||||
$this->featureContext->setResponse(
|
||||
GraphHelper::getTags(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$this->featureContext->getStepLineRef()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then /^the response should (not|)\s?contain following tag(s):$/
|
||||
*
|
||||
* @param string $shouldOrNot (not|)
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function theFollowingTagsShouldExistForUser(string $shouldOrNot, TableNode $table):void {
|
||||
$rows = $table->getRows();
|
||||
foreach ($rows as $row) {
|
||||
$responseArray = $this->featureContext->getJsonDecodedResponse($this->featureContext->getResponse())['value'];
|
||||
if ($shouldOrNot === "not") {
|
||||
Assert::assertFalse(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response should not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
} else {
|
||||
Assert::assertTrue(
|
||||
\in_array($row[0], $responseArray),
|
||||
"the response does not contain the tag $row[0].\nResponse\n"
|
||||
. print_r($responseArray, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function removeTagsFromResourceOfTheSpace(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):ResponseInterface {
|
||||
$tagNameArray = [];
|
||||
foreach ($table->getRows() as $value) {
|
||||
$tagNameArray[] = $value[0];
|
||||
}
|
||||
|
||||
if ($fileOrFolder === 'folder') {
|
||||
$resourceId = $this->spacesContext->getResourceId($user, $space, $resource);
|
||||
} else {
|
||||
$resourceId = $this->spacesContext->getFileId($user, $space, $resource);
|
||||
}
|
||||
|
||||
return GraphHelper::deleteTags(
|
||||
$this->featureContext->getBaseUrl(),
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$user,
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$resourceId,
|
||||
$tagNameArray
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" removes the following tags for (folder|file) "([^"]*)" of space "([^"]*)":$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userRemovesTagsFromResourceOfTheSpace(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):void {
|
||||
$response = $this->removeTagsFromResourceOfTheSpace($user, $fileOrFolder, $resource, $space, $table);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^user "([^"]*)" has removed the following tags for (folder|file) "([^"]*)" of space "([^"]*)":$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileOrFolder (file|folder)
|
||||
* @param string $resource
|
||||
* @param string $space
|
||||
* @param TableNode $table
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function userHAsRemovedTheFollowingTagsForFileOfSpace(string $user, string $fileOrFolder, string $resource, string $space, TableNode $table):void {
|
||||
$response = $this->removeTagsFromResourceOfTheSpace($user, $fileOrFolder, $resource, $space, $table);
|
||||
$this->featureContext->theHttpStatusCodeShouldBe(200, "", $response);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,990 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Artur Neumann <artur@jankaritech.com>
|
||||
* @copyright Copyright (c) 2018 Artur Neumann artur@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Behat\Behat\Context\Context;
|
||||
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
|
||||
use Behat\Gherkin\Node\TableNode;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use TestHelpers\HttpRequestHelper;
|
||||
use TestHelpers\WebDavHelper;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TestHelpers\OcisHelper;
|
||||
|
||||
require_once 'bootstrap.php';
|
||||
|
||||
/**
|
||||
* context containing API steps needed for the locking mechanism of webdav
|
||||
*/
|
||||
class WebDavLockingContext implements Context {
|
||||
private FeatureContext $featureContext;
|
||||
private PublicWebDavContext $publicWebDavContext;
|
||||
private SpacesContext $spacesContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string[][]
|
||||
*/
|
||||
private array $tokenOfLastLock = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
* @param string|null $fullUrl
|
||||
* @param boolean $public if the file is in a public share or not
|
||||
* @param boolean $expectToSucceed
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
private function lockFile(
|
||||
string $user,
|
||||
string $file,
|
||||
TableNode $properties,
|
||||
string $fullUrl = null,
|
||||
bool $public = false,
|
||||
bool $expectToSucceed = true
|
||||
):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
if ($public === true) {
|
||||
$type = "public-files-new";
|
||||
$password = $this->featureContext->getActualPassword("%public%");
|
||||
} else {
|
||||
$type = "files";
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
}
|
||||
$body
|
||||
= "<?xml version='1.0' encoding='UTF-8'?>" .
|
||||
"<d:lockinfo xmlns:d='DAV:'> ";
|
||||
$headers = [];
|
||||
// depth is only 0 or infinity. We don't need to set it more, as there is no lock for the folder
|
||||
$this->featureContext->verifyTableNodeRows($properties, [], ['lockscope', 'timeout']);
|
||||
$propertiesRows = $properties->getRowsHash();
|
||||
|
||||
foreach ($propertiesRows as $property => $value) {
|
||||
if ($property === "timeout") {
|
||||
//properties that are set in the header not in the xml
|
||||
$headers[$property] = $value;
|
||||
} else {
|
||||
$body .= "<d:$property><d:$value/></d:$property>";
|
||||
}
|
||||
}
|
||||
$body .= "</d:lockinfo>";
|
||||
|
||||
if (isset($fullUrl)) {
|
||||
$response = HttpRequestHelper::sendRequest(
|
||||
$fullUrl,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
"LOCK",
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$headers,
|
||||
$body
|
||||
);
|
||||
} else {
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$user,
|
||||
$password,
|
||||
"LOCK",
|
||||
$file,
|
||||
$headers,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion(),
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
|
||||
$xmlPart = $responseXml->xpath("//d:locktoken/d:href");
|
||||
if (isset($xmlPart[0])) {
|
||||
$this->tokenOfLastLock[$user][$file] = (string) $xmlPart[0];
|
||||
} else {
|
||||
if ($expectToSucceed === true) {
|
||||
Assert::fail("could not find lock token after trying to lock '$file'");
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user locks file :file using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userLocksFileSettingPropertiesUsingWebDavAPI(string $user, string $file, TableNode $properties) {
|
||||
$response = $this->lockFile($user, $file, $properties);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user tries to lock file/folder :file using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userTriesToLockFileSettingPropertiesUsingWebDavAPI(string $user, string $file, TableNode $properties) {
|
||||
$response = $this->lockFile($user, $file, $properties, null, false, false);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user locks file :file inside the space :space using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $space
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userLocksFileInProjectSpaceUsingWebDavAPI(string $user, string $file, string $space, TableNode $properties) {
|
||||
$this->featureContext->setResponse($this->userLocksFileInProjectSpace($user, $file, $space, $properties));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $space
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return ResponseInterface|null
|
||||
*
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userLocksFileInProjectSpace(string $user, string $file, string $space, TableNode $properties): ?ResponseInterface {
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($user, $space);
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . '/dav/spaces/' . $spaceId . '/' . $file;
|
||||
return $this->lockFile($user, $file, $properties, $fullUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has locked file :file inside the space :space setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $space
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function userHasLockedFileInProjectSpaceUsingWebDavAPI(string $user, string $file, string $space, TableNode $properties): void {
|
||||
$response = $this->userLocksFileInProjectSpace($user, $file, $space, $properties);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user tries to lock file :file inside the space :space using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $space
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userTriesToLockFileInProjectSpaceUsingWebDavAPI(string $user, string $file, string $space, TableNode $properties) {
|
||||
$spaceId = $this->spacesContext->getSpaceIdByName($user, $space);
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . '/dav/spaces/' . $spaceId . '/' . $file;
|
||||
$response = $this->lockFile($user, $file, $properties, $fullUrl, false, false);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user locks file :file using file-id path :path using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $filePath
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userLocksFileUsingFileIdUsingWebDavAPI(string $user, string $file, string $filePath, TableNode $properties) {
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $filePath;
|
||||
$response = $this->lockFile($user, $file, $properties, $fullUrl);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user tries to lock file :file using file-id path :path using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $filePath
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userTriesToLockFileUsingFileIdUsingWebDavAPI(string $user, string $file, string $filePath, TableNode $properties) {
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $filePath;
|
||||
$response = $this->lockFile($user, $file, $properties, $fullUrl, false, false);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has locked file :file setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasLockedFile(string $user, string $file, TableNode $properties) {
|
||||
$response = $this->lockFile($user, $file, $properties);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has locked file :file inside space :spaceName setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $spaceName
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasLockedFileInsideSpaceSettingTheFollowingProperties(string $user, string $file, string $spaceName, TableNode $properties) {
|
||||
$this->spacesContext->setSpaceIDByName($this->featureContext->getActualUsername($user), $spaceName);
|
||||
$response = $this->lockFile($user, $file, $properties);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has locked file :file using file-id path :path setting the following properties
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
* @param string $filePath
|
||||
* @param TableNode $properties table with no heading with | property | value |
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userHasLockedFileUsingFileId(string $user, string $file, string $filePath, TableNode $properties) {
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $filePath;
|
||||
$response = $this->lockFile($user, $file, $properties, $fullUrl);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the public has locked the last public link shared file/folder setting the following properties
|
||||
*
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publicHasLockedLastSharedFile(TableNode $properties) {
|
||||
$response = $this->lockFile(
|
||||
$this->featureContext->getLastCreatedPublicShareToken(),
|
||||
"/",
|
||||
$properties,
|
||||
null,
|
||||
true
|
||||
);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the public locks the last public link shared file using the WebDAV API setting the following properties
|
||||
* @When the public tries to lock the last public link shared file using the WebDAV API setting the following properties
|
||||
*
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publicLocksLastSharedFile(TableNode $properties) {
|
||||
$token = ($this->featureContext->isUsingSharingNG()) ? $this->featureContext->shareNgGetLastCreatedLinkShareToken() : $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->lockFile(
|
||||
$token,
|
||||
"/",
|
||||
$properties,
|
||||
null,
|
||||
true,
|
||||
false
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given the public has locked :file in the last public link shared folder setting the following properties
|
||||
*
|
||||
* @param string $file
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publicHasLockedFileLastSharedFolder(
|
||||
string $file,
|
||||
TableNode $properties
|
||||
) {
|
||||
$token = ($this->featureContext->isUsingSharingNG()) ? $this->featureContext->shareNgGetLastCreatedLinkShareToken() : $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->lockFile(
|
||||
$token,
|
||||
$file,
|
||||
$properties,
|
||||
null,
|
||||
true
|
||||
);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(200, '', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the public locks "([^"]*)" in the last public link shared folder using the (old|new) public WebDAV API setting the following properties$/
|
||||
* @When /^the public tries to lock "([^"]*)" in the last public link shared folder using the (old|new) public WebDAV API setting the following properties$/
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $publicWebDAVAPIVersion
|
||||
* @param TableNode $properties
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publicLocksFileLastSharedFolder(
|
||||
string $file,
|
||||
string $publicWebDAVAPIVersion,
|
||||
TableNode $properties
|
||||
) {
|
||||
$token = ($this->featureContext->isUsingSharingNG()) ? $this->featureContext->shareNgGetLastCreatedLinkShareToken() : $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->lockFile(
|
||||
$token,
|
||||
$file,
|
||||
$properties,
|
||||
null,
|
||||
true,
|
||||
false
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks the last created lock of file :file using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unlockLastLockUsingWebDavAPI(string $user, string $file) {
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$file,
|
||||
$user,
|
||||
$file
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks the last created lock of file :file inside space :spaceName using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $spaceName
|
||||
* @param string $file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUnlocksTheLastCreatedLockOfFileInsideSpaceUsingTheWebdavApi(string $user, string $spaceName, string $file) {
|
||||
$this->spacesContext->setSpaceIDByName($this->featureContext->getActualUsername($user), $spaceName);
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$file,
|
||||
$user,
|
||||
$file
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks the last created lock of file :itemToUnlock using file-id path :filePath using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $filePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUnlocksTheLastCreatedLockOfFileWithFileIdPathUsingTheWebdavApi(string $user, string $itemToUnlock, string $filePath) {
|
||||
$fullUrl = $this->featureContext->getBaseUrl() . $filePath;
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI($user, $itemToUnlock, $user, $itemToUnlock, false, $fullUrl);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unlockItemWithLastLockOfOtherItemUsingWebDavAPI(
|
||||
string $user,
|
||||
string $itemToUnlock,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$itemToUnlock,
|
||||
$user,
|
||||
$itemToUseLockOf
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks file :itemToUnlock with the last created public lock of file :itemToUseLockOf using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unlockItemWithLastPublicLockOfOtherItemUsingWebDavAPI(
|
||||
string $user,
|
||||
string $itemToUnlock,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$lockOwner = $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$itemToUnlock,
|
||||
$lockOwner,
|
||||
$itemToUseLockOf
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
private function countLockOfResources(
|
||||
string $user,
|
||||
string $itemToUnlock
|
||||
):int {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
$body
|
||||
= "<?xml version='1.0' encoding='UTF-8'?>" .
|
||||
"<d:propfind xmlns:d='DAV:'> " .
|
||||
"<d:prop><d:lockdiscovery/></d:prop>" .
|
||||
"</d:propfind>";
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$user,
|
||||
$password,
|
||||
"PROPFIND",
|
||||
$itemToUnlock,
|
||||
null,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
$body,
|
||||
$this->featureContext->getDavPathVersion()
|
||||
);
|
||||
$responseXml = $this->featureContext->getResponseXml($response, __METHOD__);
|
||||
$xmlPart = $responseXml->xpath("//d:response//d:lockdiscovery/d:activelock");
|
||||
if (\is_array($xmlPart)) {
|
||||
return \count($xmlPart);
|
||||
} else {
|
||||
throw new Exception("xmlPart for 'd:activelock' was expected to be array but found: $xmlPart");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given user :user has unlocked file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $lockOwner
|
||||
* @param string $itemToUseLockOf
|
||||
* @param boolean $public
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception|GuzzleException
|
||||
*/
|
||||
public function hasUnlockItemWithTheLastCreatedLock(
|
||||
string $user,
|
||||
string $itemToUnlock,
|
||||
string $lockOwner,
|
||||
string $itemToUseLockOf,
|
||||
bool $public = false
|
||||
) {
|
||||
$lockCount = $this->countLockOfResources($user, $itemToUnlock);
|
||||
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$itemToUnlock,
|
||||
$lockOwner,
|
||||
$itemToUseLockOf,
|
||||
$public
|
||||
);
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response);
|
||||
|
||||
$lockCountAfterUnlock = $this->countLockOfResources($user, $itemToUnlock);
|
||||
|
||||
Assert::assertEquals(
|
||||
$lockCount - 1,
|
||||
$lockCountAfterUnlock,
|
||||
"Expected $lockCount lock(s) for '$itemToUnlock' but found '$lockCount'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $lockOwner
|
||||
* @param string $itemToUseLockOf
|
||||
* @param boolean $public
|
||||
* @param string|null $fullUrl
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws GuzzleException
|
||||
* @throws JsonException
|
||||
*/
|
||||
public function unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
string $user,
|
||||
string $itemToUnlock,
|
||||
string $lockOwner,
|
||||
string $itemToUseLockOf,
|
||||
bool $public = false,
|
||||
string $fullUrl = null
|
||||
):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$lockOwner = $this->featureContext->getActualUsername($lockOwner);
|
||||
if ($public === true) {
|
||||
$type = "public-files-new";
|
||||
$password = $this->featureContext->getActualPassword("%public%");
|
||||
} else {
|
||||
$type = "files";
|
||||
$password = $this->featureContext->getPasswordForUser($user);
|
||||
}
|
||||
$baseUrl = $this->featureContext->getBaseUrl();
|
||||
if (!isset($this->tokenOfLastLock[$lockOwner][$itemToUseLockOf])) {
|
||||
Assert::fail(
|
||||
"could not find saved token of '$itemToUseLockOf' " .
|
||||
"owned by user '$lockOwner'"
|
||||
);
|
||||
}
|
||||
$headers = [
|
||||
"Lock-Token" => $this->tokenOfLastLock[$lockOwner][$itemToUseLockOf]
|
||||
];
|
||||
if (isset($fullUrl)) {
|
||||
$response = HttpRequestHelper::sendRequest(
|
||||
$fullUrl,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
"UNLOCK",
|
||||
$this->featureContext->getActualUsername($user),
|
||||
$this->featureContext->getPasswordForUser($user),
|
||||
$headers
|
||||
);
|
||||
} else {
|
||||
$response = WebDavHelper::makeDavRequest(
|
||||
$baseUrl,
|
||||
$user,
|
||||
$password,
|
||||
"UNLOCK",
|
||||
$itemToUnlock,
|
||||
$headers,
|
||||
$this->featureContext->getStepLineRef(),
|
||||
null,
|
||||
$this->featureContext->getDavPathVersion(),
|
||||
$type
|
||||
);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @When user :user unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $itemToUnlock
|
||||
* @param string $lockOwner
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUnlocksItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
string $user,
|
||||
string $itemToUnlock,
|
||||
string $lockOwner,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$user,
|
||||
$itemToUnlock,
|
||||
$lockOwner,
|
||||
$itemToUseLockOf
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the public unlocks file :itemToUnlock with the last created lock of file :itemToUseLockOf of user :lockOwner using the WebDAV API
|
||||
*
|
||||
* @param string $itemToUnlock
|
||||
* @param string $lockOwner
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unlockItemAsPublicWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
string $itemToUnlock,
|
||||
string $lockOwner,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$token = ($this->featureContext->isUsingSharingNG()) ? $this->featureContext->shareNgGetLastCreatedLinkShareToken() : $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$token,
|
||||
$itemToUnlock,
|
||||
$lockOwner,
|
||||
$itemToUseLockOf,
|
||||
true
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the public unlocks file :itemToUnlock using the WebDAV API
|
||||
*
|
||||
* @param string $itemToUnlock
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unlockItemAsPublicUsingWebDavAPI(string $itemToUnlock) {
|
||||
$token = ($this->featureContext->isUsingSharingNG()) ? $this->featureContext->shareNgGetLastCreatedLinkShareToken() : $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->unlockItemWithLastLockOfUserAndItemUsingWebDavAPI(
|
||||
$token,
|
||||
$itemToUnlock,
|
||||
$token,
|
||||
$itemToUnlock,
|
||||
true
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" moves (?:file|folder|entry) "([^"]*)" to "([^"]*)" sending the locktoken of (?:file|folder|entry) "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileSource
|
||||
* @param string $fileDestination
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function moveItemSendingLockToken(
|
||||
string $user,
|
||||
string $fileSource,
|
||||
string $fileDestination,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$response = $this->moveItemSendingLockTokenOfUser(
|
||||
$user,
|
||||
$fileSource,
|
||||
$fileDestination,
|
||||
$itemToUseLockOf,
|
||||
$user
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $fileSource
|
||||
* @param string $fileDestination
|
||||
* @param string $itemToUseLockOf
|
||||
* @param string $lockOwner
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function moveItemSendingLockTokenOfUser(
|
||||
string $user,
|
||||
string $fileSource,
|
||||
string $fileDestination,
|
||||
string $itemToUseLockOf,
|
||||
string $lockOwner
|
||||
):ResponseInterface {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$lockOwner = $this->featureContext->getActualUsername($lockOwner);
|
||||
$destination = $this->featureContext->destinationHeaderValue(
|
||||
$user,
|
||||
$fileDestination
|
||||
);
|
||||
$token = $this->tokenOfLastLock[$lockOwner][$itemToUseLockOf];
|
||||
$headers = [
|
||||
"Destination" => $destination,
|
||||
"If" => "(<$token>)"
|
||||
];
|
||||
return $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"MOVE",
|
||||
$fileSource,
|
||||
$headers
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" moves (?:file|folder|entry) "([^"]*)" to "([^"]*)" sending the locktoken of (?:file|folder|entry) "([^"]*)" of user "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $fileSource
|
||||
* @param string $fileDestination
|
||||
* @param string $itemToUseLockOf
|
||||
* @param string $lockOwner
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userMovesItemSendingLockTokenOfUser(
|
||||
string $user,
|
||||
string $fileSource,
|
||||
string $fileDestination,
|
||||
string $itemToUseLockOf,
|
||||
string $lockOwner
|
||||
) {
|
||||
$response = $this->moveItemSendingLockTokenOfUser(
|
||||
$user,
|
||||
$fileSource,
|
||||
$fileDestination,
|
||||
$itemToUseLockOf,
|
||||
$lockOwner
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^user "([^"]*)" uploads file with content "([^"]*)" to "([^"]*)" sending the locktoken of (?:file|folder|entry) "([^"]*)" using the WebDAV API$/
|
||||
*
|
||||
* @param string $user
|
||||
* @param string $content
|
||||
* @param string $destination
|
||||
* @param string $itemToUseLockOf
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function userUploadsAFileWithContentTo(
|
||||
string $user,
|
||||
string $content,
|
||||
string $destination,
|
||||
string $itemToUseLockOf
|
||||
) {
|
||||
$user = $this->featureContext->getActualUsername($user);
|
||||
$token = $this->tokenOfLastLock[$user][$itemToUseLockOf];
|
||||
$this->featureContext->pauseUploadDelete();
|
||||
$response = $this->featureContext->makeDavRequest(
|
||||
$user,
|
||||
"PUT",
|
||||
$destination,
|
||||
["If" => "(<$token>)"],
|
||||
$content
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
$this->featureContext->setLastUploadDeleteTime(\time());
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the public uploads file "([^"]*)" with content "([^"]*)" sending the locktoken of file "([^"]*)" of user "([^"]*)" using the (old|new) public WebDAV API$/
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $content
|
||||
* @param string $itemToUseLockOf
|
||||
* @param string $lockOwner
|
||||
* @param string $publicWebDAVAPIVersion
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
public function publicUploadFileSendingLockTokenOfUser(
|
||||
string $filename,
|
||||
string $content,
|
||||
string $itemToUseLockOf,
|
||||
string $lockOwner,
|
||||
string $publicWebDAVAPIVersion
|
||||
) {
|
||||
$response = $this->publicUploadWithUserLockToken(
|
||||
$filename,
|
||||
$content,
|
||||
$itemToUseLockOf,
|
||||
$lockOwner,
|
||||
$publicWebDAVAPIVersion
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param string $content
|
||||
* @param string $itemToUseLockOf
|
||||
* @param string $lockOwner
|
||||
* @param string $publicWebDAVAPIVersion
|
||||
*
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function publicUploadWithUserLockToken(
|
||||
string $filename,
|
||||
string $content,
|
||||
string $itemToUseLockOf,
|
||||
string $lockOwner,
|
||||
string $publicWebDAVAPIVersion
|
||||
): ResponseInterface {
|
||||
$lockOwner = $this->featureContext->getActualUsername($lockOwner);
|
||||
$headers = [
|
||||
"If" => "(<" . $this->tokenOfLastLock[$lockOwner][$itemToUseLockOf] . ">)"
|
||||
];
|
||||
return $this->publicWebDavContext->publicUploadContent(
|
||||
$filename,
|
||||
'',
|
||||
$content,
|
||||
false,
|
||||
$headers,
|
||||
$publicWebDAVAPIVersion
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^the public uploads file "([^"]*)" with content "([^"]*)" sending the locktoken of "([^"]*)" of the public using the (old|new) public WebDAV API$/
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $content
|
||||
* @param string $itemToUseLockOf
|
||||
* @param string $publicWebDAVAPIVersion
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function publicUploadFileSendingLockTokenOfPublic(
|
||||
string $filename,
|
||||
string $content,
|
||||
string $itemToUseLockOf,
|
||||
string $publicWebDAVAPIVersion
|
||||
) {
|
||||
$lockOwner = $this->featureContext->getLastCreatedPublicShareToken();
|
||||
$response = $this->publicUploadWithUserLockToken(
|
||||
$filename,
|
||||
$content,
|
||||
$itemToUseLockOf,
|
||||
$lockOwner,
|
||||
$publicWebDAVAPIVersion
|
||||
);
|
||||
$this->featureContext->setResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then :count locks should be reported for file :file of user :user by the WebDAV API
|
||||
*
|
||||
* @param int $count
|
||||
* @param string $file
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function numberOfLockShouldBeReported(int $count, string $file, string $user) {
|
||||
$lockCount = $this->countLockOfResources($user, $file);
|
||||
Assert::assertEquals(
|
||||
$count,
|
||||
$lockCount,
|
||||
"Expected $count lock(s) for '$file' but found '$lockCount'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When the user waits for :time seconds to expire the lock
|
||||
*
|
||||
* @param int $time
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function waitForCertainSecondsToExpireTheLock(int $time): void {
|
||||
\sleep($time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then :count locks should be reported for file :file inside the space :space of user :user
|
||||
*
|
||||
* @param int $count
|
||||
* @param string $file
|
||||
* @param string $spaceName
|
||||
* @param string $user
|
||||
*
|
||||
* @return void
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function numberOfLockShouldBeReportedInProjectSpace(int $count, string $file, string $spaceName, string $user) {
|
||||
$response = $this->spacesContext->sendPropfindRequestToSpace($user, $spaceName, $file, null, '0');
|
||||
$this->featureContext->theHTTPStatusCodeShouldBe(207, "", $response);
|
||||
$responseXml = $this->featureContext->getResponseXml($response);
|
||||
$xmlPart = $responseXml->xpath("//d:response//d:lockdiscovery/d:activelock");
|
||||
if (\is_array($xmlPart)) {
|
||||
$lockCount = \count($xmlPart);
|
||||
} else {
|
||||
throw new Exception("xmlPart for 'd:activelock' was expected to be array but found: $xmlPart");
|
||||
}
|
||||
Assert::assertEquals(
|
||||
$count,
|
||||
$lockCount,
|
||||
"Expected $count lock(s) for '$file' inside space '$spaceName' but found '$lockCount'"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run before EVERY scenario.
|
||||
* It will set the properties for this object.
|
||||
*
|
||||
* @BeforeScenario
|
||||
*
|
||||
* @param BeforeScenarioScope $scope
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function before(BeforeScenarioScope $scope) {
|
||||
// Get the environment
|
||||
$environment = $scope->getEnvironment();
|
||||
// Get all the contexts you need in this context
|
||||
$this->featureContext = $environment->getContext('FeatureContext');
|
||||
$this->publicWebDavContext = $environment->getContext('PublicWebDavContext');
|
||||
if (!OcisHelper::isTestingOnReva()) {
|
||||
$this->spacesContext = $environment->getContext('SpacesContext');
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Phil Davis <phil@jankaritech.com>
|
||||
* @copyright Copyright (c) 2020 Phil Davis phil@jankaritech.com
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License,
|
||||
* as published by the Free Software Foundation;
|
||||
* either version 3 of the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
$classLoader = new ClassLoader();
|
||||
|
||||
$classLoader->addPsr4("TestHelpers\\", __DIR__ . "/../../../TestHelpers", true);
|
||||
|
||||
$classLoader->register();
|
||||
|
||||
// while running for the local API tests, the tests code from ownCloud/core is not used
|
||||
// so we need the constants to be defined for the tests to use them, but for the case where,
|
||||
// the tests are running for oC/core API tests, the constants are already defined in the bootstrap.php there
|
||||
// so we do not declare them again to avoid the "already defined" error
|
||||
|
||||
// Sleep for 10 milliseconds
|
||||
if (!\defined('STANDARD_SLEEP_TIME_MILLISEC')) {
|
||||
\define('STANDARD_SLEEP_TIME_MILLISEC', 10);
|
||||
}
|
||||
|
||||
if (!\defined('STANDARD_SLEEP_TIME_MICROSEC')) {
|
||||
\define('STANDARD_SLEEP_TIME_MICROSEC', STANDARD_SLEEP_TIME_MILLISEC * 1000);
|
||||
}
|
||||
|
||||
// Long timeout for use in code that needs to wait for known slow UI
|
||||
if (!\defined('LONG_UI_WAIT_TIMEOUT_MILLISEC')) {
|
||||
\define('LONG_UI_WAIT_TIMEOUT_MILLISEC', 60000);
|
||||
}
|
||||
|
||||
// Default timeout for use in code that needs to wait for the UI
|
||||
if (!\defined('STANDARD_UI_WAIT_TIMEOUT_MILLISEC')) {
|
||||
\define('STANDARD_UI_WAIT_TIMEOUT_MILLISEC', 10000);
|
||||
}
|
||||
|
||||
// Minimum timeout for use in code that needs to wait for the UI
|
||||
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC')) {
|
||||
\define('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC', 500);
|
||||
}
|
||||
|
||||
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC')) {
|
||||
\define('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC', MINIMUM_UI_WAIT_TIMEOUT_MILLISEC * 1000);
|
||||
}
|
||||
|
||||
// Minimum timeout for emails
|
||||
if (!\defined('EMAIL_WAIT_TIMEOUT_SEC')) {
|
||||
\define('EMAIL_WAIT_TIMEOUT_SEC', 10);
|
||||
}
|
||||
if (!\defined('EMAIL_WAIT_TIMEOUT_MILLISEC')) {
|
||||
\define('EMAIL_WAIT_TIMEOUT_MILLISEC', EMAIL_WAIT_TIMEOUT_SEC * 1000);
|
||||
}
|
||||
|
||||
// Default number of times to retry where retries are useful
|
||||
if (!\defined('STANDARD_RETRY_COUNT')) {
|
||||
\define('STANDARD_RETRY_COUNT', 5);
|
||||
}
|
||||
// Minimum number of times to retry where retries are useful
|
||||
if (!\defined('MINIMUM_RETRY_COUNT')) {
|
||||
\define('MINIMUM_RETRY_COUNT', 2);
|
||||
}
|
||||
|
||||
// The remote server-under-test might or might not happen to have this directory.
|
||||
// If it does not exist, then the tests may end up creating it.
|
||||
if (!\defined('ACCEPTANCE_TEST_DIR_ON_REMOTE_SERVER')) {
|
||||
\define('ACCEPTANCE_TEST_DIR_ON_REMOTE_SERVER', 'tests/acceptance');
|
||||
}
|
||||
|
||||
// The following directory should NOT already exist on the remote server-under-test.
|
||||
// Acceptance tests are free to do anything needed in this directory, and to
|
||||
// delete it during or at the end of testing.
|
||||
if (!\defined('TEMPORARY_STORAGE_DIR_ON_REMOTE_SERVER')) {
|
||||
\define('TEMPORARY_STORAGE_DIR_ON_REMOTE_SERVER', ACCEPTANCE_TEST_DIR_ON_REMOTE_SERVER . '/server_tmp');
|
||||
}
|
||||
Reference in New Issue
Block a user