Skip to content

Commit 95fff6b

Browse files
authored
Merge pull request #47540 from nextcloud/fix/folder-creation
fix(files): Correctly check for already used names when creating new folder
2 parents a51e041 + d363647 commit 95fff6b

File tree

6 files changed

+144
-12
lines changed

6 files changed

+144
-12
lines changed

apps/files/src/views/FilesList.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export default defineComponent({
243243
// as the path is allowed to be undefined we need to normalize the path ('//' to '/')
244244
const normalizedPath = normalize(`${this.currentFolder?.path ?? ''}/${path ?? ''}`)
245245
// Try cache first
246-
const nodes = this.filesStore.getNodesByPath(view.id, path)
246+
const nodes = this.filesStore.getNodesByPath(view.id, normalizedPath)
247247
if (nodes.length > 0) {
248248
return nodes
249249
}

cypress/e2e/files/FilesUtils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,19 @@ export const createFolder = (folderName: string) => {
136136

137137
getRowForFile(folderName).should('be.visible')
138138
}
139+
140+
/**
141+
* Check validity of an input element
142+
* @param validity The expected validity message (empty string means it is valid)
143+
* @example
144+
* ```js
145+
* cy.findByRole('textbox')
146+
* .should(haveValidity(/must not be empty/i))
147+
* ```
148+
*/
149+
export const haveValidity = (validity: string | RegExp) => {
150+
if (typeof validity === 'string') {
151+
return (el: JQuery<HTMLElement>) => expect((el.get(0) as HTMLInputElement).validationMessage).to.equal(validity)
152+
}
153+
return (el: JQuery<HTMLElement>) => expect((el.get(0) as HTMLInputElement).validationMessage).to.match(validity)
154+
}

cypress/e2e/files/files-renaming.cy.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,7 @@
44
*/
55

66
import type { User } from '@nextcloud/cypress'
7-
import { getRowForFile, triggerActionForFile } from './FilesUtils'
8-
9-
const haveValidity = (validity: string | RegExp) => {
10-
if (typeof validity === 'string') {
11-
return (el: JQuery<HTMLElement>) => expect((el.get(0) as HTMLInputElement).validationMessage).to.equal(validity)
12-
}
13-
return (el: JQuery<HTMLElement>) => expect((el.get(0) as HTMLInputElement).validationMessage).to.match(validity)
14-
}
7+
import { getRowForFile, haveValidity, triggerActionForFile } from './FilesUtils'
158

169
describe('files: Rename nodes', { testIsolation: true }, () => {
1710
let user: User

cypress/e2e/files/new-menu.cy.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { createFolder, getRowForFile, haveValidity, navigateToFolder } from './FilesUtils'
7+
8+
describe('"New"-menu', { testIsolation: true }, () => {
9+
10+
beforeEach(() => {
11+
cy.createRandomUser().then(($user) => {
12+
cy.login($user)
13+
cy.visit('/apps/files')
14+
})
15+
})
16+
17+
it('Create new folder', () => {
18+
// Click the "new" button
19+
cy.get('[data-cy-upload-picker]')
20+
.findByRole('button', { name: 'New' })
21+
.should('be.visible')
22+
.click()
23+
// Click the "new folder" menu entry
24+
cy.findByRole('menuitem', { name: 'New folder' })
25+
.should('be.visible')
26+
.click()
27+
// Create a folder
28+
cy.intercept('MKCOL', '**/remote.php/dav/files/**').as('mkdir')
29+
cy.findByRole('dialog', { name: /create new folder/i })
30+
.findByRole('textbox', { name: 'Folder name' })
31+
.type('A new folder{enter}')
32+
cy.wait('@mkdir')
33+
// See the folder is visible
34+
getRowForFile('A new folder')
35+
.should('be.visible')
36+
})
37+
38+
it('Does not allow creating forbidden folder names', () => {
39+
// Click the "new" button
40+
cy.get('[data-cy-upload-picker]')
41+
.findByRole('button', { name: 'New' })
42+
.should('be.visible')
43+
.click()
44+
// Click the "new folder" menu entry
45+
cy.findByRole('menuitem', { name: 'New folder' })
46+
.should('be.visible')
47+
.click()
48+
// enter folder name
49+
cy.findByRole('dialog', { name: /create new folder/i })
50+
.findByRole('textbox', { name: 'Folder name' })
51+
.type('.htaccess')
52+
// See that input has invalid state set
53+
cy.findByRole('dialog', { name: /create new folder/i })
54+
.findByRole('textbox', { name: 'Folder name' })
55+
.should(haveValidity(/reserved name/i))
56+
// See that it can not create
57+
cy.findByRole('dialog', { name: /create new folder/i })
58+
.findByRole('button', { name: 'Create' })
59+
.should('be.disabled')
60+
})
61+
62+
it('Does not allow creating folders with already existing names', () => {
63+
createFolder('already exists')
64+
// Click the "new" button
65+
cy.get('[data-cy-upload-picker]')
66+
.findByRole('button', { name: 'New' })
67+
.should('be.visible')
68+
.click()
69+
// Click the "new folder" menu entry
70+
cy.findByRole('menuitem', { name: 'New folder' })
71+
.should('be.visible')
72+
.click()
73+
// enter folder name
74+
cy.findByRole('dialog', { name: /create new folder/i })
75+
.findByRole('textbox', { name: 'Folder name' })
76+
.type('already exists')
77+
// See that input has invalid state set
78+
cy.findByRole('dialog', { name: /create new folder/i })
79+
.findByRole('textbox', { name: 'Folder name' })
80+
.should(haveValidity(/already in use/i))
81+
// See that it can not create
82+
cy.findByRole('dialog', { name: /create new folder/i })
83+
.findByRole('button', { name: 'Create' })
84+
.should('be.disabled')
85+
})
86+
87+
/**
88+
* Regression test of https://github.com/nextcloud/server/issues/47530
89+
*/
90+
it('Create same folder in child folder', () => {
91+
// setup other folders
92+
createFolder('folder')
93+
createFolder('other folder')
94+
navigateToFolder('folder')
95+
96+
// Click the "new" button
97+
cy.get('[data-cy-upload-picker]')
98+
.findByRole('button', { name: 'New' })
99+
.should('be.visible')
100+
.click()
101+
// Click the "new folder" menu entry
102+
cy.findByRole('menuitem', { name: 'New folder' })
103+
.should('be.visible')
104+
.click()
105+
// enter folder name
106+
cy.findByRole('dialog', { name: /create new folder/i })
107+
.findByRole('textbox', { name: 'Folder name' })
108+
.type('other folder')
109+
// See that creating is allowed
110+
cy.findByRole('dialog', { name: /create new folder/i })
111+
.findByRole('textbox', { name: 'Folder name' })
112+
.should(haveValidity(''))
113+
// can create
114+
cy.intercept('MKCOL', '**/remote.php/dav/files/**').as('mkdir')
115+
cy.findByRole('dialog', { name: /create new folder/i })
116+
.findByRole('button', { name: 'Create' })
117+
.click()
118+
cy.wait('@mkdir')
119+
// see it is created
120+
getRowForFile('other folder')
121+
.should('be.visible')
122+
})
123+
})

dist/files-main.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/files-main.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)