mirror of
https://github.com/nextcloud/server.git
synced 2026-03-01 04:50:40 -05:00
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>
This commit is contained in:
parent
39780506f0
commit
4ebea3db3a
10 changed files with 251 additions and 85 deletions
|
|
@ -21,7 +21,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',
|
||||
|
|
@ -34,7 +34,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)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
*
|
||||
*/
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { FileAction, Permission, Node, FileType, View } from '@nextcloud/files'
|
||||
import { FileAction, Permission, Node, FileType, View, DefaultType } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import ArrowDownSvg from '@mdi/svg/svg/arrow-down.svg?raw'
|
||||
|
||||
|
|
@ -60,6 +60,8 @@ const isDownloadable = function(node: Node) {
|
|||
|
||||
export const action = new FileAction({
|
||||
id: 'download',
|
||||
default: DefaultType.DEFAULT,
|
||||
|
||||
displayName: () => t('files', 'Download'),
|
||||
iconSvgInline: () => ArrowDownSvg,
|
||||
|
||||
|
|
|
|||
|
|
@ -97,9 +97,9 @@ import type { PropType, ShallowRef } from 'vue'
|
|||
import type { FileAction, Node, View } from '@nextcloud/files'
|
||||
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { DefaultType, NodeStatus, getFileActions } from '@nextcloud/files'
|
||||
import { DefaultType, NodeStatus } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { defineComponent } from 'vue'
|
||||
import { defineComponent, inject } from 'vue'
|
||||
|
||||
import ArrowLeftIcon from 'vue-material-design-icons/ArrowLeft.vue'
|
||||
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
|
||||
|
|
@ -112,9 +112,6 @@ import { useNavigation } from '../../composables/useNavigation'
|
|||
import CustomElementRender from '../CustomElementRender.vue'
|
||||
import logger from '../../logger.js'
|
||||
|
||||
// The registered actions list
|
||||
const actions = getFileActions()
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FileEntryActions',
|
||||
|
||||
|
|
@ -153,10 +150,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,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -175,23 +174,12 @@ export default defineComponent({
|
|||
return this.source.status === NodeStatus.LOADING
|
||||
},
|
||||
|
||||
// Sorted actions that are enabled for this node
|
||||
enabledActions() {
|
||||
if (this.source.attributes.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
|
||||
|
|
@ -199,12 +187,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
|
||||
|
|
@ -219,7 +202,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)
|
||||
|
|
@ -233,7 +216,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
enabledSubmenuActions() {
|
||||
return this.enabledActions
|
||||
return this.enabledFileActions
|
||||
.filter(action => action.parent)
|
||||
.reduce((arr, action) => {
|
||||
if (!arr[action.parent!]) {
|
||||
|
|
@ -322,14 +305,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
|
||||
|
|
|
|||
|
|
@ -54,16 +54,17 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { Node } from '@nextcloud/files'
|
||||
import type { FileAction, Node } from '@nextcloud/files'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { FileType, NodeStatus, Permission } from '@nextcloud/files'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import axios from '@nextcloud/axios'
|
||||
import Vue from 'vue'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { FileType, NodeStatus } from '@nextcloud/files'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { isAxiosError} from 'axios'
|
||||
import Vue, { inject } from 'vue'
|
||||
|
||||
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
|
||||
|
||||
|
|
@ -117,8 +118,11 @@ export default Vue.extend({
|
|||
const { currentView } = useNavigation()
|
||||
const renamingStore = useRenamingStore()
|
||||
|
||||
const defaultFileAction = inject<FileAction | undefined>('defaultFileAction')
|
||||
|
||||
return {
|
||||
currentView,
|
||||
defaultFileAction,
|
||||
|
||||
renamingStore,
|
||||
}
|
||||
|
|
@ -158,32 +162,20 @@ export default Vue.extend({
|
|||
}
|
||||
}
|
||||
|
||||
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',
|
||||
}
|
||||
|
|
@ -324,12 +316,15 @@ export default Vue.extend({
|
|||
// 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()
|
||||
|
||||
// TODO: 409 means current folder does not exist, redirect ?
|
||||
if (error?.response?.status === 404) {
|
||||
|
|
@ -352,3 +347,16 @@ export default Vue.extend({
|
|||
},
|
||||
})
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
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, View } 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'
|
||||
|
|
@ -36,10 +36,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: {
|
||||
|
|
@ -56,6 +57,13 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
defaultFileAction: this.defaultFileAction,
|
||||
enabledFileActions: this.enabledFileActions,
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: '',
|
||||
|
|
@ -173,6 +181,23 @@ export default defineComponent({
|
|||
isRenaming() {
|
||||
return this.renamingStore.renamingNode === this.source
|
||||
},
|
||||
|
||||
/**
|
||||
* 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: {
|
||||
|
|
@ -254,8 +279,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) {
|
||||
|
|
|
|||
|
|
@ -596,24 +596,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;
|
||||
|
|
@ -623,7 +625,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;
|
||||
|
|
@ -764,12 +766,6 @@ tbody.files-list__tbody.files-list__tbody--grid {
|
|||
padding-top: var(--half-clickable-area);
|
||||
}
|
||||
|
||||
a.files-list__row-name-link {
|
||||
// Minus action menu
|
||||
width: calc(100% - var(--clickable-area));
|
||||
height: var(--clickable-area);
|
||||
}
|
||||
|
||||
.files-list__row-name-text {
|
||||
margin: 0;
|
||||
padding-right: 0;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import type { Configuration } from 'webpack'
|
||||
import {
|
||||
applyChangesToNextcloud,
|
||||
configureNextcloud,
|
||||
|
|
@ -6,9 +11,9 @@ import {
|
|||
waitOnNextcloud,
|
||||
} from './cypress/dockerNode'
|
||||
import { defineConfig } from 'cypress'
|
||||
import { removeDirectory } from 'cypress-delete-downloads-folder'
|
||||
import cypressSplit from 'cypress-split'
|
||||
import webpackPreprocessor from '@cypress/webpack-preprocessor'
|
||||
import type { Configuration } from 'webpack'
|
||||
|
||||
import webpackConfig from './webpack.config.js'
|
||||
|
||||
|
|
@ -55,6 +60,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') {
|
||||
|
|
|
|||
145
cypress/e2e/files/files-download.cy.ts
Normal file
145
cypress/e2e/files/files-download.cy.ts
Normal file
|
|
@ -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>')
|
||||
})
|
||||
})
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -147,9 +147,10 @@
|
|||
"css-loader": "^6.8.1",
|
||||
"cypress": "^13.13.2",
|
||||
"cypress-axe": "^1.5.0",
|
||||
"cypress-if": "^1.10.5",
|
||||
"cypress-split": "^1.21.0",
|
||||
"cypress-wait-until": "^2.0.1",
|
||||
"cypress-delete-downloads-folder": "^0.0.6",
|
||||
"cypress-if": "^1.12.5",
|
||||
"cypress-split": "^1.24.0",
|
||||
"cypress-wait-until": "^3.0.2",
|
||||
"dockerode": "^4.0.2",
|
||||
"eslint-plugin-cypress": "^2.15.2",
|
||||
"eslint-plugin-es": "^4.1.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue