From 6e7d79a0e79270e71c280a4cb644c65fb8b0a18e Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Tue, 20 Apr 2021 17:33:19 +0200 Subject: [PATCH 1/5] Fetch share again via OCS request if it's not in the response --- .../web-app-files/src/views/SharedWithMe.vue | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/web-app-files/src/views/SharedWithMe.vue b/packages/web-app-files/src/views/SharedWithMe.vue index b047c33d3eb..6d3d6ed9a34 100644 --- a/packages/web-app-files/src/views/SharedWithMe.vue +++ b/packages/web-app-files/src/views/SharedWithMe.vue @@ -226,15 +226,33 @@ export default { async triggerShareAction(resource, type) { try { + // exec share action let response = await this.$client.requests.ocs({ service: 'apps/files_sharing', action: `api/v1/shares/pending/${resource.share.id}`, method: type }) - response = await response.json() - if (response.ocs.data.length > 0) { + + // exit on failure + if (response.status !== 200) { + throw new Error() + } + + // get updated share from response or re-fetch it + let share = null + if (response.headers.map['content-length'] > 0) { + response = await response.json() + if (response.ocs.data.length > 0) { + share = response.ocs.data[0] + } + } else { + share = await this.$client.shares.getShare(resource.share.id) + } + + // update share in store + if (share) { const sharedResource = await buildSharedResource( - response.ocs.data[0], + share, true, !this.isOcis, this.configuration.server, From fd631e6ee61d0daec08bcfd97cefbe5fddeb0a88 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Wed, 28 Apr 2021 23:21:15 +0200 Subject: [PATCH 2/5] refactor root unit test stub location add mocks for styles mock cross-fetch and sync-fetch to make owncloud-sdk work add test for SharedWithMe.vue --- .../web-app-files/src/views/SharedWithMe.vue | 5 +- .../tests/views/SharedWithMe.setup.js | 81 +++++++++++++++++++ .../tests/views/SharedWithMe.spec.js | 63 +++++++++++++++ .../tests/components/TopBar.spec.js | 2 +- tests/unit/config/jest.config.js | 3 + tests/unit/config/jest.init.js | 4 + tests/unit/mocks/style.js | 1 + .../unit/{config/stubs.js => stubs/index.js} | 0 8 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 packages/web-app-files/tests/views/SharedWithMe.setup.js create mode 100644 packages/web-app-files/tests/views/SharedWithMe.spec.js create mode 100644 tests/unit/mocks/style.js rename tests/unit/{config/stubs.js => stubs/index.js} (100%) diff --git a/packages/web-app-files/src/views/SharedWithMe.vue b/packages/web-app-files/src/views/SharedWithMe.vue index 6d3d6ed9a34..797232cfef2 100644 --- a/packages/web-app-files/src/views/SharedWithMe.vue +++ b/packages/web-app-files/src/views/SharedWithMe.vue @@ -235,12 +235,11 @@ export default { // exit on failure if (response.status !== 200) { - throw new Error() + throw new Error(response.statusText) } - // get updated share from response or re-fetch it let share = null - if (response.headers.map['content-length'] > 0) { + if (response.headers.get('content-length') > 0) { response = await response.json() if (response.ocs.data.length > 0) { share = response.ocs.data[0] diff --git a/packages/web-app-files/tests/views/SharedWithMe.setup.js b/packages/web-app-files/tests/views/SharedWithMe.setup.js new file mode 100644 index 00000000000..25dad44813c --- /dev/null +++ b/packages/web-app-files/tests/views/SharedWithMe.setup.js @@ -0,0 +1,81 @@ +import { mount, createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import OwnCloud from 'owncloud-sdk' +import SharedWithMe from '../../src/views/SharedWithMe' +import { createStore } from 'vuex-extensions' +import DesignSystem from 'owncloud-design-system' + +const createFile = ({ id, status = 1, type = 'folder' }) => ({ + id: `file-id-${id}`, + type, + status, + name: `file-name-${id}`, + path: `/file-path/${id}`, + extension: '', + share: { + id: `file-share-id-${id}` + }, + indicators: [] +}) + +const localVue = createLocalVue() +localVue.prototype.$client = new OwnCloud() +localVue.prototype.$client.init({ baseUrl: 'http://none.de' }) +localVue.use(Vuex) +localVue.use(DesignSystem) + +export const store = createStore(Vuex.Store, { + getters: { + configuration: () => ({ + options: { + disablePreviews: true + } + }), + getToken: () => '', + isOcis: () => true + }, + modules: { + Files: { + state: { + resource: null + }, + getters: { + selectedFiles: () => [], + activeFiles: () => [createFile({ id: 1 }), createFile({ id: 2, status: 2 })], + activeFilesCount: () => ({ files: 0, folders: 1 }), + inProgress: () => [null], + highlightedFile: () => null + }, + mutations: { + UPDATE_RESOURCE: (state, resource) => { + state.resource = resource + } + }, + namespaced: true + } + } +}) + +export const wrapper = mount( + { ...SharedWithMe, created: jest.fn(), mounted: jest.fn() }, + { + localVue, + store, + stubs: { + 'router-link': true, + translate: true + }, + data: () => ({ + loading: false + }) + } +) + +jest.mock('../../src/helpers/resources', () => ({ + buildSharedResource: jest.fn(share => share) +})) + +export const showMessage = jest.spyOn(wrapper.vm, 'showMessage').mockImplementation(v => v) +export const getShare = jest + .spyOn(localVue.prototype.$client.shares, 'getShare') + .mockImplementation(v => v) diff --git a/packages/web-app-files/tests/views/SharedWithMe.spec.js b/packages/web-app-files/tests/views/SharedWithMe.spec.js new file mode 100644 index 00000000000..99b8af0c0ea --- /dev/null +++ b/packages/web-app-files/tests/views/SharedWithMe.spec.js @@ -0,0 +1,63 @@ +import { wrapper, store, showMessage, getShare } from './SharedWithMe.setup' + +describe('SharedWithMe component', () => { + describe('method triggerShareAction', () => { + beforeEach(() => { + fetch.resetMocks() + store.reset() + showMessage.mockClear() + getShare.mockClear() + }) + + it('errors if status is not 200', async () => { + const statusText = 'status is not 200' + fetch.mockResponse(new Error(), { status: 404, statusText }) + await wrapper + .findAll('.file-row-share-status-action') + .at(1) + .trigger('click') + + expect(showMessage.mock.results[0].value.desc).toBe(statusText) + }) + + it('returns a share if content-length header is present and valid (oc10)', async () => { + fetch.mockResponse(JSON.stringify({ ocs: { data: [{ id: 1 }] } }), { + headers: { 'content-length': 1 } + }) + await wrapper + .findAll('.file-row-share-status-action') + .at(1) + .trigger('click') + await wrapper.vm.$nextTick() + + expect(store.state.Files.resource).toMatchObject({ id: 1 }) + expect(getShare).toBeCalledTimes(0) + }) + + it('errors if content-length header is not valid (oc10)', async () => { + fetch.mockResponse(JSON.stringify({ ocs: { data: [{ id: 1 }] } }), { + headers: { 'content-length': 0 } + }) + + await wrapper + .findAll('.file-row-share-status-action') + .at(1) + .trigger('click') + await wrapper.vm.$nextTick() + + expect(showMessage.mock.results[0]).toBeFalsy() + }) + + it('returns a share if content-length header is not present (ocis)', async () => { + fetch.mockResponse(JSON.stringify({ ocs: { data: [{ id: 1 }] } }), {}) + await wrapper + .findAll('.file-row-share-status-action') + .at(1) + .trigger('click') + await wrapper.vm.$nextTick() + + expect(store.state.Files.resource).toMatch('1') + expect(getShare).toBeCalledTimes(1) + }) + }) +}) diff --git a/packages/web-runtime/tests/components/TopBar.spec.js b/packages/web-runtime/tests/components/TopBar.spec.js index 57ae8856778..f24ef68593f 100644 --- a/packages/web-runtime/tests/components/TopBar.spec.js +++ b/packages/web-runtime/tests/components/TopBar.spec.js @@ -1,7 +1,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils' import Vuex from 'vuex' import TopBar from 'web-runtime/src/components/TopBar.vue' -import stubs from '../../../../tests/unit/config/stubs' +import stubs from '../../../../tests/unit/stubs' const localVue = createLocalVue() localVue.use(Vuex) diff --git a/tests/unit/config/jest.config.js b/tests/unit/config/jest.config.js index 1667dc8f439..5bae6181b92 100644 --- a/tests/unit/config/jest.config.js +++ b/tests/unit/config/jest.config.js @@ -10,6 +10,9 @@ module.exports = { '.*\\.(vue)$': 'vue-jest', '^.+\\.svg$': 'jest-svg-transformer' }, + moduleNameMapper: { + '\\.(css|less)$': '/tests/unit/mocks/style.js' + }, transformIgnorePatterns: ['/node_modules/(?!lodash-es)'], setupFiles: ['/tests/unit/config/jest.init.js'], snapshotSerializers: ['jest-serializer-vue'], diff --git a/tests/unit/config/jest.init.js b/tests/unit/config/jest.init.js index e403776652b..fff1680ebf6 100644 --- a/tests/unit/config/jest.init.js +++ b/tests/unit/config/jest.init.js @@ -2,6 +2,10 @@ import { config } from '@vue/test-utils' import fetchMock from 'jest-fetch-mock' fetchMock.enableMocks() +try { + jest.setMock('cross-fetch', fetchMock) + jest.setMock('sync-fetch', fetchMock) +} catch (error) {} config.mocks = { $gettext: str => str diff --git a/tests/unit/mocks/style.js b/tests/unit/mocks/style.js new file mode 100644 index 00000000000..b1c6ea436a5 --- /dev/null +++ b/tests/unit/mocks/style.js @@ -0,0 +1 @@ +export default {} diff --git a/tests/unit/config/stubs.js b/tests/unit/stubs/index.js similarity index 100% rename from tests/unit/config/stubs.js rename to tests/unit/stubs/index.js From 14329a5e94d418b97efdf800f287877bd06a8244 Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Wed, 5 May 2021 14:54:24 +0200 Subject: [PATCH 3/5] Use `share.shareInfo` for updating shared with me table --- packages/web-app-files/src/views/SharedWithMe.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/web-app-files/src/views/SharedWithMe.vue b/packages/web-app-files/src/views/SharedWithMe.vue index 797232cfef2..e406624d5b1 100644 --- a/packages/web-app-files/src/views/SharedWithMe.vue +++ b/packages/web-app-files/src/views/SharedWithMe.vue @@ -246,6 +246,7 @@ export default { } } else { share = await this.$client.shares.getShare(resource.share.id) + share = share.shareInfo } // update share in store From 7ddca86526b6a4c93ab6e9f60dbb667a12c6827c Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Thu, 6 May 2021 00:14:43 +0200 Subject: [PATCH 4/5] Parse content-length header value to int --- packages/web-app-files/src/views/SharedWithMe.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web-app-files/src/views/SharedWithMe.vue b/packages/web-app-files/src/views/SharedWithMe.vue index e406624d5b1..9542b5ffa51 100644 --- a/packages/web-app-files/src/views/SharedWithMe.vue +++ b/packages/web-app-files/src/views/SharedWithMe.vue @@ -239,7 +239,7 @@ export default { } // get updated share from response or re-fetch it let share = null - if (response.headers.get('content-length') > 0) { + if (parseInt(response.headers.get('content-length')) > 0) { response = await response.json() if (response.ocs.data.length > 0) { share = response.ocs.data[0] From d9560c3dded522a9576edfce9d0b7932f7fbd67a Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 6 May 2021 16:42:51 +0200 Subject: [PATCH 5/5] fix tests --- packages/web-app-files/src/views/SharedWithMe.vue | 15 +++++++++------ .../tests/views/SharedWithMe.spec.js | 5 ++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/web-app-files/src/views/SharedWithMe.vue b/packages/web-app-files/src/views/SharedWithMe.vue index 9542b5ffa51..e46b1dc65f4 100644 --- a/packages/web-app-files/src/views/SharedWithMe.vue +++ b/packages/web-app-files/src/views/SharedWithMe.vue @@ -62,13 +62,13 @@ > folder + >folder + and file + >file + @@ -239,14 +239,17 @@ export default { } // get updated share from response or re-fetch it let share = null + // oc10 if (parseInt(response.headers.get('content-length')) > 0) { response = await response.json() + if (response.ocs.data.length > 0) { share = response.ocs.data[0] } } else { - share = await this.$client.shares.getShare(resource.share.id) - share = share.shareInfo + // ocis + const { shareInfo } = await this.$client.shares.getShare(resource.share.id) + share = shareInfo } // update share in store diff --git a/packages/web-app-files/tests/views/SharedWithMe.spec.js b/packages/web-app-files/tests/views/SharedWithMe.spec.js index 99b8af0c0ea..08e0ddcac55 100644 --- a/packages/web-app-files/tests/views/SharedWithMe.spec.js +++ b/packages/web-app-files/tests/views/SharedWithMe.spec.js @@ -49,14 +49,17 @@ describe('SharedWithMe component', () => { }) it('returns a share if content-length header is not present (ocis)', async () => { + const shareInfo = { id: 1, shareinfo: true } fetch.mockResponse(JSON.stringify({ ocs: { data: [{ id: 1 }] } }), {}) + getShare.mockReturnValueOnce({ shareInfo }) + await wrapper .findAll('.file-row-share-status-action') .at(1) .trigger('click') await wrapper.vm.$nextTick() - expect(store.state.Files.resource).toMatch('1') + expect(store.state.Files.resource).toMatchObject(shareInfo) expect(getShare).toBeCalledTimes(1) }) })