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.
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
// 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 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);
|
||||
});
|
||||
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user