aboutsummaryrefslogtreecommitdiffstats
path: root/build/integration/features/bootstrap/BasicStructure.php
diff options
context:
space:
mode:
Diffstat (limited to 'build/integration/features/bootstrap/BasicStructure.php')
-rw-r--r--build/integration/features/bootstrap/BasicStructure.php404
1 files changed, 333 insertions, 71 deletions
diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php
index d2aed82055a..59a4312913e 100644
--- a/build/integration/features/bootstrap/BasicStructure.php
+++ b/build/integration/features/bootstrap/BasicStructure.php
@@ -1,11 +1,27 @@
<?php
+/**
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+use Behat\Gherkin\Node\TableNode;
use GuzzleHttp\Client;
-use GuzzleHttp\Message\ResponseInterface;
+use GuzzleHttp\Cookie\CookieJar;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\ServerException;
+use PHPUnit\Framework\Assert;
+use Psr\Http\Message\ResponseInterface;
require __DIR__ . '/../../vendor/autoload.php';
trait BasicStructure {
+ use Auth;
+ use Avatar;
+ use Download;
+ use Mail;
+ use Theming;
+
/** @var string */
private $currentUser = '';
@@ -21,22 +37,26 @@ trait BasicStructure {
/** @var ResponseInterface */
private $response = null;
- /** @var \GuzzleHttp\Cookie\CookieJar */
+ /** @var CookieJar */
private $cookieJar;
/** @var string */
- private $requesttoken;
+ private $requestToken;
- public function __construct($baseUrl, $admin, $regular_user_password) {
+ protected $adminUser;
+ protected $regularUser;
+ protected $localBaseUrl;
+ protected $remoteBaseUrl;
+ public function __construct($baseUrl, $admin, $regular_user_password) {
// Initialize your context here
$this->baseUrl = $baseUrl;
$this->adminUser = $admin;
$this->regularUser = $regular_user_password;
- $this->localBaseUrl = substr($this->baseUrl, 0, -4);
- $this->remoteBaseUrl = substr($this->baseUrl, 0, -4);
+ $this->localBaseUrl = $this->baseUrl;
+ $this->remoteBaseUrl = $this->baseUrl;
$this->currentServer = 'LOCAL';
- $this->cookieJar = new \GuzzleHttp\Cookie\CookieJar();
+ $this->cookieJar = new CookieJar();
// in case of ci deployment we take the server url from the environment
$testServerUrl = getenv('TEST_SERVER_URL');
@@ -53,11 +73,11 @@ trait BasicStructure {
}
/**
- * @Given /^using api version "([^"]*)"$/
+ * @Given /^using api version "(\d+)"$/
* @param string $version
*/
public function usingApiVersion($version) {
- $this->apiVersion = $version;
+ $this->apiVersion = (int)$version;
}
/**
@@ -75,7 +95,7 @@ trait BasicStructure {
*/
public function usingServer($server) {
$previousServer = $this->currentServer;
- if ($server === 'LOCAL'){
+ if ($server === 'LOCAL') {
$this->baseUrl = $this->localBaseUrl;
$this->currentServer = 'LOCAL';
return $previousServer;
@@ -98,20 +118,28 @@ trait BasicStructure {
/**
* 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
*/
public function getOCSResponse($response) {
- return $response->xml()->meta[0]->statuscode;
+ $body = simplexml_load_string((string)$response->getBody());
+ if ($body === false) {
+ throw new \RuntimeException('Could not parse OCS response, body is not valid XML');
+ }
+ return $body->meta[0]->statuscode;
}
/**
* This function is needed to use a vertical fashion in the gherkin tables.
+ *
* @param array $arrayOfArrays
* @return array
*/
- public function simplifyArray($arrayOfArrays){
- $a = array_map(function($subArray) { return $subArray[0]; }, $arrayOfArrays);
+ public function simplifyArray($arrayOfArrays) {
+ $a = array_map(function ($subArray) {
+ return $subArray[0];
+ }, $arrayOfArrays);
return $a;
}
@@ -119,7 +147,7 @@ trait BasicStructure {
* @When /^sending "([^"]*)" to "([^"]*)" with$/
* @param string $verb
* @param string $url
- * @param \Behat\Gherkin\Node\TableNode $body
+ * @param TableNode $body
*/
public function sendingToWith($verb, $url, $body) {
$fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url;
@@ -127,25 +155,101 @@ trait BasicStructure {
$options = [];
if ($this->currentUser === 'admin') {
$options['auth'] = $this->adminUser;
- } else {
+ } elseif (strpos($this->currentUser, 'anonymous') !== 0) {
$options['auth'] = [$this->currentUser, $this->regularUser];
}
- if ($body instanceof \Behat\Gherkin\Node\TableNode) {
+ $options['headers'] = [
+ 'OCS-APIRequest' => 'true'
+ ];
+ if ($body instanceof TableNode) {
$fd = $body->getRowsHash();
- $options['body'] = $fd;
+ $options['form_params'] = $fd;
+ }
+
+ // TODO: Fix this hack!
+ if ($verb === 'PUT' && $body === null) {
+ $options['form_params'] = [
+ 'foo' => 'bar',
+ ];
}
try {
- $this->response = $client->send($client->createRequest($verb, $fullUrl, $options));
- } catch (\GuzzleHttp\Exception\ClientException $ex) {
+ $this->response = $client->request($verb, $fullUrl, $options);
+ } catch (ClientException $ex) {
+ $this->response = $ex->getResponse();
+ } catch (ServerException $ex) {
$this->response = $ex->getResponse();
}
}
- public function isExpectedUrl($possibleUrl, $finalPart){
+ /**
+ * @param string $verb
+ * @param string $url
+ * @param TableNode|array|null $body
+ * @param array $headers
+ */
+ protected function sendRequestForJSON(string $verb, string $url, $body = null, array $headers = []): void {
+ $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php" . $url;
+ $client = new Client();
+ $options = [];
+ if ($this->currentUser === 'admin') {
+ $options['auth'] = ['admin', 'admin'];
+ } elseif (strpos($this->currentUser, 'anonymous') !== 0) {
+ $options['auth'] = [$this->currentUser, $this->regularUser];
+ }
+ if ($body instanceof TableNode) {
+ $fd = $body->getRowsHash();
+ $options['form_params'] = $fd;
+ } elseif (is_array($body)) {
+ $options['form_params'] = $body;
+ }
+
+ $options['headers'] = array_merge($headers, [
+ 'OCS-ApiRequest' => 'true',
+ 'Accept' => 'application/json',
+ ]);
+
+ try {
+ $this->response = $client->{$verb}($fullUrl, $options);
+ } catch (ClientException $ex) {
+ $this->response = $ex->getResponse();
+ }
+ }
+
+ /**
+ * @When /^sending "([^"]*)" with exact url to "([^"]*)"$/
+ * @param string $verb
+ * @param string $url
+ */
+ public function sendingToDirectUrl($verb, $url) {
+ $this->sendingToWithDirectUrl($verb, $url, null);
+ }
+
+ public function sendingToWithDirectUrl($verb, $url, $body) {
+ $fullUrl = substr($this->baseUrl, 0, -5) . $url;
+ $client = new Client();
+ $options = [];
+ if ($this->currentUser === 'admin') {
+ $options['auth'] = $this->adminUser;
+ } elseif (strpos($this->currentUser, 'anonymous') !== 0) {
+ $options['auth'] = [$this->currentUser, $this->regularUser];
+ }
+ if ($body instanceof TableNode) {
+ $fd = $body->getRowsHash();
+ $options['form_params'] = $fd;
+ }
+
+ try {
+ $this->response = $client->request($verb, $fullUrl, $options);
+ } catch (ClientException $ex) {
+ $this->response = $ex->getResponse();
+ }
+ }
+
+ public function isExpectedUrl($possibleUrl, $finalPart) {
$baseUrlChopped = substr($this->baseUrl, 0, -4);
$endCharacter = strlen($baseUrlChopped) + strlen($finalPart);
- return (substr($possibleUrl,0,$endCharacter) == "$baseUrlChopped" . "$finalPart");
+ return (substr($possibleUrl, 0, $endCharacter) == "$baseUrlChopped" . "$finalPart");
}
/**
@@ -153,7 +257,7 @@ trait BasicStructure {
* @param int $statusCode
*/
public function theOCSStatusCodeShouldBe($statusCode) {
- PHPUnit_Framework_Assert::assertEquals($statusCode, $this->getOCSResponse($this->response));
+ Assert::assertEquals($statusCode, $this->getOCSResponse($this->response));
}
/**
@@ -161,14 +265,22 @@ trait BasicStructure {
* @param int $statusCode
*/
public function theHTTPStatusCodeShouldBe($statusCode) {
- PHPUnit_Framework_Assert::assertEquals($statusCode, $this->response->getStatusCode());
+ Assert::assertEquals($statusCode, $this->response->getStatusCode());
+ }
+
+ /**
+ * @Then /^the Content-Type should be "([^"]*)"$/
+ * @param string $contentType
+ */
+ public function theContentTypeShouldbe($contentType) {
+ Assert::assertEquals($contentType, $this->response->getHeader('Content-Type')[0]);
}
/**
* @param ResponseInterface $response
*/
private function extracRequestTokenFromResponse(ResponseInterface $response) {
- $this->requesttoken = substr(preg_replace('/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', $response->getBody()->getContents()), 0, 89);
+ $this->requestToken = substr(preg_replace('/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', $response->getBody()->getContents()), 0, 89);
}
/**
@@ -176,7 +288,8 @@ trait BasicStructure {
* @param string $user
*/
public function loggingInUsingWebAs($user) {
- $loginUrl = substr($this->baseUrl, 0, -5);
+ $baseUrl = substr($this->baseUrl, 0, -5);
+ $loginUrl = $baseUrl . '/index.php/login';
// Request a new session and extract CSRF token
$client = new Client();
$response = $client->get(
@@ -193,12 +306,15 @@ trait BasicStructure {
$response = $client->post(
$loginUrl,
[
- 'body' => [
+ 'form_params' => [
'user' => $user,
'password' => $password,
- 'requesttoken' => $this->requesttoken,
+ 'requesttoken' => $this->requestToken,
],
'cookies' => $this->cookieJar,
+ 'headers' => [
+ 'Origin' => $baseUrl,
+ ],
]
);
$this->extracRequestTokenFromResponse($response);
@@ -208,22 +324,33 @@ trait BasicStructure {
* @When Sending a :method to :url with requesttoken
* @param string $method
* @param string $url
+ * @param TableNode|array|null $body
*/
- public function sendingAToWithRequesttoken($method, $url) {
+ public function sendingAToWithRequesttoken($method, $url, $body = null) {
$baseUrl = substr($this->baseUrl, 0, -5);
+ $options = [
+ 'cookies' => $this->cookieJar,
+ 'headers' => [
+ 'requesttoken' => $this->requestToken
+ ],
+ ];
+
+ if ($body instanceof TableNode) {
+ $fd = $body->getRowsHash();
+ $options['form_params'] = $fd;
+ } elseif ($body) {
+ $options = array_merge_recursive($options, $body);
+ }
+
$client = new Client();
- $request = $client->createRequest(
- $method,
- $baseUrl . $url,
- [
- 'cookies' => $this->cookieJar,
- ]
- );
- $request->addHeader('requesttoken', $this->requesttoken);
try {
- $this->response = $client->send($request);
- } catch (\GuzzleHttp\Exception\ClientException $e) {
+ $this->response = $client->request(
+ $method,
+ $baseUrl . $url,
+ $options
+ );
+ } catch (ClientException $e) {
$this->response = $e->getResponse();
}
}
@@ -237,64 +364,199 @@ trait BasicStructure {
$baseUrl = substr($this->baseUrl, 0, -5);
$client = new Client();
- $request = $client->createRequest(
- $method,
- $baseUrl . $url,
- [
- 'cookies' => $this->cookieJar,
- ]
- );
try {
- $this->response = $client->send($request);
- } catch (\GuzzleHttp\Exception\ClientException $e) {
+ $this->response = $client->request(
+ $method,
+ $baseUrl . $url,
+ [
+ 'cookies' => $this->cookieJar
+ ]
+ );
+ } catch (ClientException $e) {
$this->response = $e->getResponse();
}
}
- public static function removeFile($path, $filename){
+ public static function removeFile($path, $filename) {
if (file_exists("$path" . "$filename")) {
unlink("$path" . "$filename");
}
}
/**
+ * @Given User :user modifies text of :filename with text :text
+ * @param string $user
+ * @param string $filename
+ * @param string $text
+ */
+ public function modifyTextOfFile($user, $filename, $text) {
+ self::removeFile($this->getDataDirectory() . "/$user/files", "$filename");
+ file_put_contents($this->getDataDirectory() . "/$user/files" . "$filename", "$text");
+ }
+
+ private function getDataDirectory() {
+ // Based on "runOcc" from CommandLine trait
+ $args = ['config:system:get', 'datadirectory'];
+ $args = array_map(function ($arg) {
+ return escapeshellarg($arg);
+ }, $args);
+ $args[] = '--no-ansi --no-warnings';
+ $args = implode(' ', $args);
+
+ $descriptor = [
+ 0 => ['pipe', 'r'],
+ 1 => ['pipe', 'w'],
+ 2 => ['pipe', 'w'],
+ ];
+ $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $ocPath = '../..');
+ $lastStdOut = stream_get_contents($pipes[1]);
+ proc_close($process);
+
+ return trim($lastStdOut);
+ }
+
+ /**
+ * @Given file :filename is created :times times in :user user data
+ * @param string $filename
+ * @param string $times
+ * @param string $user
+ */
+ public function fileIsCreatedTimesInUserData($filename, $times, $user) {
+ for ($i = 0; $i < $times; $i++) {
+ file_put_contents($this->getDataDirectory() . "/$user/files" . "$filename-$i", "content-$i");
+ }
+ }
+
+ public function createFileSpecificSize($name, $size) {
+ $file = fopen('work/' . "$name", 'w');
+ fseek($file, $size - 1, SEEK_CUR);
+ fwrite($file, 'a'); // write a dummy char at SIZE position
+ fclose($file);
+ }
+
+ public function createFileWithText($name, $text) {
+ $file = fopen('work/' . "$name", 'w');
+ fwrite($file, $text);
+ fclose($file);
+ }
+
+ /**
+ * @Given file :filename of size :size is created in local storage
+ * @param string $filename
+ * @param string $size
+ */
+ public function fileIsCreatedInLocalStorageWithSize($filename, $size) {
+ $this->createFileSpecificSize("local_storage/$filename", $size);
+ }
+
+ /**
+ * @Given file :filename with text :text is created in local storage
+ * @param string $filename
+ * @param string $text
+ */
+ public function fileIsCreatedInLocalStorageWithText($filename, $text) {
+ $this->createFileWithText("local_storage/$filename", $text);
+ }
+
+ /**
+ * @When Sleep for :seconds seconds
+ * @param int $seconds
+ */
+ public function sleepForSeconds($seconds) {
+ sleep((int)$seconds);
+ }
+
+ /**
* @BeforeSuite
*/
- public static function addFilesToSkeleton(){
- for ($i=0; $i<5; $i++){
- file_put_contents("../../core/skeleton/" . "textfile" . "$i" . ".txt", "ownCloud test text file\n");
+ public static function addFilesToSkeleton() {
+ for ($i = 0; $i < 5; $i++) {
+ file_put_contents('../../core/skeleton/' . 'textfile' . "$i" . '.txt', "Nextcloud test text file\n");
}
- if (!file_exists("../../core/skeleton/FOLDER")) {
- mkdir("../../core/skeleton/FOLDER", 0777, true);
+ if (!file_exists('../../core/skeleton/FOLDER')) {
+ mkdir('../../core/skeleton/FOLDER', 0777, true);
}
- if (!file_exists("../../core/skeleton/PARENT")) {
- mkdir("../../core/skeleton/PARENT", 0777, true);
+ if (!file_exists('../../core/skeleton/PARENT')) {
+ mkdir('../../core/skeleton/PARENT', 0777, true);
}
- file_put_contents("../../core/skeleton/PARENT/" . "parent.txt", "ownCloud test text file\n");
- if (!file_exists("../../core/skeleton/PARENT/CHILD")) {
- mkdir("../../core/skeleton/PARENT/CHILD", 0777, true);
+ file_put_contents('../../core/skeleton/PARENT/' . 'parent.txt', "Nextcloud test text file\n");
+ if (!file_exists('../../core/skeleton/PARENT/CHILD')) {
+ mkdir('../../core/skeleton/PARENT/CHILD', 0777, true);
}
- file_put_contents("../../core/skeleton/PARENT/CHILD/" . "child.txt", "ownCloud test text file\n");
+ file_put_contents('../../core/skeleton/PARENT/CHILD/' . 'child.txt', "Nextcloud test text file\n");
}
/**
* @AfterSuite
*/
- public static function removeFilesFromSkeleton(){
- for ($i=0; $i<5; $i++){
- self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt");
+ public static function removeFilesFromSkeleton() {
+ for ($i = 0; $i < 5; $i++) {
+ self::removeFile('../../core/skeleton/', 'textfile' . "$i" . '.txt');
}
- if (is_dir("../../core/skeleton/FOLDER")) {
- rmdir("../../core/skeleton/FOLDER");
+ if (is_dir('../../core/skeleton/FOLDER')) {
+ rmdir('../../core/skeleton/FOLDER');
}
- self::removeFile("../../core/skeleton/PARENT/CHILD/", "child.txt");
- if (is_dir("../../core/skeleton/PARENT/CHILD")) {
- rmdir("../../core/skeleton/PARENT/CHILD");
+ self::removeFile('../../core/skeleton/PARENT/CHILD/', 'child.txt');
+ if (is_dir('../../core/skeleton/PARENT/CHILD')) {
+ rmdir('../../core/skeleton/PARENT/CHILD');
}
- self::removeFile("../../core/skeleton/PARENT/", "parent.txt");
- if (is_dir("../../core/skeleton/PARENT")) {
- rmdir("../../core/skeleton/PARENT");
+ self::removeFile('../../core/skeleton/PARENT/', 'parent.txt');
+ if (is_dir('../../core/skeleton/PARENT')) {
+ rmdir('../../core/skeleton/PARENT');
+ }
+ }
+
+ /**
+ * @BeforeScenario @local_storage
+ */
+ public static function removeFilesFromLocalStorageBefore() {
+ $dir = './work/local_storage/';
+ $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
+ $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
+ foreach ($ri as $file) {
+ $file->isDir() ? rmdir($file) : unlink($file);
}
}
-}
+ /**
+ * @AfterScenario @local_storage
+ */
+ public static function removeFilesFromLocalStorageAfter() {
+ $dir = './work/local_storage/';
+ $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
+ $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
+ foreach ($ri as $file) {
+ $file->isDir() ? rmdir($file) : unlink($file);
+ }
+ }
+
+ /**
+ * @Given /^cookies are reset$/
+ */
+ public function cookiesAreReset() {
+ $this->cookieJar = new CookieJar();
+ }
+
+ /**
+ * @Then The following headers should be set
+ * @param TableNode $table
+ * @throws \Exception
+ */
+ public function theFollowingHeadersShouldBeSet(TableNode $table) {
+ foreach ($table->getTable() as $header) {
+ $headerName = $header[0];
+ $expectedHeaderValue = $header[1];
+ $returnedHeader = $this->response->getHeader($headerName)[0];
+ if ($returnedHeader !== $expectedHeaderValue) {
+ throw new \Exception(
+ sprintf(
+ "Expected value '%s' for header '%s', got '%s'",
+ $expectedHeaderValue,
+ $headerName,
+ $returnedHeader
+ )
+ );
+ }
+ }
+ }
+}