summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2024-10-16 01:03:40 +0200
committerskjnldsv <skjnldsv@protonmail.com>2024-10-29 14:28:58 +0100
commit55595f61df21761b245eff952e8b95bc572a34c6 (patch)
treeccec212e9c781df447a837bb5c39acd0ba378a76
parent9aec7b9b8595785996b6fea13550cded3b7803b5 (diff)
downloadnextcloud-server-55595f61df21761b245eff952e8b95bc572a34c6.tar.gz
nextcloud-server-55595f61df21761b245eff952e8b95bc572a34c6.zip
refactor(federatedfilesharing): Replace deprecated functions
* Replace deprecated OC dialogs methods * Replace deprecated global jQuery with axios * Replace deprecated jQuery event with event bus * Add component + unit tests for new dialog Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r--__tests__/setup-testing-library.js1
-rw-r--r--apps/federatedfilesharing/src/components/RemoteShareDialog.cy.ts123
-rw-r--r--apps/federatedfilesharing/src/components/RemoteShareDialog.vue67
-rw-r--r--apps/federatedfilesharing/src/external.js182
-rw-r--r--apps/federatedfilesharing/src/services/dialogService.spec.ts65
-rw-r--r--apps/federatedfilesharing/src/services/dialogService.ts36
-rw-r--r--apps/federatedfilesharing/tests/js/externalSpec.js241
7 files changed, 370 insertions, 345 deletions
diff --git a/__tests__/setup-testing-library.js b/__tests__/setup-testing-library.js
index 9f0a55dd211..190e6f93e7c 100644
--- a/__tests__/setup-testing-library.js
+++ b/__tests__/setup-testing-library.js
@@ -3,3 +3,4 @@
* SPDX-License-Identifier: CC0-1.0
*/
import '@testing-library/jest-dom/vitest'
+import 'core-js/stable/index.js'
diff --git a/apps/federatedfilesharing/src/components/RemoteShareDialog.cy.ts b/apps/federatedfilesharing/src/components/RemoteShareDialog.cy.ts
new file mode 100644
index 00000000000..79b5138327a
--- /dev/null
+++ b/apps/federatedfilesharing/src/components/RemoteShareDialog.cy.ts
@@ -0,0 +1,123 @@
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import RemoteShareDialog from './RemoteShareDialog.vue'
+
+describe('RemoteShareDialog', () => {
+ it('can be mounted', () => {
+ cy.mount(RemoteShareDialog, {
+ propsData: {
+ owner: 'user123',
+ name: 'my-photos',
+ remote: 'nextcloud.local',
+ passwordRequired: false,
+ },
+ })
+
+ cy.findByRole('dialog')
+ .should('be.visible')
+ .and('contain.text', 'user123@nextcloud.local')
+ .and('contain.text', 'my-photos')
+ cy.findByRole('button', { name: 'Cancel' })
+ .should('be.visible')
+ cy.findByRole('button', { name: /add remote share/i })
+ .should('be.visible')
+ })
+
+ it('does not show password input if not enabled', () => {
+ cy.mount(RemoteShareDialog, {
+ propsData: {
+ owner: 'user123',
+ name: 'my-photos',
+ remote: 'nextcloud.local',
+ passwordRequired: false,
+ },
+ })
+
+ cy.findByRole('dialog')
+ .should('be.visible')
+ .find('input[type="password"]')
+ .should('not.exist')
+ })
+
+ it('emits true when accepted', () => {
+ const onClose = cy.spy().as('onClose')
+
+ cy.mount(RemoteShareDialog, {
+ listeners: {
+ close: onClose,
+ },
+ propsData: {
+ owner: 'user123',
+ name: 'my-photos',
+ remote: 'nextcloud.local',
+ passwordRequired: false,
+ },
+ })
+
+ cy.findByRole('button', { name: 'Cancel' }).click()
+ cy.get('@onClose')
+ .should('have.been.calledWith', false)
+ })
+
+ it('show password input if needed', () => {
+ cy.mount(RemoteShareDialog, {
+ propsData: {
+ owner: 'admin',
+ name: 'secret-data',
+ remote: 'nextcloud.local',
+ passwordRequired: true,
+ },
+ })
+
+ cy.findByRole('dialog')
+ .should('be.visible')
+ .find('input[type="password"]')
+ .should('be.visible')
+ })
+
+ it('emits the submitted password', () => {
+ const onClose = cy.spy().as('onClose')
+
+ cy.mount(RemoteShareDialog, {
+ listeners: {
+ close: onClose,
+ },
+ propsData: {
+ owner: 'admin',
+ name: 'secret-data',
+ remote: 'nextcloud.local',
+ passwordRequired: true,
+ },
+ })
+
+ cy.get('input[type="password"]')
+ .type('my password{enter}')
+ cy.get('@onClose')
+ .should('have.been.calledWith', true, 'my password')
+ })
+
+ it('emits no password if cancelled', () => {
+ const onClose = cy.spy().as('onClose')
+
+ cy.mount(RemoteShareDialog, {
+ listeners: {
+ close: onClose,
+ },
+ propsData: {
+ owner: 'admin',
+ name: 'secret-data',
+ remote: 'nextcloud.local',
+ passwordRequired: true,
+ },
+ })
+
+ cy.get('input[type="password"]')
+ .type('my password')
+ cy.findByRole('button', { name: 'Cancel' }).click()
+ cy.get('@onClose')
+ .should('have.been.calledWith', false)
+ })
+})
diff --git a/apps/federatedfilesharing/src/components/RemoteShareDialog.vue b/apps/federatedfilesharing/src/components/RemoteShareDialog.vue
new file mode 100644
index 00000000000..68d1a9a00df
--- /dev/null
+++ b/apps/federatedfilesharing/src/components/RemoteShareDialog.vue
@@ -0,0 +1,67 @@
+<!--
+ - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<script setup lang="ts">
+import { t } from '@nextcloud/l10n'
+import { computed, ref } from 'vue'
+import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
+import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js'
+
+const props = defineProps<{
+ /** Name of the share */
+ name: string
+ /** Display name of the owner */
+ owner: string
+ /** The remote instance name */
+ remote: string
+ /** True if the user should enter a password */
+ passwordRequired: boolean
+}>()
+
+const emit = defineEmits<{
+ (e: 'close', state: boolean, password?: string): void
+}>()
+
+const password = ref('')
+
+/**
+ * The dialog buttons
+ */
+const buttons = computed(() => [
+ {
+ label: t('federatedfilesharing', 'Cancel'),
+ callback: () => emit('close', false),
+ },
+ {
+ label: t('federatedfilesharing', 'Add remote share'),
+ nativeType: props.passwordRequired ? 'submit' : undefined,
+ type: 'primary',
+ callback: () => emit('close', true, password.value),
+ },
+])
+</script>
+
+<template>
+ <NcDialog :buttons="buttons"
+ :is-form="passwordRequired"
+ :name="t('federatedfilesharing', 'Remote share')"
+ @submit="emit('close', true, password)">
+ <p>
+ {{ t('federatedfilesharing', 'Do you want to add the remote share {name} from {owner}@{remote}?', { name, owner, remote }) }}
+ </p>
+ <NcPasswordField v-if="passwordRequired"
+ class="remote-share-dialog__password"
+ :label="t('federatedfilesharing', 'Remote share password')"
+ :value.sync="password" />
+ </NcDialog>
+</template>
+
+<style scoped lang="scss">
+.remote-share-dialog {
+
+ &__password {
+ margin-block: 1em .5em;
+ }
+}
+</style>
diff --git a/apps/federatedfilesharing/src/external.js b/apps/federatedfilesharing/src/external.js
index 09e007489b5..b9aaa2a442e 100644
--- a/apps/federatedfilesharing/src/external.js
+++ b/apps/federatedfilesharing/src/external.js
@@ -3,10 +3,15 @@
* SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+import axios, { isAxiosError } from '@nextcloud/axios'
+import { showError, showInfo } from '@nextcloud/dialogs'
+import { subscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
+import { t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
+import { showRemoteShareDialog } from './services/dialogService.ts'
-window.OCA.Sharing = window.OCA.Sharing || {}
+window.OCA.Sharing = window.OCA.Sharing ?? {}
/**
* Shows "add external share" dialog.
@@ -20,57 +25,40 @@ window.OCA.Sharing = window.OCA.Sharing || {}
* @param {Function} callback the callback
*/
window.OCA.Sharing.showAddExternalDialog = function(share, passwordProtected, callback) {
- const remote = share.remote
const owner = share.ownerDisplayName || share.owner
const name = share.name
// Clean up the remote URL for display
- const remoteClean = remote
+ const remote = share.remote
.replace(/^https?:\/\//, '') // remove http:// or https://
.replace(/\/$/, '') // remove trailing slash
- if (!passwordProtected) {
- window.OC.dialogs.confirm(
- t(
- 'files_sharing',
- 'Do you want to add the remote share {name} from {owner}@{remote}?',
- { name, owner, remote: remoteClean },
- ),
- t('files_sharing', 'Remote share'),
- function(result) {
- callback(result, share)
- },
- true,
- ).then(this._adjustDialog)
- } else {
- window.OC.dialogs.prompt(
- t(
- 'files_sharing',
- 'Do you want to add the remote share {name} from {owner}@{remote}?',
- { name, owner, remote: remoteClean },
- ),
- t('files_sharing', 'Remote share'),
- function(result, password) {
- share.password = password
- callback(result, share)
- },
- true,
- t('files_sharing', 'Remote share password'),
- true,
- ).then(this._adjustDialog)
- }
+ showRemoteShareDialog(name, owner, remote, passwordProtected)
+ .then((result, password) => callback(result, { ...share, password }))
+ // eslint-disable-next-line n/no-callback-literal
+ .catch(() => callback(false, share))
}
-window.OCA.Sharing._adjustDialog = function() {
- const $dialog = $('.oc-dialog:visible')
- const $buttons = $dialog.find('button')
- // hack the buttons
- $dialog.find('.ui-icon').remove()
- $buttons.eq(1).text(t('core', 'Cancel'))
- $buttons.eq(2).text(t('files_sharing', 'Add remote share'))
-}
+window.addEventListener('DOMContentLoaded', () => {
+ processIncomingShareFromUrl()
+
+ if (loadState('federatedfilesharing', 'notificationsEnabled', true) !== true) {
+ // No notification app, display the modal
+ processSharesToConfirm()
+ }
-const reloadFilesList = function() {
+ subscribe('notifications:action:executed', ({ action, notification }) => {
+ if (notification.app === 'files_sharing' && notification.object_type === 'remote_share' && action.type === 'POST') {
+ // User accepted a remote share reload
+ reloadFilesList()
+ }
+ })
+})
+
+/**
+ * Reload the files list to show accepted shares
+ */
+function reloadFilesList() {
if (!window?.OCP?.Files?.Router?.goToRoute) {
// No router, just reload the page
window.location.reload()
@@ -89,35 +77,42 @@ const reloadFilesList = function() {
* Process incoming remote share that might have been passed
* through the URL
*/
-const processIncomingShareFromUrl = function() {
+function processIncomingShareFromUrl() {
const params = window.OC.Util.History.parseUrlQuery()
// manually add server-to-server share
if (params.remote && params.token && params.name) {
- const callbackAddShare = function(result, share) {
- const password = share.password || ''
- if (result) {
- $.post(
- generateUrl('apps/federatedfilesharing/askForFederatedShare'),
- {
- remote: share.remote,
- token: share.token,
- owner: share.owner,
- ownerDisplayName: share.ownerDisplayName || share.owner,
- name: share.name,
- password,
- },
- ).done(function(data) {
- if (Object.hasOwn(data, 'legacyMount')) {
- reloadFilesList()
- } else {
- window.OC.Notification.showTemporary(data.message)
- }
- }).fail(function(data) {
- window.OC.Notification.showTemporary(JSON.parse(data.responseText).message)
- })
+ const callbackAddShare = (result, share) => {
+ if (result === false) {
+ return
}
+
+ axios.post(
+ generateUrl('apps/federatedfilesharing/askForFederatedShare'),
+ {
+ remote: share.remote,
+ token: share.token,
+ owner: share.owner,
+ ownerDisplayName: share.ownerDisplayName || share.owner,
+ name: share.name,
+ password: share.password || '',
+ },
+ ).then(({ data }) => {
+ if (Object.hasOwn(data, 'legacyMount')) {
+ reloadFilesList()
+ } else {
+ showInfo(data.message)
+ }
+ }).catch((error) => {
+ console.error('Error while processing incoming share', error)
+
+ if (isAxiosError(error) && error.response.data.message) {
+ showError(error.response.data.message)
+ } else {
+ showError(t('federatedfilesharing', 'Incoming share could not be processed'))
+ }
+ })
}
// clear hash, it is unlikely that it contain any extra parameters
@@ -134,44 +129,23 @@ const processIncomingShareFromUrl = function() {
/**
* Retrieve a list of remote shares that need to be approved
*/
-const processSharesToConfirm = function() {
+async function processSharesToConfirm() {
// check for new server-to-server shares which need to be approved
- $.get(generateUrl('/apps/files_sharing/api/externalShares'), {}, function(shares) {
- let index
- for (index = 0; index < shares.length; ++index) {
- window.OCA.Sharing.showAddExternalDialog(
- shares[index],
- false,
- function(result, share) {
- if (result) {
- // Accept
- $.post(generateUrl('/apps/files_sharing/api/externalShares'), { id: share.id })
- .then(function() {
- reloadFilesList()
- })
- } else {
- // Delete
- $.ajax({
- url: generateUrl('/apps/files_sharing/api/externalShares/' + share.id),
- type: 'DELETE',
- })
- }
- },
- )
- }
- })
-}
-
-processIncomingShareFromUrl()
-
-if (loadState('federatedfilesharing', 'notificationsEnabled', true) !== true) {
- // No notification app, display the modal
- processSharesToConfirm()
-}
-
-$('body').on('window.OCA.Notification.Action', function(e) {
- if (e.notification.app === 'files_sharing' && e.notification.object_type === 'remote_share' && e.action.type === 'POST') {
- // User accepted a remote share reload
- reloadFilesList()
+ const { data: shares } = await axios.get(generateUrl('/apps/files_sharing/api/externalShares'))
+ for (let index = 0; index < shares.length; ++index) {
+ window.OCA.Sharing.showAddExternalDialog(
+ shares[index],
+ false,
+ function(result, share) {
+ if (result) {
+ // Accept
+ axios.post(generateUrl('/apps/files_sharing/api/externalShares'), { id: share.id })
+ .then(() => reloadFilesList())
+ } else {
+ // Delete
+ axios.delete(generateUrl('/apps/files_sharing/api/externalShares/' + share.id))
+ }
+ },
+ )
}
-})
+}
diff --git a/apps/federatedfilesharing/src/services/dialogService.spec.ts b/apps/federatedfilesharing/src/services/dialogService.spec.ts
new file mode 100644
index 00000000000..0ad02fa4e00
--- /dev/null
+++ b/apps/federatedfilesharing/src/services/dialogService.spec.ts
@@ -0,0 +1,65 @@
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { describe, expect, it } from 'vitest'
+import { showRemoteShareDialog } from './dialogService'
+import { nextTick } from 'vue'
+
+describe('federatedfilesharing: dialog service', () => {
+ it('mounts dialog', async () => {
+ showRemoteShareDialog('share-name', 'user123', 'example.com')
+ await nextTick()
+ expect(document.querySelector('[role="dialog"]')).not.toBeNull()
+ expect(document.querySelector('[role="dialog"]')!.textContent).to.contain('share-name')
+ expect(document.querySelector('[role="dialog"]')!.textContent).to.contain('user123@example.com')
+ expect(document.querySelector('[role="dialog"] input[type="password"]')).toBeNull()
+ })
+
+ it('shows password input', async () => {
+ showRemoteShareDialog('share-name', 'user123', 'example.com', true)
+ await nextTick()
+ expect(document.querySelector('[role="dialog"]')).not.toBeNull()
+ expect(document.querySelector('[role="dialog"] input[type="password"]')).not.toBeNull()
+ })
+
+ it('resolves if accepted', async () => {
+ const promise = showRemoteShareDialog('share-name', 'user123', 'example.com')
+ await nextTick()
+
+ for (const button of document.querySelectorAll('button').values()) {
+ if (button.textContent?.match(/add remote share/i)) {
+ button.click()
+ }
+ }
+
+ expect(await promise).toBe(undefined)
+ })
+
+ it('resolves password if accepted', async () => {
+ const promise = showRemoteShareDialog('share-name', 'user123', 'example.com', true)
+ await nextTick()
+
+ for (const button of document.querySelectorAll('button').values()) {
+ if (button.textContent?.match(/add remote share/i)) {
+ button.click()
+ }
+ }
+
+ expect(await promise).toBe('')
+ })
+
+ it('rejects if cancelled', async () => {
+ const promise = showRemoteShareDialog('share-name', 'user123', 'example.com')
+ await nextTick()
+
+ for (const button of document.querySelectorAll('button').values()) {
+ if (button.textContent?.match(/cancel/i)) {
+ button.click()
+ }
+ }
+
+ expect(async () => await promise).rejects.toThrow()
+ })
+})
diff --git a/apps/federatedfilesharing/src/services/dialogService.ts b/apps/federatedfilesharing/src/services/dialogService.ts
new file mode 100644
index 00000000000..a38c6c57707
--- /dev/null
+++ b/apps/federatedfilesharing/src/services/dialogService.ts
@@ -0,0 +1,36 @@
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { spawnDialog } from '@nextcloud/dialogs'
+import RemoteShareDialog from '../components/RemoteShareDialog.vue'
+
+/**
+ * Open a dialog to ask the user whether to add a remote share.
+ *
+ * @param name The name of the share
+ * @param owner The owner of the share
+ * @param remote The remote address
+ * @param passwordRequired True if the share is password protected
+ */
+export function showRemoteShareDialog(
+ name: string,
+ owner: string,
+ remote: string,
+ passwordRequired = false,
+): Promise<string|void> {
+ const { promise, reject, resolve } = Promise.withResolvers<string|void>()
+
+ spawnDialog(RemoteShareDialog, { name, owner, remote, passwordRequired }, (status, password) => {
+ if (passwordRequired && status) {
+ resolve(password as string)
+ } else if (status) {
+ resolve(undefined)
+ } else {
+ reject()
+ }
+ })
+
+ return promise
+}
diff --git a/apps/federatedfilesharing/tests/js/externalSpec.js b/apps/federatedfilesharing/tests/js/externalSpec.js
deleted file mode 100644
index b67c51aebf7..00000000000
--- a/apps/federatedfilesharing/tests/js/externalSpec.js
+++ /dev/null
@@ -1,241 +0,0 @@
-/**
- * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2015 ownCloud, Inc.
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-describe('OCA.Sharing external tests', function() {
- var plugin;
- var urlQueryStub;
- var promptDialogStub;
- var confirmDialogStub;
-
- function dummyShowDialog() {
- var deferred = $.Deferred();
- deferred.resolve();
- return deferred.promise();
- }
-
- beforeEach(function() {
- plugin = OCA.Sharing.ExternalShareDialogPlugin;
- urlQueryStub = sinon.stub(OC.Util.History, 'parseUrlQuery');
-
- confirmDialogStub = sinon.stub(OC.dialogs, 'confirm').callsFake(dummyShowDialog);
- promptDialogStub = sinon.stub(OC.dialogs, 'prompt').callsFake(dummyShowDialog);
-
- plugin.filesApp = {
- fileList: {
- reload: sinon.stub()
- }
- };
- });
- afterEach(function() {
- urlQueryStub.restore();
- confirmDialogStub.restore();
- promptDialogStub.restore();
- plugin = null;
- });
- describe('confirmation dialog from URL', function() {
- var testShare;
-
- /**
- * Checks that the server call's query matches what is
- * expected.
- *
- * @param {Object} expectedQuery expected query params
- */
- function checkRequest(expectedQuery) {
- var request = fakeServer.requests[0];
- var query = OC.parseQueryString(request.requestBody);
- expect(request.method).toEqual('POST');
- expect(query).toEqual(expectedQuery);
-
- request.respond(
- 200,
- {'Content-Type': 'application/json'},
- JSON.stringify({status: 'success'})
- );
- expect(plugin.filesApp.fileList.reload.calledOnce).toEqual(true);
- }
-
- beforeEach(function() {
- testShare = {
- remote: 'http://example.com/owncloud',
- token: 'abcdefg',
- owner: 'theowner',
- ownerDisplayName: 'The Generous Owner',
- name: 'the share name'
- };
- });
- it('does nothing when no share was passed in URL', function() {
- urlQueryStub.returns({});
- plugin.processIncomingShareFromUrl();
- expect(promptDialogStub.notCalled).toEqual(true);
- expect(confirmDialogStub.notCalled).toEqual(true);
- expect(fakeServer.requests.length).toEqual(0);
- });
- it('sends share info to server on confirm', function() {
- urlQueryStub.returns(testShare);
- plugin.processIncomingShareFromUrl();
- expect(promptDialogStub.notCalled).toEqual(true);
- expect(confirmDialogStub.calledOnce).toEqual(true);
- confirmDialogStub.getCall(0).args[2](true);
- expect(fakeServer.requests.length).toEqual(1);
- checkRequest({
- remote: 'http://example.com/owncloud',
- token: 'abcdefg',
- owner: 'theowner',
- ownerDisplayName: 'The Generous Owner',
- name: 'the share name',
- password: ''
- });
- });
- it('sends share info with password to server on confirm', function() {
- testShare = _.extend(testShare, {protected: 1});
- urlQueryStub.returns(testShare);
- plugin.processIncomingShareFromUrl();
- expect(promptDialogStub.calledOnce).toEqual(true);
- expect(confirmDialogStub.notCalled).toEqual(true);
- promptDialogStub.getCall(0).args[2](true, 'thepassword');
- expect(fakeServer.requests.length).toEqual(1);
- checkRequest({
- remote: 'http://example.com/owncloud',
- token: 'abcdefg',
- owner: 'theowner',
- ownerDisplayName: 'The Generous Owner',
- name: 'the share name',
- password: 'thepassword'
- });
- });
- it('does not send share info on cancel', function() {
- urlQueryStub.returns(testShare);
- plugin.processIncomingShareFromUrl();
- expect(promptDialogStub.notCalled).toEqual(true);
- expect(confirmDialogStub.calledOnce).toEqual(true);
- confirmDialogStub.getCall(0).args[2](false);
- expect(fakeServer.requests.length).toEqual(0);
- });
- });
- describe('show dialog for each share to confirm', function() {
- var testShare;
-
- /**
- * Call processSharesToConfirm() and make the fake server
- * return the passed response.
- *
- * @param {Array} response list of shares to process
- */
- function processShares(response) {
- plugin.processSharesToConfirm();
-
- expect(fakeServer.requests.length).toEqual(1);
-
- var req = fakeServer.requests[0];
- expect(req.method).toEqual('GET');
- expect(req.url).toEqual(OC.getRootPath() + '/index.php/apps/files_sharing/api/externalShares');
-
- req.respond(
- 200,
- {'Content-Type': 'application/json'},
- JSON.stringify(response)
- );
- }
-
- beforeEach(function() {
- testShare = {
- id: 123,
- remote: 'http://example.com/owncloud',
- token: 'abcdefg',
- owner: 'theowner',
- ownerDisplayName: 'The Generous Owner',
- name: 'the share name'
- };
- });
-
- it('does not show any dialog if no shares to confirm', function() {
- processShares([]);
- expect(confirmDialogStub.notCalled).toEqual(true);
- expect(promptDialogStub.notCalled).toEqual(true);
- });
- it('sends accept info to server on confirm', function() {
- processShares([testShare]);
-
- expect(promptDialogStub.notCalled).toEqual(true);
- expect(confirmDialogStub.calledOnce).toEqual(true);
-
- confirmDialogStub.getCall(0).args[2](true);
-
- expect(fakeServer.requests.length).toEqual(2);
-
- var request = fakeServer.requests[1];
- var query = OC.parseQueryString(request.requestBody);
- expect(request.method).toEqual('POST');
- expect(query).toEqual({id: '123'});
- expect(request.url).toEqual(
- OC.getRootPath() + '/index.php/apps/files_sharing/api/externalShares'
- );
-
- expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true);
- request.respond(
- 200,
- {'Content-Type': 'application/json'},
- JSON.stringify({status: 'success'})
- );
- expect(plugin.filesApp.fileList.reload.calledOnce).toEqual(true);
- });
- it('sends delete info to server on cancel', function() {
- processShares([testShare]);
-
- expect(promptDialogStub.notCalled).toEqual(true);
- expect(confirmDialogStub.calledOnce).toEqual(true);
-
- confirmDialogStub.getCall(0).args[2](false);
-
- expect(fakeServer.requests.length).toEqual(2);
-
- var request = fakeServer.requests[1];
- expect(request.method).toEqual('DELETE');
- expect(request.url).toEqual(
- OC.getRootPath() + '/index.php/apps/files_sharing/api/externalShares/123'
- );
-
- expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true);
- request.respond(
- 200,
- {'Content-Type': 'application/json'},
- JSON.stringify({status: 'success'})
- );
- expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true);
- });
- xit('shows another dialog when multiple shares need to be accepted', function() {
- // TODO: enable this test when fixing multiple dialogs issue / confirm loop
- var testShare2 = _.extend({}, testShare);
- testShare2.id = 256;
- processShares([testShare, testShare2]);
-
- // confirm first one
- expect(confirmDialogStub.calledOnce).toEqual(true);
- confirmDialogStub.getCall(0).args[2](true);
-
- // next dialog not shown yet
- expect(confirmDialogStub.calledOnce);
-
- // respond to the first accept request
- fakeServer.requests[1].respond(
- 200,
- {'Content-Type': 'application/json'},
- JSON.stringify({status: 'success'})
- );
-
- // don't reload yet, there are other shares to confirm
- expect(plugin.filesApp.fileList.reload.notCalled).toEqual(true);
-
- // cancel second share
- expect(confirmDialogStub.calledTwice).toEqual(true);
- confirmDialogStub.getCall(1).args[2](true);
-
- // reload only called at the very end
- expect(plugin.filesApp.fileList.reload.calledOnce).toEqual(true);
- });
- });
-});