diff options
author | Morris Jobke <hey@morrisjobke.de> | 2014-06-04 17:04:30 +0200 |
---|---|---|
committer | Morris Jobke <hey@morrisjobke.de> | 2014-06-04 17:04:30 +0200 |
commit | ca43fba513b34a60c905d526abd34f56661b6b6e (patch) | |
tree | d226b8ad4adf8e2d09ebf648ebf863419f75f6d2 /apps | |
parent | c6196c022d137f092af3c9857e6124af5abb5521 (diff) | |
parent | af6a65cbf3a122f92d91fe302e7d60e6c6a5416d (diff) | |
download | nextcloud-server-ca43fba513b34a60c905d526abd34f56661b6b6e.tar.gz nextcloud-server-ca43fba513b34a60c905d526abd34f56661b6b6e.zip |
Merge pull request #8791 from owncloud/share-overview-sharewithstatus
Update share action text to display owner/recipients
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files_sharing/js/app.js | 4 | ||||
-rw-r--r-- | apps/files_sharing/js/share.js | 239 | ||||
-rw-r--r-- | apps/files_sharing/js/sharedfilelist.js | 43 | ||||
-rw-r--r-- | apps/files_sharing/tests/js/appSpec.js | 4 | ||||
-rw-r--r-- | apps/files_sharing/tests/js/shareSpec.js | 450 | ||||
-rw-r--r-- | apps/files_sharing/tests/js/sharedfilelistSpec.js | 10 |
6 files changed, 640 insertions, 110 deletions
diff --git a/apps/files_sharing/js/app.js b/apps/files_sharing/js/app.js index 3764328a5d0..800873cd638 100644 --- a/apps/files_sharing/js/app.js +++ b/apps/files_sharing/js/app.js @@ -8,7 +8,9 @@ * */ -OCA.Sharing = {}; +if (!OCA.Sharing) { + OCA.Sharing = {}; +} OCA.Sharing.App = { _inFileList: null, diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 5a42604c866..d63a590fb8e 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -8,103 +8,166 @@ * */ -$(document).ready(function() { - if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) { - // TODO: make a separate class for this or a hook or jQuery event ? - if (OCA.Files.FileList) { - var oldCreateRow = OCA.Files.FileList.prototype._createRow; - OCA.Files.FileList.prototype._createRow = function(fileData) { - var tr = oldCreateRow.apply(this, arguments); - if (fileData.shareOwner) { - tr.attr('data-share-owner', fileData.shareOwner); - // user should always be able to rename a mount point - if (fileData.isShareMountPoint) { - tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE); - tr.attr('data-reshare-permissions', fileData.permissions); +(function() { + if (!OCA.Sharing) { + OCA.Sharing = {}; + } + OCA.Sharing.Util = { + initialize: function(fileActions) { + if (OCA.Files.FileList) { + var oldCreateRow = OCA.Files.FileList.prototype._createRow; + OCA.Files.FileList.prototype._createRow = function(fileData) { + var tr = oldCreateRow.apply(this, arguments); + if (fileData.shareOwner) { + tr.attr('data-share-owner', fileData.shareOwner); + // user should always be able to rename a mount point + if (fileData.isShareMountPoint) { + tr.attr('data-permissions', fileData.permissions | OC.PERMISSION_UPDATE); + tr.attr('data-reshare-permissions', fileData.permissions); + } } - } - return tr; - }; - } + if (fileData.recipientsDisplayName) { + tr.attr('data-share-recipients', fileData.recipientsDisplayName); + } + return tr; + }; - // use delegate to catch the case with multiple file lists - $('#content').delegate('#fileList', 'fileActionsReady',function(ev){ - // if no share action exists because the admin disabled sharing for this user - // we create a share notification action to inform the user about files - // shared with him otherwise we just update the existing share action. - var fileList = ev.fileList; - var $fileList = $(this); - $fileList.find('[data-share-owner]').each(function() { - var $tr = $(this); - var $action; - var owner; - var message; - var permissions = $tr.data('permissions'); - if(permissions & OC.PERMISSION_SHARE) { - $action = $tr.find('[data-Action="Share"]'); - $action.addClass('permanent'); - owner = $tr.closest('tr').attr('data-share-owner'); - message = ' ' + t('files_sharing', 'Shared by {owner}', {owner: owner}); - $action.find('span').text(message); - } else { - var shareNotification = '<a class="action action-share-notification permanent"' + - ' data-action="Share-Notification" href="#" original-title="">' + - ' <img class="svg" src="' + OC.imagePath('core', 'actions/share') + '"></img>'; - $tr.find('.fileactions').append(function() { - var owner = $(this).closest('tr').attr('data-share-owner'); - var shareBy = t('files_sharing', 'Shared by {owner}', {owner: owner}); - var $result = $(shareNotification + '<span> ' + shareBy + '</span></span>'); - $result.on('click', function() { - return false; - }); - return $result; - }); + var oldRenderRow = OCA.Files.FileList.prototype._renderRow; + OCA.Files.FileList.prototype._renderRow = function(fileData) { + var $tr = oldRenderRow.apply(this, arguments); + // if the statuses are loaded already, use them for the icon + // (needed when scrolling to the next page) + var shareStatus = OC.Share.statuses[fileData.id]; + if (fileData.shareOwner || fileData.recipientsDisplayName || shareStatus) { + var permissions = $tr.data('permissions'); + var hasLink = !!(shareStatus && shareStatus.link); + if (permissions & OC.PERMISSION_SHARE) { + OC.Share.markFileAsShared($tr, true, hasLink); + } else { + // if no share action exists because the admin disabled sharing for this user + // we create a share notification action to inform the user about files + // shared with him otherwise we just update the existing share action. + // TODO: make this work like/with OC.Share.markFileAsShared() + var shareNotification = '<a class="action action-share-notification permanent"' + + ' data-action="Share-Notification" href="#" original-title="">' + + ' <img class="svg" src="' + OC.imagePath('core', 'actions/share') + '"></img>'; + $tr.find('.fileactions').append(function() { + var shareBy = t('files_sharing', 'Shared by {owner}', {owner: fileData.shareOwner}); + var $result = $(shareNotification + '<span> ' + shareBy + '</span></span>'); + $result.on('click', function() { + return false; + }); + return $result; + }); + } + } + return $tr; + }; + } + + // use delegate to catch the case with multiple file lists + $('#content').delegate('#fileList', 'fileActionsReady',function(ev){ + var fileList = ev.fileList; + if (!OCA.Sharing.sharesLoaded){ + OC.Share.loadIcons('file', fileList); + // assume that we got all shares, so switching directories + // will not invalidate that list + OCA.Sharing.sharesLoaded = true; + } + else{ + // this will update the icons for all the currently visible elements + // additionally added elements when scrolling down will be + // updated in the _renderRow override + OC.Share.updateIcons('file', fileList); } }); - if (!OCA.Sharing.sharesLoaded){ - OC.Share.loadIcons('file', fileList); - // assume that we got all shares, so switching directories - // will not invalidate that list - OCA.Sharing.sharesLoaded = true; - } - else{ - OC.Share.updateIcons('file', fileList); - } - }); - - OCA.Files.fileActions.register( - 'all', - 'Share', - OC.PERMISSION_SHARE, - OC.imagePath('core', 'actions/share'), - function(filename, context) { + fileActions.register( + 'all', + 'Share', + OC.PERMISSION_SHARE, + OC.imagePath('core', 'actions/share'), + function(filename, context) { - var $tr = context.$file; - var itemType = 'file'; - if ($tr.data('type') === 'dir') { - itemType = 'folder'; - } - var possiblePermissions = $tr.data('reshare-permissions'); - if (_.isUndefined(possiblePermissions)) { - possiblePermissions = $tr.data('permissions'); - } + var $tr = context.$file; + var itemType = 'file'; + if ($tr.data('type') === 'dir') { + itemType = 'folder'; + } + var possiblePermissions = $tr.data('reshare-permissions'); + if (_.isUndefined(possiblePermissions)) { + possiblePermissions = $tr.data('permissions'); + } - var appendTo = $tr.find('td.filename'); - // Check if drop down is already visible for a different file - if (OC.Share.droppedDown) { - if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) { - OC.Share.hideDropDown(function () { - $tr.addClass('mouseOver'); - OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename); - }); + var appendTo = $tr.find('td.filename'); + // Check if drop down is already visible for a different file + if (OC.Share.droppedDown) { + if ($tr.data('id') !== $('#dropdown').attr('data-item-source')) { + OC.Share.hideDropDown(function () { + $tr.addClass('mouseOver'); + OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename); + }); + } else { + OC.Share.hideDropDown(); + } } else { - OC.Share.hideDropDown(); + $tr.addClass('mouseOver'); + OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename); } - } else { - $tr.addClass('mouseOver'); - OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename); + $('#dropdown').on('sharesChanged', function(ev) { + // files app current cannot show recipients on load, so we don't update the + // icon when changed for consistency + if (context.fileList.$el.closest('#app-content-files').length) { + return; + } + var recipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_USER], 'share_with_displayname'); + var groupRecipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_GROUP], 'share_with_displayname'); + recipients = recipients.concat(groupRecipients); + // note: we only update the data attribute because updateIcon() + // is called automatically after this event + if (recipients.length) { + $tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients)); + } + else { + $tr.removeAttr('data-share-recipients'); + } + }); + }); + }, + + /** + * Formats a recipients array to be displayed. + * The first four recipients will be shown and the + * other ones will be shown as "+x" where "x" is the number of + * remaining recipients. + * + * @param recipients recipients array + * @param count optional total recipients count (in case the array was shortened) + * @return formatted recipients display text + */ + formatRecipients: function(recipients, count) { + var maxRecipients = 4; + var text; + if (!_.isNumber(count)) { + count = recipients.length; + } + // TODO: use natural sort + recipients = _.first(recipients, maxRecipients).sort(); + text = recipients.join(', '); + if (count > maxRecipients) { + text += ', +' + (count - maxRecipients); } - }); + return text; + } + }; +})(); + +$(document).ready(function() { + // FIXME: HACK: do not init when running unit tests, need a better way + if (!window.TESTING) { + if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) { + OCA.Sharing.Util.initialize(OCA.Files.fileActions); + } } }); + diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index ef1034ecfdc..97fabf87131 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -38,6 +38,13 @@ } }, + _renderRow: function() { + // HACK: needed to call the overridden _renderRow + // this is because at the time this class is created + // the overriding hasn't been done yet... + return OCA.Files.FileList.prototype._renderRow.apply(this, arguments); + }, + _createRow: function(fileData) { // TODO: hook earlier and render the whole row here var $tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments); @@ -46,7 +53,7 @@ $tr.find('td.filename input:checkbox').remove(); $tr.attr('data-share-id', _.pluck(fileData.shares, 'id').join(',')); if (this._sharedWithUser) { - $tr.attr('data-share-owner', fileData.shares[0].ownerDisplayName); + $tr.attr('data-share-owner', fileData.shareOwner); } return $tr; }, @@ -159,7 +166,7 @@ stime: share.stime * 1000, }; if (self._sharedWithUser) { - file.share.ownerDisplayName = share.displayname_owner; + file.shareOwner = share.displayname_owner; file.name = OC.basename(share.file_target); file.path = OC.dirname(share.file_target); file.permissions = share.permissions; @@ -179,15 +186,15 @@ // inside the same file object (by file id). .reduce(function(memo, file) { var data = memo[file.id]; - var counterPart = file.share.ownerDisplayName || file.share.targetDisplayName; + var recipient = file.share.targetDisplayName; if (!data) { data = memo[file.id] = file; data.shares = [file.share]; // using a hash to make them unique, // this is only a list to be displayed - data.counterParts = {}; + data.recipients = {}; // counter is cheaper than calling _.keys().length - data.counterPartsCount = 0; + data.recipientsCount = 0; data.mtime = file.share.stime; } else { @@ -198,12 +205,14 @@ data.shares.push(file.share); } - if (file.share.type === OC.Share.SHARE_TYPE_LINK) { - data.hasLinkShare = true; - } else if (counterPart && data.counterPartsCount < 10) { + if (recipient) { // limit counterparts for output - data.counterParts[counterPart] = true; - data.counterPartsCount++; + if (data.recipientsCount < 4) { + // only store the first ones, they will be the only ones + // displayed + data.recipients[recipient] = true; + } + data.recipientsCount++; } delete file.share; @@ -213,14 +222,14 @@ .values() // Clean up .each(function(data) { - // convert the counterParts map to a flat + // convert the recipients map to a flat // array of sorted names - data.counterParts = _.chain(data.counterParts).keys().sort().value(); - if (data.hasLinkShare) { - data.counterParts.unshift(t('files_sharing', 'link')); - delete data.hasLinkShare; - } - delete data.counterPartsCount; + data.recipients = _.keys(data.recipients); + data.recipientsDisplayName = OCA.Sharing.Util.formatRecipients( + data.recipients, + data.recipientsCount + ); + delete data.recipientsCount; }) // Sort by expected sort comparator .sortBy(this._sortComparator) diff --git a/apps/files_sharing/tests/js/appSpec.js b/apps/files_sharing/tests/js/appSpec.js index 3a1b495a16b..9c46b7caf1b 100644 --- a/apps/files_sharing/tests/js/appSpec.js +++ b/apps/files_sharing/tests/js/appSpec.js @@ -122,9 +122,7 @@ describe('OCA.Sharing.App tests', function() { type: 'dir', path: '/somewhere/inside/subdir', counterParts: ['user2'], - shares: [{ - ownerDisplayName: 'user2' - }] + shareOwner: 'user2' }]); fileListIn.findFileEl('testdir').find('td a.name').click(); diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js new file mode 100644 index 00000000000..455addaccc0 --- /dev/null +++ b/apps/files_sharing/tests/js/shareSpec.js @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +describe('OCA.Sharing.Util tests', function() { + var oldFileListPrototype; + var fileList; + var testFiles; + + function getImageUrl($el) { + // might be slightly different cross-browser + var url = $el.css('background-image'); + var r = url.match(/url\(['"]?([^'")]*)['"]?\)/); + if (!r) { + return url; + } + return r[1]; + } + + beforeEach(function() { + // back up prototype, as it will be extended by + // the sharing code + oldFileListPrototype = _.extend({}, OCA.Files.FileList.prototype); + + var $content = $('<div id="content"></div>'); + $('#testArea').append($content); + // dummy file list + var $div = $( + '<div>' + + '<table id="filestable">' + + '<thead></thead>' + + '<tbody id="fileList"></tbody>' + + '</table>' + + '</div>'); + $('#content').append($div); + + var fileActions = new OCA.Files.FileActions(); + OCA.Sharing.Util.initialize(fileActions); + fileList = new OCA.Files.FileList( + $div, { + fileActions : fileActions + } + ); + + testFiles = [{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc', + shareOwner: 'User One', + isShareMountPoint: false + }]; + + OCA.Sharing.sharesLoaded = true; + OC.Share.statuses = { + 1: {link: false, path: '/subdir'} + }; + }); + afterEach(function() { + OCA.Files.FileList.prototype = oldFileListPrototype; + delete OCA.Sharing.sharesLoaded; + delete OC.Share.droppedDown; + OC.Share.statuses = {}; + OC.Share.currentShares = {}; + }); + + describe('Sharing data in table row', function() { + // TODO: test data-permissions, data-share-owner, etc + }); + describe('Share action icon', function() { + it('do not shows share text when not shared', function() { + var $action, $tr; + OC.Share.statuses = {}; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.hasClass('permanent')).toEqual(false); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder.svg'); + expect($action.find('img').length).toEqual(1); + }); + it('shows simple share text with share icon', function() { + var $action, $tr; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect($action.find('img').length).toEqual(1); + }); + it('shows simple share text with public icon when shared with link', function() { + var $action, $tr; + OC.Share.statuses = {1: {link: true, path: '/subdir'}}; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('public.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-public.svg'); + expect($action.find('img').length).toEqual(1); + }); + it('shows owner name when owner is available', function() { + var $action, $tr; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + shareOwner: 'User One', + etag: 'abc' + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared by User One'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + }); + it('shows recipients when recipients are available', function() { + var $action, $tr; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + recipientsDisplayName: 'User One, User Two', + etag: 'abc' + }]); + $tr = fileList.$el.find('tbody tr:first'); + $action = $tr.find('.action-share'); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared with User One, User Two'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect($action.find('img').length).toEqual(1); + }); + it('shows static share text when file shared with user that has no share permission', function() { + var $action, $tr; + fileList.setFiles([{ + id: 1, + type: 'dir', + name: 'One', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_CREATE, + etag: 'abc', + shareOwner: 'User One' + }]); + $tr = fileList.$el.find('tbody tr:first'); + expect($tr.find('.action-share').length).toEqual(0); + $action = $tr.find('.action-share-notification'); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text().trim()).toEqual('Shared by User One'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect($action.find('img').length).toEqual(1); + }); + }); + describe('Share action', function() { + var showDropDownStub; + + function makeDummyShareItem(displayName) { + return { + share_with_displayname: displayName + }; + } + + beforeEach(function() { + showDropDownStub = sinon.stub(OC.Share, 'showDropDown', function() { + $('#testArea').append($('<div id="dropdown"></div>')); + }); + }); + afterEach(function() { + showDropDownStub.restore(); + }); + it('adds share icon after sharing a non-shared file', function() { + var $action, $tr; + OC.Share.statuses = {}; + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + $action = fileList.$el.find('tbody tr:first .action-share'); + $tr = fileList.$el.find('tr:first'); + + expect($action.hasClass('permanent')).toEqual(false); + + $tr.find('.action-share').click(); + + expect(showDropDownStub.calledOnce).toEqual(true); + + // simulate what the dropdown does + var shares = {}; + OC.Share.itemShares[OC.Share.SHARE_TYPE_USER] = ['user1', 'user2']; + OC.Share.itemShares[OC.Share.SHARE_TYPE_GROUP] = ['group1', 'group2']; + shares[OC.Share.SHARE_TYPE_USER] = _.map(['User One', 'User Two'], makeDummyShareItem); + shares[OC.Share.SHARE_TYPE_GROUP] = _.map(['Group One', 'Group Two'], makeDummyShareItem); + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: shares})); + + expect($tr.attr('data-share-recipients')).toEqual('Group One, Group Two, User One, User Two'); + + OC.Share.updateIcon('file', 1); + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared with Group One, Group Two, User One, User Two'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + }); + it('updates share icon after updating shares of a file', function() { + var $action, $tr; + OC.Share.statuses = {1: {link: false, path: '/subdir'}}; + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + $action = fileList.$el.find('tbody tr:first .action-share'); + $tr = fileList.$el.find('tr:first'); + + expect($action.hasClass('permanent')).toEqual(true); + + $tr.find('.action-share').click(); + + expect(showDropDownStub.calledOnce).toEqual(true); + + // simulate what the dropdown does + var shares = {}; + OC.Share.itemShares[OC.Share.SHARE_TYPE_USER] = ['user1', 'user2', 'user3']; + shares[OC.Share.SHARE_TYPE_USER] = _.map(['User One', 'User Two', 'User Three'], makeDummyShareItem); + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: shares})); + + expect($tr.attr('data-share-recipients')).toEqual('User One, User Three, User Two'); + + OC.Share.updateIcon('file', 1); + + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared with User One, User Three, User Two'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + }); + it('removes share icon after removing all shares from a file', function() { + var $action, $tr; + OC.Share.statuses = {1: {link: false, path: '/subdir'}}; + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc', + recipients: 'User One, User Two' + }]); + $action = fileList.$el.find('tbody tr:first .action-share'); + $tr = fileList.$el.find('tr:first'); + + expect($action.hasClass('permanent')).toEqual(true); + + $tr.find('.action-share').click(); + + expect(showDropDownStub.calledOnce).toEqual(true); + + // simulate what the dropdown does + OC.Share.itemShares = {}; + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: {}})); + + expect($tr.attr('data-share-recipients')).not.toBeDefined(); + + OC.Share.updateIcon('file', 1); + expect($action.hasClass('permanent')).toEqual(false); + }); + it('keep share text after updating reshare', function() { + var $action, $tr; + OC.Share.statuses = {1: {link: false, path: '/subdir'}}; + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc', + shareOwner: 'User One' + }]); + $action = fileList.$el.find('tbody tr:first .action-share'); + $tr = fileList.$el.find('tr:first'); + + expect($action.hasClass('permanent')).toEqual(true); + + $tr.find('.action-share').click(); + + expect(showDropDownStub.calledOnce).toEqual(true); + + // simulate what the dropdown does + var shares = {}; + OC.Share.itemShares[OC.Share.SHARE_TYPE_USER] = ['user2']; + shares[OC.Share.SHARE_TYPE_USER] = _.map(['User Two'], makeDummyShareItem); + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: shares})); + + expect($tr.attr('data-share-recipients')).toEqual('User Two'); + + OC.Share.updateIcon('file', 1); + + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared by User One'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + }); + it('keep share text after unsharing reshare', function() { + var $action, $tr; + OC.Share.statuses = {1: {link: false, path: '/subdir'}}; + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc', + shareOwner: 'User One', + recipients: 'User Two' + }]); + $action = fileList.$el.find('tbody tr:first .action-share'); + $tr = fileList.$el.find('tr:first'); + + expect($action.hasClass('permanent')).toEqual(true); + + $tr.find('.action-share').click(); + + expect(showDropDownStub.calledOnce).toEqual(true); + + // simulate what the dropdown does + OC.Share.itemShares = {}; + $('#dropdown').trigger(new $.Event('sharesChanged', {shares: {}})); + + expect($tr.attr('data-share-recipients')).not.toBeDefined(); + + OC.Share.updateIcon('file', 1); + + expect($action.hasClass('permanent')).toEqual(true); + expect($action.find('>span').text()).toEqual('Shared by User One'); + expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); + }); + }); + describe('formatRecipients', function() { + it('returns a single recipient when one passed', function() { + expect(OCA.Sharing.Util.formatRecipients(['User one'])) + .toEqual('User one'); + }); + it('returns two recipients when two passed', function() { + expect(OCA.Sharing.Util.formatRecipients(['User one', 'User two'])) + .toEqual('User one, User two'); + }); + it('returns four recipients with plus when five passed', function() { + var recipients = [ + 'User one', + 'User two', + 'User three', + 'User four', + 'User five' + ]; + expect(OCA.Sharing.Util.formatRecipients(recipients)) + .toEqual('User four, User one, User three, User two, +1'); + }); + it('returns four recipients with plus when ten passed', function() { + var recipients = [ + 'User one', + 'User two', + 'User three', + 'User four', + 'User five', + 'User six', + 'User seven', + 'User eight', + 'User nine', + 'User ten' + ]; + expect(OCA.Sharing.Util.formatRecipients(recipients)) + .toEqual('User four, User one, User three, User two, +6'); + }); + it('returns four recipients with plus when four passed with counter', function() { + var recipients = [ + 'User one', + 'User two', + 'User three', + 'User four' + ]; + expect(OCA.Sharing.Util.formatRecipients(recipients, 10)) + .toEqual('User four, User one, User three, User two, +6'); + }); + }); + +}); diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js index 7aec8322a44..f53e79e277f 100644 --- a/apps/files_sharing/tests/js/sharedfilelistSpec.js +++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js @@ -9,7 +9,8 @@ */ describe('OCA.Sharing.FileList tests', function() { - var testFiles, alertStub, notificationStub, fileList; + var testFiles, alertStub, notificationStub, fileList, fileActions; + var oldFileListPrototype; beforeEach(function() { alertStub = sinon.stub(OC.dialogs, 'alert'); @@ -45,10 +46,17 @@ describe('OCA.Sharing.FileList tests', function() { '<div id="emptycontent">Empty content message</div>' + '</div>' ); + // back up prototype, as it will be extended by + // the sharing code + oldFileListPrototype = _.extend({}, OCA.Files.FileList.prototype); + fileActions = new OCA.Files.FileActions(); + OCA.Sharing.Util.initialize(fileActions); }); afterEach(function() { + OCA.Files.FileList.prototype = oldFileListPrototype; testFiles = undefined; fileList = undefined; + fileActions = undefined; notificationStub.restore(); alertStub.restore(); |