Commit cb6bc3b0 by jsa Committed by E. Kolpakov

Copied test specs

parent 70067eb6
!view/discussion_thread_edit_view_spec.js
!view/discussion_topic_menu_view_spec.js
...@@ -6,10 +6,41 @@ class @DiscussionSpecHelper ...@@ -6,10 +6,41 @@ class @DiscussionSpecHelper
window.user = new DiscussionUser({username: "test_user", id: "567", upvoted_ids: []}) window.user = new DiscussionUser({username: "test_user", id: "567", upvoted_ids: []})
DiscussionUtil.setUser(window.user) DiscussionUtil.setUser(window.user)
@makeTA = () ->
DiscussionUtil.roleIds["Community TA"].push(parseInt(DiscussionUtil.getUser().id))
@makeModerator = () -> @makeModerator = () ->
DiscussionUtil.roleIds["Moderator"].push(parseInt(window.user.id)) DiscussionUtil.roleIds["Moderator"].push(parseInt(DiscussionUtil.getUser().id))
@makeAjaxSpy = (fakeAjax) ->
spyOn($, "ajax").andCallFake(
(params) ->
fakeAjax(params)
{always: ->}
)
@makeEventSpy = () ->
jasmine.createSpyObj('event', ['preventDefault', 'target'])
@makeCourseSettings = (is_cohorted=true) ->
new DiscussionCourseSettings(
category_map:
children: ['Test Topic', 'Other Topic']
entries:
'Test Topic':
is_cohorted: is_cohorted
id: 'test_topic'
'Other Topic':
is_cohorted: is_cohorted
id: 'other_topic'
is_cohorted: is_cohorted
)
@setUnderscoreFixtures = -> @setUnderscoreFixtures = ->
for templateName in ['thread-show']
templateFixture = readFixtures('templates/discussion/' + templateName + '.underscore')
appendSetFixtures($('<script>', { id: templateName + '-template', type: 'text/template' })
.text(templateFixture))
appendSetFixtures(""" appendSetFixtures("""
<div id="fixture-element"></div> <div id="fixture-element"></div>
...@@ -56,56 +87,10 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -56,56 +87,10 @@ browser and pasting the output. When that file changes, this one should be rege
</article> </article>
</script> </script>
<script aria-hidden="true" type="text/template" id="thread-show-template">
<div class="discussion-post">
<header>
<% if (obj.group_id) { %>
<div class="group-visibility-label"><%- obj.group_string%></div>
<% } %>
<div class="post-header-content">
<h1><%- title %></h1>
<p class="posted-details">
<%- thread_type %> posted <span class='timeago' title='<%- created_at %>'><%- created_at %></span> by <%= author_display %>
</p>
<div class="post-labels">
<span class="post-label-pinned"><i class="icon icon-pushpin"></i>Pinned</span>
<span class="post-label-reported"><i class="icon icon-flag"></i>Reported</span>
<span class="post-label-closed"><i class="icon icon-lock"></i>Closed</span>
</div>
</div>
<div class="post-header-actions post-extended-content">
<%=
_.template(
$('#forum-actions').html(),
{
contentId: cid,
contentType: 'post',
primaryActions: ['vote', 'follow'],
secondaryActions: ['pin', 'edit', 'delete', 'report', 'close']
}
)
%>
</div>
</header>
<div class="post-body"><%- body %></div>
<% if (mode == "tab" && obj.courseware_url) { %>
<div class="post-context"><%
var courseware_link = interpolate('<a href="%s">%s</a>', [courseware_url, _.escape(courseware_title)]);
print(interpolate('(this post is about %(courseware_title_linked)s)', {'courseware_title_linked': courseware_link}, true));
%></div>
<% } %>
</div>
</script>
<script aria-hidden="true" type="text/template" id="thread-edit-template"> <script aria-hidden="true" type="text/template" id="thread-edit-template">
<div class="discussion-post edit-post-form">
<h1>Editing post</h1> <h1>Editing post</h1>
<ul class="edit-post-form-errors"></ul> <ul class="edit-post-form-errors"></ul>
<div class="forum-edit-post-form-wrapper"></div>
<div class="form-row"> <div class="form-row">
<label class="sr" for="edit-post-title">Edit post title</label> <label class="sr" for="edit-post-title">Edit post title</label>
<input type="text" id="edit-post-title" class="edit-post-title" name="title" value="<%-title %>" placeholder="Title"> <input type="text" id="edit-post-title" class="edit-post-title" name="title" value="<%-title %>" placeholder="Title">
...@@ -115,7 +100,6 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -115,7 +100,6 @@ browser and pasting the output. When that file changes, this one should be rege
</div> </div>
<input type="submit" id="edit-post-submit" class="post-update" value="Update post"> <input type="submit" id="edit-post-submit" class="post-update" value="Update post">
<a href="#" class="post-cancel">Cancel</a> <a href="#" class="post-cancel">Cancel</a>
</div>
</script> </script>
<script aria-hidden="true" type="text/template" id="thread-response-template"> <script aria-hidden="true" type="text/template" id="thread-response-template">
...@@ -145,7 +129,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -145,7 +129,7 @@ browser and pasting the output. When that file changes, this one should be rege
<%= author_display %> <%= author_display %>
<p class="posted-details"> <p class="posted-details">
<span class="timeago" title="<%= created_at %>"><%= created_at %></span> <span class="timeago" title="<%= created_at %>"><%= created_at %></span>
<% if (obj.endorsement) { %> - <%= <% if (obj.endorsement) { %> - <%=
interpolate( interpolate(
thread.get("thread_type") == "question" ? thread.get("thread_type") == "question" ?
...@@ -206,7 +190,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -206,7 +190,7 @@ browser and pasting the output. When that file changes, this one should be rege
} }
) )
%> %>
<p class="posted-details"> <p class="posted-details">
<%= <%=
interpolate( interpolate(
...@@ -254,7 +238,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -254,7 +238,7 @@ browser and pasting the output. When that file changes, this one should be rege
<i class="icon <%= icon_class %>"></i> <i class="icon <%= icon_class %>"></i>
</div><div class="forum-nav-thread-wrapper-1"> </div><div class="forum-nav-thread-wrapper-1">
<span class="forum-nav-thread-title"><%- title %></span> <span class="forum-nav-thread-title"><%- title %></span>
<% <%
var labels = ""; var labels = "";
if (pinned) { if (pinned) {
...@@ -274,7 +258,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -274,7 +258,7 @@ browser and pasting the output. When that file changes, this one should be rege
} }
%> %>
</div><div class="forum-nav-thread-wrapper-2"> </div><div class="forum-nav-thread-wrapper-2">
<span class="forum-nav-thread-votes-count">+<%= <span class="forum-nav-thread-votes-count">+<%=
interpolate( interpolate(
'%(votes_up_count)s%(span_sr_open)s votes %(span_close)s', '%(votes_up_count)s%(span_sr_open)s votes %(span_close)s',
...@@ -282,7 +266,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -282,7 +266,7 @@ browser and pasting the output. When that file changes, this one should be rege
true true
) )
%></span> %></span>
<span class="forum-nav-thread-comments-count <% if (unread_comments_count > 0) { %>is-unread<% } %>"> <span class="forum-nav-thread-comments-count <% if (unread_comments_count > 0) { %>is-unread<% } %>">
<% <%
var fmt; var fmt;
...@@ -331,50 +315,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -331,50 +315,7 @@ browser and pasting the output. When that file changes, this one should be rege
<script aria-hidden="true" type="text/template" id="new-post-template"> <script aria-hidden="true" type="text/template" id="new-post-template">
<form class="forum-new-post-form"> <form class="forum-new-post-form">
<ul class="post-errors" style="display: none"></ul> <ul class="post-errors" style="display: none"></ul>
<div class="post-field"> <div class="forum-new-post-form-wrapper"></div>
<div class="field-label">
<span class="field-label-text">
Post type:
</span><fieldset class="field-input">
<input type="radio" name="<%= form_id %>-post-type" class="post-type-input" id="<%= form_id %>-post-type-question" value="question" checked>
<label for="<%= form_id %>-post-type-question" class="post-type-label">
<i class="icon icon-question"></i>
Question
</label>
<input type="radio" name="<%= form_id %>-post-type" class="post-type-input" id="<%= form_id %>-post-type-discussion" value="discussion">
<label for="<%= form_id %>-post-type-discussion" class="post-type-label">
<i class="icon icon-comments"></i>
Discussion
</label>
</fieldset>
</div><span class="field-help">
Questions raise issues that need answers. Discussions share ideas and start conversations.
</span>
</div>
<% if (mode=="tab") { %>
<div class="post-field">
<div class="field-label">
<span class="field-label-text">
Topic Area:
</span><div class="field-input post-topic">
<a href="#" class="post-topic-button">
<span class="sr">Discussion topics; current selection is: </span>
<span class="js-selected-topic"></span>
<span class="drop-arrow" aria-hidden="true">▾</span>
</a>
<div class="topic-menu-wrapper">
<label class="topic-filter-label">
<span class="sr">Filter topics</span>
<input type="text" class="topic-filter-input" placeholder="Filter topics">
</label>
<ul class="topic-menu" role="menu"><%= topics_html %></ul>
</div>
</div>
</div><span class="field-help">
Add your post to a relevant topic to help others find it.
</span>
</div>
<% } %>
<% if (cohort_options) { %> <% if (cohort_options) { %>
<div class="post-field"> <div class="post-field">
<label class="field-label"> <label class="field-label">
...@@ -387,7 +328,7 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -387,7 +328,7 @@ browser and pasting the output. When that file changes, this one should be rege
<% }); %> <% }); %>
</select> </select>
</label><div class="field-help"> </label><div class="field-help">
Instructors can set whether a post in a cohorted topic is visible to all cohorts or only to a specific cohort. Discussion admins, moderators, and TAs can make their posts visible to all students or specify a single cohort group.
</div> </div>
</div> </div>
<% } %> <% } %>
...@@ -425,6 +366,29 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -425,6 +366,29 @@ browser and pasting the output. When that file changes, this one should be rege
</form> </form>
</script> </script>
<script aria-hidden="true" type="text/template" id="thread-type-template">
<div class="post-field">
<div class="field-label">
<span class="field-label-text">
"Post type:"
</span><fieldset class="field-input">
<input type="radio" name="<%= form_id %>-post-type" class="post-type-input" id="<%= form_id %>-post-type-question" value="question" checked>
<label for="<%= form_id %>-post-type-question" class="post-type-label">
<i class="icon icon-question"></i>
"Question"
</label>
<input type="radio" name="<%= form_id %>-post-type" class="post-type-input" id="<%= form_id %>-post-type-discussion" value="discussion">
<label for="<%= form_id %>-post-type-discussion" class="post-type-label">
<i class="icon icon-comments"></i>
"Discussion"
</label>
</fieldset>
</div><span class="field-help">
"Questions raise issues that need answers. Discussions share ideas and start conversations."
</span>
</div>
</script>
<script aria-hidden="true" type="text/template" id="new-post-menu-entry-template"> <script aria-hidden="true" type="text/template" id="new-post-menu-entry-template">
<li role="menuitem" class="topic-menu-item"> <li role="menuitem" class="topic-menu-item">
<a href="#" class="topic-title" data-discussion-id="<%- id %>" data-cohorted="<%- is_cohorted %>"><%- text %></a> <a href="#" class="topic-title" data-discussion-id="<%- id %>" data-cohorted="<%- is_cohorted %>"><%- text %></a>
...@@ -438,6 +402,27 @@ browser and pasting the output. When that file changes, this one should be rege ...@@ -438,6 +402,27 @@ browser and pasting the output. When that file changes, this one should be rege
</li> </li>
</script> </script>
<script aria-hidden="true" type="text/template" id="topic-template">
<div class="field-label">
<span class="field-label-text">Topic Area:</span><div class="field-input post-topic">
<a href="#" class="post-topic-button">
<span class="sr">Discussion topics; current selection is: </span>
<span class="js-selected-topic"></span>
<span class="drop-arrow" aria-hidden="true">▾</span>
</a>
<div class="topic-menu-wrapper">
<label class="topic-filter-label">
<span class="sr">Filter topics</span>
<input type="text" class="topic-filter-input" placeholder="Filter topics">
</label>
<ul class="topic-menu" role="menu"><%= topics_html %></ul>
</div>
</div>
</div><span class="field-help">
Add your post to a relevant topic to help others find it.
</span>
</script>
......
...@@ -2,75 +2,8 @@ describe "DiscussionThreadListView", -> ...@@ -2,75 +2,8 @@ describe "DiscussionThreadListView", ->
beforeEach -> beforeEach ->
DiscussionSpecHelper.setUpGlobals() DiscussionSpecHelper.setUpGlobals()
setFixtures """ DiscussionSpecHelper.setUnderscoreFixtures()
<script type="text/template" id="thread-list-item-template"> appendSetFixtures("""
<li data-id="<%- id %>" class="forum-nav-thread<% if (typeof(read) != "undefined" && !read) { %> is-unread<% } %>">
<a href="#" class="forum-nav-thread-link">
<div class="forum-nav-thread-wrapper-0">
<%
var icon_class, sr_text;
if (thread_type == "discussion") {
icon_class = "icon-comments";
sr_text = "discussion";
} else if (endorsed) {
icon_class = "icon-ok";
sr_text = "answered question";
} else {
icon_class = "icon-question";
sr_text = "unanswered question";
}
%>
<span class="sr"><%= sr_text %></span>
<i class="icon <%= icon_class %>"></i>
</div><div class="forum-nav-thread-wrapper-1">
<span class="forum-nav-thread-title"><%- title %></span>
<%
var labels = "";
if (pinned) {
labels += '<li class="forum-nav-thread-label-pinned"><i class="icon icon-pushpin"></i>Pinned</li> ';
}
if (typeof(subscribed) != "undefined" && subscribed) {
labels += '<li class="forum-nav-thread-label-following"><i class="icon icon-star"></i>Following</li> ';
}
if (staff_authored) {
labels += '<li class="forum-nav-thread-label-staff"><i class="icon icon-user"></i>By: Staff</li> ';
}
if (community_ta_authored) {
labels += '<li class="forum-nav-thread-label-community-ta"><i class="icon icon-user"></i>By: Community TA</li> ';
}
if (labels != "") {
print('<ul class="forum-nav-thread-labels">' + labels + '</ul>');
}
%>
</div><div class="forum-nav-thread-wrapper-2">
<span class="forum-nav-thread-votes-count">+<%=
interpolate(
'%(votes_up_count)s%(span_sr_open)s votes %(span_close)s',
{'span_sr_open': '<span class="sr">', 'span_close': '</span>', 'votes_up_count': votes['up_count']},
true
)
%></span>
<span class="forum-nav-thread-comments-count <% if (unread_comments_count > 0) { %>is-unread<% } %>">
<%
var fmt;
var data = {
'span_sr_open': '<span class="sr">',
'span_close': '</span>',
'unread_comments_count': unread_comments_count,
'comments_count': comments_count
};
if (unread_comments_count > 0) {
fmt = '%(comments_count)s %(span_sr_open)scomments (%(unread_comments_count)s unread comments)%(span_close)s';
} else {
fmt = '%(comments_count)s %(span_sr_open)scomments %(span_close)s';
}
print(interpolate(fmt, data, true));
%>
</span>
</div>
</a>
</li>
</script>
<script type="text/template" id="thread-list-template"> <script type="text/template" id="thread-list-template">
<div class="forum-nav-header"> <div class="forum-nav-header">
<a href="#" class="forum-nav-browse" aria-haspopup="true"> <a href="#" class="forum-nav-browse" aria-haspopup="true">
...@@ -83,6 +16,7 @@ describe "DiscussionThreadListView", -> ...@@ -83,6 +16,7 @@ describe "DiscussionThreadListView", ->
<label> <label>
<span class="sr">Search</span> <span class="sr">Search</span>
<input class="forum-nav-search-input" type="text" placeholder="Search all posts"> <input class="forum-nav-search-input" type="text" placeholder="Search all posts">
<i class="icon icon-search"></i>
</label> </label>
</form> </form>
</div> </div>
...@@ -126,7 +60,7 @@ describe "DiscussionThreadListView", -> ...@@ -126,7 +60,7 @@ describe "DiscussionThreadListView", ->
<li <li
class="forum-nav-browse-menu-item" class="forum-nav-browse-menu-item"
data-discussion-id="other" data-discussion-id="other"
data-cohorted="false" data-cohorted="true"
> >
<a href="#" class="forum-nav-browse-title">Other Category</a> <a href="#" class="forum-nav-browse-title">Other Category</a>
</li> </li>
...@@ -142,6 +76,16 @@ describe "DiscussionThreadListView", -> ...@@ -142,6 +76,16 @@ describe "DiscussionThreadListView", ->
<option value="flagged">Flagged</option> <option value="flagged">Flagged</option>
</select> </select>
</label> </label>
<% if (isCohorted && isPrivilegedUser) { %>
<label class="forum-nav-filter-cohort">
<span class="sr">Cohort:</span>
<select class="forum-nav-filter-cohort-control">
<option value="">in all cohorts</option>
<option value="1">Cohort1</option>
<option value="2">Cohort2</option>
</select>
</label>
<% } %>
<label class="forum-nav-sort"> <label class="forum-nav-sort">
<select class="forum-nav-sort-control"> <select class="forum-nav-sort-control">
<option value="date">by recent activity</option> <option value="date">by recent activity</option>
...@@ -154,24 +98,13 @@ describe "DiscussionThreadListView", -> ...@@ -154,24 +98,13 @@ describe "DiscussionThreadListView", ->
<div class="search-alerts"></div> <div class="search-alerts"></div>
<ul class="forum-nav-thread-list"></ul> <ul class="forum-nav-thread-list"></ul>
</script> </script>
<script aria-hidden="true" type="text/template" id="search-alert-template"> """)
<div class="search-alert" id="search-alert-<%- cid %>">
<div class="search-alert-content">
<p class="message"><%- message %></p>
</div>
<div class="search-alert-controls">
<a href="#" class="dismiss control control-dismiss"><i class="icon icon-remove"></i></a>
</div>
</div>
</script>
<div class="forum-nav"></div>
"""
@threads = [ @threads = [
DiscussionViewSpecHelper.makeThreadWithProps({ DiscussionViewSpecHelper.makeThreadWithProps({
id: "1", id: "1",
title: "Thread1", title: "Thread1",
votes: {up_count: '20'}, votes: {up_count: '20'},
pinned: true,
comments_count: 1, comments_count: 1,
created_at: '2013-04-03T20:08:39Z', created_at: '2013-04-03T20:08:39Z',
}), }),
...@@ -189,21 +122,43 @@ describe "DiscussionThreadListView", -> ...@@ -189,21 +122,43 @@ describe "DiscussionThreadListView", ->
comments_count: 3, comments_count: 3,
created_at: '2013-04-03T20:06:39Z', created_at: '2013-04-03T20:06:39Z',
}), }),
DiscussionViewSpecHelper.makeThreadWithProps({
id: "4",
title: "Thread4",
votes: {up_count: '25'},
comments_count: 0,
pinned: true,
created_at: '2013-04-03T20:05:39Z',
}),
] ]
spyOn($, "ajax") spyOn($, "ajax")
@discussion = new Discussion([]) @discussion = new Discussion([])
@view = new DiscussionThreadListView({collection: @discussion, el: $(".forum-nav")}) @view = new DiscussionThreadListView(
collection: @discussion,
el: $("#fixture-element"),
courseSettings: new DiscussionCourseSettings({is_cohorted: true})
)
@view.render() @view.render()
setupAjax = (callback) ->
$.ajax.andCallFake(
(params) =>
if callback
callback(params)
params.success({discussion_data: [], page: 1, num_pages: 1})
{always: ->}
)
renderSingleThreadWithProps = (props) -> renderSingleThreadWithProps = (props) ->
makeView(new Discussion([new Thread(DiscussionViewSpecHelper.makeThreadWithProps(props))])).render() makeView(new Discussion([new Thread(DiscussionViewSpecHelper.makeThreadWithProps(props))])).render()
makeView = (discussion) -> makeView = (discussion) ->
return new DiscussionThreadListView( return new DiscussionThreadListView(
el: $(".forum-nav"), el: $("#fixture-element"),
collection: discussion collection: discussion,
courseSettings: new DiscussionCourseSettings({is_cohorted: true})
) )
expectFilter = (filterVal) -> expectFilter = (filterVal) ->
...@@ -225,6 +180,28 @@ describe "DiscussionThreadListView", -> ...@@ -225,6 +180,28 @@ describe "DiscussionThreadListView", ->
expect($.ajax).toHaveBeenCalled() expect($.ajax).toHaveBeenCalled()
) )
describe "cohort selector", ->
it "should not be visible to students", ->
expect(@view.$(".forum-nav-filter-cohort-control:visible")).not.toExist()
it "should allow moderators to select visibility", ->
DiscussionSpecHelper.makeModerator()
@view.render()
expectedGroupId = null
setupAjax((params) => expect(params.data.group_id).toEqual(expectedGroupId))
_.each(
[
{val: "", expectedGroupId: undefined},
{val: "1", expectedGroupId: "1"},
{val: "2", expectedGroupId: "2"}
],
(optionInfo) =>
expectedGroupId = optionInfo.expectedGroupId
@view.$(".forum-nav-filter-cohort-control").val(optionInfo.val).change()
expect($.ajax).toHaveBeenCalled()
$.ajax.reset()
)
it "search should clear filter", -> it "search should clear filter", ->
expectFilter(null) expectFilter(null)
@view.$(".forum-nav-filter-main-control").val("flagged") @view.$(".forum-nav-filter-main-control").val("flagged")
...@@ -232,10 +209,11 @@ describe "DiscussionThreadListView", -> ...@@ -232,10 +209,11 @@ describe "DiscussionThreadListView", ->
expect(@view.$(".forum-nav-filter-main-control").val()).toEqual("all") expect(@view.$(".forum-nav-filter-main-control").val()).toEqual("all")
checkThreadsOrdering = (view, sort_order, type) -> checkThreadsOrdering = (view, sort_order, type) ->
expect(view.$el.find(".forum-nav-thread").children().length).toEqual(3) expect(view.$el.find(".forum-nav-thread").children().length).toEqual(4)
expect(view.$el.find(".forum-nav-thread:nth-child(1) .forum-nav-thread-title").text()).toEqual(sort_order[0]) expect(view.$el.find(".forum-nav-thread:nth-child(1) .forum-nav-thread-title").text()).toEqual(sort_order[0])
expect(view.$el.find(".forum-nav-thread:nth-child(2) .forum-nav-thread-title").text()).toEqual(sort_order[1]) expect(view.$el.find(".forum-nav-thread:nth-child(2) .forum-nav-thread-title").text()).toEqual(sort_order[1])
expect(view.$el.find(".forum-nav-thread:nth-child(3) .forum-nav-thread-title").text()).toEqual(sort_order[2]) expect(view.$el.find(".forum-nav-thread:nth-child(3) .forum-nav-thread-title").text()).toEqual(sort_order[2])
expect(view.$el.find(".forum-nav-thread:nth-child(4) .forum-nav-thread-title").text()).toEqual(sort_order[3])
expect(view.$el.find(".forum-nav-sort-control").val()).toEqual(type) expect(view.$el.find(".forum-nav-sort-control").val()).toEqual(type)
describe "thread rendering should be correct", -> describe "thread rendering should be correct", ->
...@@ -244,17 +222,17 @@ describe "DiscussionThreadListView", -> ...@@ -244,17 +222,17 @@ describe "DiscussionThreadListView", ->
view = makeView(discussion) view = makeView(discussion)
view.render() view.render()
checkThreadsOrdering(view, sort_order, type) checkThreadsOrdering(view, sort_order, type)
expect(view.$el.find(".forum-nav-thread-comments-count:visible").length).toEqual(if type == "votes" then 0 else 3) expect(view.$el.find(".forum-nav-thread-comments-count:visible").length).toEqual(if type == "votes" then 0 else 4)
expect(view.$el.find(".forum-nav-thread-votes-count:visible").length).toEqual(if type == "votes" then 3 else 0) expect(view.$el.find(".forum-nav-thread-votes-count:visible").length).toEqual(if type == "votes" then 4 else 0)
it "with sort preference date", -> it "with sort preference date", ->
checkRender(@threads, "date", [ "Thread1", "Thread2", "Thread3"]) checkRender(@threads, "date", ["Thread1", "Thread4", "Thread2", "Thread3"])
it "with sort preference votes", -> it "with sort preference votes", ->
checkRender(@threads, "votes", [ "Thread2", "Thread1", "Thread3"]) checkRender(@threads, "votes", ["Thread4", "Thread1", "Thread2", "Thread3"])
it "with sort preference comments", -> it "with sort preference comments", ->
checkRender(@threads, "comments", [ "Thread3", "Thread2", "Thread1"]) checkRender(@threads, "comments", ["Thread1", "Thread4", "Thread3", "Thread2"])
describe "Sort change should be correct", -> describe "Sort change should be correct", ->
changeSorting = (threads, selected_type, new_type, sort_order) -> changeSorting = (threads, selected_type, new_type, sort_order) ->
...@@ -265,11 +243,11 @@ describe "DiscussionThreadListView", -> ...@@ -265,11 +243,11 @@ describe "DiscussionThreadListView", ->
expect(sortControl.val()).toEqual(selected_type) expect(sortControl.val()).toEqual(selected_type)
sorted_threads = [] sorted_threads = []
if new_type == 'date' if new_type == 'date'
sorted_threads = [threads[0], threads[1], threads[2]] sorted_threads = [threads[0], threads[3], threads[1], threads[2]]
else if new_type == 'comments' else if new_type == 'comments'
sorted_threads = [threads[2], threads[1], threads[0]] sorted_threads = [threads[0], threads[3], threads[2], threads[1]]
else if new_type == 'votes' else if new_type == 'votes'
sorted_threads = [threads[1], threads[0], threads[2]] sorted_threads = [threads[3], threads[0], threads[1], threads[2]]
$.ajax.andCallFake((params) => $.ajax.andCallFake((params) =>
params.success( params.success(
{"discussion_data":sorted_threads, page:1, num_pages:1} {"discussion_data":sorted_threads, page:1, num_pages:1}
...@@ -281,13 +259,13 @@ describe "DiscussionThreadListView", -> ...@@ -281,13 +259,13 @@ describe "DiscussionThreadListView", ->
checkThreadsOrdering(view, sort_order, new_type) checkThreadsOrdering(view, sort_order, new_type)
it "with sort preference date", -> it "with sort preference date", ->
changeSorting(@threads, "comments", "date", ["Thread1", "Thread2", "Thread3"]) changeSorting(@threads, "comments", "date", ["Thread1", "Thread4", "Thread2", "Thread3"])
it "with sort preference votes", -> it "with sort preference votes", ->
changeSorting(@threads, "date", "votes", ["Thread2", "Thread1", "Thread3"]) changeSorting(@threads, "date", "votes", ["Thread4", "Thread1", "Thread2", "Thread3"])
it "with sort preference comments", -> it "with sort preference comments", ->
changeSorting(@threads, "votes", "comments", ["Thread3", "Thread2", "Thread1"]) changeSorting(@threads, "votes", "comments", ["Thread1", "Thread4", "Thread3", "Thread2"])
describe "search alerts", -> describe "search alerts", ->
...@@ -354,6 +332,20 @@ describe "DiscussionThreadListView", -> ...@@ -354,6 +332,20 @@ describe "DiscussionThreadListView", ->
@view.collection.trigger("change", new Thread({id: 1})) @view.collection.trigger("change", new Thread({id: 1}))
expect(@view.clearSearchAlerts).toHaveBeenCalled() expect(@view.clearSearchAlerts).toHaveBeenCalled()
describe "Search events", ->
it "perform search when enter pressed inside search textfield", ->
setupAjax()
spyOn(@view, "searchFor")
@view.$el.find(".forum-nav-search-input").trigger($.Event("keydown", {which: 13}))
expect(@view.searchFor).toHaveBeenCalled()
it "perform search when search icon is clicked", ->
setupAjax()
spyOn(@view, "searchFor")
@view.$el.find(".icon-search").click()
expect(@view.searchFor).toHaveBeenCalled()
describe "username search", -> describe "username search", ->
it "makes correct ajax calls", -> it "makes correct ajax calls", ->
...@@ -444,38 +436,29 @@ describe "DiscussionThreadListView", -> ...@@ -444,38 +436,29 @@ describe "DiscussionThreadListView", ->
it "for pinned", -> it "for pinned", ->
renderSingleThreadWithProps({pinned: true}) renderSingleThreadWithProps({pinned: true})
expect($(".forum-nav-thread-label-pinned").length).toEqual(1) expect($(".post-label-pinned").length).toEqual(1)
it "for following", -> it "for following", ->
renderSingleThreadWithProps({subscribed: true}) renderSingleThreadWithProps({subscribed: true})
expect($(".forum-nav-thread-label-following").length).toEqual(1) expect($(".post-label-following").length).toEqual(1)
it "for moderator", -> it "for moderator", ->
renderSingleThreadWithProps({user_id: @moderatorId}) renderSingleThreadWithProps({user_id: @moderatorId})
expect($(".forum-nav-thread-label-staff").length).toEqual(1) expect($(".post-label-by-staff").length).toEqual(1)
it "for administrator", -> it "for administrator", ->
renderSingleThreadWithProps({user_id: @administratorId}) renderSingleThreadWithProps({user_id: @administratorId})
expect($(".forum-nav-thread-label-staff").length).toEqual(1) expect($(".post-label-by-staff").length).toEqual(1)
it "for community TA", -> it "for community TA", ->
renderSingleThreadWithProps({user_id: @communityTaId}) renderSingleThreadWithProps({user_id: @communityTaId})
expect($(".forum-nav-thread-label-community-ta").length).toEqual(1) expect($(".post-label-by-community-ta").length).toEqual(1)
it "when none should be present", -> it "when none should be present", ->
renderSingleThreadWithProps({}) renderSingleThreadWithProps({})
expect($(".forum-nav-thread-labels").length).toEqual(0) expect($(".forum-nav-thread-labels").length).toEqual(0)
describe "browse menu", -> describe "browse menu", ->
setupAjax = (callback) ->
$.ajax.andCallFake(
(params) =>
if callback
callback(params)
params.success({discussion_data: [], page: 1, num_pages: 1})
{always: ->}
)
afterEach -> afterEach ->
# Remove handler added to make browse menu disappear # Remove handler added to make browse menu disappear
$("body").unbind("click") $("body").unbind("click")
...@@ -551,9 +534,30 @@ describe "DiscussionThreadListView", -> ...@@ -551,9 +534,30 @@ describe "DiscussionThreadListView", ->
$(".forum-nav-browse-menu-following .forum-nav-browse-title").click() $(".forum-nav-browse-menu-following .forum-nav-browse-title").click()
expect($(".forum-nav-browse-current").text()).toEqual("Posts I'm Following") expect($(".forum-nav-browse-current").text()).toEqual("Posts I'm Following")
it "should show/hide the cohort selector", ->
DiscussionSpecHelper.makeModerator()
@view.render()
setupAjax()
_.each(
[
{selector: ".forum-nav-browse-menu-all", cohortVisibility: true},
{selector: ".forum-nav-browse-menu-following", cohortVisibility: false},
{
selector: ".forum-nav-browse-menu-item:has(.forum-nav-browse-menu-item .forum-nav-browse-menu-item)",
cohortVisibility: false
},
{selector: "[data-discussion-id=child]", cohortVisibility: false},
{selector: "[data-discussion-id=other]", cohortVisibility: true}
],
(itemInfo) =>
@view.$("#{itemInfo.selector} > .forum-nav-browse-title").click()
expect(@view.$(".forum-nav-filter-cohort").is(":visible")).toEqual(itemInfo.cohortVisibility)
)
testSelectionRequest = (callback, itemText) -> testSelectionRequest = (callback, itemText) ->
setupAjax(callback) setupAjax(callback)
$(".forum-nav-browse-title:contains(#{itemText})").click() $(".forum-nav-browse-title:contains(#{itemText})").click()
expect($.ajax).toHaveBeenCalled()
it "should get all discussions", -> it "should get all discussions", ->
testSelectionRequest( testSelectionRequest(
...@@ -561,15 +565,6 @@ describe "DiscussionThreadListView", -> ...@@ -561,15 +565,6 @@ describe "DiscussionThreadListView", ->
"All" "All"
) )
it "should get flagged threads", ->
testSelectionRequest(
(params) ->
expect(params.url.path()).toEqual(DiscussionUtil.urlFor("search"))
expect(params.data.flagged).toEqual(true)
,
"Flagged"
)
it "should get followed threads", -> it "should get followed threads", ->
testSelectionRequest( testSelectionRequest(
(params) -> (params) ->
...@@ -579,6 +574,7 @@ describe "DiscussionThreadListView", -> ...@@ -579,6 +574,7 @@ describe "DiscussionThreadListView", ->
, ,
"Following" "Following"
) )
expect($.ajax.mostRecentCall.args[0].data.group_id).toBeUndefined();
it "should get threads for the selected leaf", -> it "should get threads for the selected leaf", ->
testSelectionRequest( testSelectionRequest(
......
...@@ -142,3 +142,18 @@ describe "DiscussionThreadShowView", -> ...@@ -142,3 +142,18 @@ describe "DiscussionThreadShowView", ->
$el = $('#fixture-element').html(@view.getAuthorDisplay()) $el = $('#fixture-element').html(@view.getAuthorDisplay())
expect($el.find('a.username').length).toEqual(0) expect($el.find('a.username').length).toEqual(0)
expect($el.text()).toMatch(/^(\s*)anonymous(\s*)$/) expect($el.text()).toMatch(/^(\s*)anonymous(\s*)$/)
describe "cohorting", ->
it "renders correctly for an uncohorted thread", ->
@view.render()
expect(@view.$('.group-visibility-label').text().trim()).toEqual(
'This post is visible to everyone.'
)
it "renders correctly for a cohorted thread", ->
@thread.set('group_id', '1')
@thread.set('group_name', 'Mock Cohort')
@view.render()
expect(@view.$('.group-visibility-label').text().trim()).toEqual(
'This post is visible only to Mock Cohort.'
)
...@@ -6,10 +6,12 @@ describe "DiscussionThreadView", -> ...@@ -6,10 +6,12 @@ describe "DiscussionThreadView", ->
jasmine.Clock.useMock() jasmine.Clock.useMock()
@threadData = DiscussionViewSpecHelper.makeThreadWithProps({}) @threadData = DiscussionViewSpecHelper.makeThreadWithProps({})
@thread = new Thread(@threadData) @thread = new Thread(@threadData)
@discussion = new Discussion(@thread)
spyOn($, "ajax") spyOn($, "ajax")
# Avoid unnecessary boilerplate # Avoid unnecessary boilerplate
spyOn(DiscussionThreadShowView.prototype, "convertMath") spyOn(DiscussionThreadShowView.prototype, "convertMath")
spyOn(DiscussionContentView.prototype, "makeWmdEditor") spyOn(DiscussionContentView.prototype, "makeWmdEditor")
spyOn(DiscussionUtil, "makeWmdEditor")
spyOn(ThreadResponseView.prototype, "renderShowView") spyOn(ThreadResponseView.prototype, "renderShowView")
renderWithContent = (view, content) -> renderWithContent = (view, content) ->
...@@ -40,9 +42,46 @@ describe "DiscussionThreadView", -> ...@@ -40,9 +42,46 @@ describe "DiscussionThreadView", ->
else else
expect(view.$el.find(".load-response-button").length).toEqual(0) expect(view.$el.find(".load-response-button").length).toEqual(0)
describe "closed and open Threads", ->
checkCommentForm = (originallyClosed, mode) ->
threadData = DiscussionViewSpecHelper.makeThreadWithProps({closed: originallyClosed})
thread = new Thread(threadData)
discussion = new Discussion(thread)
view = new DiscussionThreadView(
model: thread
el: $("#fixture-element")
mode: mode
course_settings: DiscussionSpecHelper.makeCourseSettings()
)
renderWithContent(view, {resp_total: 1, children: [{}]})
if mode == "inline"
view.expand()
spyOn(DiscussionUtil, "updateWithUndo").andCallFake(
(model, updates, safeAjaxParams, errorMsg) ->
model.set(updates)
)
expect(view.$('.comment-form').closest('li').is(":visible")).toBe(not originallyClosed)
expect(view.$(".discussion-reply-new").is(":visible")).toBe(not originallyClosed)
view.$(".action-close").click()
expect(view.$('.comment-form').closest('li').is(":visible")).toBe(originallyClosed)
expect(view.$(".discussion-reply-new").is(":visible")).toBe(originallyClosed)
_.each(["tab", "inline"], (mode) =>
it 'Test that in #{mode} mode when a closed thread is opened the comment form is displayed', ->
checkCommentForm(true, mode)
it 'Test that in #{mode} mode when a open thread is closed the comment form is hidden', ->
checkCommentForm(false, mode)
)
describe "tab mode", -> describe "tab mode", ->
beforeEach -> beforeEach ->
@view = new DiscussionThreadView({ model: @thread, el: $("#fixture-element"), mode: "tab"}) @view = new DiscussionThreadView(
model: @thread
el: $("#fixture-element")
mode: "tab"
course_settings: DiscussionSpecHelper.makeCourseSettings()
)
describe "response count and pagination", -> describe "response count and pagination", ->
it "correctly render for a thread with no responses", -> it "correctly render for a thread with no responses", ->
...@@ -83,7 +122,12 @@ describe "DiscussionThreadView", -> ...@@ -83,7 +122,12 @@ describe "DiscussionThreadView", ->
describe "inline mode", -> describe "inline mode", ->
beforeEach -> beforeEach ->
@view = new DiscussionThreadView({ model: @thread, el: $("#fixture-element"), mode: "inline"}) @view = new DiscussionThreadView(
model: @thread
el: $("#fixture-element")
mode: "inline"
course_settings: DiscussionSpecHelper.makeCourseSettings()
)
describe "render", -> describe "render", ->
it "shows content that should be visible when collapsed", -> it "shows content that should be visible when collapsed", ->
...@@ -150,11 +194,26 @@ describe "DiscussionThreadView", -> ...@@ -150,11 +194,26 @@ describe "DiscussionThreadView", ->
expect($(".post-body").text()).toEqual(maliciousAbbreviation) expect($(".post-body").text()).toEqual(maliciousAbbreviation)
expect($(".post-body").html()).not.toContain("<script") expect($(".post-body").html()).not.toContain("<script")
it "re-renders the show view correctly when leaving the edit view", ->
DiscussionViewSpecHelper.setNextResponseContent({resp_total: 0, children: []})
@view.render()
@view.expand()
assertExpandedContentVisible(@view, true)
@view.edit()
assertContentVisible(@view, ".edit-post-body", true)
expect(@view.$el.find(".post-actions-list").length).toBe(0)
@view.closeEditView(DiscussionSpecHelper.makeEventSpy())
expect(@view.$el.find(".edit-post-body").length).toBe(0)
assertContentVisible(@view, ".post-actions-list", true)
describe "for question threads", -> describe "for question threads", ->
beforeEach -> beforeEach ->
@thread.set("thread_type", "question") @thread.set("thread_type", "question")
@view = new DiscussionThreadView( @view = new DiscussionThreadView(
{model: @thread, el: $("#fixture-element"), mode: "tab"} model: @thread
el: $("#fixture-element")
mode: "tab"
course_settings: DiscussionSpecHelper.makeCourseSettings()
) )
renderTestCase = (view, numEndorsed, numNonEndorsed) -> renderTestCase = (view, numEndorsed, numNonEndorsed) ->
......
(function() {
'use strict';
describe('DiscussionTopicMenuView', function() {
beforeEach(function() {
this.createTopicView = function (options) {
options = _.extend({
course_settings: this.course_settings,
topicId: void 0
}, options);
this.view = new DiscussionTopicMenuView(options);
this.view.render().appendTo('#fixture-element');
this.defaultTextWidth = this.view.getNameWidth(this.completeText);
};
this.openMenu = function () {
var menuWrapper = this.view.$('.topic-menu-wrapper');
expect(menuWrapper).toBeHidden();
this.view.$el.find('.post-topic-button').first().click();
expect(menuWrapper).toBeVisible();
};
this.closeMenu = function () {
var menuWrapper = this.view.$('.topic-menu-wrapper');
expect(menuWrapper).toBeVisible();
this.view.$el.find('.post-topic-button').first().click();
expect(menuWrapper).toBeHidden();
};
DiscussionSpecHelper.setUpGlobals();
DiscussionSpecHelper.setUnderscoreFixtures();
this.course_settings = new DiscussionCourseSettings({
'category_map': {
'subcategories': {
'Basic Question Types': {
'subcategories': {},
'children': ['Selection From Options', 'Numerical Input'],
'entries': {
'Selection From Options': {
'sort_key': null,
'is_cohorted': true,
'id': 'cba3e4cd91d0466b9ac50926e495b76f'
},
'Numerical Input': {
'sort_key': null,
'is_cohorted': false,
'id': 'c49f0dfb8fc94c9c8d9999cc95190c56'
}
}
}
},
'children': ['Basic Question Types'],
'entries': {}
},
'is_cohorted': true
});
this.parentCategoryText = 'Basic Question Types';
this.selectedOptionText = 'Selection From Options';
this.completeText = this.parentCategoryText + ' / ' + this.selectedOptionText;
});
it('completely show parent category and sub-category', function() {
var dropdownText;
this.createTopicView();
this.view.maxNameWidth = this.defaultTextWidth + 1;
this.view.$el.find('a.topic-title').first().click();
dropdownText = this.view.$el.find('.js-selected-topic').text();
expect(this.completeText).toEqual(dropdownText);
});
it('completely show just sub-category', function() {
var dropdownText;
this.createTopicView();
this.view.maxNameWidth = this.defaultTextWidth - 10;
this.view.$el.find('a.topic-title').first().click();
dropdownText = this.view.$el.find('.js-selected-topic').text();
expect(dropdownText.indexOf('…')).toEqual(0);
expect(dropdownText).toContain(this.selectedOptionText);
});
it('partially show sub-category', function() {
this.createTopicView();
var parentWidth = this.view.getNameWidth(this.parentCategoryText),
dropdownText;
this.view.maxNameWidth = this.defaultTextWidth - parentWidth;
this.view.$el.find('a.topic-title').first().click();
dropdownText = this.view.$el.find('.js-selected-topic').text();
expect(dropdownText.indexOf('…')).toEqual(0);
expect(dropdownText.lastIndexOf('…')).toBeGreaterThan(0);
});
it('broken span doesn\'t occur', function() {
var dropdownText;
this.createTopicView();
this.view.maxNameWidth = this.view.getNameWidth(this.selectedOptionText) + 100;
this.view.$el.find('a.topic-title').first().click();
dropdownText = this.view.$el.find('.js-selected-topic').text();
expect(dropdownText.indexOf('/ span>')).toEqual(-1);
});
it('appropriate topic is selected if `topicId` is passed', function () {
var completeText = this.parentCategoryText + ' / Numerical Input',
dropdownText;
this.createTopicView({
topicId: 'c49f0dfb8fc94c9c8d9999cc95190c56'
});
this.view.maxNameWidth = this.defaultTextWidth + 1;
this.view.render();
dropdownText = this.view.$el.find('.js-selected-topic').text();
expect(completeText).toEqual(dropdownText);
});
it('click outside of the dropdown close it', function () {
this.createTopicView();
this.openMenu();
$(document.body).click();
expect(this.view.$('.topic-menu-wrapper')).toBeHidden();
});
it('can toggle the menu', function () {
this.createTopicView();
this.openMenu();
this.closeMenu();
});
});
}).call(this);
...@@ -7,6 +7,7 @@ class @DiscussionViewSpecHelper ...@@ -7,6 +7,7 @@ class @DiscussionViewSpecHelper
pinned: false, pinned: false,
endorsed: false, endorsed: false,
votes: {up_count: '0'}, votes: {up_count: '0'},
read: false,
unread_comments_count: 0, unread_comments_count: 0,
comments_count: 0, comments_count: 0,
abuse_flaggers: [], abuse_flaggers: [],
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
describe "NewPostView", -> describe "NewPostView", ->
beforeEach -> beforeEach ->
setFixtures( DiscussionSpecHelper.setUpGlobals()
""" DiscussionSpecHelper.setUnderscoreFixtures()
<div class="discussion-body">
<div class="discussion-column">
<article class="new-post-article" style="display: block;"></article>
</div>
</div>
<script aria-hidden="true" type="text/template" id="new-post-template">
<form class="forum-new-post-form">
<% if (mode=="tab") { %>
<div class="post-field">
<div class="field-label">
<span class="field-label-text">
Topic Area:
</span>
<div class="field-input post-topic">
<a href="#" class="post-topic-button">
<span class="sr">${_("Discussion topics; current selection is: ")}</span>
<span class="js-selected-topic"></span>
<span class="drop-arrow" aria-hidden="true">▾</span>
</a>
<div class="topic-menu-wrapper">
<ul class="topic-menu" role="menu"><%= topics_html %></ul>
</div>
</div>
</div>
</div>
<% } %>
<select class="js-group-select">
<option value="">All Groups</option>
<option value="1">Group 1</option>
<option value="2">Group 2</option>
</select>
</form>
</script>
<script aria-hidden="true" type="text/template" id="new-post-menu-entry-template">
<li role="menuitem">
<a href="#" class="topic-title" data-discussion-id="<%- id %>" data-cohorted="<%- is_cohorted %>"><%- text %></a>
</li>
</script>
<script aria-hidden="true" type="text/template" id="new-post-menu-category-template">
<li role="menuitem">
<span class="topic-title"><%- text %></span>
<ul role="menu" class="topic-submenu"><%= entries %></ul>
</li>
</script>
"""
)
window.$$course_id = "edX/999/test" window.$$course_id = "edX/999/test"
spyOn(DiscussionUtil, "makeWmdEditor") spyOn(DiscussionUtil, "makeWmdEditor").andCallFake(
($content, $local, cls_identifier) ->
$local("." + cls_identifier).html("<textarea></textarea>")
)
@discussion = new Discussion([], {pages: 1}) @discussion = new Discussion([], {pages: 1})
describe "Drop down works correct", -> describe "cohort selector", ->
beforeEach -> beforeEach ->
@course_settings = new DiscussionCourseSettings({ @course_settings = new DiscussionCourseSettings({
"category_map": { "category_map": {
"subcategories": { "children": ["Topic"],
"Basic Question Types": { "entries": {"Topic": {"is_cohorted": true, "id": "topic"}}
"subcategories": {},
"children": ["Selection From Options"],
"entries": {
"Selection From Options": {
"sort_key": null,
"is_cohorted": true,
"id": "cba3e4cd91d0466b9ac50926e495b76f"
}
},
},
},
"children": ["Basic Question Types"],
"entries": {}
}, },
"allow_anonymous": true, "allow_anonymous": false,
"allow_anonymous_to_peers": true "allow_anonymous_to_peers": false,
"is_cohorted": true,
"cohorts": [
{"id": 1, "name": "Cohort1"},
{"id": 2, "name": "Cohort2"}
]
}) })
@view = new NewPostView( @view = new NewPostView(
el: $(".new-post-article"), el: $("#fixture-element"),
collection: @discussion, collection: @discussion,
course_settings: @course_settings, course_settings: @course_settings,
mode: "tab" mode: "tab"
) )
@view.render()
@parent_category_text = "Basic Question Types"
@selected_option_text = "Selection From Options"
it "completely show parent category and sub-category", -> checkVisibility = (view, expectedVisible) =>
complete_text = @parent_category_text + " / " + @selected_option_text view.render()
selected_text_width = @view.getNameWidth(complete_text) expect(view.$(".js-group-select").is(":visible")).toEqual(expectedVisible)
@view.maxNameWidth = selected_text_width + 1 if expectedVisible
@view.$el.find( "a.topic-title" ).first().click() expect(view.$(".js-group-select").prop("disabled")).toEqual(false)
dropdown_text = @view.$el.find(".js-selected-topic").text()
expect(complete_text).toEqual(dropdown_text)
it "completely show just sub-category", -> it "is not visible to students", ->
complete_text = @parent_category_text + " / " + @selected_option_text checkVisibility(@view, false)
selected_text_width = @view.getNameWidth(complete_text)
@view.maxNameWidth = selected_text_width - 10
@view.$el.find( "a.topic-title" ).first().click()
dropdown_text = @view.$el.find(".js-selected-topic").text()
expect(dropdown_text.indexOf("…")).toEqual(0)
expect(dropdown_text).toContain(@selected_option_text)
it "partially show sub-category", -> it "allows TAs to see the cohort selector", ->
parent_width = @view.getNameWidth(@parent_category_text) DiscussionSpecHelper.makeTA()
complete_text = @parent_category_text + " / " + @selected_option_text checkVisibility(@view, true)
selected_text_width = @view.getNameWidth(complete_text)
@view.maxNameWidth = selected_text_width - parent_width
@view.$el.find( "a.topic-title" ).first().click()
dropdown_text = @view.$el.find(".js-selected-topic").text()
expect(dropdown_text.indexOf("…")).toEqual(0)
expect(dropdown_text.lastIndexOf("…")).toBeGreaterThan(0)
it "broken span doesn't occur", -> it "allows moderators to see the cohort selector", ->
complete_text = @parent_category_text + " / " + @selected_option_text DiscussionSpecHelper.makeModerator()
selected_text_width = @view.getNameWidth(complete_text) checkVisibility(@view, true)
@view.maxNameWidth = @view.getNameWidth(@selected_option_text) + 100
@view.$el.find( "a.topic-title" ).first().click()
dropdown_text = @view.$el.find(".js-selected-topic").text()
expect(dropdown_text.indexOf("/ span>")).toEqual(-1)
describe "cohort selector", -> it "allows the user to make a cohort selection", ->
renderWithCohortedTopics = (course_settings, view, isCohortedFirst) -> DiscussionSpecHelper.makeModerator()
course_settings.set( @view.render()
"category_map", expectedGroupId = null
{ DiscussionSpecHelper.makeAjaxSpy(
"children": if isCohortedFirst then ["Cohorted", "Non-Cohorted"] else ["Non-Cohorted", "Cohorted"], (params) -> expect(params.data.group_id).toEqual(expectedGroupId)
"entries": { )
"Non-Cohorted": {
"sort_key": null, _.each(
"is_cohorted": false, ["1", "2", ""],
"id": "non-cohorted" (groupIdStr) =>
}, expectedGroupId = groupIdStr
"Cohorted": { @view.$(".js-group-select").val(groupIdStr)
"sort_key": null, @view.$(".js-post-title").val("dummy title")
"is_cohorted": true, @view.$(".js-post-body textarea").val("dummy body")
"id": "cohorted" @view.$(".forum-new-post-form").submit()
expect($.ajax).toHaveBeenCalled()
$.ajax.reset()
)
describe "cancel post resets form ", ->
beforeEach ->
@course_settings = new DiscussionCourseSettings({
"allow_anonymous_to_peers":true,
"allow_anonymous":true,
"category_map": {
"subcategories": {
"Week 1": {
"subcategories": {},
"children": [
"Topic-Level Student-Visible Label"
],
"entries": {
"Topic-Level Student-Visible Label": {
"sort_key": null,
"is_cohorted": false,
"id": "2b3a858d0c884eb4b272dbbe3f2ffddd"
}
} }
} }
},
"children": [
"General",
"Week 1"
],
"entries": {
"General": {
"sort_key": "General",
"is_cohorted": false,
"id": "i4x-waqastest-waqastest-course-waqastest"
}
} }
) }
view.render() })
expectCohortSelectorEnabled = (view, enabled) ->
expect(view.$(".js-group-select").prop("disabled")).toEqual(not enabled)
if not enabled
expect(view.$(".js-group-select option:selected").attr("value")).toEqual("")
it "is disabled with non-cohorted default topic and enabled by selecting cohorted topic", -> checkPostCancelReset = (mode, discussion, course_settings) ->
renderWithCohortedTopics(@course_settings, @view, false) view = new NewPostView(
expectCohortSelectorEnabled(@view, false) el: $("#fixture-element"),
@view.$("a.topic-title[data-discussion-id=cohorted]").click() collection: discussion,
expectCohortSelectorEnabled(@view, true) course_settings: course_settings,
mode: mode
)
view.render()
eventSpy = jasmine.createSpy('eventSpy')
view.listenTo(view, "newPost:cancel", eventSpy)
view.$(".post-errors").html("<li class='post-error'>Title can't be empty</li>")
view.$("label[for$='post-type-discussion']").click()
view.$(".js-post-title").val("Test Title")
view.$(".js-post-body textarea").val("Test body")
view.$(".wmd-preview p").html("Test body")
view.$(".js-follow").prop("checked", false)
view.$(".js-anon").prop("checked", true)
view.$(".js-anon-peers").prop("checked", true)
if mode == "tab"
view.$("a[data-discussion-id='2b3a858d0c884eb4b272dbbe3f2ffddd']").click()
view.$(".cancel").click()
expect(eventSpy).toHaveBeenCalled()
expect(view.$(".post-errors").html()).toEqual("");
expect($("input[id$='post-type-question']")).toBeChecked()
expect($("input[id$='post-type-discussion']")).not.toBeChecked()
expect(view.$(".js-post-title").val()).toEqual("");
expect(view.$(".js-post-body textarea").val()).toEqual("");
expect(view.$(".js-follow")).toBeChecked()
expect(view.$(".js-anon")).not.toBeChecked()
expect(view.$(".js-anon-peers")).not.toBeChecked()
if mode == "tab"
expect(view.$(".js-selected-topic").text()).toEqual("General")
it "is enabled with cohorted default topic and disabled by selecting non-cohorted topic", -> _.each(["tab", "inline"], (mode) =>
renderWithCohortedTopics(@course_settings, @view, true) it "resets the form in #{mode} mode", ->
expectCohortSelectorEnabled(@view, true) checkPostCancelReset(mode, @discussion, @course_settings)
@view.$("a.topic-title[data-discussion-id=non-cohorted]").click() )
expectCohortSelectorEnabled(@view, false)
it "posts to the correct URL", -> it "posts to the correct URL", ->
topicId = "test_topic" topicId = "test_topic"
...@@ -171,7 +150,7 @@ describe "NewPostView", -> ...@@ -171,7 +150,7 @@ describe "NewPostView", ->
{always: ->} {always: ->}
) )
view = new NewPostView( view = new NewPostView(
el: $(".new-post-article"), el: $("#fixture-element"),
collection: @discussion, collection: @discussion,
course_settings: new DiscussionCourseSettings({ course_settings: new DiscussionCourseSettings({
allow_anonymous: false, allow_anonymous: false,
......
...@@ -17,12 +17,10 @@ describe 'ResponseCommentView', -> ...@@ -17,12 +17,10 @@ describe 'ResponseCommentView', ->
spyOn(DiscussionUtil, "makeWmdEditor") spyOn(DiscussionUtil, "makeWmdEditor")
@view.render() @view.render()
makeEventSpy = () -> jasmine.createSpyObj('event', ['preventDefault', 'target'])
describe '_delete', -> describe '_delete', ->
beforeEach -> beforeEach ->
@comment.updateInfo {ability: {can_delete: true}} @comment.updateInfo {ability: {can_delete: true}}
@event = makeEventSpy() @event = DiscussionSpecHelper.makeEventSpy()
spyOn(@comment, "remove") spyOn(@comment, "remove")
spyOn(@view.$el, "remove") spyOn(@view.$el, "remove")
...@@ -81,9 +79,9 @@ describe 'ResponseCommentView', -> ...@@ -81,9 +79,9 @@ describe 'ResponseCommentView', ->
# Without calling renderEditView first, renderShowView is a no-op # Without calling renderEditView first, renderShowView is a no-op
@view.renderEditView() @view.renderEditView()
@view.renderShowView() @view.renderShowView()
@view.showView.trigger "comment:_delete", makeEventSpy() @view.showView.trigger "comment:_delete", DiscussionSpecHelper.makeEventSpy()
expect(@view._delete).toHaveBeenCalled() expect(@view._delete).toHaveBeenCalled()
@view.showView.trigger "comment:edit", makeEventSpy() @view.showView.trigger "comment:edit", DiscussionSpecHelper.makeEventSpy()
expect(@view.edit).toHaveBeenCalled() expect(@view.edit).toHaveBeenCalled()
expect(@view.$(".edit-post-form#comment_#{@comment.id}")).not.toHaveClass("edit-post-form") expect(@view.$(".edit-post-form#comment_#{@comment.id}")).not.toHaveClass("edit-post-form")
...@@ -92,9 +90,9 @@ describe 'ResponseCommentView', -> ...@@ -92,9 +90,9 @@ describe 'ResponseCommentView', ->
spyOn(@view, "update") spyOn(@view, "update")
spyOn(@view, "cancelEdit") spyOn(@view, "cancelEdit")
@view.renderEditView() @view.renderEditView()
@view.editView.trigger "comment:update", makeEventSpy() @view.editView.trigger "comment:update", DiscussionSpecHelper.makeEventSpy()
expect(@view.update).toHaveBeenCalled() expect(@view.update).toHaveBeenCalled()
@view.editView.trigger "comment:cancel_edit", makeEventSpy() @view.editView.trigger "comment:cancel_edit", DiscussionSpecHelper.makeEventSpy()
expect(@view.cancelEdit).toHaveBeenCalled() expect(@view.cancelEdit).toHaveBeenCalled()
expect(@view.$(".edit-post-form#comment_#{@comment.id}")).toHaveClass("edit-post-form") expect(@view.$(".edit-post-form#comment_#{@comment.id}")).toHaveClass("edit-post-form")
...@@ -138,7 +136,7 @@ describe 'ResponseCommentView', -> ...@@ -138,7 +136,7 @@ describe 'ResponseCommentView', ->
it 'calls the update endpoint correctly and displays the show view on success', -> it 'calls the update endpoint correctly and displays the show view on success', ->
@ajaxSucceed = true @ajaxSucceed = true
@view.update(makeEventSpy()) @view.update(DiscussionSpecHelper.makeEventSpy())
expect($.ajax).toHaveBeenCalled() expect($.ajax).toHaveBeenCalled()
expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update')
expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody) expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody)
...@@ -148,7 +146,7 @@ describe 'ResponseCommentView', -> ...@@ -148,7 +146,7 @@ describe 'ResponseCommentView', ->
it 'handles AJAX errors', -> it 'handles AJAX errors', ->
originalBody = @comment.get("body") originalBody = @comment.get("body")
@ajaxSucceed = false @ajaxSucceed = false
@view.update(makeEventSpy()) @view.update(DiscussionSpecHelper.makeEventSpy())
expect($.ajax).toHaveBeenCalled() expect($.ajax).toHaveBeenCalled()
expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update') expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/update')
expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody) expect($.ajax.mostRecentCall.args[0].data.body).toEqual(@updatedBody)
......
...@@ -45,6 +45,7 @@ describe "ThreadResponseShowView", -> ...@@ -45,6 +45,7 @@ describe "ThreadResponseShowView", ->
it "renders endorsement correctly for a marked answer in a question thread", -> it "renders endorsement correctly for a marked answer in a question thread", ->
endorsement = { endorsement = {
"username": "test_endorser", "username": "test_endorser",
"user_id": "test_id",
"time": new Date().toISOString() "time": new Date().toISOString()
} }
@thread.set("thread_type", "question") @thread.set("thread_type", "question")
...@@ -56,6 +57,7 @@ describe "ThreadResponseShowView", -> ...@@ -56,6 +57,7 @@ describe "ThreadResponseShowView", ->
expect(@view.$(".posted-details").text().replace(/\s+/g, " ")).toMatch( expect(@view.$(".posted-details").text().replace(/\s+/g, " ")).toMatch(
"marked as answer less than a minute ago by " + endorsement.username "marked as answer less than a minute ago by " + endorsement.username
) )
expect(@view.$(".posted-details > a").attr('href')).toEqual("/courses/edX/999/test/discussion/forum/users/test_id")
it "renders anonymous endorsement correctly for a marked answer in a question thread", -> it "renders anonymous endorsement correctly for a marked answer in a question thread", ->
endorsement = { endorsement = {
...@@ -74,6 +76,7 @@ describe "ThreadResponseShowView", -> ...@@ -74,6 +76,7 @@ describe "ThreadResponseShowView", ->
it "renders endorsement correctly for an endorsed response in a discussion thread", -> it "renders endorsement correctly for an endorsed response in a discussion thread", ->
endorsement = { endorsement = {
"username": "test_endorser", "username": "test_endorser",
"user_id": "test_id",
"time": new Date().toISOString() "time": new Date().toISOString()
} }
@thread.set("thread_type", "discussion") @thread.set("thread_type", "discussion")
...@@ -85,6 +88,7 @@ describe "ThreadResponseShowView", -> ...@@ -85,6 +88,7 @@ describe "ThreadResponseShowView", ->
expect(@view.$(".posted-details").text().replace(/\s+/g, " ")).toMatch( expect(@view.$(".posted-details").text().replace(/\s+/g, " ")).toMatch(
"endorsed less than a minute ago by " + endorsement.username "endorsed less than a minute ago by " + endorsement.username
) )
expect(@view.$(".posted-details > a").attr('href')).toEqual("/courses/edX/999/test/discussion/forum/users/test_id")
it "renders anonymous endorsement correctly for an endorsed response in a discussion thread", -> it "renders anonymous endorsement correctly for an endorsed response in a discussion thread", ->
endorsement = { endorsement = {
......
...@@ -3,13 +3,42 @@ describe 'ThreadResponseView', -> ...@@ -3,13 +3,42 @@ describe 'ThreadResponseView', ->
DiscussionSpecHelper.setUpGlobals() DiscussionSpecHelper.setUpGlobals()
DiscussionSpecHelper.setUnderscoreFixtures() DiscussionSpecHelper.setUnderscoreFixtures()
@thread = new Thread({"thread_type": "discussion"})
@response = new Comment { @response = new Comment {
children: [{}, {}] children: [{}, {}],
thread: @thread,
} }
@view = new ThreadResponseView({model: @response, el: $("#fixture-element")}) @view = new ThreadResponseView({model: @response, el: $("#fixture-element")})
spyOn(ThreadResponseShowView.prototype, "render") spyOn(ThreadResponseShowView.prototype, "render")
spyOn(ResponseCommentView.prototype, "render") spyOn(ResponseCommentView.prototype, "render")
describe 'closed and open Threads', ->
checkCommentForm = (closed) ->
thread = new Thread({"thread_type": "discussion", "closed": closed})
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: [],
type: "comment",
children: [],
thread: thread,
}
comment = new Comment(commentData)
view = new ThreadResponseView({
model: comment, el: $("#fixture-element"),
})
view.render()
expect(view.$('.comment-form').closest('li').is(":visible")).toBe(not closed)
it 'hides comment form when thread is closed', ->
checkCommentForm(true)
it 'show comment form when thread is open', ->
checkCommentForm(false)
describe 'renderComments', -> describe 'renderComments', ->
it 'hides "show comments" link if collapseComments is not set', -> it 'hides "show comments" link if collapseComments is not set', ->
@view.render() @view.render()
...@@ -17,7 +46,7 @@ describe 'ThreadResponseView', -> ...@@ -17,7 +46,7 @@ describe 'ThreadResponseView', ->
expect(@view.$(".action-show-comments")).not.toBeVisible() expect(@view.$(".action-show-comments")).not.toBeVisible()
it 'hides "show comments" link if collapseComments is set but response has no comments', -> it 'hides "show comments" link if collapseComments is set but response has no comments', ->
@response = new Comment { children: [] } @response = new Comment { children: [], thread: @thread }
@view = new ThreadResponseView({ @view = new ThreadResponseView({
model: @response, el: $("#fixture-element"), model: @response, el: $("#fixture-element"),
collapseComments: true collapseComments: true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment