diff --git a/changelog/unreleased/enhancement-trash-bin-breadcrumbs b/changelog/unreleased/enhancement-trash-bin-breadcrumbs
new file mode 100644
index 00000000000..8388d7373ab
--- /dev/null
+++ b/changelog/unreleased/enhancement-trash-bin-breadcrumbs
@@ -0,0 +1,9 @@
+Enhancement: Trash bin breadcrumbs
+
+We've improved the trash bin in general:
+* Add a breadcrumb for personal trash bin
+* Improve the breadcrumb for spaces trash bin, also add 'Navigate to space' action to context menu
+* Fix wrong page title in spaces trash bin
+
+https://github.com/owncloud/web/pull/6609
+
diff --git a/packages/web-app-files/src/components/AppBar/AppBar.vue b/packages/web-app-files/src/components/AppBar/AppBar.vue
index 71abe73b9ef..30f2dfd5e78 100644
--- a/packages/web-app-files/src/components/AppBar/AppBar.vue
+++ b/packages/web-app-files/src/components/AppBar/AppBar.vue
@@ -22,7 +22,7 @@
:items="breadcrumbs"
>
-
+
@@ -95,6 +95,7 @@ export default {
isPublicLocation: useActiveLocation(isLocationPublicActive, 'files-public-files'),
isSpacesProjectsLocation: useActiveLocation(isLocationSpacesActive, 'files-spaces-projects'),
isSpacesProjectLocation: useActiveLocation(isLocationSpacesActive, 'files-spaces-project'),
+ isTrashPersonalActive: useActiveLocation(isLocationTrashActive, 'files-trash-personal'),
isTrashSpacesProjectActive: useActiveLocation(
isLocationTrashActive,
'files-trash-spaces-project'
@@ -119,7 +120,7 @@ export default {
...mapState('Files', ['areHiddenFilesShown']),
showContextActions() {
- if (this.isTrashSpacesProjectActive) {
+ if (this.isTrashPersonalActive) {
return false
}
if (this.isSpacesProjectLocation) {
@@ -128,6 +129,12 @@ export default {
return this.currentFolder && this.breadcrumbs.length > 1
},
+ contextActionItems() {
+ if (this.isTrashSpacesProjectActive) {
+ return []
+ }
+ return [this.currentFolder]
+ },
currentPath() {
const path = this.$route.params.item || ''
if (path.endsWith('/')) {
@@ -176,24 +183,34 @@ export default {
this.isPersonalLocation ||
this.isSpacesProjectsLocation ||
this.isSpacesProjectLocation ||
+ this.isTrashPersonalActive ||
this.isTrashSpacesProjectActive
)
) {
return []
}
- if (this.isTrashSpacesProjectActive) {
+ if (this.isTrashPersonalActive) {
return [
{
- text: this.$gettext('Spaces'),
- to: '/files/spaces/projects'
+ text: this.$gettext('Deleted files'),
+ to: '/files/trash'
},
{
- text: this.$route.params.storageId,
- to: `/files/spaces/projects/${this.$route.params.storageId}`
+ text: this.$gettext('Personal'),
+ onClick: () => bus.publish('app.files.list.load')
+ }
+ ]
+ }
+
+ if (this.isTrashSpacesProjectActive) {
+ return [
+ {
+ text: this.$gettext('Deleted files'),
+ to: '/files/trash'
},
{
- text: this.$gettext('Deleted Files'),
+ text: this.$route.params.storageId,
onClick: () => bus.publish('app.files.list.load')
}
]
diff --git a/packages/web-app-files/src/components/FilesList/ContextActions.vue b/packages/web-app-files/src/components/FilesList/ContextActions.vue
index fa43d33f521..1e28893e703 100644
--- a/packages/web-app-files/src/components/FilesList/ContextActions.vue
+++ b/packages/web-app-files/src/components/FilesList/ContextActions.vue
@@ -41,6 +41,7 @@ import ShowDetails from '../../mixins/actions/showDetails'
import ShowShares from '../../mixins/actions/showShares'
import SetSpaceImage from '../../mixins/spaces/actions/setImage'
import SetSpaceReadme from '../../mixins/spaces/actions/setReadme'
+import SpaceNavigate from '../../mixins/spaces/actions/navigate'
export default {
name: 'ContextActions',
@@ -64,7 +65,8 @@ export default {
ShowDetails,
ShowShares,
SetSpaceImage,
- SetSpaceReadme
+ SetSpaceReadme,
+ SpaceNavigate
],
props: {
@@ -165,7 +167,8 @@ export default {
...this.$_acceptShare_items,
...this.$_declineShare_items,
...this.$_setSpaceImage_items,
- ...this.$_setSpaceReadme_items
+ ...this.$_setSpaceReadme_items,
+ ...this.$_navigate_space_items
].filter((item) => item.isEnabled(this.filterParams))
},
diff --git a/packages/web-app-files/src/components/Trashbin.vue b/packages/web-app-files/src/components/TrashBin.vue
similarity index 99%
rename from packages/web-app-files/src/components/Trashbin.vue
rename to packages/web-app-files/src/components/TrashBin.vue
index 11fa15ac363..1572b6e13e2 100644
--- a/packages/web-app-files/src/components/Trashbin.vue
+++ b/packages/web-app-files/src/components/TrashBin.vue
@@ -62,7 +62,7 @@ import { useResourcesViewDefaults } from '../composables'
import { bus } from 'web-pkg/src/instance'
export default {
- name: 'Trashbin',
+ name: 'TrashBin',
components: { ResourceTable, ListLoader, NoContentMessage, ListInfo, Pagination, ContextActions },
diff --git a/packages/web-app-files/src/helpers/resources.js b/packages/web-app-files/src/helpers/resources.js
index ab2e3d6fbc1..62f66f02b5a 100644
--- a/packages/web-app-files/src/helpers/resources.js
+++ b/packages/web-app-files/src/helpers/resources.js
@@ -543,7 +543,22 @@ export function buildDeletedResource(resource) {
indicators: [],
canUpload: () => false,
canDownload: () => false,
- canBeDeleted: () => true,
+ canBeDeleted: () => {
+ /** FIXME: once https://github.com/owncloud/ocis/issues/3339 gets implemented,
+ * we want to add a check if the permission is set.
+ * We might to be careful and do an early return true if DavProperty.Permissions is not set
+ * as oc10 does not support it.
+ **/
+ return true
+ },
+ canBeRestored: function () {
+ /** FIXME: once https://github.com/owncloud/ocis/issues/3339 gets implemented,
+ * we want to add a check if the permission is set.
+ * We might to be careful and do an early return true if DavProperty.Permissions is not set
+ * as oc10 does not support it.
+ **/
+ return true
+ },
canRename: () => false,
canShare: () => false,
canCreate: () => false,
diff --git a/packages/web-app-files/src/mixins/actions/restore.js b/packages/web-app-files/src/mixins/actions/restore.js
index 28c7f9d3061..8727d86e353 100644
--- a/packages/web-app-files/src/mixins/actions/restore.js
+++ b/packages/web-app-files/src/mixins/actions/restore.js
@@ -26,6 +26,10 @@ export default {
) {
return false
}
+ if (!resources.every((r) => r.canBeRestored())) {
+ return false
+ }
+
return resources.length > 0
},
componentType: 'oc-button',
diff --git a/packages/web-app-files/src/mixins/spaces/actions/navigate.js b/packages/web-app-files/src/mixins/spaces/actions/navigate.js
new file mode 100644
index 00000000000..34188b871a8
--- /dev/null
+++ b/packages/web-app-files/src/mixins/spaces/actions/navigate.js
@@ -0,0 +1,37 @@
+import { createLocationSpaces, isLocationTrashActive } from '../../../router'
+
+export default {
+ computed: {
+ $_navigate_space_items() {
+ return [
+ {
+ name: 'navigate',
+ icon: 'layout-grid',
+ label: () => {
+ return this.$gettext('Navigate to space')
+ },
+ handler: this.$_navigate_space_trigger,
+ isEnabled: ({ resources }) => {
+ if (resources.length) {
+ return false
+ }
+ return isLocationTrashActive(this.$router, 'files-trash-spaces-project')
+ },
+ componentType: 'oc-button',
+ class: 'oc-files-actions-navigate-trigger'
+ }
+ ]
+ }
+ },
+ methods: {
+ $_navigate_space_trigger() {
+ this.$router.push(
+ createLocationSpaces('files-spaces-project', {
+ params: {
+ storageId: this.$router.currentRoute.params.storageId
+ }
+ })
+ )
+ }
+ }
+}
diff --git a/packages/web-app-files/src/views/Trashbin.vue b/packages/web-app-files/src/views/Trashbin.vue
index 2ab9482f50b..c990e021a0a 100644
--- a/packages/web-app-files/src/views/Trashbin.vue
+++ b/packages/web-app-files/src/views/Trashbin.vue
@@ -1,9 +1,9 @@
-
+
diff --git a/packages/web-app-files/src/views/spaces/Project.vue b/packages/web-app-files/src/views/spaces/Project.vue
index 6c47e7fbd98..41a084551bc 100644
--- a/packages/web-app-files/src/views/spaces/Project.vue
+++ b/packages/web-app-files/src/views/spaces/Project.vue
@@ -238,7 +238,7 @@ export default {
'totalFilesCount',
'totalFilesSize'
]),
- ...mapGetters(['user', 'getToken']),
+ ...mapGetters(['user', 'getToken', 'configuration']),
selected: {
get() {
@@ -360,7 +360,7 @@ export default {
async mounted() {
await this.loadResourcesTask.perform(this, false, this.$route.params.item || '')
- document.title = `${this.space.name} - ${this.$route.meta.title}`
+ document.title = `${this.$route.meta.title} - ${this.space.name} - ${this.configuration.currentTheme.general.name}`
this.$route.params.name = this.space.name
const loadSpaceEventToken = bus.subscribe('app.files.list.load', (path) => {
diff --git a/packages/web-app-files/src/views/spaces/Trashbin.vue b/packages/web-app-files/src/views/spaces/Trashbin.vue
index aa2b5c74dc6..0709839d210 100644
--- a/packages/web-app-files/src/views/spaces/Trashbin.vue
+++ b/packages/web-app-files/src/views/spaces/Trashbin.vue
@@ -1,9 +1,44 @@
-
+
diff --git a/packages/web-app-files/tests/unit/components/AppBar/AppBar.spec.js b/packages/web-app-files/tests/unit/components/AppBar/AppBar.spec.js
index fb63f2a3571..8572d9c8c06 100644
--- a/packages/web-app-files/tests/unit/components/AppBar/AppBar.spec.js
+++ b/packages/web-app-files/tests/unit/components/AppBar/AppBar.spec.js
@@ -8,7 +8,8 @@ import {
createLocationCommon,
createLocationPublic,
createLocationShares,
- createLocationSpaces
+ createLocationSpaces,
+ createLocationTrash
} from '../../../../src/router'
const localVue = createLocalVue()
@@ -134,6 +135,167 @@ describe('AppBar component', () => {
})
})
+ describe('computed showContextActions', () => {
+ describe('if isPersonalLocation is true', () => {
+ describe('and item is selected', () => {
+ it('should be true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationSpaces('files-spaces-personal-home', {
+ params: {
+ storageId: '1',
+ item: 'New folder'
+ }
+ }),
+ meta: {}
+ }
+
+ const wrapper = getShallowWrapper(route, store, {
+ isPersonalLocation: true
+ })
+ expect(wrapper.vm.showContextActions).toBeTruthy()
+ })
+ })
+ describe('and no item is selected', () => {
+ it('should be false', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationSpaces('files-spaces-personal-home', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+
+ const wrapper = getShallowWrapper(route, store, {
+ isPersonalLocation: true
+ })
+ expect(wrapper.vm.showContextActions).toBeFalsy()
+ })
+ })
+ })
+
+ describe('if isSpacesProjectLocation is true', () => {
+ describe('and item is selected', () => {
+ it('should be true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1',
+ item: 'New folder'
+ }
+ }),
+ meta: {}
+ }
+
+ const wrapper = getShallowWrapper(route, store, {
+ isSpacesProjectLocation: true
+ })
+ expect(wrapper.vm.showContextActions).toBeTruthy()
+ })
+ })
+
+ describe('and no item is selected', () => {
+ it('should be false', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+
+ const wrapper = getShallowWrapper(route, store, {
+ isSpacesProjectLocation: true
+ })
+ expect(wrapper.vm.showContextActions).toBeFalsy()
+ })
+ })
+ })
+
+ describe('if isTrashPersonalActive is true', () => {
+ it('should be false', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+ const wrapper = getShallowWrapper(route, store, { isTrashPersonalActive: true })
+ expect(wrapper.vm.showContextActions).toBeFalsy()
+ })
+ })
+ })
+
+ describe('computed contextActionItems', () => {
+ it('should be empty if isTrashSpacesProjectActive is true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+ const wrapper = getShallowWrapper(route, store, { isTrashSpacesProjectActive: true })
+ expect(wrapper.vm.contextActionItems).toEqual([])
+ })
+
+ it('should not be empty if isTrashPersonalActive is true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+ const wrapper = getShallowWrapper(route, store, { isTrashPersonalActive: true })
+ expect(wrapper.vm.contextActionItems).toEqual([wrapper.vm.currentFolder])
+ })
+ })
+
+ describe('computed breadcrumbs', () => {
+ it('should contain two items if isTrashPersonalActive is true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-personal', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+ const wrapper = getShallowWrapper(route, store, { isTrashSpacesProjectActive: true })
+ expect(wrapper.vm.breadcrumbs[0].to).toEqual('/files/trash')
+ expect(wrapper.vm.breadcrumbs.length).toEqual(2)
+ })
+
+ it('should contain two items if isTrashSpacesProjectActive is true', () => {
+ const store = createStore({ selected: [], currentFolder })
+ const route = {
+ ...createLocationTrash('files-trash-spaces-project', {
+ params: {
+ storageId: '1'
+ }
+ }),
+ meta: {}
+ }
+ const wrapper = getShallowWrapper(route, store, { isTrashSpacesProjectActive: true })
+ expect(wrapper.vm.breadcrumbs[0].to).toEqual('/files/trash')
+ expect(wrapper.vm.breadcrumbs.length).toEqual(2)
+ })
+ })
+
describe.each([favoritesLocation.name, sharesWithOthersLocation.name, sharesWithMeLocation.name])(
'%s page',
(page) => {
@@ -184,7 +346,7 @@ describe('AppBar component', () => {
)
})
-function getShallowWrapper(route = {}, store = {}) {
+function getShallowWrapper(route = {}, store = {}, mocks = {}) {
return shallowMount(AppBar, {
localVue,
mocks: {
@@ -196,7 +358,8 @@ function getShallowWrapper(route = {}, store = {}) {
}
},
publicPage: jest.fn(() => false),
- isIE11: jest.fn(() => false)
+ isIE11: jest.fn(() => false),
+ ...mocks
},
store
})
diff --git a/packages/web-app-files/tests/unit/components/Trashbin.spec.js b/packages/web-app-files/tests/unit/components/TrashBin.spec.js
similarity index 98%
rename from packages/web-app-files/tests/unit/components/Trashbin.spec.js
rename to packages/web-app-files/tests/unit/components/TrashBin.spec.js
index dc5a84ea535..da871bd466f 100644
--- a/packages/web-app-files/tests/unit/components/Trashbin.spec.js
+++ b/packages/web-app-files/tests/unit/components/TrashBin.spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils'
-import Trashbin from '@files/src/components/Trashbin.vue'
+import TrashBin from '@files/src/components/TrashBin.vue'
import { getStore, localVue, createFile } from '@files/tests/unit/components/components.setup.js'
const stubs = {
@@ -176,7 +176,7 @@ describe('Trashbin component', () => {
paginationPages = 12,
paginationPage = 21
} = {}) {
- const component = { ...Trashbin, created: jest.fn() }
+ const component = { ...TrashBin, created: jest.fn() }
const store = createStore({
totalFilesCount: { files: paginatedResources.length, folders: 0 },
selectedFiles
diff --git a/packages/web-app-files/tests/unit/components/__snapshots__/Trashbin.spec.js.snap b/packages/web-app-files/tests/unit/components/__snapshots__/TrashBin.spec.js.snap
similarity index 100%
rename from packages/web-app-files/tests/unit/components/__snapshots__/Trashbin.spec.js.snap
rename to packages/web-app-files/tests/unit/components/__snapshots__/TrashBin.spec.js.snap
diff --git a/packages/web-app-files/tests/unit/mixins/actions/restore.spec.js b/packages/web-app-files/tests/unit/mixins/actions/restore.spec.js
index 4ff703ac89d..f151f770cb4 100644
--- a/packages/web-app-files/tests/unit/mixins/actions/restore.spec.js
+++ b/packages/web-app-files/tests/unit/mixins/actions/restore.spec.js
@@ -22,9 +22,17 @@ describe('restore', () => {
const wrapper = getWrapper()
expect(wrapper.vm.$_restore_items[0].isEnabled({ resources: [] })).toBe(false)
})
- it('should be true when resource is given', () => {
+ it('should be true when permission is sufficient', () => {
const wrapper = getWrapper()
- expect(wrapper.vm.$_restore_items[0].isEnabled({ resources: [{}] })).toBe(true)
+ expect(
+ wrapper.vm.$_restore_items[0].isEnabled({ resources: [{ canBeRestored: () => true }] })
+ ).toBe(true)
+ })
+ it('should be false when permission is not sufficient', () => {
+ const wrapper = getWrapper()
+ expect(
+ wrapper.vm.$_restore_items[0].isEnabled({ resources: [{ canBeRestored: () => false }] })
+ ).toBe(false)
})
it('should be false when location is invalid', () => {
const wrapper = getWrapper({ invalidLocation: true })
diff --git a/packages/web-app-files/tests/unit/mixins/spaces/navigate.spec.js b/packages/web-app-files/tests/unit/mixins/spaces/navigate.spec.js
new file mode 100644
index 00000000000..93eebb68c27
--- /dev/null
+++ b/packages/web-app-files/tests/unit/mixins/spaces/navigate.spec.js
@@ -0,0 +1,86 @@
+import Vuex from 'vuex'
+import { createStore } from 'vuex-extensions'
+import { mount, createLocalVue } from '@vue/test-utils'
+import Navigate from '@files/src/mixins/spaces/actions/navigate.js'
+import { createLocationSpaces, createLocationTrash } from '../../../../src/router'
+
+const localVue = createLocalVue()
+localVue.use(Vuex)
+
+const Component = {
+ render() {},
+ mixins: [Navigate]
+}
+
+describe('navigate', () => {
+ afterEach(() => jest.clearAllMocks())
+
+ describe('isEnabled property', () => {
+ it('should be true when no resource given', () => {
+ const wrapper = getWrapper()
+ expect(wrapper.vm.$_navigate_space_items[0].isEnabled({ resources: [] })).toBe(true)
+ })
+ it('should be false when resource is given', () => {
+ const wrapper = getWrapper()
+ expect(wrapper.vm.$_navigate_space_items[0].isEnabled({ resources: [{}] })).toBe(false)
+ })
+ it('should be false when location is invalid', () => {
+ const wrapper = getWrapper({ invalidLocation: true })
+ expect(wrapper.vm.$_navigate_space_items[0].isEnabled({ resources: [] })).toBe(false)
+ })
+ })
+
+ describe('method "$_navigate_space_trigger"', () => {
+ it('should trigger route change', async () => {
+ const wrapper = getWrapper()
+ await wrapper.vm.$_navigate_space_trigger()
+
+ expect(wrapper.vm.$router.push).toHaveBeenCalledWith(
+ createLocationSpaces('files-spaces-project', {
+ params: {
+ storageId: wrapper.vm.$router.currentRoute.params.storageId
+ }
+ })
+ )
+ })
+ })
+})
+
+function getWrapper({ invalidLocation = false } = {}) {
+ return mount(Component, {
+ localVue,
+ mocks: {
+ $router: {
+ currentRoute: invalidLocation
+ ? createLocationTrash('files-trash-personal')
+ : createLocationTrash('files-trash-spaces-project', { params: { storageId: '1' } }),
+ resolve: (r) => {
+ return { href: r.name }
+ },
+ push: jest.fn()
+ },
+ $gettext: jest.fn()
+ },
+ store: createStore(Vuex.Store, {
+ actions: {
+ createModal: jest.fn(),
+ hideModal: jest.fn(),
+ showMessage: jest.fn()
+ },
+ getters: {
+ configuration: () => ({
+ server: 'https://example.com'
+ }),
+ getToken: () => 'token'
+ },
+ modules: {
+ Files: {
+ namespaced: true,
+ mutations: {
+ REMOVE_FILE: jest.fn()
+ }
+ }
+ }
+ })
+ })
+}
diff --git a/packages/web-app-files/tests/unit/views/Trashbin.spec.js b/packages/web-app-files/tests/unit/views/Trashbin.spec.js
deleted file mode 100644
index 1797f5fbae5..00000000000
--- a/packages/web-app-files/tests/unit/views/Trashbin.spec.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import { mount } from '@vue/test-utils'
-import Trashbin from '@files/src/components/Trashbin.vue'
-import { getStore, localVue, createFile } from '@files/tests/unit/views/views.setup.js'
-
-const stubs = {
- 'list-loader': true,
- 'no-content-message': true,
- 'resource-table': true,
- 'context-actions': true,
- pagination: true,
- 'list-info': true,
- 'router-link': true
-}
-
-const listLoaderStub = 'list-loader-stub'
-const noContentStub = 'no-content-message-stub'
-const filesTableStub = 'resource-table-stub'
-const filesTableSelector = '#files-trashbin-table'
-const contextActionsStub = 'context-actions-stub'
-const listInfoStub = 'list-info-stub'
-const paginationStub = 'pagination-stub'
-
-describe('Trashbin component', () => {
- it('should show the list loader when the view is still loading', () => {
- const wrapper = getMountedWrapper({ loading: true })
-
- expect(wrapper.find(listLoaderStub).exists()).toBeTruthy()
- expect(wrapper.find(noContentStub).exists()).toBeFalsy()
- expect(wrapper.find(filesTableStub).exists()).toBeFalsy()
- })
-
- describe('when the view is not loading anymore', () => {
- it('should show the no content message component if the paginated resources is empty', () => {
- const wrapper = getMountedWrapper()
-
- expect(wrapper.find(listLoaderStub).exists()).toBeFalsy()
- expect(wrapper.find(filesTableStub).exists()).toBeFalsy()
- expect(wrapper.find(noContentStub).exists()).toBeTruthy()
- })
-
- describe('when length of the paginated resources is greater than zero', () => {
- const resourceList = [
- createFile({ id: '1234' }),
- createFile({ id: '5896' }),
- createFile({ id: '9856' })
- ]
- const wrapper = getMountedWrapper({
- paginatedResources: resourceList
- })
-
- it('should not show the no content message component', () => {
- expect(wrapper.find(noContentStub).exists()).toBeFalsy()
- })
-
- it('should load the resource table with correct props', () => {
- stubs['resource-table'] = false
- const wrapper = getMountedWrapper({
- paginatedResources: resourceList
- })
- const filesTable = wrapper.find(filesTableSelector)
-
- expect(filesTable.exists()).toBeTruthy()
- expect(filesTable).toMatchSnapshot()
-
- stubs['resource-table'] = true
- })
-
- describe('context menu', () => {
- let wrapper
- const selectedResources = [resourceList[0], resourceList[1]]
- const notSelectedResources = [resourceList[2]]
- beforeEach(() => {
- stubs['resource-table'] = false
-
- wrapper = getMountedWrapper({
- selectedFiles: selectedResources,
- paginatedResources: resourceList,
- paginationPage: 1,
- paginationPages: 2
- })
- })
- afterEach(() => {
- stubs['resource-table'] = true
- })
- it('should show the context actions for every selected resource', () => {
- selectedResources.forEach((selectedResource) => {
- const fileRow = wrapper.find(`[data-item-id="${selectedResource.id}"]`)
- const contextMenu = fileRow.find(contextActionsStub)
- expect(contextMenu.exists()).toBeTruthy()
- expect(contextMenu.props().items).toMatchObject(selectedResources)
- })
- })
- it('should not show the context actions for a resource that is not selected', () => {
- notSelectedResources.forEach((notSelectedResource) => {
- const fileRow = wrapper.find(`[data-item-id="${notSelectedResource.id}"]`)
- const contextMenu = fileRow.find(contextActionsStub)
- expect(contextMenu.exists()).toBeFalsy()
- })
- })
- })
-
- describe('pagination', () => {
- it('should be visible if the paginated pages is greater than zero', () => {
- stubs['resource-table'] = false
- const wrapper = getMountedWrapper({
- paginatedResources: resourceList,
- paginationPages: 2,
- paginationPage: 1
- })
-
- const pagination = wrapper.find(paginationStub)
-
- expect(pagination.exists()).toBeTruthy()
- expect(pagination.props()).toMatchObject({
- pages: 2,
- currentPage: 1
- })
- stubs['resource-table'] = true
- })
- })
-
- describe('list info', () => {
- it('should be present if the paginated resources list is not empty', () => {
- stubs['resource-table'] = false
-
- const wrapper = getMountedWrapper({
- paginatedResources: resourceList,
- paginationPage: 1,
- paginationPages: 2
- })
-
- const listInfo = wrapper.find(listInfoStub)
- expect(listInfo.exists()).toBeTruthy()
- expect(listInfo.props()).toMatchObject({
- files: 3,
- folders: 0
- })
- stubs['resource-table'] = true
- })
- })
- })
- })
-
- function mountOptions({ store, loading, paginatedResources, paginationPages, paginationPage }) {
- const $route = { params: { page: 1 } }
- const $router = {
- afterEach: jest.fn(),
- currentRoute: {
- query: {}
- }
- }
- return {
- localVue,
- store: store,
- stubs,
- mocks: {
- $route,
- $router
- },
- setup: () => ({
- loadResourcesTask: {
- isRunning: loading,
- perform: jest.fn()
- },
- paginatedResources: paginatedResources,
- paginationPages: paginationPages,
- paginationPage: paginationPage
- })
- }
- }
-
- function getMountedWrapper({
- selectedFiles = [],
- loading = false,
- paginatedResources = [],
- paginationPages = 12,
- paginationPage = 21
- } = {}) {
- const component = { ...Trashbin, created: jest.fn() }
- const store = createStore({
- totalFilesCount: { files: paginatedResources.length, folders: 0 },
- selectedFiles
- })
- return mount(
- component,
- mountOptions({
- store,
- loading,
- paginatedResources,
- paginationPages,
- paginationPage
- })
- )
- }
-
- function createStore({ totalFilesCount, highlightedFile, selectedFiles } = {}) {
- return getStore({
- highlightedFile,
- totalFilesCount,
- selectedFiles
- })
- }
-})
diff --git a/packages/web-app-files/tests/unit/views/__snapshots__/Trashbin.spec.js.snap b/packages/web-app-files/tests/unit/views/__snapshots__/Trashbin.spec.js.snap
deleted file mode 100644
index 4655f395437..00000000000
--- a/packages/web-app-files/tests/unit/views/__snapshots__/Trashbin.spec.js.snap
+++ /dev/null
@@ -1,87 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Trashbin component when the view is not loading anymore when length of the paginated resources is greater than zero should load the resource table with correct props 1`] = `
-
-
-
-
-
-
- |
-
-
- file-name-1234
-
-
- file-path
-
-
-
- |
- |
-
-
- |
-
-
- |
-
-
- file-name-5896
-
-
- file-path
-
-
-
- |
- |
-
-
- |
-
-
- |
-
-
- file-name-9856
-
-
- file-path
-
-
-
- |
- |
-
-
- |
-
-
-
-
-`;
diff --git a/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js b/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js
new file mode 100644
index 00000000000..4001d7510b7
--- /dev/null
+++ b/packages/web-app-files/tests/unit/views/spaces/Trashbin.spec.js
@@ -0,0 +1,70 @@
+import Vuex from 'vuex'
+import { mount, createLocalVue } from '@vue/test-utils'
+import Trashbin from '@files/src/views/spaces/Trashbin.vue'
+import { createStore } from 'vuex-extensions'
+import { createLocationTrash } from '../../../../src/router'
+import { waitFor } from '@testing-library/dom'
+
+const localVue = createLocalVue()
+localVue.use(Vuex)
+
+afterEach(() => jest.clearAllMocks())
+
+describe('Trashbin', () => {
+ describe('method "mounted"', () => {
+ it('should change document title', async () => {
+ const wrapper = getWrapper()
+ expect(wrapper.vm.loadResourcesTask.perform).toBeCalled()
+ await waitFor(() => expect(document.title).toBe('Deleted files - Space - ownCloud'))
+ })
+ })
+})
+
+function getWrapper() {
+ return mount(Trashbin, {
+ localVue,
+ mocks: {
+ $router: {
+ currentRoute: {
+ ...createLocationTrash('files-trash-spaces-project'),
+ meta: {
+ title: 'Deleted files'
+ }
+ },
+ resolve: (r) => {
+ return { href: r.name }
+ }
+ },
+ loadResourcesTask: {
+ isRunning: false,
+ perform: jest.fn()
+ },
+ space: {
+ name: 'Space'
+ },
+ $gettext: jest.fn(),
+ document: {
+ title: ''
+ }
+ },
+ store: createStore(Vuex.Store, {
+ actions: {
+ showMessage: jest.fn()
+ },
+ getters: {
+ configuration: () => ({
+ server: 'https://example.com',
+ currentTheme: {
+ general: {
+ name: 'ownCloud'
+ }
+ }
+ }),
+ getToken: () => 'token'
+ }
+ }),
+ stubs: {
+ 'trash-bin': true
+ }
+ })
+}
diff --git a/packages/web-pkg/src/constants/dav.ts b/packages/web-pkg/src/constants/dav.ts
index 1199618b60e..197382fdfd5 100644
--- a/packages/web-pkg/src/constants/dav.ts
+++ b/packages/web-pkg/src/constants/dav.ts
@@ -75,6 +75,7 @@ export abstract class DavProperties {
DavProperty.ResourceType,
DavProperty.TrashbinOriginalLocation,
DavProperty.TrashbinOriginalFilename,
- DavProperty.TrashbinDeletedDate
+ DavProperty.TrashbinDeletedDate,
+ DavProperty.Permissions
]
}