diff --git a/common/static/coffee/spec/discussion/view/discussion_content_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_content_view_spec.coffee index 85ab5ec254..71495ad9c6 100644 --- a/common/static/coffee/spec/discussion/view/discussion_content_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_content_view_spec.coffee @@ -1,13 +1,12 @@ describe "DiscussionContentView", -> beforeEach -> - setFixtures - ( + setFixtures( """
robot @@ -23,16 +22,21 @@ describe "DiscussionContentView", -> """ ) - @thread = new Thread { - id: '01234567', - user_id: '567', - course_id: 'mitX/999/test', - body: 'this is a thread', - created_at: '2013-04-03T20:08:39Z', - abuse_flaggers: ['123'] - roles: [] + @threadData = { + id: '01234567', + user_id: '567', + course_id: 'mitX/999/test', + body: 'this is a thread', + created_at: '2013-04-03T20:08:39Z', + abuse_flaggers: ['123'], + votes: {up_count: '42'}, + type: "thread", + roles: [] } + @thread = new Thread(@threadData) @view = new DiscussionContentView({ model: @thread }) + @view.setElement($('.discussion-post')) + window.user = new DiscussionUser({id: '567', upvoted_ids: []}) it 'defines the tag', -> expect($('#jasmine-fixtures')).toExist @@ -56,3 +60,15 @@ describe "DiscussionContentView", -> @thread.set("abuse_flaggers",temp_array) @thread.unflagAbuse() expect(@thread.get 'abuse_flaggers').toEqual [] + + it 'renders the vote button properly', -> + DiscussionViewSpecHelper.checkRenderVote(@view, @thread) + + it 'votes correctly', -> + DiscussionViewSpecHelper.checkVote(@view, @thread, @threadData, false) + + it 'unvotes correctly', -> + DiscussionViewSpecHelper.checkUnvote(@view, @thread, @threadData, false) + + it 'toggles the vote correctly', -> + DiscussionViewSpecHelper.checkToggleVote(@view, @thread) diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee new file mode 100644 index 0000000000..f10d30d0af --- /dev/null +++ b/common/static/coffee/spec/discussion/view/discussion_thread_profile_view_spec.coffee @@ -0,0 +1,40 @@ +describe "DiscussionThreadProfileView", -> + beforeEach -> + setFixtures( + """ +
+ """ + ) + + @threadData = { + id: "dummy", + user_id: "567", + course_id: "TestOrg/TestCourse/TestRun", + body: "this is a thread", + created_at: "2013-04-03T20:08:39Z", + abuse_flaggers: [], + votes: {up_count: "42"} + } + @thread = new Thread(@threadData) + @view = new DiscussionThreadProfileView({ model: @thread }) + @view.setElement($(".discussion-post")) + window.user = new DiscussionUser({id: "567", upvoted_ids: []}) + + it "renders the vote correctly", -> + DiscussionViewSpecHelper.checkRenderVote(@view, @thread) + + it "votes correctly", -> + DiscussionViewSpecHelper.checkVote(@view, @thread, @threadData, true) + + it "unvotes correctly", -> + DiscussionViewSpecHelper.checkUnvote(@view, @thread, @threadData, true) + + it "toggles the vote correctly", -> + DiscussionViewSpecHelper.checkToggleVote(@view, @thread) + + it "vote button activates on appropriate events", -> + DiscussionViewSpecHelper.checkVoteButtonEvents(@view) diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee new file mode 100644 index 0000000000..69e4b231a2 --- /dev/null +++ b/common/static/coffee/spec/discussion/view/discussion_thread_show_view_spec.coffee @@ -0,0 +1,40 @@ +describe "DiscussionThreadShowView", -> + beforeEach -> + setFixtures( + """ + + """ + ) + + @threadData = { + id: "dummy", + user_id: "567", + course_id: "TestOrg/TestCourse/TestRun", + body: "this is a thread", + created_at: "2013-04-03T20:08:39Z", + abuse_flaggers: [], + votes: {up_count: "42"} + } + @thread = new Thread(@threadData) + @view = new DiscussionThreadShowView({ model: @thread }) + @view.setElement($(".discussion-post")) + window.user = new DiscussionUser({id: "567", upvoted_ids: []}) + + it "renders the vote correctly", -> + DiscussionViewSpecHelper.checkRenderVote(@view, @thread) + + it "votes correctly", -> + DiscussionViewSpecHelper.checkVote(@view, @thread, @threadData, true) + + it "unvotes correctly", -> + DiscussionViewSpecHelper.checkUnvote(@view, @thread, @threadData, true) + + it 'toggles the vote correctly', -> + DiscussionViewSpecHelper.checkToggleVote(@view, @thread) + + it "vote button activates on appropriate events", -> + DiscussionViewSpecHelper.checkVoteButtonEvents(@view) diff --git a/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee b/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee new file mode 100644 index 0000000000..d5c25aa5e2 --- /dev/null +++ b/common/static/coffee/spec/discussion/view/discussion_view_spec_helper.coffee @@ -0,0 +1,113 @@ +class @DiscussionViewSpecHelper + @expectVoteRendered = (view, voted) -> + button = view.$el.find(".vote-btn") + if voted + expect(button.hasClass("is-cast")).toBe(true) + expect(button.attr("aria-pressed")).toEqual("true") + expect(button.attr("data-tooltip")).toEqual("remove vote") + expect(button.find(".votes-count-number").html()).toEqual("43") + expect(button.find(".sr").html()).toEqual("votes (click to remove your vote)") + else + expect(button.hasClass("is-cast")).toBe(false) + expect(button.attr("aria-pressed")).toEqual("false") + expect(button.attr("data-tooltip")).toEqual("vote") + expect(button.find(".votes-count-number").html()).toEqual("42") + expect(button.find(".sr").html()).toEqual("votes (click to vote)") + + @checkRenderVote = (view, model) -> + view.renderVote() + DiscussionViewSpecHelper.expectVoteRendered(view, false) + window.user.vote(model) + view.renderVote() + DiscussionViewSpecHelper.expectVoteRendered(view, true) + window.user.unvote(model) + view.renderVote() + DiscussionViewSpecHelper.expectVoteRendered(view, false) + + @checkVote = (view, model, modelData, checkRendering) -> + view.renderVote() + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, false) + + spyOn($, "ajax").andCallFake((params) => + newModelData = {} + $.extend(newModelData, modelData, {votes: {up_count: "43"}}) + params.success(newModelData, "success") + # Caller invokes always function on return value but it doesn't matter here + {always: ->} + ) + + view.vote() + expect(window.user.voted(model)).toBe(true) + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, true) + expect($.ajax).toHaveBeenCalled() + $.ajax.reset() + + # Check idempotence + view.vote() + expect(window.user.voted(model)).toBe(true) + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, true) + expect($.ajax).toHaveBeenCalled() + + @checkUnvote = (view, model, modelData, checkRendering) -> + window.user.vote(model) + expect(window.user.voted(model)).toBe(true) + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, true) + + spyOn($, "ajax").andCallFake((params) => + newModelData = {} + $.extend(newModelData, modelData, {votes: {up_count: "42"}}) + params.success(newModelData, "success") + # Caller invokes always function on return value but it doesn't matter here + {always: ->} + ) + + view.unvote() + expect(window.user.voted(model)).toBe(false) + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, false) + expect($.ajax).toHaveBeenCalled() + $.ajax.reset() + + # Check idempotence + view.unvote() + expect(window.user.voted(model)).toBe(false) + if checkRendering + DiscussionViewSpecHelper.expectVoteRendered(view, false) + expect($.ajax).toHaveBeenCalled() + + @checkToggleVote = (view, model) -> + event = {preventDefault: ->} + spyOn(event, "preventDefault") + spyOn(view, "vote").andCallFake(() -> window.user.vote(model)) + spyOn(view, "unvote").andCallFake(() -> window.user.unvote(model)) + + expect(window.user.voted(model)).toBe(false) + view.toggleVote(event) + expect(view.vote).toHaveBeenCalled() + expect(view.unvote).not.toHaveBeenCalled() + expect(event.preventDefault.callCount).toEqual(1) + + view.vote.reset() + view.unvote.reset() + expect(window.user.voted(model)).toBe(true) + view.toggleVote(event) + expect(view.vote).not.toHaveBeenCalled() + expect(view.unvote).toHaveBeenCalled() + expect(event.preventDefault.callCount).toEqual(2) + + @checkVoteButtonEvents = (view) -> + spyOn(view, "toggleVote") + button = view.$el.find(".vote-btn") + + button.click() + expect(view.toggleVote).toHaveBeenCalled() + view.toggleVote.reset() + button.trigger($.Event("keydown", {which: 13})) + expect(view.toggleVote).toHaveBeenCalled() + view.toggleVote.reset() + button.trigger($.Event("keydown", {which: 32})) + expect(view.toggleVote).not.toHaveBeenCalled() diff --git a/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee b/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee new file mode 100644 index 0000000000..7ba00c66d1 --- /dev/null +++ b/common/static/coffee/spec/discussion/view/thread_response_show_view_spec.coffee @@ -0,0 +1,40 @@ +describe "ThreadResponseShowView", -> + beforeEach -> + setFixtures( + """ + + """ + ) + + @commentData = { + id: "dummy", + user_id: "567", + course_id: "TestOrg/TestCourse/TestRun", + body: "this is a comment", + created_at: "2013-04-03T20:08:39Z", + abuse_flaggers: [], + votes: {up_count: "42"} + } + @comment = new Comment(@commentData) + @view = new ThreadResponseShowView({ model: @comment }) + @view.setElement($(".discussion-post")) + window.user = new DiscussionUser({id: "567", upvoted_ids: []}) + + it "renders the vote correctly", -> + DiscussionViewSpecHelper.checkRenderVote(@view, @comment) + + it "votes correctly", -> + DiscussionViewSpecHelper.checkVote(@view, @comment, @commentData, true) + + it "unvotes correctly", -> + DiscussionViewSpecHelper.checkUnvote(@view, @comment, @commentData, true) + + it 'toggles the vote correctly', -> + DiscussionViewSpecHelper.checkToggleVote(@view, @comment) + + it "vote button activates on appropriate events", -> + DiscussionViewSpecHelper.checkVoteButtonEvents(@view) diff --git a/common/static/coffee/src/discussion/content.coffee b/common/static/coffee/src/discussion/content.coffee index 23a31ae7e6..5e3d4ce20b 100644 --- a/common/static/coffee/src/discussion/content.coffee +++ b/common/static/coffee/src/discussion/content.coffee @@ -99,6 +99,13 @@ if Backbone? @get("abuse_flaggers").pop(window.user.get('id')) @trigger "change", @ + vote: -> + @get("votes")["up_count"] = parseInt(@get("votes")["up_count"]) + 1 + @trigger "change", @ + + unvote: -> + @get("votes")["up_count"] = parseInt(@get("votes")["up_count"]) - 1 + @trigger "change", @ class @Thread extends @Content urlMappers: @@ -130,14 +137,6 @@ if Backbone? unfollow: -> @set('subscribed', false) - vote: -> - @get("votes")["up_count"] = parseInt(@get("votes")["up_count"]) + 1 - @trigger "change", @ - - unvote: -> - @get("votes")["up_count"] = parseInt(@get("votes")["up_count"]) - 1 - @trigger "change", @ - display_body: -> if @has("highlighted_body") String(@get("highlighted_body")).replace(/${"<% if (obj.username) { %>"} @@ -123,7 +123,7 @@