diff options
-rw-r--r-- | apps/files_sharing/js/sharetabview.js | 1 | ||||
-rw-r--r-- | apps/files_sharing/tests/js/shareSpec.js | 125 | ||||
-rw-r--r-- | core/js/core.json | 7 | ||||
-rw-r--r-- | core/js/share.js | 4 | ||||
-rw-r--r-- | core/js/shareconfigmodel.js | 2 | ||||
-rw-r--r-- | core/js/sharedialoglinkshareview.js | 2 | ||||
-rw-r--r-- | core/js/tests/specs/shareSpec.js | 1100 | ||||
-rw-r--r-- | core/js/tests/specs/sharedialogviewSpec.js | 911 | ||||
-rw-r--r-- | core/js/tests/specs/shareitemmodelSpec.js | 234 | ||||
-rw-r--r-- | tests/karma.config.js | 3 |
10 files changed, 1217 insertions, 1172 deletions
diff --git a/apps/files_sharing/js/sharetabview.js b/apps/files_sharing/js/sharetabview.js index 1ad17365957..68288500ae0 100644 --- a/apps/files_sharing/js/sharetabview.js +++ b/apps/files_sharing/js/sharetabview.js @@ -55,6 +55,7 @@ owner: owner })); + // TODO: the model should read these directly off the passed fileInfoModel var attributes = { itemType: this.model.isDirectory() ? 'folder' : 'file', itemSource: this.model.get('id'), diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js index b6368b901ee..96a96f1b814 100644 --- a/apps/files_sharing/tests/js/shareSpec.js +++ b/apps/files_sharing/tests/js/shareSpec.js @@ -97,7 +97,6 @@ describe('OCA.Sharing.Util tests', function() { }]); $tr = fileList.$el.find('tbody tr:first'); $action = $tr.find('.action-share'); - expect($action.hasClass('permanent')).toEqual(true); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder.svg'); expect($action.find('img').length).toEqual(1); @@ -116,7 +115,6 @@ describe('OCA.Sharing.Util tests', function() { }]); $tr = fileList.$el.find('tbody tr:first'); $action = $tr.find('.action-share'); - expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text().trim()).toEqual('Shared'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); @@ -137,7 +135,6 @@ describe('OCA.Sharing.Util tests', function() { }]); $tr = fileList.$el.find('tbody tr:first'); $action = $tr.find('.action-share'); - expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text().trim()).toEqual('Shared'); expect(OC.basename($action.find('img').attr('src'))).toEqual('public.svg'); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-public.svg'); @@ -158,7 +155,6 @@ describe('OCA.Sharing.Util tests', function() { }]); $tr = fileList.$el.find('tbody tr:first'); $action = $tr.find('.action-share'); - expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text().trim()).toEqual('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); @@ -178,7 +174,6 @@ describe('OCA.Sharing.Util tests', function() { }]); $tr = fileList.$el.find('tbody tr:first'); $action = $tr.find('.action-share'); - expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text().trim()).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 .thumbnail')))).toEqual('folder-shared.svg'); @@ -200,7 +195,6 @@ describe('OCA.Sharing.Util tests', function() { $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('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); @@ -225,7 +219,7 @@ describe('OCA.Sharing.Util tests', function() { }); }); describe('Share action', function() { - var showDropDownStub; + var shareTab; function makeDummyShareItem(displayName) { return { @@ -234,12 +228,35 @@ describe('OCA.Sharing.Util tests', function() { } beforeEach(function() { - showDropDownStub = sinon.stub(OC.Share, 'showDropDown', function() { - $('#testArea').append($('<div id="dropdown"></div>')); - }); + // make it look like not the "All files" list + fileList.id = 'test'; + shareTab = fileList._detailsView._tabViews[0]; }); afterEach(function() { - showDropDownStub.restore(); + shareTab = null; + }); + it('clicking share action opens sidebar and share tab', function() { + var showDetailsViewStub = sinon.stub(fileList, 'showDetailsView'); + + fileList.setFiles([{ + id: 1, + type: 'file', + name: 'One.txt', + path: '/subdir', + mimetype: 'text/plain', + size: 12, + permissions: OC.PERMISSION_ALL, + etag: 'abc' + }]); + + var $tr = fileList.$el.find('tr:first'); + $tr.find('.action-share').click(); + + expect(showDetailsViewStub.calledOnce).toEqual(true); + expect(showDetailsViewStub.getCall(0).args[0]).toEqual('One.txt'); + expect(showDetailsViewStub.getCall(0).args[1]).toEqual('shareTabView'); + + showDetailsViewStub.restore(); }); it('adds share icon after sharing a non-shared file', function() { var $action, $tr; @@ -257,24 +274,20 @@ describe('OCA.Sharing.Util tests', function() { $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']; - 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})); + // simulate updating shares + shareTab._dialog.model.set({ + shares: [ + {share_with_displayname: 'User One'}, + {share_with_displayname: 'User Two'}, + {share_with_displayname: 'Group One'}, + {share_with_displayname: 'Group Two'} + ] + }); 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().trim()).toEqual('Shared with Group One, Group Two, User One, User Two'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); }); @@ -294,23 +307,19 @@ describe('OCA.Sharing.Util tests', function() { $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})); + // simulate updating shares + shareTab._dialog.model.set({ + shares: [ + {share_with_displayname: 'User One'}, + {share_with_displayname: 'User Two'}, + {share_with_displayname: 'User Three'} + ] + }); 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().trim()).toEqual('Shared with User One, User Three, User Two'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); }); @@ -331,20 +340,14 @@ describe('OCA.Sharing.Util tests', function() { $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: {}})); + // simulate updating shares + shareTab._dialog.model.set({ + shares: [] + }); expect($tr.attr('data-share-recipients')).not.toBeDefined(); - - OC.Share.updateIcon('file', 1); - expect($action.hasClass('permanent')).toEqual(true); }); it('keep share text after updating reshare', function() { var $action, $tr; @@ -363,23 +366,15 @@ describe('OCA.Sharing.Util tests', function() { $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})); + // simulate updating shares + shareTab._dialog.model.set({ + shares: [{share_with_displayname: 'User Two'}] + }); 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().trim()).toEqual('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); }); @@ -401,21 +396,15 @@ describe('OCA.Sharing.Util tests', function() { $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: {}})); + // simulate updating shares + shareTab._dialog.model.set({ + 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().trim()).toEqual('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); }); diff --git a/core/js/core.json b/core/js/core.json index a67491c4a35..a80636e8463 100644 --- a/core/js/core.json +++ b/core/js/core.json @@ -24,6 +24,13 @@ "l10n.js", "apps.js", "share.js", + "shareconfigmodel.js", + "shareitemmodel.js", + "sharedialogview.js", + "sharedialogexpirationview.js", + "sharedialoglinkshareview.js", + "sharedialogresharerinfoview.js", + "sharedialogshareelistview.js", "octemplate.js", "eventsource.js", "config.js", diff --git a/core/js/share.js b/core/js/share.js index 0a3bba49b6c..a2e6e6af0fc 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -3,7 +3,7 @@ /** * @namespace */ -OC.Share = _.extend(OC.Share, { +OC.Share = _.extend(OC.Share || {}, { SHARE_TYPE_USER:0, SHARE_TYPE_GROUP:1, SHARE_TYPE_LINK:3, @@ -445,7 +445,7 @@ $(document).ready(function() { var target = $(event.target); var isMatched = !target.is('.drop, .ui-datepicker-next, .ui-datepicker-prev, .ui-icon') && !target.closest('#ui-datepicker-div').length && !target.closest('.ui-autocomplete').length; - if (OC.Share.droppedDown && isMatched && $('#dropdown').has(event.target).length === 0) { + if (OC.Share && OC.Share.droppedDown && isMatched && $('#dropdown').has(event.target).length === 0) { OC.Share.hideDropDown(); } }); diff --git a/core/js/shareconfigmodel.js b/core/js/shareconfigmodel.js index 16f7e2514d8..8729698d136 100644 --- a/core/js/shareconfigmodel.js +++ b/core/js/shareconfigmodel.js @@ -14,6 +14,8 @@ OC.Share.Types = {}; } + // FIXME: the config model should populate its own model attributes based on + // the old DOM-based config var ShareConfigModel = OC.Backbone.Model.extend({ defaults: { publicUploadEnabled: false, diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 1191aa401b4..2c7914b2545 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -236,7 +236,7 @@ })); // TODO: move this to delegate events instead - this.$el.find('#linkCheckbox').change(this.onLinkCheckBoxChange); + this.$el.find('#linkCheckbox').click(this.onLinkCheckBoxChange); this.$el.find('#sharingDialogAllowPublicUpload').change(this.onAllowPublicUploadChange); this.$el.find('#linkText').click(this.onLinkTextClick); this.$el.find('#showPassword').click(this.onShowPasswordClick); diff --git a/core/js/tests/specs/shareSpec.js b/core/js/tests/specs/shareSpec.js index 5a59a117d77..9e80f4fe19d 100644 --- a/core/js/tests/specs/shareSpec.js +++ b/core/js/tests/specs/shareSpec.js @@ -21,1090 +21,6 @@ /* global oc_appconfig */ describe('OC.Share tests', function() { - describe('dropdown', function() { - var $container; - var oldAppConfig; - var loadItemStub; - var autocompleteStub; - var oldEnableAvatars; - var avatarStub; - var placeholderStub; - var oldCurrentUser; - - beforeEach(function() { - $('#testArea').append($('<div id="shareContainer"></div>')); - // horrible parameters - $('#testArea').append('<input id="allowShareWithLink" type="hidden" value="yes">'); - $('#testArea').append('<input id="mailPublicNotificationEnabled" name="mailPublicNotificationEnabled" type="hidden" value="yes">'); - $container = $('#shareContainer'); - /* jshint camelcase:false */ - oldAppConfig = _.extend({}, oc_appconfig.core); - oc_appconfig.core.enforcePasswordForPublicLink = false; - - loadItemStub = sinon.stub(OC.Share, 'loadItem'); - loadItemStub.returns({ - reshare: [], - shares: [] - }); - - autocompleteStub = sinon.stub($.fn, 'autocomplete', function() { - // dummy container with the expected attributes - if (!$(this).length) { - // simulate the real autocomplete that returns - // nothing at all when no element is specified - // (and potentially break stuff) - return null; - } - var $el = $('<div></div>').data('ui-autocomplete', {}); - return $el; - }); - - oldEnableAvatars = oc_config.enable_avatars; - oc_config.enable_avatars = false; - avatarStub = sinon.stub($.fn, 'avatar'); - placeholderStub = sinon.stub($.fn, 'imageplaceholder'); - - oldCurrentUser = OC.currentUser; - OC.currentUser = 'user0'; - }); - afterEach(function() { - OC.currentUser = oldCurrentUser; - /* jshint camelcase:false */ - oc_appconfig.core = oldAppConfig; - loadItemStub.restore(); - - autocompleteStub.restore(); - avatarStub.restore(); - placeholderStub.restore(); - oc_config.enable_avatars = oldEnableAvatars; - $('#dropdown').remove(); - }); - it('calls loadItem with the correct arguments', function() { - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - expect(loadItemStub.calledOnce).toEqual(true); - expect(loadItemStub.calledWith('file', 123)).toEqual(true); - }); - it('shows the dropdown with default values', function() { - var $el; - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - $el = $container.find('#dropdown'); - expect($el.length).toEqual(1); - expect($el.attr('data-item-type')).toEqual('file'); - expect($el.attr('data-item-source')).toEqual('123'); - // TODO: expect that other parts are rendered correctly - }); - describe('Share with link', function() { - // TODO: test ajax calls - // TODO: test password field visibility (whenever enforced or not) - it('update password on focus out', function() { - $('#allowShareWithLink').val('yes'); - - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - - // Toggle linkshare - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - // Enable password, enter password and focusout - $('#dropdown [name=showPassword]').click(); - $('#dropdown #linkPassText').focus(); - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').focusout(); - - expect(fakeServer.requests[1].method).toEqual('POST'); - var body = OC.parseQueryString(fakeServer.requests[1].requestBody); - expect(body['shareWith']).toEqual('foo'); - - // Set password response - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - expect($('#dropdown #linkPassText').val()).toEqual(''); - expect($('#dropdown #linkPassText').attr('placeholder')).toEqual('Password protected'); - }); - it('update password on enter', function() { - $('#allowShareWithLink').val('yes'); - - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - - // Toggle linkshare - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - // Enable password and enter password - $('#dropdown [name=showPassword]').click(); - $('#dropdown #linkPassText').focus(); - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - - expect(fakeServer.requests[1].method).toEqual('POST'); - var body = OC.parseQueryString(fakeServer.requests[1].requestBody); - expect(body['shareWith']).toEqual('foo'); - - // Set password response - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - expect($('#dropdown #linkPassText').val()).toEqual(''); - expect($('#dropdown #linkPassText').attr('placeholder')).toEqual('Password protected'); - }); - it('shows share with link checkbox when allowed', function() { - $('#allowShareWithLink').val('yes'); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - expect($('#dropdown #linkCheckbox').length).toEqual(1); - }); - it('does not show share with link checkbox when not allowed', function() { - $('#allowShareWithLink').val('no'); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - expect($('#dropdown #linkCheckbox').length).toEqual(0); - }); - it('Reset link when password is enforced and link is toggled', function() { - var old = oc_appconfig.core.enforcePasswordForPublicLink; - oc_appconfig.core.enforcePasswordForPublicLink = true; - $('#allowShareWithLink').val('yes'); - - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - - // Toggle linkshare - $('#dropdown [name=linkCheckbox]').click(); - expect($('#dropdown #linkText').val()).toEqual(''); - - // Set password - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - // Remove link - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - - /* - * Try to share again - * The linkText should be emptied - */ - $('#dropdown [name=linkCheckbox]').click(); - expect($('#dropdown #linkText').val()).toEqual(''); - - /* - * Do not set password but untoggle - * Since there is no share this should not result in another request to the server - */ - $('#dropdown [name=linkCheckbox]').click(); - expect(fakeServer.requests.length).toEqual(2); - - oc_appconfig.core.enforcePasswordForPublicLink = old; - }); - - it('Reset password placeholder when password is enforced and link is toggled', function() { - var old = oc_appconfig.core.enforcePasswordForPublicLink; - oc_appconfig.core.enforcePasswordForPublicLink = true; - $('#allowShareWithLink').val('yes'); - - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - - // Toggle linkshare - $('#dropdown [name=linkCheckbox]').click(); - expect($('#dropdown #linkPassText').attr('placeholder')).toEqual('Choose a password for the public link'); - - // Set password - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - expect($('#dropdown #linkPassText').attr('placeholder')).toEqual('**********'); - - // Remove link - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - - // Try to share again - $('#dropdown [name=linkCheckbox]').click(); - expect($('#dropdown #linkPassText').attr('placeholder')).toEqual('Choose a password for the public link'); - - oc_appconfig.core.enforcePasswordForPublicLink = old; - }); - it('reset password on toggle of share', function() { - $('#allowShareWithLink').val('yes'); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - //Password protection should be unchecked and password field not visible - expect($('#dropdown [name=showPassword]').prop('checked')).toEqual(false); - expect($('#dropdown #linkPass').is(":visible")).toEqual(false); - - // Toggle and set password - $('#dropdown [name=showPassword]').click(); - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz2'}, status: 'success'}) - ); - - // Unshare - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[2].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - - // Toggle share again - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[3].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz3'}, status: 'success'}) - ); - - - // Password checkbox should be unchecked - expect($('#dropdown [name=showPassword]').prop('checked')).toEqual(false); - expect($('#dropdown #linkPass').is(":visible")).toEqual(false); - }); - it('reset expiration on toggle of share', function() { - $('#allowShareWithLink').val('yes'); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - //Expiration should be unchecked and expiration field not visible - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); - expect($('#dropdown #expirationDate').is(":visible")).toEqual(false); - - // Toggle and set password - $('#dropdown [name=expirationCheckbox]').click(); - d = new Date(); - d.setDate(d.getDate() + 1); - date=d.getDate() + '-' + (d.getMonth()+1) + '-' + d.getFullYear(); - $('#dropdown #expirationDate').val(date); - $('#dropdown #expirationDate').change(); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz2'}, status: 'success'}) - ); - - // Unshare - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[2].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - - // Toggle share again - $('#dropdown [name=linkCheckbox]').click(); - fakeServer.requests[3].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz3'}, status: 'success'}) - ); - - // Recheck expire visibility - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); - expect($('#dropdown #expirationDate').is(":visible")).toEqual(false); - }); - it('shows populated link share when a link share exists', function() { - loadItemStub.returns({ - reshare: [], - /* jshint camelcase: false */ - shares: [{ - displayname_owner: 'root', - expiration: null, - file_source: 123, - file_target: '/folder', - id: 20, - item_source: '123', - item_type: 'folder', - mail_send: '0', - parent: null, - path: '/folder', - permissions: OC.PERMISSION_READ, - share_type: OC.Share.SHARE_TYPE_LINK, - share_with: null, - stime: 1403884258, - storage: 1, - token: 'tehtoken', - uid_owner: 'root' - }] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'folder' - ); - expect($('#dropdown #linkCheckbox').prop('checked')).toEqual(true); - // this is how the OC.Share class does it... - var link = parent.location.protocol + '//' + location.host + - OC.generateUrl('/s/') + 'tehtoken'; - expect($('#dropdown #linkText').val()).toEqual(link); - }); - it('does not show populated link share when a link share exists for a different file', function() { - loadItemStub.returns({ - reshare: [], - /* jshint camelcase: false */ - shares: [{ - displayname_owner: 'root', - expiration: null, - file_source: 123, - file_target: '/folder', - id: 20, - item_source: '123', - item_type: 'folder', - mail_send: '0', - parent: null, - path: '/folder', - permissions: OC.PERMISSION_READ, - share_type: OC.Share.SHARE_TYPE_LINK, - share_with: null, - stime: 1403884258, - storage: 1, - token: 'tehtoken', - uid_owner: 'root' - }] - }); - OC.Share.showDropDown( - 'file', - 456, // another file - $container, - true, - 31, - 'folder' - ); - expect($('#dropdown #linkCheckbox').prop('checked')).toEqual(false); - }); - it('shows correct link share when a nest link share exists along with parent one', function() { - loadItemStub.returns({ - reshare: [], - /* jshint camelcase: false */ - shares: [{ - displayname_owner: 'root', - expiration: null, - file_source: 123, - file_target: '/folder', - id: 20, - item_source: '123', - item_type: 'file', - mail_send: '0', - parent: null, - path: '/folder', - permissions: OC.PERMISSION_READ, - share_type: OC.Share.SHARE_TYPE_LINK, - share_with: null, - stime: 1403884258, - storage: 1, - token: 'tehtoken', - uid_owner: 'root' - }, { - displayname_owner: 'root', - expiration: null, - file_source: 456, - file_target: '/file_in_folder.txt', - id: 21, - item_source: '456', - item_type: 'file', - mail_send: '0', - parent: null, - path: '/folder/file_in_folder.txt', - permissions: OC.PERMISSION_READ, - share_type: OC.Share.SHARE_TYPE_LINK, - share_with: null, - stime: 1403884509, - storage: 1, - token: 'anothertoken', - uid_owner: 'root' - }] - }); - - // parent one - OC.Share.showDropDown( - 'folder', - 123, - $container, - true, - 31, - 'folder' - ); - expect($('#dropdown #linkCheckbox').prop('checked')).toEqual(true); - // this is how the OC.Share class does it... - var link = parent.location.protocol + '//' + location.host + - OC.generateUrl('/s/') + 'tehtoken'; - expect($('#dropdown #linkText').val()).toEqual(link); - - // nested one - OC.Share.showDropDown( - 'file', - 456, - $container, - true, - 31, - 'file_in_folder.txt' - ); - expect($('#dropdown #linkCheckbox').prop('checked')).toEqual(true); - // this is how the OC.Share class does it... - link = parent.location.protocol + '//' + location.host + - OC.generateUrl('/s/') + 'anothertoken'; - expect($('#dropdown #linkText').val()).toEqual(link); - }); - describe('expiration date', function() { - var shareData; - var shareItem; - var clock; - var expectedMinDate; - - function showDropDown() { - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'folder' - ); - } - - beforeEach(function() { - // pick a fake date - clock = sinon.useFakeTimers(new Date(2014, 0, 20, 14, 0, 0).getTime()); - expectedMinDate = new Date(2014, 0, 21, 14, 0, 0); - shareItem = { - displayname_owner: 'root', - expiration: null, - file_source: 123, - file_target: '/folder', - id: 20, - item_source: '123', - item_type: 'folder', - mail_send: '0', - parent: null, - path: '/folder', - permissions: OC.PERMISSION_READ, - share_type: OC.Share.SHARE_TYPE_LINK, - share_with: null, - stime: 1403884258, - storage: 1, - token: 'tehtoken', - uid_owner: 'root' - }; - shareData = { - reshare: [], - shares: [] - }; - loadItemStub.returns(shareData); - oc_appconfig.core.defaultExpireDate = 7; - oc_appconfig.core.enforcePasswordForPublicLink = false; - oc_appconfig.core.defaultExpireDateEnabled = false; - oc_appconfig.core.defaultExpireDateEnforced = false; - }); - afterEach(function() { - clock.restore(); - }); - - it('does not check expiration date checkbox when no date was set', function() { - shareItem.expiration = null; - shareData.shares.push(shareItem); - showDropDown(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); - expect($('#dropdown #expirationDate').val()).toEqual(''); - }); - it('does not check expiration date checkbox for new share', function() { - showDropDown(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); - expect($('#dropdown #expirationDate').val()).toEqual(''); - }); - it('checks expiration date checkbox and populates field when expiration date was set', function() { - shareItem.expiration = 1234; - shareData.shares.push(shareItem); - showDropDown(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - expect($('#dropdown #expirationDate').val()).toEqual('1234'); - }); - it('sets default date when default date setting is enabled', function() { - /* jshint camelcase:false */ - oc_appconfig.core.defaultExpireDateEnabled = true; - showDropDown(); - $('#dropdown [name=linkCheckbox]').click(); - // enabled by default - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - // TODO: those zeros must go... - expect($('#dropdown #expirationDate').val()).toEqual('2014-1-27 00:00:00'); - - // disabling is allowed - $('#dropdown [name=expirationCheckbox]').click(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(false); - }); - it('enforces default date when enforced date setting is enabled', function() { - /* jshint camelcase:false */ - oc_appconfig.core.defaultExpireDateEnabled = true; - oc_appconfig.core.defaultExpireDateEnforced = true; - showDropDown(); - $('#dropdown [name=linkCheckbox]').click(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - // TODO: those zeros must go... - expect($('#dropdown #expirationDate').val()).toEqual('2014-1-27 00:00:00'); - - // disabling is not allowed - expect($('#dropdown [name=expirationCheckbox]').prop('disabled')).toEqual(true); - $('#dropdown [name=expirationCheckbox]').click(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - }); - it('enforces default date when enforced date setting is enabled and password is enforced', function() { - /* jshint camelcase:false */ - oc_appconfig.core.enforcePasswordForPublicLink = true; - oc_appconfig.core.defaultExpireDateEnabled = true; - oc_appconfig.core.defaultExpireDateEnforced = true; - showDropDown(); - $('#dropdown [name=linkCheckbox]').click(); - - //Enter password - $('#dropdown #linkPassText').val('foo'); - $('#dropdown #linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({data: {token: 'xyz'}, status: 'success'}) - ); - - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - // TODO: those zeros must go... - expect($('#dropdown #expirationDate').val()).toEqual('2014-1-27 00:00:00'); - - // disabling is not allowed - expect($('#dropdown [name=expirationCheckbox]').prop('disabled')).toEqual(true); - $('#dropdown [name=expirationCheckbox]').click(); - expect($('#dropdown [name=expirationCheckbox]').prop('checked')).toEqual(true); - }); - it('displayes email form when sending emails is enabled', function() { - $('input[name=mailPublicNotificationEnabled]').val('yes'); - showDropDown(); - expect($('#emailPrivateLink').length).toEqual(1); - }); - it('not renders email form when sending emails is disabled', function() { - $('input[name=mailPublicNotificationEnabled]').val('no'); - showDropDown(); - expect($('#emailPrivateLink').length).toEqual(0); - }); - it('sets picker minDate to today and no maxDate by default', function() { - showDropDown(); - $('#dropdown [name=linkCheckbox]').click(); - $('#dropdown [name=expirationCheckbox]').click(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(null); - }); - it('limits the date range to X days after share time when enforced', function() { - /* jshint camelcase:false */ - oc_appconfig.core.defaultExpireDateEnabled = true; - oc_appconfig.core.defaultExpireDateEnforced = true; - showDropDown(); - $('#dropdown [name=linkCheckbox]').click(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); - }); - it('limits the date range to X days after share time when enforced, even when redisplayed the next days', function() { - // item exists, was created two days ago - shareItem.expiration = '2014-1-27'; - // share time has time component but must be stripped later - shareItem.stime = new Date(2014, 0, 20, 11, 0, 25).getTime() / 1000; - shareData.shares.push(shareItem); - /* jshint camelcase:false */ - oc_appconfig.core.defaultExpireDateEnabled = true; - oc_appconfig.core.defaultExpireDateEnforced = true; - showDropDown(); - expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); - expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); - }); - }); - }); - describe('check for avatar', function() { - beforeEach(function() { - loadItemStub.returns({ - reshare: { - share_type: OC.Share.SHARE_TYPE_USER, - uid_owner: 'owner', - displayname_owner: 'Owner', - permissions: 31 - }, - shares: [{ - id: 100, - item_source: 123, - permissions: 31, - share_type: OC.Share.SHARE_TYPE_USER, - share_with: 'user1', - share_with_displayname: 'User One' - },{ - id: 101, - item_source: 123, - permissions: 31, - share_type: OC.Share.SHARE_TYPE_GROUP, - share_with: 'group', - share_with_displayname: 'group' - },{ - id: 102, - item_source: 123, - permissions: 31, - share_type: OC.Share.SHARE_TYPE_REMOTE, - share_with: 'foo@bar.com/baz', - share_with_displayname: 'foo@bar.com/baz' - - }] - }); - }); - - describe('avatars enabled', function() { - beforeEach(function() { - oc_config.enable_avatars = true; - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - }); - - afterEach(function() { - oc_config.enable_avatars = false; - }); - - it('test correct function calls', function() { - expect(avatarStub.calledTwice).toEqual(true); - expect(placeholderStub.calledTwice).toEqual(true); - expect($('#shareWithList').children().length).toEqual(3); - expect($('.avatar').length).toEqual(4); - }); - - it('test avatar owner', function() { - var args = avatarStub.getCall(0).args; - expect(args.length).toEqual(2); - expect(args[0]).toEqual('owner'); - }); - - it('test avatar user', function() { - var args = avatarStub.getCall(1).args; - expect(args.length).toEqual(2); - expect(args[0]).toEqual('user1'); - }); - - it('test avatar for groups', function() { - var args = placeholderStub.getCall(0).args; - expect(args.length).toEqual(1); - expect(args[0]).toEqual('group ' + OC.Share.SHARE_TYPE_GROUP); - }); - - it('test avatar for remotes', function() { - var args = placeholderStub.getCall(1).args; - expect(args.length).toEqual(1); - expect(args[0]).toEqual('foo@bar.com/baz ' + OC.Share.SHARE_TYPE_REMOTE); - }); - }); - - describe('avatars disabled', function() { - beforeEach(function() { - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - }); - - it('no avatar classes', function() { - expect($('.avatar').length).toEqual(0); - expect(avatarStub.callCount).toEqual(0); - expect(placeholderStub.callCount).toEqual(0); - }); - }); - }); - describe('"sharesChanged" event', function() { - var autocompleteOptions; - var handler; - beforeEach(function() { - handler = sinon.stub(); - loadItemStub.returns({ - reshare: [], - shares: [{ - id: 100, - item_source: 123, - permissions: 31, - share_type: OC.Share.SHARE_TYPE_USER, - share_with: 'user1', - share_with_displayname: 'User One' - }] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - 31, - 'shared_file_name.txt' - ); - $('#dropdown').on('sharesChanged', handler); - autocompleteOptions = autocompleteStub.getCall(0).args[0]; - }); - afterEach(function() { - autocompleteOptions = null; - handler = null; - }); - it('triggers "sharesChanged" event when adding shares', function() { - // simulate autocomplete selection - autocompleteOptions.select(new $.Event('select'), { - item: { - label: 'User Two', - value: { - shareType: OC.Share.SHARE_TYPE_USER, - shareWith: 'user2' - } - } - }); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - expect(handler.calledOnce).toEqual(true); - var shares = handler.getCall(0).args[0].shares; - expect(shares).toBeDefined(); - expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); - expect(shares[OC.Share.SHARE_TYPE_USER][1].share_with_displayname).toEqual('User Two'); - expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); - }); - it('triggers "sharesChanged" event when deleting shares', function() { - $('#dropdown .unshare:eq(0)').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - expect(handler.calledOnce).toEqual(true); - var shares = handler.getCall(0).args[0].shares; - expect(shares).toBeDefined(); - expect(shares[OC.Share.SHARE_TYPE_USER]).toEqual([]); - expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); - }); - it('triggers "sharesChanged" event when toggling link share', function() { - // simulate autocomplete selection - $('#dropdown #linkCheckbox').click(); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success', data: { token: 'abc' }}) - ); - expect(handler.calledOnce).toEqual(true); - var shares = handler.getCall(0).args[0].shares; - expect(shares).toBeDefined(); - expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); - expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); - - handler.reset(); - - // uncheck checkbox - $('#dropdown #linkCheckbox').click(); - fakeServer.requests[1].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({status: 'success'}) - ); - - expect(handler.calledOnce).toEqual(true); - shares = handler.getCall(0).args[0].shares; - expect(shares).toBeDefined(); - expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); - expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); - }); - }); - describe('share permissions', function() { - beforeEach(function() { - oc_appconfig.core.resharingAllowed = true; - }); - - /** - * Tests sharing with the given possible permissions - * - * @param {int} possiblePermissions - * @return {int} permissions sent to the server - */ - function testWithPermissions(possiblePermissions) { - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - possiblePermissions, - 'shared_file_name.txt' - ); - var autocompleteOptions = autocompleteStub.getCall(0).args[0]; - // simulate autocomplete selection - autocompleteOptions.select(new $.Event('select'), { - item: { - label: 'User Two', - value: { - shareType: OC.Share.SHARE_TYPE_USER, - shareWith: 'user2' - } - } - }); - autocompleteStub.reset(); - var requestBody = OC.parseQueryString(_.last(fakeServer.requests).requestBody); - return parseInt(requestBody.permissions, 10); - } - - describe('regular sharing', function() { - it('shares with given permissions with default config', function() { - loadItemStub.returns({ - reshare: [], - shares: [] - }); - expect( - testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) - ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE); - expect( - testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_SHARE) - ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_SHARE); - }); - it('removes share permission when not allowed', function() { - oc_appconfig.core.resharingAllowed = false; - loadItemStub.returns({ - reshare: [], - shares: [] - }); - expect( - testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) - ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE); - }); - it('automatically adds READ permission even when not specified', function() { - oc_appconfig.core.resharingAllowed = false; - loadItemStub.returns({ - reshare: [], - shares: [] - }); - expect( - testWithPermissions(OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) - ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_UPDATE); - }); - it('does not show sharing options when sharing not allowed', function() { - loadItemStub.returns({ - reshare: [], - shares: [] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - OC.PERMISSION_READ, - 'shared_file_name.txt' - ); - expect($('#dropdown #shareWithList').length).toEqual(0); - }); - }); - describe('resharing', function() { - it('shares with given permissions when original share had all permissions', function() { - loadItemStub.returns({ - reshare: { - permissions: OC.PERMISSION_ALL - }, - shares: [] - }); - expect( - testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) - ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE); - }); - it('reduces reshare permissions to the ones from the original share', function() { - loadItemStub.returns({ - reshare: { - permissions: OC.PERMISSION_READ, - uid_owner: 'user1' - }, - shares: [] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - OC.PERMISSION_ALL, - 'shared_file_name.txt' - ); - // no resharing allowed - expect($('#dropdown #shareWithList').length).toEqual(0); - }); - it('reduces reshare permissions to possible permissions', function() { - loadItemStub.returns({ - reshare: { - permissions: OC.PERMISSION_ALL, - uid_owner: 'user1' - }, - shares: [] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - OC.PERMISSION_READ, - 'shared_file_name.txt' - ); - // no resharing allowed - expect($('#dropdown #shareWithList').length).toEqual(0); - }); - it('does not show sharing options when resharing not allowed', function() { - loadItemStub.returns({ - reshare: { - permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE, - uid_owner: 'user1' - }, - shares: [] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - OC.PERMISSION_ALL, - 'shared_file_name.txt' - ); - expect($('#dropdown #shareWithList').length).toEqual(0); - }); - it('allows owner to share their own share when they are also the recipient', function() { - OC.currentUser = 'user1'; - loadItemStub.returns({ - reshare: { - permissions: OC.PERMISSION_READ, - uid_owner: 'user1' - }, - shares: [] - }); - OC.Share.showDropDown( - 'file', - 123, - $container, - true, - OC.PERMISSION_ALL, - 'shared_file_name.txt' - ); - // sharing still allowed - expect($('#dropdown #shareWithList').length).toEqual(1); - }); - }); - }); - }); describe('markFileAsShared', function() { var $file; var tipsyStub; @@ -1316,21 +232,5 @@ describe('OC.Share tests', function() { }); }); }); - describe('OC.Share utils', function() { - it('parseTime should properly parse strings', function() { - - _.each([ - [ '123456', 123456], - [ 123456 , 123456], - ['0123456', 123456], - ['abcdefg', null], - ['0x12345', null], - [ '', null], - ], function(value) { - expect(OC.Share._parseTime(value[0])).toEqual(value[1]); - }); - - }); - }); }); diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js new file mode 100644 index 00000000000..b50432a034f --- /dev/null +++ b/core/js/tests/specs/sharedialogviewSpec.js @@ -0,0 +1,911 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2015 Vincent Petry <pvince81@owncloud.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +/* global oc_appconfig */ +describe('OC.Share.ShareDialogView', function() { + var $container; + var oldAppConfig; + var autocompleteStub; + var oldEnableAvatars; + var avatarStub; + var placeholderStub; + var oldCurrentUser; + + var fetchStub; + + var configModel; + var shareModel; + var fileInfoModel; + var dialog; + + beforeEach(function() { + // horrible parameters + $('#testArea').append('<input id="allowShareWithLink" type="hidden" value="yes">'); + $('#testArea').append('<input id="mailPublicNotificationEnabled" name="mailPublicNotificationEnabled" type="hidden" value="yes">'); + $container = $('#shareContainer'); + /* jshint camelcase:false */ + oldAppConfig = _.extend({}, oc_appconfig.core); + oc_appconfig.core.enforcePasswordForPublicLink = false; + + fetchStub = sinon.stub(OC.Share.ShareItemModel.prototype, 'fetch'); + + fileInfoModel = new OCA.Files.FileInfoModel({ + id: 123, + name: 'shared_file_name.txt', + path: '/subdir', + size: 100, + mimetype: 'text/plain', + permissions: 31, + sharePermissions: 31 + }); + + var attributes = { + itemType: fileInfoModel.isDirectory() ? 'folder' : 'file', + itemSource: fileInfoModel.get('id'), + possiblePermissions: 31, + permissions: 31 + }; + configModel = new OC.Share.ShareConfigModel(); + shareModel = new OC.Share.ShareItemModel(attributes, { + configModel: configModel, + fileInfoModel: fileInfoModel + }); + dialog = new OC.Share.ShareDialogView({ + configModel: configModel, + model: shareModel + }); + + // triggers rendering + shareModel.set({ + shares: [], + linkShare: {isLinkShare: false} + }); + + autocompleteStub = sinon.stub($.fn, 'autocomplete', function() { + // dummy container with the expected attributes + if (!$(this).length) { + // simulate the real autocomplete that returns + // nothing at all when no element is specified + // (and potentially break stuff) + return null; + } + var $el = $('<div></div>').data('ui-autocomplete', {}); + return $el; + }); + + oldEnableAvatars = oc_config.enable_avatars; + oc_config.enable_avatars = false; + avatarStub = sinon.stub($.fn, 'avatar'); + placeholderStub = sinon.stub($.fn, 'imageplaceholder'); + + oldCurrentUser = OC.currentUser; + OC.currentUser = 'user0'; + }); + afterEach(function() { + OC.currentUser = oldCurrentUser; + /* jshint camelcase:false */ + oc_appconfig.core = oldAppConfig; + + fetchStub.restore(); + + autocompleteStub.restore(); + avatarStub.restore(); + placeholderStub.restore(); + oc_config.enable_avatars = oldEnableAvatars; + }); + describe('Share with link', function() { + beforeEach(function() { + configModel.set('enforcePasswordForPublicLink', false); + }); + // TODO: test ajax calls + // TODO: test password field visibility (whenever enforced or not) + it('update password on focus out', function() { + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + // Toggle linkshare + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + // Enable password, enter password and focusout + dialog.$el.find('[name=showPassword]').click(); + dialog.$el.find('#linkPassText').focus(); + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').focusout(); + + expect(fakeServer.requests[1].method).toEqual('POST'); + var body = OC.parseQueryString(fakeServer.requests[1].requestBody); + expect(body['shareWith']).toEqual('foo'); + + // Set password response + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + expect(dialog.$el.find('#linkPassText').val()).toEqual(''); + expect(dialog.$el.find('#linkPassText').attr('placeholder')).toEqual('Password protected'); + }); + it('update password on enter', function() { + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + // Toggle linkshare + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + // Enable password and enter password + dialog.$el.find('[name=showPassword]').click(); + dialog.$el.find('#linkPassText').focus(); + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); + + expect(fakeServer.requests[1].method).toEqual('POST'); + var body = OC.parseQueryString(fakeServer.requests[1].requestBody); + expect(body['shareWith']).toEqual('foo'); + + // Set password response + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + expect(dialog.$el.find('#linkPassText').val()).toEqual(''); + expect(dialog.$el.find('#linkPassText').attr('placeholder')).toEqual('Password protected'); + }); + it('shows share with link checkbox when allowed', function() { + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + expect(dialog.$el.find('#linkCheckbox').length).toEqual(1); + }); + it('does not show share with link checkbox when not allowed', function() { + $('#allowShareWithLink').val('no'); + + dialog.render(); + + expect(dialog.$el.find('#linkCheckbox').length).toEqual(0); + }); + it('Reset link when password is enforced and link is toggled', function() { + var old = oc_appconfig.core.enforcePasswordForPublicLink; + oc_appconfig.core.enforcePasswordForPublicLink = true; + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + // Toggle linkshare + dialog.$el.find('[name=linkCheckbox]').click(); + expect(dialog.$el.find('#linkText').val()).toEqual(''); + + // Set password + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + // Remove link + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + /* + * Try to share again + * The linkText should be emptied + */ + dialog.$el.find('[name=linkCheckbox]').click(); + expect(dialog.$el.find('#linkText').val()).toEqual(''); + + /* + * Do not set password but untoggle + * Since there is no share this should not result in another request to the server + */ + dialog.$el.find('[name=linkCheckbox]').click(); + expect(fakeServer.requests.length).toEqual(2); + + oc_appconfig.core.enforcePasswordForPublicLink = old; + }); + + it('Reset password placeholder when password is enforced and link is toggled', function() { + var old = oc_appconfig.core.enforcePasswordForPublicLink; + oc_appconfig.core.enforcePasswordForPublicLink = true; + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + // Toggle linkshare + dialog.$el.find('[name=linkCheckbox]').click(); + expect(dialog.$el.find('#linkPassText').attr('placeholder')).toEqual('Choose a password for the public link'); + + // Set password + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + expect(dialog.$el.find('#linkPassText').attr('placeholder')).toEqual('**********'); + + // Remove link + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + // Try to share again + dialog.$el.find('[name=linkCheckbox]').click(); + expect(dialog.$el.find('#linkPassText').attr('placeholder')).toEqual('Choose a password for the public link'); + + oc_appconfig.core.enforcePasswordForPublicLink = old; + }); + it('reset password on toggle of share', function() { + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + //Password protection should be unchecked and password field not visible + expect(dialog.$el.find('[name=showPassword]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#linkPass').is(":visible")).toEqual(false); + + // Toggle and set password + dialog.$el.find('[name=showPassword]').click(); + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz2'}, status: 'success'}) + ); + + // Unshare + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[2].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + // Toggle share again + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[3].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz3'}, status: 'success'}) + ); + + + // Password checkbox should be unchecked + expect(dialog.$el.find('[name=showPassword]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#linkPass').is(":visible")).toEqual(false); + }); + it('reset expiration on toggle of share', function() { + $('#allowShareWithLink').val('yes'); + + dialog.render(); + + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + //Expiration should be unchecked and expiration field not visible + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#expirationDate').is(":visible")).toEqual(false); + + // Toggle and set password + dialog.$el.find('[name=expirationCheckbox]').click(); + d = new Date(); + d.setDate(d.getDate() + 1); + date=d.getDate() + '-' + (d.getMonth()+1) + '-' + d.getFullYear(); + dialog.$el.find('#expirationDate').val(date); + dialog.$el.find('#expirationDate').change(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz2'}, status: 'success'}) + ); + + // Unshare + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[2].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + // Toggle share again + dialog.$el.find('[name=linkCheckbox]').click(); + fakeServer.requests[3].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz3'}, status: 'success'}) + ); + + // Recheck expire visibility + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#expirationDate').is(":visible")).toEqual(false); + }); + it('shows populated link share when a link share exists', function() { + shareModel.set('linkShare', { + isLinkShare: true, + token: 'tehtoken', + link: 'TODO', + expiration: '', + permissions: OC.PERMISSION_READ, + stime: 1403884258, + }); + + expect(dialog.$el.find('#linkCheckbox').prop('checked')).toEqual(true); + // this is how the OC.Share class does it... + var link = parent.location.protocol + '//' + location.host + + OC.generateUrl('/s/') + 'tehtoken'; + expect(dialog.$el.find('#linkText').val()).toEqual(link); + }); + describe('expiration date', function() { + var shareData; + var shareItem; + var clock; + var expectedMinDate; + + beforeEach(function() { + // pick a fake date + clock = sinon.useFakeTimers(new Date(2014, 0, 20, 14, 0, 0).getTime()); + expectedMinDate = new Date(2014, 0, 21, 14, 0, 0); + + oc_appconfig.core.defaultExpireDate = 7; + oc_appconfig.core.enforcePasswordForPublicLink = false; + oc_appconfig.core.defaultExpireDateEnabled = false; + oc_appconfig.core.defaultExpireDateEnforced = false; + + shareModel.set('linkShare', { + isLinkShare: true, + token: 'tehtoken', + permissions: OC.PERMISSION_READ, + expiration: null + }); + }); + afterEach(function() { + clock.restore(); + }); + + it('does not check expiration date checkbox when no date was set', function() { + shareModel.get('linkShare').expiration = null; + dialog.render(); + + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#expirationDate').val()).toEqual(''); + }); + it('does not check expiration date checkbox for new share', function() { + dialog.render(); + + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); + expect(dialog.$el.find('#expirationDate').val()).toEqual(''); + }); + it('checks expiration date checkbox and populates field when expiration date was set', function() { + shareModel.get('linkShare').expiration = 1234; + dialog.render(); + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + expect(dialog.$el.find('#expirationDate').val()).toEqual('1234'); + }); + it('sets default date when default date setting is enabled', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + dialog.render(); + dialog.$el.find('[name=linkCheckbox]').click(); + // enabled by default + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + // TODO: those zeros must go... + expect(dialog.$el.find('#expirationDate').val()).toEqual('2014-1-27 00:00:00'); + + // disabling is allowed + dialog.$el.find('[name=expirationCheckbox]').click(); + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(false); + }); + it('enforces default date when enforced date setting is enabled', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + dialog.render(); + dialog.$el.find('[name=linkCheckbox]').click(); + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + // TODO: those zeros must go... + expect(dialog.$el.find('#expirationDate').val()).toEqual('2014-1-27 00:00:00'); + + // disabling is not allowed + expect(dialog.$el.find('[name=expirationCheckbox]').prop('disabled')).toEqual(true); + dialog.$el.find('[name=expirationCheckbox]').click(); + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + }); + it('enforces default date when enforced date setting is enabled and password is enforced', function() { + /* jshint camelcase:false */ + oc_appconfig.core.enforcePasswordForPublicLink = true; + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + dialog.render(); + dialog.$el.find('[name=linkCheckbox]').click(); + + //Enter password + dialog.$el.find('#linkPassText').val('foo'); + dialog.$el.find('#linkPassText').trigger(new $.Event('keyup', {keyCode: 13})); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {token: 'xyz'}, status: 'success'}) + ); + + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + // TODO: those zeros must go... + expect(dialog.$el.find('#expirationDate').val()).toEqual('2014-1-27 00:00:00'); + + // disabling is not allowed + expect(dialog.$el.find('[name=expirationCheckbox]').prop('disabled')).toEqual(true); + dialog.$el.find('[name=expirationCheckbox]').click(); + expect(dialog.$el.find('[name=expirationCheckbox]').prop('checked')).toEqual(true); + }); + it('displayes email form when sending emails is enabled', function() { + $('input[name=mailPublicNotificationEnabled]').val('yes'); + dialog.render(); + expect($('#emailPrivateLink').length).toEqual(1); + }); + it('not renders email form when sending emails is disabled', function() { + $('input[name=mailPublicNotificationEnabled]').val('no'); + dialog.render(); + expect($('#emailPrivateLink').length).toEqual(0); + }); + it('sets picker minDate to today and no maxDate by default', function() { + dialog.render(); + dialog.$el.find('[name=linkCheckbox]').click(); + dialog.$el.find('[name=expirationCheckbox]').click(); + expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); + expect($.datepicker._defaults.maxDate).toEqual(null); + }); + it('limits the date range to X days after share time when enforced', function() { + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + dialog.render(); + dialog.$el.find('[name=linkCheckbox]').click(); + expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); + expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); + }); + it('limits the date range to X days after share time when enforced, even when redisplayed the next days', function() { + // item exists, was created two days ago + shareItem.expiration = '2014-1-27'; + // share time has time component but must be stripped later + shareItem.stime = new Date(2014, 0, 20, 11, 0, 25).getTime() / 1000; + shareData.shares.push(shareItem); + /* jshint camelcase:false */ + oc_appconfig.core.defaultExpireDateEnabled = true; + oc_appconfig.core.defaultExpireDateEnforced = true; + dialog.render(); + expect($.datepicker._defaults.minDate).toEqual(expectedMinDate); + expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); + }); + }); + }); + describe('check for avatar', function() { + beforeEach(function() { + loadItemStub.returns({ + reshare: { + share_type: OC.Share.SHARE_TYPE_USER, + uid_owner: 'owner', + displayname_owner: 'Owner', + permissions: 31 + }, + shares: [{ + id: 100, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One' + },{ + id: 101, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_GROUP, + share_with: 'group', + share_with_displayname: 'group' + },{ + id: 102, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_REMOTE, + share_with: 'foo@bar.com/baz', + share_with_displayname: 'foo@bar.com/baz' + + }] + }); + }); + + describe('avatars enabled', function() { + beforeEach(function() { + oc_config.enable_avatars = true; + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + 31, + 'shared_file_name.txt' + ); + }); + + afterEach(function() { + oc_config.enable_avatars = false; + }); + + it('test correct function calls', function() { + expect(avatarStub.calledTwice).toEqual(true); + expect(placeholderStub.calledTwice).toEqual(true); + expect($('#shareWithList').children().length).toEqual(3); + expect($('.avatar').length).toEqual(4); + }); + + it('test avatar owner', function() { + var args = avatarStub.getCall(0).args; + expect(args.length).toEqual(2); + expect(args[0]).toEqual('owner'); + }); + + it('test avatar user', function() { + var args = avatarStub.getCall(1).args; + expect(args.length).toEqual(2); + expect(args[0]).toEqual('user1'); + }); + + it('test avatar for groups', function() { + var args = placeholderStub.getCall(0).args; + expect(args.length).toEqual(1); + expect(args[0]).toEqual('group ' + OC.Share.SHARE_TYPE_GROUP); + }); + + it('test avatar for remotes', function() { + var args = placeholderStub.getCall(1).args; + expect(args.length).toEqual(1); + expect(args[0]).toEqual('foo@bar.com/baz ' + OC.Share.SHARE_TYPE_REMOTE); + }); + }); + + describe('avatars disabled', function() { + beforeEach(function() { + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + 31, + 'shared_file_name.txt' + ); + }); + + it('no avatar classes', function() { + expect($('.avatar').length).toEqual(0); + expect(avatarStub.callCount).toEqual(0); + expect(placeholderStub.callCount).toEqual(0); + }); + }); + }); + describe('"sharesChanged" event', function() { + var autocompleteOptions; + var handler; + beforeEach(function() { + handler = sinon.stub(); + loadItemStub.returns({ + reshare: [], + shares: [{ + id: 100, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One' + }] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + 31, + 'shared_file_name.txt' + ); + $('#dropdown').on('sharesChanged', handler); + autocompleteOptions = autocompleteStub.getCall(0).args[0]; + }); + afterEach(function() { + autocompleteOptions = null; + handler = null; + }); + it('triggers "sharesChanged" event when adding shares', function() { + // simulate autocomplete selection + autocompleteOptions.select(new $.Event('select'), { + item: { + label: 'User Two', + value: { + shareType: OC.Share.SHARE_TYPE_USER, + shareWith: 'user2' + } + } + }); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_USER][1].share_with_displayname).toEqual('User Two'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + it('triggers "sharesChanged" event when deleting shares', function() { + dialog.$el.find('.unshare:eq(0)').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER]).toEqual([]); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + it('triggers "sharesChanged" event when toggling link share', function() { + // simulate autocomplete selection + dialog.$el.find('#linkCheckbox').click(); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success', data: { token: 'abc' }}) + ); + expect(handler.calledOnce).toEqual(true); + var shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + + handler.reset(); + + // uncheck checkbox + dialog.$el.find('#linkCheckbox').click(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + expect(handler.calledOnce).toEqual(true); + shares = handler.getCall(0).args[0].shares; + expect(shares).toBeDefined(); + expect(shares[OC.Share.SHARE_TYPE_USER][0].share_with_displayname).toEqual('User One'); + expect(shares[OC.Share.SHARE_TYPE_GROUP]).not.toBeDefined(); + }); + }); + describe('share permissions', function() { + beforeEach(function() { + oc_appconfig.core.resharingAllowed = true; + }); + + /** + * Tests sharing with the given possible permissions + * + * @param {int} possiblePermissions + * @return {int} permissions sent to the server + */ + function testWithPermissions(possiblePermissions) { + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + possiblePermissions, + 'shared_file_name.txt' + ); + var autocompleteOptions = autocompleteStub.getCall(0).args[0]; + // simulate autocomplete selection + autocompleteOptions.select(new $.Event('select'), { + item: { + label: 'User Two', + value: { + shareType: OC.Share.SHARE_TYPE_USER, + shareWith: 'user2' + } + } + }); + autocompleteStub.reset(); + var requestBody = OC.parseQueryString(_.last(fakeServer.requests).requestBody); + return parseInt(requestBody.permissions, 10); + } + + describe('regular sharing', function() { + it('shares with given permissions with default config', function() { + loadItemStub.returns({ + reshare: [], + shares: [] + }); + expect( + testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) + ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE); + expect( + testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_SHARE) + ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_SHARE); + }); + it('removes share permission when not allowed', function() { + oc_appconfig.core.resharingAllowed = false; + loadItemStub.returns({ + reshare: [], + shares: [] + }); + expect( + testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) + ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE); + }); + it('automatically adds READ permission even when not specified', function() { + oc_appconfig.core.resharingAllowed = false; + loadItemStub.returns({ + reshare: [], + shares: [] + }); + expect( + testWithPermissions(OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) + ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_UPDATE); + }); + it('does not show sharing options when sharing not allowed', function() { + loadItemStub.returns({ + reshare: [], + shares: [] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + OC.PERMISSION_READ, + 'shared_file_name.txt' + ); + expect(dialog.$el.find('#shareWithList').length).toEqual(0); + }); + }); + describe('resharing', function() { + it('shares with given permissions when original share had all permissions', function() { + loadItemStub.returns({ + reshare: { + permissions: OC.PERMISSION_ALL + }, + shares: [] + }); + expect( + testWithPermissions(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE) + ).toEqual(OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_SHARE); + }); + it('reduces reshare permissions to the ones from the original share', function() { + loadItemStub.returns({ + reshare: { + permissions: OC.PERMISSION_READ, + uid_owner: 'user1' + }, + shares: [] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + OC.PERMISSION_ALL, + 'shared_file_name.txt' + ); + // no resharing allowed + expect(dialog.$el.find('#shareWithList').length).toEqual(0); + }); + it('reduces reshare permissions to possible permissions', function() { + loadItemStub.returns({ + reshare: { + permissions: OC.PERMISSION_ALL, + uid_owner: 'user1' + }, + shares: [] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + OC.PERMISSION_READ, + 'shared_file_name.txt' + ); + // no resharing allowed + expect(dialog.$el.find('#shareWithList').length).toEqual(0); + }); + it('does not show sharing options when resharing not allowed', function() { + loadItemStub.returns({ + reshare: { + permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE | OC.PERMISSION_DELETE, + uid_owner: 'user1' + }, + shares: [] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + OC.PERMISSION_ALL, + 'shared_file_name.txt' + ); + expect(dialog.$el.find('#shareWithList').length).toEqual(0); + }); + it('allows owner to share their own share when they are also the recipient', function() { + OC.currentUser = 'user1'; + loadItemStub.returns({ + reshare: { + permissions: OC.PERMISSION_READ, + uid_owner: 'user1' + }, + shares: [] + }); + OC.Share.showDropDown( + 'file', + 123, + $container, + true, + OC.PERMISSION_ALL, + 'shared_file_name.txt' + ); + // sharing still allowed + expect(dialog.$el.find('#shareWithList').length).toEqual(1); + }); + }); + }); +}); + diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js new file mode 100644 index 00000000000..d3c4b7d4004 --- /dev/null +++ b/core/js/tests/specs/shareitemmodelSpec.js @@ -0,0 +1,234 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2015 Vincent Petry <pvince81@owncloud.com> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE +* License as published by the Free Software Foundation; either +* version 3 of the License, or any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU AFFERO GENERAL PUBLIC LICENSE for more details. +* +* You should have received a copy of the GNU Affero General Public +* License along with this library. If not, see <http://www.gnu.org/licenses/>. +* +*/ + +/* global oc_appconfig */ +describe('OC.Share.ShareItemModel', function() { + var loadItemStub; + var fileInfoModel, configModel, model; + + beforeEach(function() { + loadItemStub = sinon.stub(OC.Share, 'loadItem'); + loadItemStub.returns({ + reshare: [], + shares: [] + }); + + fileInfoModel = new OCA.Files.FileInfoModel({ + id: 123, + name: 'shared_file_name.txt', + path: '/subdir', + size: 100, + mimetype: 'text/plain', + permissions: 31, + sharePermissions: 31 + }); + + var attributes = { + itemType: fileInfoModel.isDirectory() ? 'folder' : 'file', + itemSource: fileInfoModel.get('id'), + possiblePermissions: fileInfoModel.get('sharePermissions') + }; + configModel = new OC.Share.ShareConfigModel(); + model = new OC.Share.ShareItemModel(attributes, { + configModel: configModel, + fileInfoModel: fileInfoModel + }); + }); + afterEach(function() { + loadItemStub.restore(); + }); + + describe('Fetching and parsing', function() { + it('fetching calls loadItem with the correct arguments', function() { + model.fetch(); + + expect(loadItemStub.calledOnce).toEqual(true); + expect(loadItemStub.calledWith('file', 123)).toEqual(true); + }); + it('populates attributes with parsed response', function() { + loadItemStub.returns({ + /* jshint camelcase: false */ + reshare: { + share_type: OC.Share.SHARE_TYPE_USER, + uid_owner: 'owner', + displayname_owner: 'Owner', + permissions: 31 + }, + shares: [{ + id: 100, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + share_with_displayname: 'User One' + }, { + id: 101, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_GROUP, + share_with: 'group', + share_with_displayname: 'group' + }, { + id: 102, + item_source: 123, + permissions: 31, + share_type: OC.Share.SHARE_TYPE_REMOTE, + share_with: 'foo@bar.com/baz', + share_with_displayname: 'foo@bar.com/baz' + + }, { + displayname_owner: 'root', + expiration: null, + file_source: 123, + file_target: '/folder', + id: 20, + item_source: '123', + item_type: 'folder', + mail_send: '0', + parent: null, + path: '/folder', + permissions: OC.PERMISSION_READ, + share_type: OC.Share.SHARE_TYPE_LINK, + share_with: null, + stime: 1403884258, + storage: 1, + token: 'tehtoken', + uid_owner: 'root' + }] + }); + model.fetch(); + + var shares = model.get('shares'); + expect(shares.length).toEqual(3); + expect(shares.file_source).toEqual(123); + + var linkShare = model.get('linkShare'); + expect(linkShare.isLinkShare).toEqual(true); + + // TODO: check more attributes + }); + it('does not parse link share when for a different file', function() { + loadItemStub.returns({ + reshare: [], + /* jshint camelcase: false */ + shares: [{ + displayname_owner: 'root', + expiration: null, + file_source: 456, + file_target: '/folder', + id: 20, + item_source: '456', + item_type: 'folder', + mail_send: '0', + parent: null, + path: '/folder', + permissions: OC.PERMISSION_READ, + share_type: OC.Share.SHARE_TYPE_LINK, + share_with: null, + stime: 1403884258, + storage: 1, + token: 'tehtoken', + uid_owner: 'root' + }] + }); + + model.fetch(); + + var shares = model.get('shares'); + expect(shares.length).toEqual(0); + + var linkShare = model.get('linkShare'); + expect(linkShare.isLinkShare).toEqual(false); + }); + it('parsess correct link share when a nested link share exists along with parent one', function() { + loadItemStub.returns({ + reshare: [], + /* jshint camelcase: false */ + shares: [{ + displayname_owner: 'root', + expiration: 1111, + file_source: 123, + file_target: '/folder', + id: 20, + item_source: '123', + item_type: 'file', + mail_send: '0', + parent: null, + path: '/folder', + permissions: OC.PERMISSION_READ, + share_type: OC.Share.SHARE_TYPE_LINK, + share_with: null, + stime: 1403884258, + storage: 1, + token: 'tehtoken', + uid_owner: 'root' + }, { + displayname_owner: 'root', + expiration: 2222, + file_source: 456, + file_target: '/file_in_folder.txt', + id: 21, + item_source: '456', + item_type: 'file', + mail_send: '0', + parent: null, + path: '/folder/file_in_folder.txt', + permissions: OC.PERMISSION_READ, + share_type: OC.Share.SHARE_TYPE_LINK, + share_with: null, + stime: 1403884509, + storage: 1, + token: 'anothertoken', + uid_owner: 'root' + }] + }); + + model.fetch(); + + var shares = model.get('shares'); + expect(shares.length).toEqual(0); + + var linkShare = model.get('linkShare'); + expect(linkShare.isLinkShare).toEqual(false); + expect(linkShare.token).toEqual('tehtoken'); + + // TODO: check child too + }); + }); + + describe('Util', function() { + it('parseTime should properly parse strings', function() { + + _.each([ + [ '123456', 123456], + [ 123456 , 123456], + ['0123456', 123456], + ['abcdefg', null], + ['0x12345', null], + [ '', null], + ], function(value) { + expect(OC.Share._parseTime(value[0])).toEqual(value[1]); + }); + + }); + }); +}); + diff --git a/tests/karma.config.js b/tests/karma.config.js index d3280b2939a..64a94ef230b 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -55,7 +55,8 @@ module.exports = function(config) { 'apps/files_sharing/js/sharedfilelist.js', 'apps/files_sharing/js/share.js', 'apps/files_sharing/js/external.js', - 'apps/files_sharing/js/public.js' + 'apps/files_sharing/js/public.js', + 'apps/files_sharing/js/sharetabview.js' ], testFiles: ['apps/files_sharing/tests/js/*.js'] }, |