aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2024-07-26 01:42:31 +0200
committerFerdinand Thiessen <opensource@fthiessen.de>2024-08-01 01:54:42 +0200
commita39f13e94e3b943f2b073e0aa2dfd9d4e3b5f6b8 (patch)
tree09482793f3753158d83991f781eb3eb0a5b76b55
parentbfde05340a22fbb97eec6645eb74e7e0372eada2 (diff)
downloadnextcloud-server-a39f13e94e3b943f2b073e0aa2dfd9d4e3b5f6b8.tar.gz
nextcloud-server-a39f13e94e3b943f2b073e0aa2dfd9d4e3b5f6b8.zip
fix(files): Provide file actions from list entry to make it reactive
This fixes non reactive default action text of the name component. Also use download action as default action so that only one place is needed to define how to download a file. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r--apps/files/src/actions/downloadAction.spec.ts4
-rw-r--r--apps/files/src/actions/downloadAction.ts6
-rw-r--r--apps/files/src/components/FileEntry/FileEntryActions.vue41
-rw-r--r--apps/files/src/components/FileEntry/FileEntryName.vue54
-rw-r--r--apps/files/src/components/FileEntryMixin.ts42
-rw-r--r--apps/files/src/components/FilesListVirtual.vue16
-rw-r--r--cypress.config.ts5
-rw-r--r--cypress/e2e/files/files-download.cy.ts145
-rw-r--r--cypress/e2e/files_sharing/file-request.cy.ts6
-rw-r--r--cypress/e2e/files_sharing/files-shares-view.cy.ts4
-rw-r--r--package-lock.json7
-rw-r--r--package.json1
12 files changed, 252 insertions, 79 deletions
diff --git a/apps/files/src/actions/downloadAction.spec.ts b/apps/files/src/actions/downloadAction.spec.ts
index 8aca20eb4d4..59e533441be 100644
--- a/apps/files/src/actions/downloadAction.spec.ts
+++ b/apps/files/src/actions/downloadAction.spec.ts
@@ -4,7 +4,7 @@
*/
import { action } from './downloadAction'
import { expect } from '@jest/globals'
-import { File, Folder, Permission, View, FileAction } from '@nextcloud/files'
+import { File, Folder, Permission, View, FileAction, DefaultType } from '@nextcloud/files'
const view = {
id: 'files',
@@ -23,7 +23,7 @@ describe('Download action conditions tests', () => {
expect(action.id).toBe('download')
expect(action.displayName([], view)).toBe('Download')
expect(action.iconSvgInline([], view)).toBe('<svg>SvgMock</svg>')
- expect(action.default).toBeUndefined()
+ expect(action.default).toBe(DefaultType.DEFAULT)
expect(action.order).toBe(30)
})
})
diff --git a/apps/files/src/actions/downloadAction.ts b/apps/files/src/actions/downloadAction.ts
index 3ba4e23f0cf..cce1e48579a 100644
--- a/apps/files/src/actions/downloadAction.ts
+++ b/apps/files/src/actions/downloadAction.ts
@@ -4,9 +4,9 @@
*/
import type { ShareAttribute } from '../../../files_sharing/src/sharing'
-import { FileAction, Permission, Node, FileType, View } from '@nextcloud/files'
+import { FileAction, Permission, Node, FileType, View, DefaultType } from '@nextcloud/files'
+import { t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
-import { translate as t } from '@nextcloud/l10n'
import ArrowDownSvg from '@mdi/svg/svg/arrow-down.svg?raw'
@@ -46,6 +46,8 @@ const isDownloadable = function(node: Node) {
export const action = new FileAction({
id: 'download',
+ default: DefaultType.DEFAULT,
+
displayName: () => t('files', 'Download'),
iconSvgInline: () => ArrowDownSvg,
diff --git a/apps/files/src/components/FileEntry/FileEntryActions.vue b/apps/files/src/components/FileEntry/FileEntryActions.vue
index 3df4289b1a0..f886d4be3ec 100644
--- a/apps/files/src/components/FileEntry/FileEntryActions.vue
+++ b/apps/files/src/components/FileEntry/FileEntryActions.vue
@@ -79,10 +79,10 @@
import type { PropType, ShallowRef } from 'vue'
import type { FileAction, Node, View } from '@nextcloud/files'
-import { DefaultType, NodeStatus, getFileActions } from '@nextcloud/files'
+import { DefaultType, NodeStatus } from '@nextcloud/files'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
-import { defineComponent } from 'vue'
+import { defineComponent, inject } from 'vue'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
@@ -95,9 +95,6 @@ import CustomElementRender from '../CustomElementRender.vue'
import { useNavigation } from '../../composables/useNavigation'
import logger from '../../logger.js'
-// The registered actions list
-const actions = getFileActions()
-
export default defineComponent({
name: 'FileEntryActions',
@@ -136,10 +133,12 @@ export default defineComponent({
setup() {
const { currentView } = useNavigation()
+ const enabledFileActions = inject<FileAction[]>('enabledFileActions', [])
return {
// The file list is guaranteed to be only shown with active view
currentView: currentView as ShallowRef<View>,
+ enabledFileActions,
}
},
@@ -158,23 +157,12 @@ export default defineComponent({
return this.source.status === NodeStatus.LOADING
},
- // Sorted actions that are enabled for this node
- enabledActions() {
- if (this.source.status === NodeStatus.FAILED) {
- return []
- }
-
- return actions
- .filter(action => !action.enabled || action.enabled([this.source], this.currentView))
- .sort((a, b) => (a.order || 0) - (b.order || 0))
- },
-
// Enabled action that are displayed inline
enabledInlineActions() {
if (this.filesListWidth < 768 || this.gridMode) {
return []
}
- return this.enabledActions.filter(action => action?.inline?.(this.source, this.currentView))
+ return this.enabledFileActions.filter(action => action?.inline?.(this.source, this.currentView))
},
// Enabled action that are displayed inline with a custom render function
@@ -182,12 +170,7 @@ export default defineComponent({
if (this.gridMode) {
return []
}
- return this.enabledActions.filter(action => typeof action.renderInline === 'function')
- },
-
- // Default actions
- enabledDefaultActions() {
- return this.enabledActions.filter(action => !!action?.default)
+ return this.enabledFileActions.filter(action => typeof action.renderInline === 'function')
},
// Actions shown in the menu
@@ -202,7 +185,7 @@ export default defineComponent({
// Showing inline first for the NcActions inline prop
...this.enabledInlineActions,
// Then the rest
- ...this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN && typeof action.renderInline !== 'function'),
+ ...this.enabledFileActions.filter(action => action.default !== DefaultType.HIDDEN && typeof action.renderInline !== 'function'),
].filter((value, index, self) => {
// Then we filter duplicates to prevent inline actions to be shown twice
return index === self.findIndex(action => action.id === value.id)
@@ -216,7 +199,7 @@ export default defineComponent({
},
enabledSubmenuActions() {
- return this.enabledActions
+ return this.enabledFileActions
.filter(action => action.parent)
.reduce((arr, action) => {
if (!arr[action.parent!]) {
@@ -305,14 +288,6 @@ export default defineComponent({
}
}
},
- execDefaultAction(event) {
- if (this.enabledDefaultActions.length > 0) {
- event.preventDefault()
- event.stopPropagation()
- // Execute the first default action if any
- this.enabledDefaultActions[0].exec(this.source, this.currentView, this.currentDir)
- }
- },
isMenu(id: string) {
return this.enabledSubmenuActions[id]?.length > 0
diff --git a/apps/files/src/components/FileEntry/FileEntryName.vue b/apps/files/src/components/FileEntry/FileEntryName.vue
index 7a6ad2a1051..329ec7fdf19 100644
--- a/apps/files/src/components/FileEntry/FileEntryName.vue
+++ b/apps/files/src/components/FileEntry/FileEntryName.vue
@@ -37,19 +37,20 @@
</template>
<script lang="ts">
-import type { Node } from '@nextcloud/files'
+import type { FileAction, Node } from '@nextcloud/files'
import type { PropType } from 'vue'
import axios, { isAxiosError } from '@nextcloud/axios'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
-import { FileType, NodeStatus, Permission } from '@nextcloud/files'
+import { FileType, NodeStatus } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
-import { defineComponent } from 'vue'
+import { defineComponent, inject } from 'vue'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import { useNavigation } from '../../composables/useNavigation'
+import { useRouteParameters } from '../../composables/useRouteParameters.ts'
import { useRenamingStore } from '../../store/renaming.ts'
import { getFilenameValidity } from '../../utils/filenameValidity.ts'
import logger from '../../logger.js'
@@ -98,8 +99,11 @@ export default defineComponent({
const { currentView } = useNavigation()
const renamingStore = useRenamingStore()
+ const defaultFileAction = inject<FileAction | undefined>('defaultFileAction')
+
return {
currentView,
+ defaultFileAction,
renamingStore,
}
@@ -139,32 +143,20 @@ export default defineComponent({
}
}
- const enabledDefaultActions = this.$parent?.$refs?.actions?.enabledDefaultActions
- if (enabledDefaultActions?.length > 0) {
- const action = enabledDefaultActions[0]
- const displayName = action.displayName([this.source], this.currentView)
+ if (this.defaultFileAction && this.currentView) {
+ const displayName = this.defaultFileAction.displayName([this.source], this.currentView)
return {
- is: 'a',
+ is: 'button',
params: {
+ 'aria-label': displayName,
title: displayName,
- role: 'button',
- tabindex: '0',
- },
- }
- }
-
- if (this.source?.permissions & Permission.READ) {
- return {
- is: 'a',
- params: {
- download: this.source.basename,
- href: this.source.source,
- title: t('files', 'Download file {name}', { name: `${this.basename}${this.extension}` }),
tabindex: '0',
},
}
}
+ // nothing interactive here, there is no default action
+ // so if not even the download action works we only can show the list entry
return {
is: 'span',
}
@@ -280,12 +272,15 @@ export default defineComponent({
// Reset the renaming store
this.stopRenaming()
this.$nextTick(() => {
- this.$refs.basename?.focus()
+ const nameContainter = this.$refs.basename as HTMLElement | undefined
+ nameContainter?.focus()
})
} catch (error) {
logger.error('Error while renaming file', { error })
+ // Rename back as it failed
this.source.rename(oldName)
- this.$refs.renameInput?.focus()
+ // And ensure we reset to the renaming state
+ this.startRenaming()
if (isAxiosError(error)) {
// TODO: 409 means current folder does not exist, redirect ?
@@ -309,3 +304,16 @@ export default defineComponent({
},
})
</script>
+
+<style scoped lang="scss">
+button.files-list__row-name-link {
+ background-color: unset;
+ border: none;
+ font-weight: normal;
+
+ &:active {
+ // No active styles - handled by the row entry
+ background-color: unset !important;
+ }
+}
+</style>
diff --git a/apps/files/src/components/FileEntryMixin.ts b/apps/files/src/components/FileEntryMixin.ts
index d9117053dd8..e18841e159e 100644
--- a/apps/files/src/components/FileEntryMixin.ts
+++ b/apps/files/src/components/FileEntryMixin.ts
@@ -3,11 +3,11 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import type { ComponentPublicInstance, PropType } from 'vue'
+import type { PropType } from 'vue'
import type { FileSource } from '../types.ts'
import { showError } from '@nextcloud/dialogs'
-import { FileType, Permission, Folder, File as NcFile, NodeStatus, Node } from '@nextcloud/files'
+import { FileType, Permission, Folder, File as NcFile, NodeStatus, Node, getFileActions } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
import { vOnClickOutside } from '@vueuse/components'
@@ -19,10 +19,11 @@ import { getDragAndDropPreview } from '../utils/dragUtils.ts'
import { hashCode } from '../utils/hashUtils.ts'
import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts'
import logger from '../logger.js'
-import FileEntryActions from '../components/FileEntry/FileEntryActions.vue'
Vue.directive('onClickOutside', vOnClickOutside)
+const actions = getFileActions()
+
export default defineComponent({
props: {
source: {
@@ -47,6 +48,13 @@ export default defineComponent({
},
},
+ provide() {
+ return {
+ defaultFileAction: this.defaultFileAction,
+ enabledFileActions: this.enabledFileActions,
+ }
+ },
+
data() {
return {
loading: '',
@@ -178,6 +186,23 @@ export default defineComponent({
color: `color-mix(in srgb, var(--color-main-text) ${ratio}%, var(--color-text-maxcontrast))`,
}
},
+
+ /**
+ * Sorted actions that are enabled for this node
+ */
+ enabledFileActions() {
+ if (this.source.status === NodeStatus.FAILED) {
+ return []
+ }
+
+ return actions
+ .filter(action => !action.enabled || action.enabled([this.source], this.currentView))
+ .sort((a, b) => (a.order || 0) - (b.order || 0))
+ },
+
+ defaultFileAction() {
+ return this.enabledFileActions.find((action) => action.default !== undefined)
+ },
},
watch: {
@@ -261,8 +286,15 @@ export default defineComponent({
return false
}
- const actions = this.$refs.actions as ComponentPublicInstance<typeof FileEntryActions>
- actions.execDefaultAction(event)
+ if (this.defaultFileAction) {
+ event.preventDefault()
+ event.stopPropagation()
+ // Execute the first default action if any
+ this.defaultFileAction.exec(this.source, this.currentView, this.currentDir)
+ } else {
+ // fallback to open in current tab
+ window.open(generateUrl('/f/{fileId}', { fileId: this.fileid }), '_self')
+ }
},
openDetailsIfAvailable(event) {
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue
index 1b9475333ab..37638aeabe6 100644
--- a/apps/files/src/components/FilesListVirtual.vue
+++ b/apps/files/src/components/FilesListVirtual.vue
@@ -600,24 +600,26 @@ export default defineComponent({
// Take as much space as possible
flex: 1 1 auto;
- a {
+ button.files-list__row-name-link {
display: flex;
align-items: center;
+ text-align: start;
// Fill cell height and width
width: 100%;
height: 100%;
// Necessary for flex grow to work
min-width: 0;
+ margin: 0;
// Already added to the inner text, see rule below
&:focus-visible {
- outline: none;
+ outline: none !important;
}
// Keyboard indicator a11y
&:focus .files-list__row-name-text {
- outline: 2px solid var(--color-main-text) !important;
- border-radius: 20px;
+ outline: var(--border-width-input-focused) solid var(--color-main-text) !important;
+ border-radius: var(--border-radius-element);
}
&:focus:not(:focus-visible) .files-list__row-name-text {
outline: none !important;
@@ -627,7 +629,7 @@ export default defineComponent({
.files-list__row-name-text {
color: var(--color-main-text);
// Make some space for the outline
- padding: 5px 10px;
+ padding: var(--default-grid-baseline) calc(2 * var(--default-grid-baseline));
margin-left: -10px;
// Align two name and ext
display: inline-flex;
@@ -791,10 +793,6 @@ tbody.files-list__tbody.files-list__tbody--grid {
height: var(--icon-preview-size);
}
- a.files-list__row-name-link {
- height: var(--name-height);
- }
-
.files-list__row-name-text {
margin: 0;
// Ensure that the outline is not too close to the text.
diff --git a/cypress.config.ts b/cypress.config.ts
index 8c35f354735..e9b09f2012d 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -2,6 +2,7 @@
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+import type { Configuration } from 'webpack'
import {
applyChangesToNextcloud,
configureNextcloud,
@@ -11,8 +12,8 @@ import {
} from './cypress/dockerNode'
import { defineConfig } from 'cypress'
import cypressSplit from 'cypress-split'
+import { removeDirectory } from 'cypress-delete-downloads-folder'
import webpackPreprocessor from '@cypress/webpack-preprocessor'
-import type { Configuration } from 'webpack'
import webpackConfig from './webpack.config.js'
@@ -63,6 +64,8 @@ export default defineConfig({
on('file:preprocessor', webpackPreprocessor({ webpackOptions: webpackConfig as Configuration }))
+ on('task', { removeDirectory })
+
// Disable spell checking to prevent rendering differences
on('before:browser:launch', (browser, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
diff --git a/cypress/e2e/files/files-download.cy.ts b/cypress/e2e/files/files-download.cy.ts
new file mode 100644
index 00000000000..5522fb947d6
--- /dev/null
+++ b/cypress/e2e/files/files-download.cy.ts
@@ -0,0 +1,145 @@
+/*!
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import type { User } from '@nextcloud/cypress'
+import { getRowForFile, navigateToFolder, triggerActionForFile } from './FilesUtils'
+import { deleteDownloadsFolderBeforeEach } from 'cypress-delete-downloads-folder'
+
+describe('files: Download files using file actions', { testIsolation: true }, () => {
+ let user: User
+
+ deleteDownloadsFolderBeforeEach()
+
+ beforeEach(() => {
+ cy.createRandomUser().then(($user) => {
+ user = $user
+ })
+ })
+
+ it('can download file', () => {
+ cy.uploadContent(user, new Blob(['<content>']), 'text/plain', '/file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ getRowForFile('file.txt').should('be.visible')
+
+ triggerActionForFile('file.txt', 'download')
+
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+
+ /**
+ * Regression test of https://github.com/nextcloud/server/issues/44855
+ */
+ it('can download file with hash name', () => {
+ cy.uploadContent(user, new Blob(['<content>']), 'text/plain', '/#file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ triggerActionForFile('#file.txt', 'download')
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/#file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+
+ /**
+ * Regression test of https://github.com/nextcloud/server/issues/44855
+ */
+ it('can download file from folder with hash name', () => {
+ cy.mkdir(user, '/#folder')
+ .uploadContent(user, new Blob(['<content>']), 'text/plain', '/#folder/file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ navigateToFolder('#folder')
+ // All are visible by default
+ getRowForFile('file.txt').should('be.visible')
+
+ triggerActionForFile('file.txt', 'download')
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+})
+
+describe('files: Download files using default action', { testIsolation: true }, () => {
+ let user: User
+
+ deleteDownloadsFolderBeforeEach()
+
+ beforeEach(() => {
+ cy.createRandomUser().then(($user) => {
+ user = $user
+ })
+ })
+
+ it('can download file', () => {
+ cy.uploadContent(user, new Blob(['<content>']), 'text/plain', '/file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ getRowForFile('file.txt')
+ .should('be.visible')
+ .findByRole('button', { name: 'Download' })
+ .click()
+
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+
+ /**
+ * Regression test of https://github.com/nextcloud/server/issues/44855
+ */
+ it('can download file with hash name', () => {
+ cy.uploadContent(user, new Blob(['<content>']), 'text/plain', '/#file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ getRowForFile('#file.txt')
+ .should('be.visible')
+ .findByRole('button', { name: 'Download' })
+ .click()
+
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/#file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+
+ /**
+ * Regression test of https://github.com/nextcloud/server/issues/44855
+ */
+ it('can download file from folder with hash name', () => {
+ cy.mkdir(user, '/#folder')
+ .uploadContent(user, new Blob(['<content>']), 'text/plain', '/#folder/file.txt')
+ cy.login(user)
+ cy.visit('/apps/files')
+
+ navigateToFolder('#folder')
+ // All are visible by default
+ getRowForFile('file.txt')
+ .should('be.visible')
+ .findByRole('button', { name: 'Download' })
+ .click()
+
+ const downloadsFolder = Cypress.config('downloadsFolder')
+ cy.readFile(`${downloadsFolder}/file.txt`, { timeout: 15000 })
+ .should('exist')
+ .and('have.length.gt', 8)
+ .and('equal', '<content>')
+ })
+})
diff --git a/cypress/e2e/files_sharing/file-request.cy.ts b/cypress/e2e/files_sharing/file-request.cy.ts
index 793383e9a77..7c33594e25c 100644
--- a/cypress/e2e/files_sharing/file-request.cy.ts
+++ b/cypress/e2e/files_sharing/file-request.cy.ts
@@ -4,7 +4,7 @@
*/
import type { User } from '@nextcloud/cypress'
-import { createFolder, getRowForFile } from '../files/FilesUtils'
+import { createFolder, getRowForFile, navigateToFolder } from '../files/FilesUtils'
import { createFileRequest, enterGuestName } from './FilesSharingUtils'
describe('Files', { testIsolation: true }, () => {
@@ -53,7 +53,9 @@ describe('Files', { testIsolation: true }, () => {
it('Check the uploaded file', () => {
cy.login(user)
cy.visit(`/apps/files/files?dir=/${folderName}`)
- getRowForFile('Guest').should('be.visible').get('a[data-cy-files-list-row-name-link]').click()
+ getRowForFile('Guest')
+ .should('be.visible')
+ navigateToFolder('Guest')
getRowForFile('file.txt').should('be.visible')
})
})
diff --git a/cypress/e2e/files_sharing/files-shares-view.cy.ts b/cypress/e2e/files_sharing/files-shares-view.cy.ts
index 01083e6dda9..12a67d9ee0f 100644
--- a/cypress/e2e/files_sharing/files-shares-view.cy.ts
+++ b/cypress/e2e/files_sharing/files-shares-view.cy.ts
@@ -35,7 +35,7 @@ describe('files_sharing: Files view', { testIsolation: true }, () => {
// see the shared folder
getRowForFile('folder').should('be.visible')
// click on the folder should open it in files
- getRowForFile('folder').findByRole('button', { name: 'folder' }).click()
+ getRowForFile('folder').findByRole('button', { name: /open in files/i }).click()
// See the URL has changed
cy.url().should('match', /apps\/files\/files\/.+dir=\/folder/)
// Content of the shared folder
@@ -50,7 +50,7 @@ describe('files_sharing: Files view', { testIsolation: true }, () => {
// see the shared folder
getRowForFile('folder').should('be.visible')
// click on the folder should open it in files
- getRowForFile('folder').findByRole('button', { name: 'folder' }).click()
+ getRowForFile('folder').findByRole('button', { name: /open in files/i }).click()
// See the URL has changed
cy.url().should('match', /apps\/files\/files\/.+dir=\/folder/)
// Content of the shared folder
diff --git a/package-lock.json b/package-lock.json
index 1969bfe7543..af849079c2c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -119,6 +119,7 @@
"css-loader": "^6.8.1",
"cypress": "^13.13.1",
"cypress-axe": "^1.5.0",
+ "cypress-delete-downloads-folder": "^0.0.6",
"cypress-if": "^1.12.4",
"cypress-split": "^1.24.0",
"cypress-wait-until": "^3.0.2",
@@ -10051,6 +10052,12 @@
"cypress": "^10 || ^11 || ^12 || ^13"
}
},
+ "node_modules/cypress-delete-downloads-folder": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/cypress-delete-downloads-folder/-/cypress-delete-downloads-folder-0.0.6.tgz",
+ "integrity": "sha512-oKMhBM/O74a3XWCrMdFrv3iWMK/UAOdYX8PU/ZUGLaRjmC0p/XWFrMRJZFAYo7owpip3jvmf+bkm82cV0RJhAw==",
+ "dev": true
+ },
"node_modules/cypress-if": {
"version": "1.12.4",
"resolved": "https://registry.npmjs.org/cypress-if/-/cypress-if-1.12.4.tgz",
diff --git a/package.json b/package.json
index 115487c2b94..1a945f2d785 100644
--- a/package.json
+++ b/package.json
@@ -147,6 +147,7 @@
"css-loader": "^6.8.1",
"cypress": "^13.13.1",
"cypress-axe": "^1.5.0",
+ "cypress-delete-downloads-folder": "^0.0.6",
"cypress-if": "^1.12.4",
"cypress-split": "^1.24.0",
"cypress-wait-until": "^3.0.2",