From e56fe07bbc15c3fe432b68473ba52e52bab4445c Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Thu, 25 Jul 2024 22:51:12 +0200 Subject: [PATCH] fix(files): Correctly validate new node name * Resolves https://github.com/nextcloud/server/issues/45409 This includes two fixes: 1. The name in the "new node" dialog is correctly selected (e.g. `file.txt` only `file` is selected by default), to allow quick naming 2. `@nextcloud/files` functions for filename validation are used, this allows to use new Nextcloud 30 capabilities (e.g. reserved names) Signed-off-by: Ferdinand Thiessen --- .../components/FileEntry/FileEntryName.vue | 6 +- apps/files/src/components/NewNodeDialog.vue | 321 +++++++----------- cypress/e2e/files/files-renaming.cy.ts | 77 +++++ 3 files changed, 206 insertions(+), 198 deletions(-) create mode 100644 cypress/e2e/files/files-renaming.cy.ts diff --git a/apps/files/src/components/FileEntry/FileEntryName.vue b/apps/files/src/components/FileEntry/FileEntryName.vue index d157730a3df..9aa3bcfeb87 100644 --- a/apps/files/src/components/FileEntry/FileEntryName.vue +++ b/apps/files/src/components/FileEntry/FileEntryName.vue @@ -44,7 +44,7 @@ class="files-list__row-name-link" data-cy-files-list-row-name-link v-bind="linkTo.params"> - + @@ -140,7 +140,7 @@ export default defineComponent({ renameLabel() { const matchLabel: Record = { - [FileType.File]: t('files', 'File name'), + [FileType.File]: t('files', 'Filename'), [FileType.Folder]: t('files', 'Folder name'), } return matchLabel[this.source.type] @@ -190,7 +190,7 @@ export default defineComponent({ watch: { /** - * If renaming starts, select the file name + * If renaming starts, select the filename * in the input, without the extension. * @param renaming */ diff --git a/apps/files/src/components/NewNodeDialog.vue b/apps/files/src/components/NewNodeDialog.vue index 0f6a739d21c..b4647724de3 100644 --- a/apps/files/src/components/NewNodeDialog.vue +++ b/apps/files/src/components/NewNodeDialog.vue @@ -1,226 +1,157 @@ + - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> - - diff --git a/cypress/e2e/files/files-renaming.cy.ts b/cypress/e2e/files/files-renaming.cy.ts new file mode 100644 index 00000000000..9404c9544b0 --- /dev/null +++ b/cypress/e2e/files/files-renaming.cy.ts @@ -0,0 +1,77 @@ +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import type { User } from '@nextcloud/cypress' +import { getRowForFile, triggerActionForFile } from './FilesUtils' + +const haveValidity = (validity: string | RegExp) => { + if (typeof validity === 'string') { + return (el: JQuery) => expect((el.get(0) as HTMLInputElement).validationMessage).to.equal(validity) + } + return (el: JQuery) => expect((el.get(0) as HTMLInputElement).validationMessage).to.match(validity) +} + +describe('files: Rename nodes', { testIsolation: true }, () => { + let user: User + + beforeEach(() => cy.createRandomUser().then(($user) => { + user = $user + + cy.uploadContent(user, new Blob([]), 'text/plain', '/file.txt') + cy.login(user) + cy.visit('/apps/files') + })) + + it('can rename a file', () => { + // All are visible by default + getRowForFile('file.txt').should('be.visible') + + triggerActionForFile('file.txt', 'rename') + + getRowForFile('file.txt') + .findByRole('textbox', { name: 'Filename' }) + .should('be.visible') + .type('{selectAll}other.txt') + .should(haveValidity('')) + .type('{enter}') + + // See it is renamed + getRowForFile('other.txt').should('be.visible') + }) + + /** + * If this test gets flaky than we have a problem: + * It means that the selection is not reliable set to the basename + */ + it('only selects basename of file', () => { + // All are visible by default + getRowForFile('file.txt').should('be.visible') + + triggerActionForFile('file.txt', 'rename') + + getRowForFile('file.txt') + .findByRole('textbox', { name: 'Filename' }) + .should('be.visible') + .should((el) => { + const input = el.get(0) as HTMLInputElement + expect(input.selectionStart).to.equal(0) + expect(input.selectionEnd).to.equal('file'.length) + }) + }) + + it('show validation error on file rename', () => { + // All are visible by default + getRowForFile('file.txt').should('be.visible') + + triggerActionForFile('file.txt', 'rename') + + getRowForFile('file.txt') + .findByRole('textbox', { name: 'Filename' }) + .should('be.visible') + .type('{selectAll}.htaccess') + // See validity + .should(haveValidity(/reserved name/i)) + }) +})