diff options
author | Julius Härtl <jus@bitgrid.net> | 2022-11-09 17:45:20 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-09 17:45:20 +0300 |
commit | 4f1a9a0afb279b14812500aa6b0db184e06fde64 (patch) | |
tree | 55af3f5f349cd51c3c0c8774b0f294907765705e | |
parent | deaa87c8594e7178d8417dcbb3569f68b61e6fd5 (diff) | |
parent | f7596d29f3e17e52f5c9825b8128fbb3117e6130 (diff) |
Merge pull request #3401 from nextcloud/cleanup/direct-editing
-rw-r--r-- | cypress/e2e/directediting.spec.js | 104 | ||||
-rw-r--r-- | cypress/support/commands.js | 10 | ||||
-rw-r--r-- | lib/Controller/DirectSessionController.php | 141 |
3 files changed, 114 insertions, 141 deletions
diff --git a/cypress/e2e/directediting.spec.js b/cypress/e2e/directediting.spec.js new file mode 100644 index 000000000..37ae66e68 --- /dev/null +++ b/cypress/e2e/directediting.spec.js @@ -0,0 +1,104 @@ +import { initUserAndFiles, randHash } from '../utils/index.js' + +const randUser = randHash() + +const createDirectEditingLink = (user, file) => { + cy.login(user, 'password') + return cy.request({ + method: 'POST', + url: `${Cypress.env('baseUrl')}/ocs/v2.php/apps/files/api/v1/directEditing/open?format=json`, + form: true, + body: { + path: file, + }, + auth: { user, pass: 'password' }, + headers: { + 'OCS-ApiRequest': 'true', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }).then(response => { + cy.log(response) + const token = response.body?.ocs?.data?.url + cy.log(`Created direct editing token for ${user}`, token) + return cy.wrap(token) + }) +} + +const createDirectEditingLinkForNewFile = (user, file) => { + cy.login(user, 'password') + return cy.request({ + method: 'POST', + url: `${Cypress.env('baseUrl')}/ocs/v2.php/apps/files/api/v1/directEditing/create?format=json`, + form: true, + body: { + path: file, + editorId: 'text', + creatorId: 'textdocument', + }, + auth: { user, pass: 'password' }, + headers: { + 'OCS-ApiRequest': 'true', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }).then(response => { + cy.log(response) + const token = response.body?.ocs?.data?.url + cy.log(`Created direct editing token for ${user}`, token) + return cy.wrap(token) + }) +} + +describe('direct editing', function() { + before(function() { + initUserAndFiles(randUser, 'test.md', 'empty.md') + }) + + it('Open an existing file, edit and close it', () => { + createDirectEditingLink(randUser, 'empty.md') + .then((token) => { + cy.logout() + cy.visit(token) + }) + const closeRequestAlias = 'closeRequest' + cy.intercept({ method: 'POST', url: '**/session/close' }).as(closeRequestAlias) + + cy.getContent() + .type('# This is a headline') + .type('{enter}') + .type('Some text') + .type('{enter}') + + cy.get('button.icon-close').click() + cy.wait(`@${closeRequestAlias}`).then(() => { + cy.getFileContent(randUser, 'empty.md').then((content) => { + // FIXME: This currently fails due to the save not happening fast enough + // The best would be if we always send the markdown at least on close and perform a save if the content changed + // expect(content).to.equal('# This is a headline\n\nSome text'); + }) + }) + }) + it('Create a file, edit and close it', () => { + createDirectEditingLinkForNewFile(randUser, 'newfile.md') + .then((token) => { + cy.logout() + cy.visit(token) + }) + const closeRequestAlias = 'closeRequest' + cy.intercept({ method: 'POST', url: '**/session/close' }).as(closeRequestAlias) + + cy.getContent() + .type('# This is a headline') + .type('{enter}') + .type('Some text') + .type('{enter}') + + cy.get('button.icon-close').click() + cy.wait(`@${closeRequestAlias}`).then(() => { + cy.getFileContent(randUser, 'newfile.md').then((content) => { + // FIXME: This currently fails due to the save not happening fast enough + // The best would be if we always send the markdown at least on close and perform a save if the content changed + // expect(content).to.equal('# This is a headline\n\nSome text'); + }) + }) + }) +}) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index d9632335d..027d42509 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -228,6 +228,16 @@ Cypress.Commands.add('copyFile', (path, destinationPath) => cy.window() .then(win => win.OC.Files.getClient().copy(path, destinationPath)) ) +Cypress.Commands.add('getFileContent', (userId, path) => { + return cy.request({ + method: 'GET', + url: `${Cypress.env('baseUrl')}/remote.php/webdav/${path}`, + auth: { user: userId, pass: 'password' }, + }).then(response => { + cy.wrap(response.body) + }) +}) + Cypress.Commands.add('propfindFolder', (path, depth = 0) => { return cy.window() .then(win => { diff --git a/lib/Controller/DirectSessionController.php b/lib/Controller/DirectSessionController.php deleted file mode 100644 index bfb2af4d2..000000000 --- a/lib/Controller/DirectSessionController.php +++ /dev/null @@ -1,141 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> - * - * @author Julius Härtl <jus@bitgrid.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program 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 (at your option) 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/>. - * - */ - -declare(strict_types=1); -/** - * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> - * - * @author Julius Härtl <jus@bitgrid.net> - * - * @license GNU AGPL version 3 or any later version - * - * This program 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 (at your option) 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/>. - * - */ - -namespace OCA\Text\Controller; - -use OC\Authentication\Exceptions\InvalidTokenException; -use OCA\Text\Service\ApiService; -use OCP\AppFramework\Controller; -use OCP\AppFramework\Http\Response; -use OCP\DirectEditing\IManager; -use OCP\AppFramework\Http\DataResponse; -use OCP\IRequest; -use OCP\IUserManager; -use OCP\IUserSession; - -class DirectSessionController extends Controller { - private ApiService $apiService; - private IManager $directManager; - private IUserSession $userSession; - private IUserManager $userManager; - - public function __construct(string $appName, IRequest $request, ApiService $apiService, IManager $directManager, IUserSession $userSession, IUserManager $userManager) { - parent::__construct($appName, $request); - $this->apiService = $apiService; - $this->directManager = $directManager; - $this->userSession = $userSession; - $this->userManager = $userManager; - } - - /** - * @PublicPage - */ - public function create(string $token, string $file = null, $guestName = null, bool $forceRecreate = false): DataResponse { - try { - $tokenObject = $this->directManager->getToken($token); - $tokenObject->extend(); - $tokenObject->useTokenScope(); - $node = $tokenObject->getFile(); - $node->touch(); - return new DataResponse([ - 'mtime' => $node->getMTime() - ]); - } catch (InvalidTokenException $e) { - return new DataResponse('error'); - } - //return $this->apiService->create(null, $file, $token, $guestName, $forceRecreate); - } - - /** - * @NoAdminRequired - * @PublicPage - */ - public function fetch(int $documentId, string $sessionId, string $sessionToken): Response { - return $this->apiService->fetch($documentId, $sessionId, $sessionToken); - } - - /** - * @NoAdminRequired - * @PublicPage - */ - public function close(int $documentId, int $sessionId, string $sessionToken): DataResponse { - return $this->apiService->close($documentId, $sessionId, $sessionToken); - } - - /** - * @NoAdminRequired - * @PublicPage - */ - public function push(int $documentId, int $sessionId, string $sessionToken, int $version, array $steps, string $token): DataResponse { - $this->loginTokenUser($token); - return $this->apiService->push($documentId, $sessionId, $sessionToken, $version, $steps, $token); - } - - /** - * @NoAdminRequired - * @PublicPage - */ - public function sync(string $token, int $documentId, int $sessionId, string $sessionToken, int $version = 0, string $autosaveContent = null, bool $force = false, bool $manualSave = false): DataResponse { - $this->loginTokenUser($token); - return $this->apiService->sync($documentId, $sessionId, $sessionToken, $version, $autosaveContent, $force, $manualSave, $token); - } - - /** - * @NoAdminRequired - * @PublicPage - */ - public function updateSession(int $documentId, int $sessionId, string $sessionToken, string $guestName) { - return $this->apiService->updateSession($documentId, $sessionId, $sessionToken, $guestName); - } - - private function loginTokenUser(string $token) { - $tokenObject = $this->directManager->getToken($token); - $user = $this->userManager->get($tokenObject->getUser()); - if ($user !== null) { - $this->userSession->setUser($user); - } - } -} |