From 4bf19d4472c5dbaa22c0f365cf6d39bc74b3538a Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 7 Oct 2015 17:50:51 +0200 Subject: [PATCH 1/2] Fix share email sending feedback Redisplay email address after failure --- core/js/sharedialoglinkshareview.js | 10 ++++++++-- core/js/shareitemmodel.js | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js index 792062f0e1..1bbd10d572 100644 --- a/core/js/sharedialoglinkshareview.js +++ b/core/js/sharedialoglinkshareview.js @@ -194,13 +194,19 @@ $emailField.prop('disabled', true); $emailButton.prop('disabled', true); $emailField.val(t('core', 'Sending ...')); - this.model.sendEmailPrivateLink(email).then(function() { + this.model.sendEmailPrivateLink(email).done(function() { $emailField.css('font-weight', 'bold').val(t('core','Email sent')); setTimeout(function() { - $emailField.css('font-weight', 'normal').val(''); + $emailField.val(''); + $emailField.css('font-weight', 'normal'); $emailField.prop('disabled', false); $emailButton.prop('disabled', false); }, 2000); + }).fail(function() { + $emailField.val(email); + $emailField.css('font-weight', 'normal'); + $emailField.prop('disabled', false); + $emailButton.prop('disabled', false); }); } return false; diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index 328d291b77..1cf116f08f 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -522,11 +522,12 @@ * @param {string} recipientEmail recipient email address */ sendEmailPrivateLink: function(recipientEmail) { + var deferred = $.Deferred(); var itemType = this.get('itemType'); var itemSource = this.get('itemSource'); var linkShare = this.get('linkShare'); - return $.post( + $.post( OC.generateUrl('core/ajax/share.php'), { action: 'email', toaddress: recipientEmail, @@ -540,8 +541,13 @@ if (!result || result.status !== 'success') { // FIXME: a model should not show dialogs OC.dialogs.alert(result.data.message, t('core', 'Error while sending notification')); + deferred.reject(); + } else { + deferred.resolve(); } }); + + return deferred.promise(); }, /** From 08600a7ed5f41cfe18a9d11cf6874cb51d741009 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Thu, 8 Oct 2015 12:21:38 +0200 Subject: [PATCH 2/2] Add unit tests for sending e-mail for link shares --- core/js/tests/specs/sharedialogviewSpec.js | 80 ++++++++++++++--- core/js/tests/specs/shareitemmodelSpec.js | 100 +++++++++++++++++++++ 2 files changed, 170 insertions(+), 10 deletions(-) diff --git a/core/js/tests/specs/sharedialogviewSpec.js b/core/js/tests/specs/sharedialogviewSpec.js index 22ae63e796..fe4cf8e8c2 100644 --- a/core/js/tests/specs/sharedialogviewSpec.js +++ b/core/js/tests/specs/sharedialogviewSpec.js @@ -380,16 +380,6 @@ describe('OC.Share.ShareDialogView', function() { 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(dialog.$('#emailPrivateLink').length).toEqual(1); - }); - it('not renders email form when sending emails is disabled', function() { - $('input[name=mailPublicNotificationEnabled]').val('no'); - dialog.render(); - expect(dialog.$('#emailPrivateLink').length).toEqual(0); - }); it('sets picker minDate to today and no maxDate by default', function() { dialog.render(); dialog.$el.find('[name=linkCheckbox]').click(); @@ -422,6 +412,76 @@ describe('OC.Share.ShareDialogView', function() { expect($.datepicker._defaults.maxDate).toEqual(new Date(2014, 0, 27, 0, 0, 0, 0)); }); }); + describe('send link by email', function() { + var sendEmailPrivateLinkStub; + var clock; + + beforeEach(function() { + configModel.set({ + isMailPublicNotificationEnabled: true + }); + + shareModel.set('linkShare', { + isLinkShare: true, + token: 'tehtoken', + permissions: OC.PERMISSION_READ, + expiration: null + }); + + sendEmailPrivateLinkStub = sinon.stub(dialog.model, "sendEmailPrivateLink"); + clock = sinon.useFakeTimers(); + }); + afterEach(function() { + sendEmailPrivateLinkStub.restore(); + clock.restore(); + }); + + it('displayes form when sending emails is enabled', function() { + $('input[name=mailPublicNotificationEnabled]').val('yes'); + dialog.render(); + expect(dialog.$('#emailPrivateLink').length).toEqual(1); + }); + it('form not rendered when sending emails is disabled', function() { + $('input[name=mailPublicNotificationEnabled]').val('no'); + dialog.render(); + expect(dialog.$('#emailPrivateLink').length).toEqual(0); + }); + it('input cleared on success', function() { + var defer = $.Deferred(); + sendEmailPrivateLinkStub.returns(defer.promise()); + + $('input[name=mailPublicNotificationEnabled]').val('yes'); + dialog.render(); + + dialog.$el.find('#emailPrivateLink #email').val('a@b.c'); + dialog.$el.find('#emailPrivateLink').trigger('submit'); + + expect(sendEmailPrivateLinkStub.callCount).toEqual(1); + expect(dialog.$el.find('#emailPrivateLink #email').val()).toEqual('Sending ...'); + + defer.resolve(); + expect(dialog.$el.find('#emailPrivateLink #email').val()).toEqual('Email sent'); + + clock.tick(2000); + expect(dialog.$el.find('#emailPrivateLink #email').val()).toEqual(''); + }); + it('input not cleared on failure', function() { + var defer = $.Deferred(); + sendEmailPrivateLinkStub.returns(defer.promise()); + + $('input[name=mailPublicNotificationEnabled]').val('yes'); + dialog.render(); + + dialog.$el.find('#emailPrivateLink #email').val('a@b.c'); + dialog.$el.find('#emailPrivateLink').trigger('submit'); + + expect(sendEmailPrivateLinkStub.callCount).toEqual(1); + expect(dialog.$el.find('#emailPrivateLink #email').val()).toEqual('Sending ...'); + + defer.reject(); + expect(dialog.$el.find('#emailPrivateLink #email').val()).toEqual('a@b.c'); + }); + }); }); describe('check for avatar', function() { beforeEach(function() { diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js index b4403e2847..28daf86039 100644 --- a/core/js/tests/specs/shareitemmodelSpec.js +++ b/core/js/tests/specs/shareitemmodelSpec.js @@ -378,5 +378,105 @@ describe('OC.Share.ShareItemModel', function() { }); }); + + describe('sendEmailPrivateLink', function() { + it('succeeds', function() { + loadItemStub.yields({ + 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' + }] + }); + model.fetch(); + + var res = model.sendEmailPrivateLink('foo@bar.com'); + + expect(res.state()).toEqual('pending'); + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].url).toEqual(OC.generateUrl('core/ajax/share.php')); + expect(OC.parseQueryString(fakeServer.requests[0].requestBody)).toEqual( + { + action: 'email', + toaddress: 'foo@bar.com', + link: model.get('linkShare').link, + itemType: 'file', + itemSource: '123', + file: 'shared_file_name.txt', + expiration: '' + } + ) + + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(res.state()).toEqual('resolved'); + }); + + it('fails', function() { + loadItemStub.yields({ + 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' + }] + }); + model.fetch(); + + var res = model.sendEmailPrivateLink('foo@bar.com'); + + expect(res.state()).toEqual('pending'); + expect(fakeServer.requests.length).toEqual(1); + expect(fakeServer.requests[0].url).toEqual(OC.generateUrl('core/ajax/share.php')); + expect(OC.parseQueryString(fakeServer.requests[0].requestBody)).toEqual( + { + action: 'email', + toaddress: 'foo@bar.com', + link: model.get('linkShare').link, + itemType: 'file', + itemSource: '123', + file: 'shared_file_name.txt', + expiration: '' + } + ) + + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({data: {message: 'fail'}, status: 'error'}) + ); + expect(res.state()).toEqual('rejected'); + }); + }); });