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([ ...@@ -38,84 +38,109 @@ define([
}; };
createPost = function(requests, view, title, body, threadID) { createPost = function(requests, view, title, body, threadID) {
title = title || "Test title"; runs(function() {
body = body || "Test body"; title = title || "Test title";
threadID = threadID || "999"; body = body || "Test body";
view.$('.new-post-button').click(); threadID = threadID || "999";
view.$('.js-post-title').val(title); view.$('.new-post-button').click();
view.$('.js-post-body textarea').val(body); view.$('.js-post-title').val(title);
view.$('.submit').click(); view.$('.js-post-body textarea').val(body);
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()
}); });
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) { expandReplies = function(requests, view, threadID) {
view.$('.forum-thread-expand').first().click(); waitsFor(function() {
AjaxHelpers.expectRequest( return $('.forum-thread-expand').length;
requests, 'GET', }, "Forum expando link never appeared", 1000);
interpolate(
'/courses/%(courseID)s/discussion/forum/%(discussionID)s/threads/%(threadID)s?ajax=1&resp_skip=0&resp_limit=25', runs(function() {
{ view.$('.forum-thread-expand').first().click();
courseID: TeamSpecHelpers.testCourseID, AjaxHelpers.expectRequest(
discussionID: TeamSpecHelpers.testTeamDiscussionID, requests, 'GET',
threadID: threadID || "999" interpolate(
}, '/courses/%(courseID)s/discussion/forum/%(discussionID)s/threads/%(threadID)s?ajax=1&resp_skip=0&resp_limit=25',
true {
) courseID: TeamSpecHelpers.testCourseID,
); discussionID: TeamSpecHelpers.testTeamDiscussionID,
AjaxHelpers.respondWithJson(requests, { threadID: threadID || "999"
content: TeamSpecHelpers.createMockThreadResponse(), },
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo() true
}); )
);
AjaxHelpers.respondWithJson(requests, {
content: TeamSpecHelpers.createMockThreadResponse(),
annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo()
});
});
}; };
postReply = function(requests, view, reply, threadID) { postReply = function(requests, view, reply, threadID) {
var replyForm = view.$('.discussion-reply-new').first(); var replyForm;
replyForm.find('.reply-body textarea').val(reply); runs(function() {
replyForm.find('.discussion-submit-post').click(); replyForm = view.$('.discussion-reply-new').first();
AjaxHelpers.expectRequest( });
requests, 'POST',
interpolate( waitsFor(function() {
'/courses/%(courseID)s/discussion/threads/%(threadID)s/reply?ajax=1', return replyForm.find('.discussion-submit-post').length;
{ }, "submit reply button never appeared", 1000);
courseID: TeamSpecHelpers.testCourseID,
threadID: threadID || "999" runs(function() {
}, replyForm.find('.reply-body textarea').val(reply);
true replyForm.find('.discussion-submit-post').click();
), AjaxHelpers.expectRequest(
'body=' + reply.replace(/ /g, '+') requests, 'POST',
); interpolate(
AjaxHelpers.respondWithJson(requests, { '/courses/%(courseID)s/discussion/threads/%(threadID)s/reply?ajax=1',
content: TeamSpecHelpers.createMockThreadResponse({ {
body: reply, courseID: TeamSpecHelpers.testCourseID,
comments_count: 1 threadID: threadID || "999"
}), },
"annotated_content_info": TeamSpecHelpers.createAnnotatedContentInfo() 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([ ...@@ -127,17 +152,26 @@ define([
it('can create a new post', function() { it('can create a new post', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests), view,
testTitle = 'New Post', testTitle = 'New Post',
testBody = 'New post body', testBody = 'New post body',
newThreadElement; 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 runs(function() {
expect(view.$('.discussion-thread').length).toEqual(4); // Expect the first thread to be the new post
newThreadElement = view.$('.discussion-thread').first(); expect(view.$('.discussion-thread').length).toEqual(4);
expect(newThreadElement.find('.post-header-content h1').text().trim()).toEqual(testTitle); newThreadElement = view.$('.discussion-thread').first();
expect(newThreadElement.find('.post-body').text().trim()).toEqual(testBody); 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() { it('can post a reply', function() {
...@@ -145,59 +179,95 @@ define([ ...@@ -145,59 +179,95 @@ define([
view = createDiscussionView(requests), view = createDiscussionView(requests),
testReply = "Test reply", testReply = "Test reply",
testThreadID = "1"; testThreadID = "1";
expandReplies(requests, view, testThreadID); runs(function() {
postReply(requests, view, testReply, testThreadID); expandReplies(requests, view, testThreadID);
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply); 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() { it('can post a reply to a new post', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests, []), view = createDiscussionView(requests, []),
testReply = "Test reply"; testReply = "Test reply";
createPost(requests, view); runs(function() {
expandReplies(requests, view); createPost(requests, view);
postReply(requests, view, testReply); expandReplies(requests, view);
expect(view.$('.discussion-response .response-body').text().trim()).toBe(testReply); 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() { it('cannot move an existing thread to a different topic', function() {
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
view = createDiscussionView(requests), view,
postTopicButton, updatedThreadElement, postTopicButton, updatedThreadElement,
updatedTitle = 'Updated title', updatedTitle = 'Updated title',
updatedBody = 'Updated body', updatedBody = 'Updated body',
testThreadID = "1"; testThreadID = "1";
expandReplies(requests, view, testThreadID); runs(function() {
view.$('.action-more .icon').first().click(); view = createDiscussionView(requests);
view.$('.action-edit').first().click(); expandReplies(requests, view, testThreadID);
postTopicButton = view.$('.post-topic'); });
expect(postTopicButton.length).toBe(0);
view.$('.js-post-post-title').val(updatedTitle); waitsFor(function() {
view.$('.js-post-body textarea').val(updatedBody); return view.$('.action-more .icon').length;
view.$('.submit').click(); }, "Expanding replies never finished", 1000);
AjaxHelpers.expectRequest(
requests, 'POST', runs(function() {
interpolate( view.$('.action-more .icon').first().click();
'/courses/%(courseID)s/discussion/%(discussionID)s/threads/create?ajax=1', view.$('.action-edit').first().click();
{ postTopicButton = view.$('.post-topic');
courseID: TeamSpecHelpers.testCourseID, expect(postTopicButton.length).toBe(0);
discussionID: TeamSpecHelpers.testTeamDiscussionID view.$('.js-post-post-title').val(updatedTitle);
}, view.$('.js-post-body textarea').val(updatedBody);
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 waitsFor(function() {
updatedThreadElement = view.$('.discussion-thread').first(); return $('.submit').length;
expect(updatedThreadElement.find('.post-header-content h1').text().trim()).toEqual(updatedTitle); }, "submit button never appeared", 1000);
expect(updatedThreadElement.find('.post-body').text().trim()).toEqual(updatedBody);
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() { 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