The app which enables the users to edit office documents from Nextcloud using ONLYOFFICE Document Server, allows multiple users to collaborate in real time and to save back those changes to Nextcloud
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
onlyoffice-nextcloud/tests/integration/behat/features/bootstrap/CoreContext.php

1451 lines
59 KiB

<?php
declare(strict_types=1);
require __DIR__ . '/../../../../../vendor-bin/behat/vendor/autoload.php';
use Behat\Behat\Context\Context;
use Behat\Hook\AfterScenario;
use Behat\Hook\BeforeSuite;
use Behat\Step\Given;
use Behat\Step\Then;
use Behat\Step\When;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use PHPUnit\Framework\Assert;
use Psr\Http\Message\ResponseInterface;
class CoreContext implements Context
{
const TEST_PASSWORD = "password";
const REGULAR_USER = "editortest";
private ResponseInterface $response;
private ?string $currentUser = null;
private array $createdUsers = [];
private array $createdFiles = [];
private ?int $lastTemplateId = null;
private ?int $lastFileId = null;
private ?array $lastCreatedFile = null;
private ?string $lastCreatedUser = null;
private array $lastCreatedUsers = [];
private array $lastUserList = [];
private ?array $lastMentionResponse = null;
private ?array $lastReferenceResponse = null;
private ?array $lastUrlResponse = null;
private ?ResponseInterface $lastDownloadResponse = null;
private ?array $lastHistoryResponse = null;
private ?array $lastVersionResponse = null;
private ?array $lastConfigResponse = null;
private ?string $lastFilePath = null;
private ?string $lastShareId = null;
private ?string $lastShareToken = null;
private ?array $lastExtraPermissionsResponse = null;
private ?array $lastKeyOperationResponse = null;
private ?array $lastFederationKeyResponse = null;
private ?array $lastHealthcheckResponse = null;
private bool $advancedEnabled = false;
private array $lastAddressSettings = [];
private ?int $otherFileId = null;
private ?array $lastEmailsResponse = null;
public function __construct(
private string $baseUrl,
private string $adminUser,
private string $adminPassword
) {}
#[BeforeSuite]
public static function createPHPUnitConfiguration(): void {
(new \PHPUnit\TextUI\Configuration\Builder())->build([]);
}
#[AfterScenario]
public function cleanUp(): void
{
foreach ($this->createdFiles as [$user, $path]) {
$this->deleteFileViaWebDav($user, $path);
}
$this->createdFiles = [];
$this->setCurrentUser($this->adminUser);
foreach ($this->createdUsers as $username) {
$this->sendOcsRequest('DELETE', "/cloud/users/$username");
}
$this->createdUsers = [];
if ($this->lastTemplateId !== null) {
$this->sendFrontpageRequest('DELETE', 'apps/onlyoffice/ajax/template', ['templateId' => $this->lastTemplateId]);
$this->lastTemplateId = null;
}
$this->lastFileId = null;
$this->lastCreatedFile = null;
$this->lastCreatedUser = null;
$this->lastCreatedUsers = [];
$this->lastUserList = [];
$this->lastMentionResponse = null;
$this->lastReferenceResponse = null;
$this->lastUrlResponse = null;
$this->lastDownloadResponse = null;
$this->lastHistoryResponse = null;
$this->lastVersionResponse = null;
$this->lastConfigResponse = null;
$this->lastFilePath = null;
$this->lastShareId = null;
$this->lastShareToken = null;
$this->lastExtraPermissionsResponse = null;
$this->lastKeyOperationResponse = null;
$this->lastFederationKeyResponse = null;
$this->lastHealthcheckResponse = null;
$this->lastEmailsResponse = null;
if ($this->advancedEnabled) {
$this->disableAdvancedMode();
}
}
#[Given('I am logged in as a regular user')]
public function iAmLoggedInAsARegularUser(): void
{
if (!isset($this->createdUsers[self::REGULAR_USER])) {
$this->setCurrentUser($this->adminUser);
$this->sendOcsRequest('POST', '/cloud/users', [
'userid' => self::REGULAR_USER,
'password' => self::TEST_PASSWORD,
]);
$this->createdUsers[self::REGULAR_USER] = self::REGULAR_USER;
}
$this->setCurrentUser(self::REGULAR_USER);
}
#[Given('a file named :name already exists in my home folder')]
public function aFileNamedAlreadyExistsInMyHomeFolder(string $name): void
{
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/new', [
'name' => $name,
'dir' => '/',
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertArrayNotHasKey('error', $body, 'Failed to create prerequisite file: ' . ($body['error'] ?? ''));
$this->createdFiles[] = [self::REGULAR_USER, '/' . $body['name']];
}
#[Given('a global template :name exists')]
public function aGlobalTemplateExists(string $name): void
{
$previousUser = $this->setCurrentUser($this->adminUser);
$tmp = tempnam(sys_get_temp_dir(), 'behat_') . '.' . pathinfo($name, PATHINFO_EXTENSION);
file_put_contents($tmp, 'placeholder');
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/template', [
'multipart' => [
'name' => 'file',
'contents' => fopen($tmp, 'r'),
'filename' => $name,
],
]);
unlink($tmp);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertArrayHasKey('id', $body, 'Failed to upload template');
$this->lastTemplateId = $body['id'];
$this->setCurrentUser($previousUser);
}
#[When('I create a blank file named :name in my home folder')]
public function iCreateABlankFileNamedInMyHomeFolder(string $name): void
{
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/new', [
'name' => $name,
'dir' => '/',
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
if (isset($body['id'])) {
$this->lastCreatedFile = $body;
$this->createdFiles[] = [self::REGULAR_USER, '/' . $body['name']];
}
}
#[When('I create a file from that template in my home folder')]
public function iCreateAFileFromThatTemplateInMyHomeFolder(): void
{
Assert::assertNotNull($this->lastTemplateId, 'No template was created in this scenario');
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/new', [
'name' => 'fromtemplate.docx',
'dir' => '/',
'templateId' => $this->lastTemplateId,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertArrayNotHasKey('error', $body, 'Failed to create file from template: ' . ($body['error'] ?? ''));
$this->lastCreatedFile = $body;
$this->createdFiles[] = [self::REGULAR_USER, '/' . $body['name']];
}
#[Given('I have the :filename asset file in my home folder')]
public function iHaveTheAssetFileInMyHomeFolder(string $filename): void
{
$assetPath = __DIR__ . '/../../../../assets/' . $filename;
Assert::assertFileExists($assetPath, "Asset file not found: $assetPath");
$client = new Client();
$response = $client->put("{$this->baseUrl}/remote.php/webdav/$filename", [
'auth' => [self::REGULAR_USER, self::TEST_PASSWORD],
'body' => fopen($assetPath, 'r'),
'headers' => ['OCS-ApiRequest' => 'true'],
]);
$fileId = $response->getHeaderLine('OC-FileId');
Assert::assertNotEmpty($fileId, "WebDAV upload did not return OC-FileId for $filename");
$this->lastFileId = (int) $fileId;
$this->lastFilePath = "/$filename";
$this->createdFiles[] = [self::REGULAR_USER, "/$filename"];
}
#[Given('I have a :ext file in my home folder')]
public function iHaveAFileInMyHomeFolder(string $ext): void
{
$name = "testfile.$ext";
$client = new Client();
$response = $client->put("{$this->baseUrl}/remote.php/webdav/$name", [
'auth' => [self::REGULAR_USER, self::TEST_PASSWORD],
'body' => 'placeholder',
'headers' => ['OCS-ApiRequest' => 'true'],
]);
$fileId = $response->getHeaderLine('OC-FileId');
Assert::assertNotEmpty($fileId, "WebDAV upload did not return OC-FileId for $name");
$this->lastFileId = (int) $fileId;
$this->lastFilePath = "/$name";
$this->createdFiles[] = [self::REGULAR_USER, "/$name"];
}
#[When('I convert the file')]
public function iConvertTheFile(): void
{
Assert::assertNotNull($this->lastFileId, 'No file was uploaded in this scenario');
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/convert', [
'fileId' => $this->lastFileId,
]);
$this->response->getBody()->rewind();
$this->lastCreatedFile = json_decode($this->response->getBody()->getContents(), true);
if (isset($this->lastCreatedFile['name'])) {
$this->createdFiles[] = [self::REGULAR_USER, '/' . $this->lastCreatedFile['name']];
}
}
#[Then('the conversion should succeed')]
public function theConversionShouldSucceed(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastCreatedFile ?? [], 'Conversion returned an error: ' . ($this->lastCreatedFile['error'] ?? ''));
Assert::assertArrayHasKey('id', $this->lastCreatedFile ?? []);
}
#[Then('the converted file should be a :ext file')]
public function theConvertedFileShouldBeA(string $ext): void
{
$name = $this->lastCreatedFile['name'] ?? '';
Assert::assertSame($ext, strtolower(pathinfo($name, PATHINFO_EXTENSION)));
}
#[Then('the conversion should not be required')]
public function theConversionShouldNotBeRequired(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertSame('Conversion is not required', $this->lastCreatedFile['error'] ?? null);
}
#[Then('the conversion should fail with an unsupported format error')]
public function theConversionShouldFailWithAnUnsupportedFormatError(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertSame('Format is not supported', $this->lastCreatedFile['error'] ?? null);
}
#[When('I create a file with no name in my home folder')]
public function iCreateAFileWithNoNameInMyHomeFolder(): void
{
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/new', [
'name' => '',
'dir' => '/',
]);
$this->response->getBody()->rewind();
$this->lastCreatedFile = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the file should be created successfully')]
public function theFileShouldBeCreatedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastCreatedFile ?? [], 'File creation returned an error: ' . ($this->lastCreatedFile['error'] ?? ''));
Assert::assertArrayHasKey('id', $this->lastCreatedFile ?? []);
}
#[Then('the created file should be named :name')]
public function theCreatedFileShouldBeNamed(string $name): void
{
Assert::assertSame($name, $this->lastCreatedFile['name'] ?? null);
}
#[Then('the created file should have a different name than :name')]
public function theCreatedFileShouldHaveADifferentNameThan(string $name): void
{
Assert::assertNotSame($name, $this->lastCreatedFile['name'] ?? null);
}
#[Then('the creation should fail')]
public function theCreationShouldFail(): void
{
Assert::assertArrayHasKey('error', $this->lastCreatedFile ?? [], 'Expected creation to fail but no error was returned');
Assert::assertNotEmpty($this->lastCreatedFile['error']);
}
#[Given('another user with an email exists')]
public function anotherUserWithAnEmailExists(): void
{
$this->createTestUser('userwithmail', 'user@example.com');
}
#[Given('another user without an email exists')]
public function anotherUserWithoutAnEmailExists(): void
{
$this->createTestUser('userwithoutmail', null);
}
#[Given('a user with display name :displayName and an email exists')]
public function aUserWithDisplayNameAndAnEmailExists(string $displayName): void
{
$uid = strtolower(str_replace(' ', '_', $displayName));
$this->createTestUser($uid, "$uid@example.com", $displayName);
$this->lastCreatedUser = $uid;
}
#[When('I request the user list for the file')]
public function iRequestTheUserListForTheFile(): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/users?fileId={$this->lastFileId}");
$this->response->getBody()->rewind();
$this->lastUserList = json_decode($this->response->getBody()->getContents(), true) ?? [];
}
#[When('I search for :query in the user list for the file')]
public function iSearchForInTheUserListForTheFile(string $query): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/users?fileId={$this->lastFileId}&search=" . urlencode($query));
$this->response->getBody()->rewind();
$this->lastUserList = json_decode($this->response->getBody()->getContents(), true) ?? [];
}
#[Then('the response should contain that user')]
public function theResponseShouldContainThatUser(): void
{
Assert::assertNotNull($this->lastCreatedUser);
$ids = array_column($this->lastUserList, 'id');
Assert::assertContains($this->lastCreatedUser, $ids);
}
#[Then('the response should not contain that user')]
public function theResponseShouldNotContainThatUser(): void
{
Assert::assertNotNull($this->lastCreatedUser);
$ids = array_column($this->lastUserList, 'id');
Assert::assertNotContains($this->lastCreatedUser, $ids);
}
#[Then('the response should not contain the current user')]
public function theResponseShouldNotContainTheCurrentUser(): void
{
$ids = array_column($this->lastUserList, 'id');
Assert::assertNotContains(self::REGULAR_USER, $ids);
}
#[Then('the response should contain a user named :name')]
public function theResponseShouldContainAUserNamed(string $name): void
{
$names = array_column($this->lastUserList, 'name');
Assert::assertContains($name, $names);
}
#[Then('the response should not contain a user named :name')]
public function theResponseShouldNotContainAUserNamed(string $name): void
{
$names = array_column($this->lastUserList, 'name');
Assert::assertNotContains($name, $names);
}
#[When('I request user info for that user')]
public function iRequestUserInfoForThatUser(): void
{
Assert::assertNotNull($this->lastCreatedUser);
$this->requestUserInfo([$this->lastCreatedUser]);
}
#[When('I request user info for all created users')]
public function iRequestUserInfoForAllCreatedUsers(): void
{
$this->requestUserInfo($this->lastCreatedUsers);
}
#[When('I request user info for :userId')]
public function iRequestUserInfoFor(string $userId): void
{
$this->requestUserInfo([$userId]);
}
#[Then('the response should contain one user')]
public function theResponseShouldContainOneUser(): void
{
Assert::assertCount(1, $this->lastUserList);
}
#[Then('the response should contain :count users')]
public function theResponseShouldContainUsers(int $count): void
{
Assert::assertCount($count, $this->lastUserList);
}
#[Then("that user's name should be :name")]
public function thatUserSNameShouldBe(string $name): void
{
Assert::assertSame($name, $this->lastUserList[0]['name'] ?? null);
}
#[Then('that user should not have an image field')]
public function thatUserShouldNotHaveAnImageField(): void
{
Assert::assertArrayNotHasKey('image', $this->lastUserList[0] ?? []);
}
#[Then('the response should be an empty list')]
public function theResponseShouldBeAnEmptyList(): void
{
Assert::assertSame([], $this->lastUserList);
}
#[When('I mention that user in the document with comment :comment')]
public function iMentionThatUserInTheDocumentWithComment(string $comment): void
{
Assert::assertNotNull($this->lastFileId);
Assert::assertNotNull($this->lastCreatedUser);
$email = "{$this->lastCreatedUser}@example.com";
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/mention', [
'fileId' => $this->lastFileId,
'anchor' => 'anchor1',
'comment' => $comment,
'emails' => [$email],
]);
$this->response->getBody()->rewind();
$this->lastMentionResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the mention should be sent successfully')]
public function theMentionShouldBeSentSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastMentionResponse ?? []);
Assert::assertArrayHasKey('message', $this->lastMentionResponse ?? []);
}
#[Then('the file should be shared with that user')]
public function theFileShouldBeSharedWithThatUser(): void
{
Assert::assertNotNull($this->lastCreatedUser);
$previousUser = $this->setCurrentUser($this->lastCreatedUser);
$this->sendOcsRequest('GET', '/apps/files_sharing/api/v1/shares?shared_with_me=true');
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$sharedFileIds = array_column($body['ocs']['data'] ?? [], 'item_source');
Assert::assertContains($this->lastFileId, $sharedFileIds);
$this->setCurrentUser($previousUser);
}
#[When('I resolve the file by path')]
#[Given('I have already resolved the file by path')]
public function iResolveTheFileByPath(): void
{
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/reference', [
'json' => ['referenceData' => [], 'path' => '/testfile.docx'],
]);
$this->response->getBody()->rewind();
$this->lastReferenceResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I resolve the file by its reference data')]
public function iResolveTheFileByItsReferenceData(): void
{
Assert::assertNotNull($this->lastReferenceResponse);
Assert::assertArrayHasKey('referenceData', $this->lastReferenceResponse, 'No referenceData in previous response');
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/reference', [
'json' => ['referenceData' => $this->lastReferenceResponse['referenceData']],
]);
$this->response->getBody()->rewind();
$this->lastReferenceResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I resolve a file by a path that does not exist')]
public function iResolveAFileByAPathThatDoesNotExist(): void
{
$this->sendFrontpageRequest('POST', 'apps/onlyoffice/ajax/reference', [
'json' => ['referenceData' => [], 'path' => '/nonexistent.docx'],
]);
$this->response->getBody()->rewind();
$this->lastReferenceResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the reference should be resolved successfully')]
public function theReferenceShouldBeResolvedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastReferenceResponse ?? []);
Assert::assertArrayHasKey('fileType', $this->lastReferenceResponse ?? []);
Assert::assertArrayHasKey('url', $this->lastReferenceResponse ?? []);
}
#[Then('the response should contain reference data with a file key and instance id')]
public function theResponseShouldContainReferenceDataWithAFileKeyAndInstanceId(): void
{
$referenceData = $this->lastReferenceResponse['referenceData'] ?? [];
Assert::assertArrayHasKey('fileKey', $referenceData);
Assert::assertArrayHasKey('instanceId', $referenceData);
Assert::assertNotEmpty($referenceData['fileKey']);
Assert::assertNotEmpty($referenceData['instanceId']);
}
#[Then('the reference should not be found')]
public function theReferenceShouldNotBeFound(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastReferenceResponse ?? []);
}
private function requestUserInfo(array $userIds): void
{
$encoded = urlencode(json_encode($userIds));
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/userInfo?userIds=$encoded");
$this->response->getBody()->rewind();
$this->lastUserList = json_decode($this->response->getBody()->getContents(), true) ?? [];
}
private function createTestUser(string $uid, ?string $email, ?string $displayName = null): void
{
$previousUser = $this->setCurrentUser($this->adminUser);
$this->sendOcsRequest('POST', '/cloud/users', array_filter([
'userid' => $uid,
'password' => self::TEST_PASSWORD,
'email' => $email,
'displayName' => $displayName,
]));
$this->createdUsers[$uid] = $uid;
$this->lastCreatedUser = $uid;
$this->lastCreatedUsers[] = $uid;
$this->setCurrentUser($previousUser);
}
#[When('I request the URL for the file')]
public function iRequestTheUrlForTheFile(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/ajax/url?filePath=/testfile.docx');
$this->response->getBody()->rewind();
$this->lastUrlResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I request the URL for a file that does not exist')]
public function iRequestTheUrlForAFileThatDoesNotExist(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/ajax/url?filePath=/nonexistent.docx');
$this->response->getBody()->rewind();
$this->lastUrlResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the response should contain a download URL')]
public function theResponseShouldContainADownloadUrl(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('url', $this->lastUrlResponse ?? []);
Assert::assertNotEmpty($this->lastUrlResponse['url']);
}
#[Then('the file type in the response should be :ext')]
public function theFileTypeInTheResponseShouldBe(string $ext): void
{
Assert::assertSame($ext, $this->lastUrlResponse['fileType'] ?? null);
}
#[Then('the URL request should fail')]
public function theUrlRequestShouldFail(): void
{
Assert::assertArrayHasKey('error', $this->lastUrlResponse ?? []);
}
#[When('I download the file converting it to :ext')]
public function iDownloadTheFileConvertingItTo(string $ext): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest(
'GET',
"apps/onlyoffice/downloadas?fileId={$this->lastFileId}&toExtension=$ext"
);
$this->lastDownloadResponse = $this->response;
}
#[When('I download a file that does not exist')]
public function iDownloadAFileThatDoesNotExist(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/downloadas?fileId=999999');
$this->lastDownloadResponse = $this->response;
}
#[Then('the download should succeed')]
public function theDownloadShouldSucceed(): void
{
Assert::assertSame(200, $this->lastDownloadResponse->getStatusCode());
Assert::assertNotEmpty($this->lastDownloadResponse->getHeaderLine('Content-Disposition'));
}
#[Then('the downloaded file should have the extension :ext')]
public function theDownloadedFileShouldHaveTheExtension(string $ext): void
{
$disposition = $this->lastDownloadResponse->getHeaderLine('Content-Disposition');
Assert::assertSame(1, preg_match('/filename=(?:"(?<quoted>[^"]+)"|(?<unquoted>[^";\s]+))/', $disposition, $matches));
$filename = $matches['quoted'] !== '' ? $matches['quoted'] : $matches['unquoted'];
Assert::assertSame($ext, pathinfo($filename, PATHINFO_EXTENSION));
}
#[Then('no file should be served for download')]
public function noFileShouldBeServedForDownload(): void
{
Assert::assertEmpty($this->lastDownloadResponse->getHeaderLine('Content-Disposition'));
}
#[When('I request the editor config for the file')]
public function iRequestTheEditorConfigForTheFile(): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendOcsRequest('GET', "/apps/onlyoffice/api/v1/config/{$this->lastFileId}");
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastConfigResponse = $body ?? null;
}
#[When('I request the editor config for a file that does not exist')]
public function iRequestTheEditorConfigForAFileThatDoesNotExist(): void
{
$this->sendOcsRequest('GET', '/apps/onlyoffice/api/v1/config/999999');
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastConfigResponse = $body ?? null;
}
#[Then('the config should be returned successfully')]
public function theConfigShouldBeReturnedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertIsArray($this->lastConfigResponse);
Assert::assertArrayNotHasKey('error', $this->lastConfigResponse);
}
#[Then('the config should contain document and editor settings')]
public function theConfigShouldContainDocumentAndEditorSettings(): void
{
Assert::assertArrayHasKey('document', $this->lastConfigResponse ?? []);
Assert::assertArrayHasKey('documentType', $this->lastConfigResponse ?? []);
Assert::assertArrayHasKey('editorConfig', $this->lastConfigResponse ?? []);
Assert::assertArrayHasKey('fileType', $this->lastConfigResponse['document'] ?? []);
Assert::assertArrayHasKey('key', $this->lastConfigResponse['document'] ?? []);
Assert::assertArrayHasKey('title', $this->lastConfigResponse['document'] ?? []);
}
#[Then('the document type should be :type')]
public function theDocumentTypeShouldBe(string $type): void
{
Assert::assertSame($type, $this->lastConfigResponse['documentType'] ?? null);
}
#[Then('the config request should fail with an unsupported format error')]
public function theConfigRequestShouldFailWithAnUnsupportedFormatError(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertSame('Format is not supported', $this->lastConfigResponse['error'] ?? null);
}
#[Then('the config request should fail')]
public function theConfigRequestShouldFail(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastConfigResponse ?? []);
}
#[Given('the file is shared via a link')]
public function theFileIsSharedViaALink(): void
{
$this->createLinkShare(1); // READ only
}
#[Given('the file is shared via a public link with edit permission')]
public function theFileIsSharedViaAPublicLinkWithEditPermission(): void
{
$this->createLinkShare(15); // READ | UPDATE | CREATE | DELETE
}
private function createLinkShare(int $permissions): void
{
Assert::assertNotNull($this->lastFilePath, 'No file has been created in this scenario');
$previousUser = $this->setCurrentUser(self::REGULAR_USER);
$this->sendOcsRequest('POST', '/apps/files_sharing/api/v1/shares', [
'path' => $this->lastFilePath,
'shareType' => 3,
'permissions' => $permissions,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastShareToken = $body['ocs']['data']['token'] ?? null;
$this->lastShareId = (string) ($body['ocs']['data']['id'] ?? '');
Assert::assertNotEmpty($this->lastShareToken, 'Failed to create link share: ' . json_encode($body['ocs']['meta'] ?? []));
$this->setCurrentUser($previousUser);
}
#[When('I lock the document via the share token')]
public function iLockTheDocumentViaTheShareToken(): void
{
Assert::assertNotNull($this->lastShareToken);
$this->sendOcsRequest('POST', '/apps/onlyoffice/api/v1/keylock', [
'shareToken' => $this->lastShareToken,
'path' => '',
'lock' => 1,
'fs' => 0,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastKeyOperationResponse = $body['ocs']['data'] ?? null;
}
#[When('I unlock the document via the share token')]
public function iUnlockTheDocumentViaTheShareToken(): void
{
Assert::assertNotNull($this->lastShareToken);
$this->sendOcsRequest('POST', '/apps/onlyoffice/api/v1/keylock', [
'shareToken' => $this->lastShareToken,
'path' => '',
'lock' => 0,
'fs' => 0,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastKeyOperationResponse = $body['ocs']['data'] ?? null;
}
#[When('I request a preview for the template')]
public function iRequestAPreviewForTheTemplate(): void
{
Assert::assertNotNull($this->lastTemplateId, 'No template was created in this scenario');
$this->sendFrontpageRequest('GET', "apps/onlyoffice/preview?fileId={$this->lastTemplateId}");
}
#[When('I request a preview for a non-existent template')]
public function iRequestAPreviewForANonExistentTemplate(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/preview?fileId=999999');
}
#[When('I request a preview with a zero file id')]
public function iRequestAPreviewWithAZeroFileId(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/preview?fileId=0');
}
#[When('I request a preview with zero dimensions')]
public function iRequestAPreviewWithZeroDimensions(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/preview?fileId=1&x=0&y=0');
}
#[Then('the preview request should be rejected')]
public function thePreviewRequestShouldBeRejected(): void
{
Assert::assertSame(400, $this->response->getStatusCode());
}
#[Then('the preview should not be found')]
public function thePreviewShouldNotBeFound(): void
{
Assert::assertSame(404, $this->response->getStatusCode());
}
#[Then('the preview request should not be rejected')]
public function thePreviewRequestShouldNotBeRejected(): void
{
Assert::assertNotSame(400, $this->response->getStatusCode());
}
#[When('I lock the document via an invalid share token')]
public function iLockTheDocumentViaAnInvalidShareToken(): void
{
$this->sendOcsRequest('POST', '/apps/onlyoffice/api/v1/keylock', [
'shareToken' => 'invalidtoken',
'path' => '',
'lock' => 1,
'fs' => 0,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastKeyOperationResponse = $body['ocs']['data'] ?? null;
}
#[Then('the key operation should succeed')]
public function theKeyOperationShouldSucceed(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastKeyOperationResponse ?? []);
}
#[Then('the key operation should fail')]
public function theKeyOperationShouldFail(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastKeyOperationResponse ?? []);
}
#[Given('the advanced feature is enabled')]
public function theAdvancedFeatureIsEnabled(): void
{
$this->enableAdvancedMode();
}
#[Given('another user exists')]
public function anotherUserExists(): void
{
$this->createTestUser('sharetarget', null);
}
#[Given('the file is shared with that user with update permission and without resharing')]
public function theFileIsSharedWithThatUser(): void
{
Assert::assertNotNull($this->lastFilePath, 'No file has been created in this scenario');
Assert::assertNotNull($this->lastCreatedUser, 'No other user has been created in this scenario');
$previousUser = $this->setCurrentUser(self::REGULAR_USER);
$this->sendOcsRequest('POST', '/apps/files_sharing/api/v1/shares', [
'path' => $this->lastFilePath,
'shareType' => 0,
'shareWith' => $this->lastCreatedUser,
'permissions' => 3, // READ | UPDATE, no SHARE
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastShareId = (string) ($body['ocs']['data']['id'] ?? '');
Assert::assertNotEmpty($this->lastShareId, 'Failed to create share: ' . json_encode($body['ocs']['meta'] ?? []));
$this->setCurrentUser($previousUser);
}
#[When('I request the extra permissions for the file')]
public function iRequestTheExtraPermissionsForTheFile(): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendOcsRequest('GET', "/apps/onlyoffice/api/v1/shares/{$this->lastFileId}");
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastExtraPermissionsResponse = $body['ocs']['data'] ?? null;
}
#[When('I set the review permission on a non-existent share')]
public function iSetTheReviewPermissionOnANonExistentShare(): void
{
$this->sendOcsRequest('PUT', '/apps/onlyoffice/api/v1/shares', [
'extraId' => 0,
'shareId' => 'nonexistent',
'fileId' => 999999,
'permissions' => 1,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastExtraPermissionsResponse = $body['ocs']['data'] ?? null;
}
#[When('I set the review permission on that share')]
public function iSetTheReviewPermissionOnThatShare(): void
{
Assert::assertNotNull($this->lastShareId, 'No share has been created in this scenario');
Assert::assertNotNull($this->lastFileId);
$this->sendOcsRequest('PUT', '/apps/onlyoffice/api/v1/shares', [
'extraId' => 0,
'shareId' => $this->lastShareId,
'fileId' => $this->lastFileId,
'permissions' => 1,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastExtraPermissionsResponse = $body['ocs']['data'] ?? null;
}
#[Then('the extra permissions request should fail')]
public function theExtraPermissionsRequestShouldFail(): void
{
Assert::assertSame(400, $this->response->getStatusCode());
}
#[Then('the extra permissions should be an empty list')]
public function theExtraPermissionsShouldBeAnEmptyList(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertSame([], $this->lastExtraPermissionsResponse);
}
#[Then('the extra permissions request should succeed')]
public function theExtraPermissionsRequestShouldSucceed(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertIsArray($this->lastExtraPermissionsResponse);
}
#[Then('the share should have the review permission set')]
public function theShareShouldHaveTheReviewPermissionSet(): void
{
Assert::assertSame(1, $this->lastExtraPermissionsResponse['permissions'] ?? null);
}
#[Given('a third user exists with a :ext file')]
public function aThirdUserExistsWithAFile(string $ext): void
{
$this->createTestUser('attacker', null);
$name = "attackerfile.$ext";
$client = new Client();
$response = $client->put("{$this->baseUrl}/remote.php/webdav/$name", [
'auth' => ['attacker', self::TEST_PASSWORD],
'body' => 'placeholder',
'headers' => ['OCS-ApiRequest' => 'true'],
]);
$fileId = $response->getHeaderLine('OC-FileId');
Assert::assertNotEmpty($fileId, "WebDAV upload did not return OC-FileId for $name");
$this->otherFileId = (int) $fileId;
$this->createdFiles[] = ['attacker', "/$name"];
}
#[When('the third user sets the review permission using the first user\'s share on their own file')]
public function theThirdUserSetsTheReviewPermissionUsingTheFirstUsersShare(): void
{
Assert::assertNotNull($this->lastShareId, 'No share has been created in this scenario');
Assert::assertNotNull($this->otherFileId, 'No attacker file has been created in this scenario');
$previousUser = $this->setCurrentUser('attacker');
$this->sendOcsRequest('PUT', '/apps/onlyoffice/api/v1/shares', [
'extraId' => 0,
'shareId' => $this->lastShareId,
'fileId' => $this->otherFileId,
'permissions' => 1,
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastExtraPermissionsResponse = $body['ocs']['data'] ?? null;
$this->setCurrentUser($previousUser);
}
#[Given('I am logged in as that share recipient')]
public function iAmLoggedInAsThatShareRecipient(): void
{
Assert::assertNotNull($this->lastCreatedUser, 'No other user has been created in this scenario');
$this->setCurrentUser($this->lastCreatedUser);
}
#[Given('I have updated the file content')]
public function iHaveUpdatedTheFileContent(): void
{
$lastFile = end($this->createdFiles);
Assert::assertNotEmpty($lastFile, 'No file has been created yet');
[$user, $path] = $lastFile;
$auth = $user === $this->adminUser
? [$this->adminUser, $this->adminPassword]
: [$user, self::TEST_PASSWORD];
$client = new Client();
$response = $client->put("{$this->baseUrl}/remote.php/webdav$path", [
'auth' => $auth,
'body' => 'updated content',
'headers' => ['OCS-ApiRequest' => 'true'],
]);
Assert::assertLessThan(400, $response->getStatusCode());
}
#[When('I request the history for the file')]
public function iRequestTheHistoryForTheFile(): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/history?fileId={$this->lastFileId}");
$this->response->getBody()->rewind();
$this->lastHistoryResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I request the history for a file that does not exist')]
public function iRequestTheHistoryForAFileThatDoesNotExist(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/ajax/history?fileId=999999');
$this->response->getBody()->rewind();
$this->lastHistoryResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I request version :version of the file')]
public function iRequestVersionOfTheFile(int $version): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/version?fileId={$this->lastFileId}&version=$version");
$this->response->getBody()->rewind();
$this->lastVersionResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I request version :version of a file that does not exist')]
public function iRequestVersionOfAFileThatDoesNotExist(int $version): void
{
$this->sendFrontpageRequest('GET', "apps/onlyoffice/ajax/version?fileId=999999&version=$version");
$this->response->getBody()->rewind();
$this->lastVersionResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I restore version :version of the file')]
public function iRestoreVersionOfTheFile(int $version): void
{
Assert::assertNotNull($this->lastFileId);
$this->sendFrontpageRequest('PUT', 'apps/onlyoffice/ajax/restore', [
'fileId' => $this->lastFileId,
'version' => $version,
]);
$this->response->getBody()->rewind();
$this->lastHistoryResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[When('I restore version :version of a file that does not exist')]
public function iRestoreVersionOfAFileThatDoesNotExist(int $version): void
{
$this->sendFrontpageRequest('PUT', 'apps/onlyoffice/ajax/restore', [
'fileId' => 999999,
'version' => $version,
]);
$this->response->getBody()->rewind();
$this->lastHistoryResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the history should be retrieved successfully')]
public function theHistoryShouldBeRetrievedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertIsArray($this->lastHistoryResponse);
Assert::assertArrayNotHasKey('error', $this->lastHistoryResponse);
}
#[Then('the history should contain at least 1 entry')]
public function theHistoryShouldContainAtLeast1Entry(): void
{
Assert::assertNotEmpty($this->lastHistoryResponse);
}
#[Then('each history entry should have a key, version, and created timestamp')]
public function eachHistoryEntryShouldHaveAKeyVersionAndCreatedTimestamp(): void
{
Assert::assertNotEmpty($this->lastHistoryResponse);
foreach ($this->lastHistoryResponse as $entry) {
Assert::assertArrayHasKey('key', $entry);
Assert::assertArrayHasKey('version', $entry);
Assert::assertArrayHasKey('created', $entry);
}
}
#[Then('the history request should fail')]
public function theHistoryRequestShouldFail(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastHistoryResponse ?? []);
}
#[Then('the version data should be retrieved successfully')]
public function theVersionDataShouldBeRetrievedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastVersionResponse ?? []);
}
#[Then('the version data should contain a file type and download URL')]
public function theVersionDataShouldContainAFileTypeAndDownloadUrl(): void
{
Assert::assertArrayHasKey('fileType', $this->lastVersionResponse ?? []);
Assert::assertArrayHasKey('url', $this->lastVersionResponse ?? []);
Assert::assertArrayHasKey('key', $this->lastVersionResponse ?? []);
Assert::assertArrayHasKey('version', $this->lastVersionResponse ?? []);
}
#[Then('the version request should fail')]
public function theVersionRequestShouldFail(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastVersionResponse ?? []);
}
#[When('I request the document key via the share token')]
public function iRequestTheDocumentKeyViaTheShareToken(): void
{
Assert::assertNotNull($this->lastShareToken);
$this->sendOcsRequest('POST', '/apps/onlyoffice/api/v1/key', [
'shareToken' => $this->lastShareToken,
'path' => '',
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastFederationKeyResponse = $body['ocs']['data'] ?? null;
}
#[When('I request the document key via an invalid share token')]
public function iRequestTheDocumentKeyViaAnInvalidShareToken(): void
{
$this->sendOcsRequest('POST', '/apps/onlyoffice/api/v1/key', [
'shareToken' => 'invalidtoken',
'path' => '',
]);
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastFederationKeyResponse = $body['ocs']['data'] ?? null;
}
#[Then('the key response should contain a document key')]
public function theKeyResponseShouldContainADocumentKey(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayNotHasKey('error', $this->lastFederationKeyResponse ?? []);
Assert::assertArrayHasKey('key', $this->lastFederationKeyResponse ?? []);
Assert::assertNotEmpty($this->lastFederationKeyResponse['key']);
}
#[Then('the key response should contain an error')]
public function theKeyResponseShouldContainAnError(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertArrayHasKey('error', $this->lastFederationKeyResponse ?? []);
}
#[When('I request the federation healthcheck')]
public function iRequestTheFederationHealthcheck(): void
{
$this->sendOcsRequest('GET', '/apps/onlyoffice/api/v1/healthcheck');
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
$this->lastHealthcheckResponse = $body['ocs']['data'] ?? null;
}
#[Then('the healthcheck should report the service is alive')]
public function theHealthcheckShouldReportTheServiceIsAlive(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertTrue($this->lastHealthcheckResponse['alive'] ?? false);
}
#[Given('a user :username exists')]
public function aUserExists(string $username): void
{
if (!isset($this->createdUsers[$username])) {
$this->createTestUser($username, null);
}
}
#[Given('I am logged in as :username')]
public function iAmLoggedInAs(string $username): void
{
if ($username === 'admin') {
$this->setCurrentUser($this->adminUser);
} else {
$this->setCurrentUser($username);
}
}
#[When('I send a GET request to :path')]
public function iSendAGetRequestTo(string $path): void
{
$this->setCurrentUser($this->adminUser);
$this->sendFrontpageRequest('GET', $path);
}
#[Then('the response status code should be :code')]
public function theResponseStatusCodeShouldBe(int $code): void
{
Assert::assertSame($code, $this->response->getStatusCode());
}
#[Then('the response should be an empty JSON array')]
public function theResponseShouldBeAnEmptyJsonArray(): void
{
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertSame([], $body);
}
#[Then('the response should be an empty JSON object')]
public function theResponseShouldBeAnEmptyJsonObject(): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertSame([], $body);
}
#[Then('the response should contain field :field')]
public function theResponseShouldContainField(string $field): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertIsArray($body);
Assert::assertArrayHasKey($field, $body, "Response does not contain field \"$field\"");
}
#[Then('the response field :field should equal :value')]
public function theResponseFieldShouldEqual(string $field, string $value): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertIsArray($body);
Assert::assertArrayHasKey($field, $body, "Response does not contain field \"$field\"");
Assert::assertSame($value, $body[$field]);
}
#[Then('the response field :field should be empty')]
public function theResponseFieldShouldBeEmpty(string $field): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertIsArray($body);
Assert::assertArrayHasKey($field, $body, "Response does not contain field \"$field\"");
Assert::assertEmpty($body[$field], "Expected field \"$field\" to be empty");
}
#[When('I save valid address settings')]
public function iSaveValidAddressSettings(): void
{
$this->lastAddressSettings = [
'documentserver' => getenv('ONLYOFFICE_DOCUMENT_SERVER_URL') ?: 'http://localhost:8080/',
'documentserverInternal' => getenv('ONLYOFFICE_DOCUMENT_SERVER_INTERNAL_URL') ?: 'http://localhost:8080/',
'storageUrl' => getenv('ONLYOFFICE_STORAGE_URL') ?: 'http://localhost/',
'verifyPeerOff' => 'false',
'secret' => getenv('ONLYOFFICE_SECRET') ?: 'secret',
'jwtHeader' => 'Authorization',
'demo' => 'false',
];
$this->sendFrontpageRequest('PUT', '/apps/onlyoffice/ajax/settings/address', $this->lastAddressSettings);
}
#[When('I save invalid address settings')]
public function iSaveInvalidAddressSettings(): void
{
$this->sendFrontpageRequest('PUT', '/apps/onlyoffice/ajax/settings/address', [
'documentserver' => 'http://invalid.onlyoffice.example/',
'documentserverInternal' => '',
'storageUrl' => '',
'verifyPeerOff' => 'false',
'secret' => '',
'jwtHeader' => 'Authorization',
'demo' => 'false',
]);
}
#[Then('the settings should be saved successfully')]
public function theSettingsShouldBeSavedSuccessfully(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertEmpty($body['error'] ?? '', 'Settings save returned an error: ' . ($body['error'] ?? ''));
}
#[Then('the settings should report a connection error')]
public function theSettingsShouldReportAConnectionError(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertNotEmpty($body['error'] ?? '', 'Expected a connection error but error field was empty');
}
#[Then('the settings should reflect the changes')]
public function theSettingsShouldReflectTheChanges(): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertSame($this->lastAddressSettings['documentserver'], $body['documentserver']);
Assert::assertSame($this->lastAddressSettings['documentserverInternal'], $body['documentserverInternal']);
Assert::assertSame($this->lastAddressSettings['storageUrl'], $body['storageUrl']);
Assert::assertSame($this->lastAddressSettings['jwtHeader'], $body['jwtHeader']);
}
#[Then('the response should contain all address settings fields')]
public function theResponseShouldContainAllAddressSettingsFields(): void
{
$this->response->getBody()->rewind();
$body = json_decode($this->response->getBody()->getContents(), true);
Assert::assertIsArray($body);
foreach (['documentserver', 'documentserverInternal', 'storageUrl', 'verifyPeerOff', 'secret', 'jwtHeader', 'error', 'version'] as $field) {
Assert::assertArrayHasKey($field, $body, "Response does not contain field \"$field\"");
}
}
private function deleteFileViaWebDav(string $user, string $path): void
{
$client = new Client();
$auth = $user === $this->adminUser
? [$this->adminUser, $this->adminPassword]
: [$user, self::TEST_PASSWORD];
try {
$client->delete("{$this->baseUrl}/remote.php/webdav$path", [
'auth' => $auth,
'headers' => ['OCS-ApiRequest' => 'true'],
]);
} catch (ClientException | ServerException) {
// best-effort cleanup
}
}
private function enableAdvancedMode(): void
{
$previousUser = $this->setCurrentUser($this->adminUser);
$this->sendFrontpageRequest('PUT', 'apps/onlyoffice/ajax/settings/common', [
'json' => [
'defFormats' => [],
'editFormats' => [],
'restrictExternalStorage' => false,
'sameTab' => false,
'enableSharing' => false,
'preview' => false,
'advanced' => true,
'cronChecker' => false,
'emailNotifications' => false,
'versionHistory' => false,
'chat' => false,
'compactHeader' => false,
'feedback' => false,
'forcesave' => false,
'liveViewOnShare' => false,
'help' => false,
'reviewDisplay' => 'original',
'theme' => 'default',
'unknownAuthor' => '',
],
]);
$this->advancedEnabled = true;
$this->setCurrentUser($previousUser);
}
private function disableAdvancedMode(): void
{
$previousUser = $this->setCurrentUser($this->adminUser);
$this->sendFrontpageRequest('PUT', 'apps/onlyoffice/ajax/settings/common', [
'json' => [
'defFormats' => [],
'editFormats' => [],
'restrictExternalStorage' => false,
'sameTab' => false,
'enableSharing' => false,
'preview' => false,
'advanced' => false,
'cronChecker' => false,
'emailNotifications' => false,
'versionHistory' => false,
'chat' => false,
'compactHeader' => false,
'feedback' => false,
'forcesave' => false,
'liveViewOnShare' => false,
'help' => false,
'reviewDisplay' => 'original',
'theme' => 'default',
'unknownAuthor' => '',
],
]);
$this->advancedEnabled = false;
$this->setCurrentUser($previousUser);
}
private function setCurrentUser(?string $user): ?string {
$currentUser = $this->currentUser;
$this->currentUser = $user;
return $currentUser;
}
private function sendFrontpageRequest(string $verb, string $url, array|string|null $body = null, array $headers = []): void {
$this->sendRequest($verb, "{$this->baseUrl}/index.php/$url", $body, $headers);
}
private function sendOcsRequest(string $verb, string $url, array|string|null $body = null, array $headers = []): void {
$this->sendRequest($verb, "{$this->baseUrl}/ocs/v2.php/$url", $body, $headers);
}
private function sendRequest(string $verb, string $fullUrl, array|string|null $body = null, array $headers = []): void {
$client = new Client();
$options = [];
if ($this->currentUser === $this->adminUser) {
$options['auth'] = [$this->adminUser, $this->adminPassword];
} elseif ($this->currentUser !== null) {
$options['auth'] = [$this->currentUser, self::TEST_PASSWORD];
}
if (is_array($body) && array_key_exists('multipart', $body)) {
$options['multipart'] = $body;
} elseif (is_array($body) && array_key_exists('json', $body)) {
$options['json'] = $body['json'];
} elseif (is_array($body)) {
$options['form_params'] = $body;
} elseif (is_string($body)) {
$options['body'] = $body;
}
$options['headers'] = [
'OCS-ApiRequest' => 'true',
'Accept' => 'application/json',
...$headers,
];
try {
$this->response = $client->{$verb}($fullUrl, $options);
} catch (ClientException $e) {
$this->response = $e->getResponse();
} catch (ServerException $e) {
$this->response = $e->getResponse();
}
}
#[When('I request the email address list')]
public function iRequestTheEmailAddressList(): void
{
$this->sendFrontpageRequest('GET', 'apps/onlyoffice/ajax/emails');
$this->response->getBody()->rewind();
$this->lastEmailsResponse = json_decode($this->response->getBody()->getContents(), true);
}
#[Then('the email list response should succeed')]
public function theEmailListResponseShouldSucceed(): void
{
Assert::assertSame(200, $this->response->getStatusCode());
Assert::assertIsArray($this->lastEmailsResponse, 'Response body is not valid JSON');
}
#[Then('the response should contain an emails key')]
public function theResponseShouldContainAnEmailsKey(): void
{
Assert::assertArrayHasKey('emails', $this->lastEmailsResponse ?? []);
Assert::assertIsArray($this->lastEmailsResponse['emails']);
}
#[Then('the emails array should be empty')]
public function theEmailsArrayShouldBeEmpty(): void
{
Assert::assertArrayHasKey('emails', $this->lastEmailsResponse ?? []);
Assert::assertEmpty($this->lastEmailsResponse['emails']);
}
}