Commit d64c2b29 by Eric Fischer

Fix for flaky TeamDiscussionView js tests

After being able to reproduce the errors exactly by making certain
elements unfindable, I concluded that the issues we've been seeing
on headless jenkins runs are due to execution happening too quickly
and elements not loading in time to be interacted with.

The fix is to make liberal use of Jasmine 1.3 `runs` and `waitsFor`
functionality, to ensure that execution happens in the order that
we want, with rendering being checked before proceeding.

Once again, I can't be 100% sure that this fixes the Jenkins errors,
as those are very hard to reliably reproduce, but this is an
educated guess at fixing the problem with no drawbacks, as I've
been able to successfully run all tests locally.
parent 45832b98
......@@ -38,84 +38,109 @@ define([
};
createPost = function(requests, view, title, body, threadID) {
title = title || "Test title";
body = body || "Test body";
threadID = threadID || "999";
view.$('.new-post-button').click();
view.$('.js-post-title').val(title);
view.$('.js-post-body textarea').val(body);
view.$('.submit').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/%(discussionID)s/threads/create?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID
},
true
),
interpolate(
'thread_type=discussion&title=%(title)s&body=%(body)s&anonymous=false&anonymous_to_peers=false&auto_subscribe=true',
{
title: title.replace(/ /g, '+'),
body: body.replace(/ /g, '+')
},
true
)
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockPostResponse({
id: threadID,
title: title,
body: body
}),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
runs(function() {
title = title || "Test title";
body = body || "Test body";
threadID = threadID || "999";
view.$('.new-post-button').click();
view.$('.js-post-title').val(title);
view.$('.js-post-body textarea').val(body);
});
waitsFor(function() {
return $('.submit').length;
}, "Submit button never appeared", 1000);
runs(function() {
view.$('.submit').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/%(discussionID)s/threads/create?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID
},
true
),
interpolate(
'thread_type=discussion&title=%(title)s&body=%(body)s&anonymous=false&anonymous_to_peers=false&auto_subscribe=true',
{
title: title.replace(/ /g, '+'),
body: body.replace(/ /g, '+')
},
true
)
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockPostResponse({
id: threadID,
title: title,
body: body
}),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
});
});
};
expandReplies = function(requests, view, threadID) {
view.$('.forum-thread-expand').first().click();
AjaxHelpers.expectRequest(
requests, 'GET',
interpolate(
'/courses/%(courseID)s/discussion/forum/%(discussionID)s/threads/%(threadID)s?ajax=1&resp_skip=0&resp_limit=25',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID,
threadID: threadID || "999"
},
true
)
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockThreadResponse(),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
});
waitsFor(function() {
return $('.forum-thread-expand').length;
}, "Forum expando link never appeared", 1000);
runs(function() {
view.$('.forum-thread-expand').first().click();
AjaxHelpers.expectRequest(
requests, 'GET',
interpolate(
'/courses/%(courseID)s/discussion/forum/%(discussionID)s/threads/%(threadID)s?ajax=1&resp_skip=0&resp_limit=25',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID,
threadID: threadID || "999"
},
true
)
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockThreadResponse(),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
});
});
};
postReply = function(requests, view, reply, threadID) {
var replyForm = view.$('.discussion-reply-new').first();
replyForm.find('.reply-body textarea').val(reply);
replyForm.find('.discussion-submit-post').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/threads/%(threadID)s/reply?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
threadID: threadID || "999"
},
true
),
'body=' + reply.replace(/ /g, '+')
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockThreadResponse({
body: reply,
comments_count: 1
}),
"annotated_content_info": TeamSpecHelpers.createAnnotatedContentInfo()
var replyForm;
runs(function() {
replyForm = view.$('.discussion-reply-new').first();
});
waitsFor(function() {
return replyForm.find('.discussion-submit-post').length;
}, "submit reply button never appeared", 1000);
runs(function() {
replyForm.find('.reply-body textarea').val(reply);
replyForm.find('.discussion-submit-post').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/threads/%(threadID)s/reply?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
threadID: threadID || "999"
},
true
),
'body=' + reply.replace(/ /g, '+')
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockThreadResponse({
body: reply,
comments_count: 1
}),
"annotated_content_info": TeamSpecHelpers.createAnnotatedContentInfo()
});
});
};
......@@ -127,17 +152,26 @@ define([
it('can create a new post', function() {
var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests),
view,
testTitle = 'New Post',
testBody = 'New post body',
newThreadElement;
createPost(requests, view, testTitle, testBody);
runs(function() {
view = createDiscussionView(requests);
createPost(requests, view, testTitle, testBody);
});
waitsFor(function() {
return $('.discussion-thread').length;
}, "Discussion thread never appeared", 1000);
// Expect the first thread to be the new post
expect(view.$('.discussion-thread').length).toEqual(4);
newThreadElement = view.$('.discussion-thread').first();
expect(newThreadElement.find('.post-header-content h1').text().trim()).toEqual(testTitle);
expect(newThreadElement.find('.post-body').text().trim()).toEqual(testBody);
runs(function() {
// Expect the first thread to be the new post
expect(view.$('.discussion-thread').length).toEqual(4);
newThreadElement = view.$('.discussion-thread').first();
expect(newThreadElement.find('.post-header-content h1').text().trim()).toEqual(testTitle);
expect(newThreadElement.find('.post-body').text().trim()).toEqual(testBody);
});
});
it('can post a reply', function() {
......@@ -145,59 +179,95 @@ define([
view = createDiscussionView(requests),
testReply = "Test reply",
testThreadID = "1";
expandReplies(requests, view, testThreadID);
postReply(requests, view, testReply, testThreadID);
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply);
runs(function() {
expandReplies(requests, view, testThreadID);
postReply(requests, view, testReply, testThreadID);
});
waitsFor(function() {
return view.$('.discussion-response .response-body').length;
}, "Discussion response never made visible", 1000);
runs(function() {
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply);
});
});
it('can post a reply to a new post', function() {
var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests, []),
testReply = "Test reply";
createPost(requests, view);
expandReplies(requests, view);
postReply(requests, view, testReply);
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply);
runs(function() {
createPost(requests, view);
expandReplies(requests, view);
postReply(requests, view, testReply);
});
waitsFor(function() {
return view.$('.discussion-response .response-body').length;
}, "Discussion response never made visible", 1000);
runs(function() {
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply);
});
});
it('cannot move an existing thread to a different topic', function() {
var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests),
view,
postTopicButton, updatedThreadElement,
updatedTitle = 'Updated title',
updatedBody = 'Updated body',
testThreadID = "1";
expandReplies(requests, view, testThreadID);
view.$('.action-more .icon').first().click();
view.$('.action-edit').first().click();
postTopicButton = view.$('.post-topic');
expect(postTopicButton.length).toBe(0);
view.$('.js-post-post-title').val(updatedTitle);
view.$('.js-post-body textarea').val(updatedBody);
view.$('.submit').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/%(discussionID)s/threads/create?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID
},
true
),
'thread_type=discussion&title=&body=Updated+body&anonymous=false&anonymous_to_peers=false&auto_subscribe=true'
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockPostResponse({
id: "999", title: updatedTitle, body: updatedBody
}),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
runs(function() {
view = createDiscussionView(requests);
expandReplies(requests, view, testThreadID);
});
waitsFor(function() {
return view.$('.action-more .icon').length;
}, "Expanding replies never finished", 1000);
runs(function() {
view.$('.action-more .icon').first().click();
view.$('.action-edit').first().click();
postTopicButton = view.$('.post-topic');
expect(postTopicButton.length).toBe(0);
view.$('.js-post-post-title').val(updatedTitle);
view.$('.js-post-body textarea').val(updatedBody);
});
// Expect the thread to have been updated
updatedThreadElement = view.$('.discussion-thread').first();
expect(updatedThreadElement.find('.post-header-content h1').text().trim()).toEqual(updatedTitle);
expect(updatedThreadElement.find('.post-body').text().trim()).toEqual(updatedBody);
waitsFor(function() {
return $('.submit').length;
}, "submit button never appeared", 1000);
runs(function() {
view.$('.submit').click();
AjaxHelpers.expectRequest(
requests, 'POST',
interpolate(
'/courses/%(courseID)s/discussion/%(discussionID)s/threads/create?ajax=1',
{
courseID: TeamSpecHelpers.testCourseID,
discussionID: TeamSpecHelpers.testTeamDiscussionID
},
true
),
'thread_type=discussion&title=&body=Updated+body&anonymous=false&anonymous_to_peers=false&auto_subscribe=true'
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockPostResponse({
id: "999", title: updatedTitle, body: updatedBody
}),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
});
// Expect the thread to have been updated
updatedThreadElement = view.$('.discussion-thread').first();
expect(updatedThreadElement.find('.post-header-content h1').text().trim()).toEqual(updatedTitle);
expect(updatedThreadElement.find('.post-body').text().trim()).toEqual(updatedBody);
});
});
it('cannot move a new thread to a different topic', function() {
......
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