diff --git a/Changelog.md b/Changelog.md index 552dc21ad..d3769a835 100644 --- a/Changelog.md +++ b/Changelog.md @@ -53,6 +53,7 @@ With the port to Bootstrap 3, app/views/terms/default.haml has a new structure. * Optionally make your extended profile details public [#6162](https://github.com/diaspora/diaspora/pull/6162) * Add admin dashboard showing latest diaspora\* version [#6216](https://github.com/diaspora/diaspora/pull/6216) * Display poll & location on mobile [#6238](https://github.com/diaspora/diaspora/pull/6238) +* Update counts on contacts page dynamically [#6240](https://github.com/diaspora/diaspora/pull/6240) # 0.5.3.0 diff --git a/app/assets/javascripts/app/models/contact.js b/app/assets/javascripts/app/models/contact.js index 5457f2c4e..22f26804b 100644 --- a/app/assets/javascripts/app/models/contact.js +++ b/app/assets/javascripts/app/models/contact.js @@ -2,12 +2,12 @@ app.models.Contact = Backbone.Model.extend({ initialize : function() { - this.aspect_memberships = new app.collections.AspectMemberships(this.get('aspect_memberships')); - if( this.get('person') ) this.person = new app.models.Person(this.get('person')); + this.aspectMemberships = new app.collections.AspectMemberships(this.get("aspect_memberships")); + if(this.get("person")) { this.person = new app.models.Person(this.get("person")); } }, inAspect : function(id) { - return this.aspect_memberships.any(function(membership){ return membership.get('aspect').id === id; }); + return this.aspectMemberships.any(function(membership){ return membership.get("aspect").id === id; }); } }); // @license-end diff --git a/app/assets/javascripts/app/pages/contacts.js b/app/assets/javascripts/app/pages/contacts.js index 9b26efcae..86f7c20fb 100644 --- a/app/assets/javascripts/app/pages/contacts.js +++ b/app/assets/javascripts/app/pages/contacts.js @@ -20,6 +20,8 @@ app.pages.Contacts = Backbone.View.extend({ $("#people_stream.contacts .header i").tooltip({"placement": "bottom"}); $(document).on("ajax:success", "form.edit_aspect", this.updateAspectName); app.events.on("aspect:create", function(){ window.location.reload() }); + app.events.on("aspect_membership:create", this.addAspectMembership, this); + app.events.on("aspect_membership:destroy", this.removeAspectMembership, this); this.aspectCreateView = new app.views.AspectCreate({ el: $("#newAspectContainer") }); this.aspectCreateView.render(); @@ -95,6 +97,51 @@ app.pages.Contacts = Backbone.View.extend({ revert: true, helper: "clone" }); + }, + + updateBadgeCount: function(selector, change) { + var count = parseInt($("#aspect_nav " + selector + " .badge").text(), 10); + $("#aspect_nav " + selector + " .badge").text(count + change); + }, + + addAspectMembership: function(data) { + if(data.startSharing) { + this.updateBadgeCount(".all_aspects", 1); + + var contact = this.stream.collection.find(function(c) { + return c.get("person").id === data.membership.personId; + }); + + if(contact && contact.person.get("relationship") === "sharing") { + contact.person.set({relationship: "mutual"}); + this.updateBadgeCount(".only_sharing", -1); + } + else if(contact && contact.person.get("relationship") === "not_sharing") { + contact.person.set({relationship: "receiving"}); + this.updateBadgeCount(".all_contacts", 1); + } + } + this.updateBadgeCount("[data-aspect-id='" + data.membership.aspectId + "']", 1); + }, + + removeAspectMembership: function(data) { + if(data.stopSharing) { + this.updateBadgeCount(".all_aspects", -1); + + var contact = this.stream.collection.find(function(c) { + return c.get("person").id === data.membership.personId; + }); + + if(contact && contact.person.get("relationship") === "mutual") { + contact.person.set({relationship: "sharing"}); + this.updateBadgeCount(".only_sharing", 1); + } + else if(contact && contact.person.get("relationship") === "receiving") { + contact.person.set({relationship: "not_sharing"}); + this.updateBadgeCount(".all_contacts", -1); + } + } + this.updateBadgeCount("[data-aspect-id='" + data.membership.aspectId + "']", -1); } }); // @license-end diff --git a/app/assets/javascripts/app/views/aspect_membership_view.js b/app/assets/javascripts/app/views/aspect_membership_view.js index e15d654a4..bbf81d749 100644 --- a/app/assets/javascripts/app/views/aspect_membership_view.js +++ b/app/assets/javascripts/app/views/aspect_membership_view.js @@ -77,20 +77,28 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({ return aspect_membership.save(); }, - _successSaveCb: function(aspect_membership) { - var aspect_id = aspect_membership.get('aspect_id'); - var membership_id = aspect_membership.get('id'); - var li = this.dropdown.find('li[data-aspect_id="'+aspect_id+'"]'); + _successSaveCb: function(aspectMembership) { + var aspectId = aspectMembership.get("aspect_id"), + membershipId = aspectMembership.get("id"), + li = this.dropdown.find("li[data-aspect_id='" + aspectId + "']"), + personId = li.closest("ul.dropdown-menu").data("person_id"), + startSharing = false; // the user didn't have this person in any aspects before, congratulate them // on their newly found friendship ;) - if( this.dropdown.find('li.selected').length === 0 ) { - var msg = Diaspora.I18n.t('aspect_dropdown.started_sharing_with', { 'name': this._name() }); - Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg }); + if( this.dropdown.find("li.selected").length === 0 ) { + var msg = Diaspora.I18n.t("aspect_dropdown.started_sharing_with", { "name": this._name() }); + startSharing = true; + Diaspora.page.flashMessages.render({ "success": true, "notice": msg }); } - li.attr('data-membership_id', membership_id) // just to be sure... - .data('membership_id', membership_id); + app.events.trigger("aspect_membership:create", { + membership: { aspectId: aspectId, personId: personId }, + startSharing: startSharing + }); + + li.attr("data-membership_id", membershipId) // just to be sure... + .data("membership_id", membershipId); this.updateSummary(li); this._done(); @@ -119,21 +127,30 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({ return aspect_membership.destroy(); }, - _successDestroyCb: function(aspect_membership) { - var membership_id = aspect_membership.get('id'); - var li = this.dropdown.find('li[data-membership_id="'+membership_id+'"]'); + _successDestroyCb: function(aspectMembership) { + var membershipId = aspectMembership.get("id"), + li = this.dropdown.find("li[data-membership_id='" + membershipId + "']"), + aspectId = li.data("aspect_id"), + personId = li.closest("ul.dropdown-menu").data("person_id"), + stopSharing = false; - li.removeAttr('data-membership_id') - .removeData('membership_id'); + li.removeAttr("data-membership_id") + .removeData("membership_id"); this.updateSummary(li); // we just removed the last aspect, inform the user with a flash message // that he is no longer sharing with that person - if( this.dropdown.find('li.selected').length === 0 ) { - var msg = Diaspora.I18n.t('aspect_dropdown.stopped_sharing_with', { 'name': this._name() }); - Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg }); + if( this.dropdown.find("li.selected").length === 0 ) { + var msg = Diaspora.I18n.t("aspect_dropdown.stopped_sharing_with", { "name": this._name() }); + stopSharing = true; + Diaspora.page.flashMessages.render({ "success": true, "notice": msg }); } + app.events.trigger("aspect_membership:destroy", { + membership: { aspectId: aspectId, personId: personId }, + stopSharing: stopSharing + }); + this._done(); }, diff --git a/app/assets/javascripts/app/views/contact_view.js b/app/assets/javascripts/app/views/contact_view.js index 87422ed32..5277d65cc 100644 --- a/app/assets/javascripts/app/views/contact_view.js +++ b/app/assets/javascripts/app/views/contact_view.js @@ -36,31 +36,49 @@ app.views.Contact = app.views.Base.extend({ addContactToAspect: function(){ var self = this; - this.model.aspect_memberships.create({ - 'person_id': this.model.get('person_id'), - 'aspect_id': app.aspect.get('id') + // do we create the first aspect membership for this person? + var startSharing = this.model.aspectMemberships.length === 0; + this.model.aspectMemberships.create({ + "person_id": this.model.get("person_id"), + "aspect_id": app.aspect.get("id") },{ success: function(){ + app.events.trigger("aspect_membership:create", { + membership: { + aspectId: app.aspect.get("id"), + personId: self.model.get("person_id") + }, + startSharing: startSharing + }); self.render(); }, error: function(){ - var msg = Diaspora.I18n.t('contacts.error_add', { 'name': self.model.get('person').name }); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); + var msg = Diaspora.I18n.t("contacts.error_add", { "name": self.model.get("person").name }); + Diaspora.page.flashMessages.render({ "success": false, "notice": msg }); } }); }, removeContactFromAspect: function(){ var self = this; - this.model.aspect_memberships - .find(function(membership){ return membership.get('aspect').id === app.aspect.id; }) + // do we destroy the last aspect membership for this person? + var stopSharing = this.model.aspectMemberships.length <= 1; + this.model.aspectMemberships + .find(function(membership){ return membership.get("aspect").id === app.aspect.id; }) .destroy({ success: function(){ + app.events.trigger("aspect_membership:destroy", { + membership: { + aspectId: app.aspect.get("id"), + personId: self.model.get("person_id") + }, + stopSharing: stopSharing + }); self.render(); }, error: function(){ - var msg = Diaspora.I18n.t('contacts.error_remove', { 'name': self.model.get('person').name }); - Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg }); + var msg = Diaspora.I18n.t("contacts.error_remove", { "name": self.model.get("person").name }); + Diaspora.page.flashMessages.render({ "success": false, "notice": msg }); } }); } diff --git a/spec/controllers/jasmine_fixtures/contacts_spec.rb b/spec/controllers/jasmine_fixtures/contacts_spec.rb index 6311c3b34..11207e0f6 100644 --- a/spec/controllers/jasmine_fixtures/contacts_spec.rb +++ b/spec/controllers/jasmine_fixtures/contacts_spec.rb @@ -17,6 +17,7 @@ describe ContactsController, :type => :controller do it "generates the aspects_manage fixture", :fixture => true do get :index, :a_id => @aspect.id save_fixture(html_for("body"), "aspects_manage") + save_fixture(controller.gon.preloads[:contacts].to_json, "aspects_manage_contacts_json") end it "generates the contacts_json fixture", :fixture => true do diff --git a/spec/javascripts/app/pages/contacts_spec.js b/spec/javascripts/app/pages/contacts_spec.js index b7679ffe9..e961aaaf6 100644 --- a/spec/javascripts/app/pages/contacts_spec.js +++ b/spec/javascripts/app/pages/contacts_spec.js @@ -1,9 +1,12 @@ describe("app.pages.Contacts", function(){ beforeEach(function() { spec.loadFixture("aspects_manage"); + var contactsData = spec.readFixture("aspects_manage_contacts_json"); + app.contacts = new app.collections.Contacts(JSON.parse(contactsData)); this.view = new app.pages.Contacts({ stream: { - render: function(){} + render: function(){}, + collection: app.contacts } }); Diaspora.I18n.load({ @@ -98,4 +101,194 @@ describe("app.pages.Contacts", function(){ expect(this.view.stream.search).toHaveBeenCalledWith("Username"); }); }); + + describe("updateBadgeCount", function() { + it("increases the badge count of an aspect", function() { + var aspect = $("#aspect_nav .aspect").eq(0); + $(".badge", aspect).text("15"); + this.view.updateBadgeCount("[data-aspect-id='" + aspect.data("aspect-id") + "']", 27); + expect($(".badge", aspect).text()).toBe("42"); + }); + + it("decreases the badge count of an aspect", function() { + var aspect = $("#aspect_nav .aspect").eq(1); + $(".badge", aspect).text("42"); + this.view.updateBadgeCount("[data-aspect-id='" + aspect.data("aspect-id") + "']", -15); + expect($(".badge", aspect).text()).toBe("27"); + }); + + it("increases the badge count of 'my aspects'", function() { + $("#aspect_nav .all_aspects .badge").text("15"); + this.view.updateBadgeCount(".all_aspects", 27); + expect($("#aspect_nav .all_aspects .badge").text()).toBe("42"); + }); + + it("decreases the badge count of 'my aspects'", function() { + $("#aspect_nav .all_aspects .badge").text("42"); + this.view.updateBadgeCount(".all_aspects", -15); + expect($("#aspect_nav .all_aspects .badge").text()).toBe("27"); + }); + }); + + describe("addAspectMembership", function() { + context("when the user starts sharing", function() { + beforeEach(function() { + this.contact = app.contacts.first(); + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(1).data("aspect-id"), + personId: this.contact.person.id + }, + startSharing: true + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:create", function() { + spyOn(app.pages.Contacts.prototype, "addAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:create", this.data); + expect(app.pages.Contacts.prototype.addAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("calls updateContactCount for 'all aspects'", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_aspects", 1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", 1 + ); + }); + + it("calls updateContactCount for 'all contacts' if there was no relationship before", function() { + this.contact.person.set({relationship: "not_sharing"}); + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_contacts", 1); + expect(this.contact.person.get("relationship")).toBe("receiving"); + }); + + it("calls updateContactCount for 'only sharing' if the relationship was 'sharing'", function() { + this.contact.person.set({relationship: "sharing"}); + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".only_sharing", -1); + expect(this.contact.person.get("relationship")).toBe("mutual"); + }); + }); + + context("when the user doesn't start sharing", function() { + beforeEach(function() { + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(1).data("aspect-id"), + personId: app.contacts.first().person.id + }, + startSharing: false + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:create", function() { + spyOn(app.pages.Contacts.prototype, "addAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:create", this.data); + expect(app.pages.Contacts.prototype.addAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("doesn't call updateBadgeCount for 'all aspects'", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).not.toHaveBeenCalledWith(".all_aspects", 1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.addAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", 1 + ); + }); + }); + }); + + describe("removeAspectMembership", function() { + context("when the user stops sharing", function() { + beforeEach(function() { + this.contact = app.contacts.first(); + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(0).data("aspect-id"), + personId: this.contact.person.id + }, + stopSharing: true + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:destroy", function() { + spyOn(app.pages.Contacts.prototype, "removeAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:destroy", this.data); + expect(app.pages.Contacts.prototype.removeAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("calls updateContactCount for 'all aspects'", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_aspects", -1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", -1 + ); + }); + + it("calls updateContactCount for 'all contacts' if the relationship was 'receiving'", function() { + this.contact.person.set({relationship: "receiving"}); + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".all_contacts", -1); + expect(this.contact.person.get("relationship")).toBe("not_sharing"); + }); + + it("calls updateContactCount for 'only sharing' if the relationship was 'mutual'", function() { + this.contact.person.set({relationship: "mutual"}); + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith(".only_sharing", 1); + expect(this.contact.person.get("relationship")).toBe("sharing"); + }); + }); + + context("when the user doesn't stop sharing", function() { + beforeEach(function() { + this.data = { + membership: { + aspectId: $("#aspect_nav .aspect").eq(0).data("aspect-id"), + personId: app.contacts.first().person.id + }, + stopSharing: false + }; + spyOn(this.view, "updateBadgeCount").and.callThrough(); + }); + + it("is called on aspect_membership:destroy", function() { + spyOn(app.pages.Contacts.prototype, "removeAspectMembership"); + this.view = new app.pages.Contacts({stream: {render: function(){}, collection: app.contacts}}); + app.events.trigger("aspect_membership:destroy", this.data); + expect(app.pages.Contacts.prototype.removeAspectMembership).toHaveBeenCalledWith(this.data); + }); + + it("doesn't call updateBadgeCount for 'all aspects'", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).not.toHaveBeenCalledWith(".all_aspects", -1); + }); + + it("calls updateBadgeCount for the aspect", function() { + this.view.removeAspectMembership(this.data); + expect(this.view.updateBadgeCount).toHaveBeenCalledWith( + "[data-aspect-id='" + this.data.membership.aspectId + "']", -1 + ); + }); + }); + }); }); diff --git a/spec/javascripts/app/views/aspect_membership_view_spec.js b/spec/javascripts/app/views/aspect_membership_view_spec.js index eb33fe203..7ff709ead 100644 --- a/spec/javascripts/app/views/aspect_membership_view_spec.js +++ b/spec/javascripts/app/views/aspect_membership_view_spec.js @@ -1,13 +1,13 @@ describe("app.views.AspectMembership", function(){ - var resp_success = {status: 200, responseText: '{}'}; + var success = {status: 200, responseText: "{}"}; var resp_fail = {status: 400}; beforeEach(function() { // mock a dummy aspect dropdown spec.loadFixture("aspect_membership_dropdown"); this.view = new app.views.AspectMembership({el: $('.aspect_membership_dropdown')}); - this.person_id = $('.dropdown-menu').data('person_id'); - this.person_name = $('.dropdown-menu').data('person-short-name'); + this.personId = $(".dropdown-menu").data("person_id"); + this.personName = $(".dropdown-menu").data("person-short-name"); Diaspora.I18n.load({ aspect_dropdown: { started_sharing_with: 'you started sharing with <%= name %>', @@ -26,7 +26,7 @@ describe("app.views.AspectMembership", function(){ it('marks the aspect as selected', function() { this.newAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); expect(this.newAspect.attr('class')).toContain('selected'); }); @@ -34,19 +34,30 @@ describe("app.views.AspectMembership", function(){ it('displays flash message when added to first aspect', function() { spec.content().find('li').removeClass('selected'); this.newAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); expect($('[id^="flash"]')).toBeSuccessFlashMessage( - Diaspora.I18n.t('aspect_dropdown.started_sharing_with', {name: this.person_name}) + Diaspora.I18n.t("aspect_dropdown.started_sharing_with", {name: this.personName}) ); }); + it("triggers aspect_membership:create", function() { + spyOn(app.events, "trigger"); + spec.content().find("li").removeClass("selected"); + this.newAspect.trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith(success); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:create", { + membership: {aspectId: this.newAspectId, personId: this.personId}, + startSharing: true + }); + }); + it('displays an error when it fails', function() { this.newAspect.trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith(resp_fail); expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t('aspect_dropdown.error', {name: this.person_name}) + Diaspora.I18n.t("aspect_dropdown.error", {name: this.personName}) ); }); }); @@ -59,7 +70,7 @@ describe("app.views.AspectMembership", function(){ it('marks the aspect as unselected', function(){ this.oldAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); expect(this.oldAspect.attr('class')).not.toContain('selected'); }); @@ -67,19 +78,30 @@ describe("app.views.AspectMembership", function(){ it('displays a flash message when removed from last aspect', function() { spec.content().find('li.selected:last').removeClass('selected'); this.oldAspect.trigger('click'); - jasmine.Ajax.requests.mostRecent().respondWith(resp_success); + jasmine.Ajax.requests.mostRecent().respondWith(success); expect($('[id^="flash"]')).toBeSuccessFlashMessage( - Diaspora.I18n.t('aspect_dropdown.stopped_sharing_with', {name: this.person_name}) + Diaspora.I18n.t("aspect_dropdown.stopped_sharing_with", {name: this.personName}) ); }); + it("triggers aspect_membership:destroy", function() { + spyOn(app.events, "trigger"); + spec.content().find("li.selected:last").removeClass("selected"); + this.oldAspect.trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith(success); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:destroy", { + membership: {aspectId: this.oldAspect.data("aspect_id"), personId: this.personId}, + stopSharing: true + }); + }); + it('displays an error when it fails', function() { this.oldAspect.trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith(resp_fail); expect($('[id^="flash"]')).toBeErrorFlashMessage( - Diaspora.I18n.t('aspect_dropdown.error_remove', {name: this.person_name}) + Diaspora.I18n.t("aspect_dropdown.error_remove", {name: this.personName}) ); }); }); diff --git a/spec/javascripts/app/views/contact_view_spec.js b/spec/javascripts/app/views/contact_view_spec.js index b1d400ed1..709882058 100644 --- a/spec/javascripts/app/views/contact_view_spec.js +++ b/spec/javascripts/app/views/contact_view_spec.js @@ -36,8 +36,8 @@ describe("app.views.Contact", function(){ this.view.render(); this.button = this.view.$el.find('.contact_add-to-aspect'); this.contact = this.view.$el.find('.stream_element.contact'); - this.aspect_membership = {id: 42, aspect: app.aspect.toJSON()}; - this.response = JSON.stringify(this.aspect_membership); + this.aspectMembership = {id: 42, aspect: app.aspect.toJSON()}; + this.response = JSON.stringify(this.aspectMembership); }); it('sends a correct ajax request', function() { @@ -48,13 +48,26 @@ describe("app.views.Contact", function(){ }); it('adds a aspect_membership to the contact', function() { - expect(this.model.aspect_memberships.length).toBe(1); + expect(this.model.aspectMemberships.length).toBe(1); $('.contact_add-to-aspect',this.contact).trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response }); - expect(this.model.aspect_memberships.length).toBe(2); + expect(this.model.aspectMemberships.length).toBe(2); + }); + + it("triggers aspect_membership:create", function() { + spyOn(app.events, "trigger"); + $(".contact_add-to-aspect", this.contact).trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, // success + responseText: this.response + }); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:create", { + membership: {aspectId: app.aspect.get("id"), personId: this.model.get("person_id")}, + startSharing: false + }); }); it('calls render', function() { @@ -88,25 +101,38 @@ describe("app.views.Contact", function(){ this.view.render(); this.button = this.view.$el.find('.contact_remove-from-aspect'); this.contact = this.view.$el.find('.stream_element.contact'); - this.aspect_membership = this.model.aspect_memberships.first().toJSON(); - this.response = JSON.stringify(this.aspect_membership); + this.aspectMembership = this.model.aspectMemberships.first().toJSON(); + this.response = JSON.stringify(this.aspectMembership); }); it('sends a correct ajax request', function() { $('.contact_remove-from-aspect',this.contact).trigger('click'); expect(jasmine.Ajax.requests.mostRecent().url).toBe( - "/aspect_memberships/"+this.aspect_membership.id + "/aspect_memberships/"+this.aspectMembership.id ); }); it('removes the aspect_membership from the contact', function() { - expect(this.model.aspect_memberships.length).toBe(1); + expect(this.model.aspectMemberships.length).toBe(1); $('.contact_remove-from-aspect',this.contact).trigger('click'); jasmine.Ajax.requests.mostRecent().respondWith({ status: 200, // success responseText: this.response }); - expect(this.model.aspect_memberships.length).toBe(0); + expect(this.model.aspectMemberships.length).toBe(0); + }); + + it("triggers aspect_membership:destroy", function() { + spyOn(app.events, "trigger"); + $(".contact_remove-from-aspect", this.contact).trigger("click"); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, // success + responseText: this.response + }); + expect(app.events.trigger).toHaveBeenCalledWith("aspect_membership:destroy", { + membership: {aspectId: app.aspect.get("id"), personId: this.model.get("person_id")}, + stopSharing: true + }); }); it('calls render', function() {