Commit 1c910cfb by Peter Fogg

Merge pull request #9631 from edx/peter-fogg/teams-ajax-errors

Respond to AJAX errors in Teams UI.
parents 34e01581 95339311
...@@ -102,6 +102,11 @@ class TeamsPage(CoursePage): ...@@ -102,6 +102,11 @@ class TeamsPage(CoursePage):
""" Click on the breadcrumb for a specific topic """ """ Click on the breadcrumb for a specific topic """
self.q(css='a.nav-item').filter(text=topic)[0].click() self.q(css='a.nav-item').filter(text=topic)[0].click()
@property
def warning_message(self):
"""Return the text of the team warning message."""
return self.q(css='.warning').results[0].text
class MyTeamsPage(CoursePage, PaginatedUIMixin, TeamCardsMixin): class MyTeamsPage(CoursePage, PaginatedUIMixin, TeamCardsMixin):
""" """
......
...@@ -198,6 +198,42 @@ class TeamsTabTest(TeamsTabBase): ...@@ -198,6 +198,42 @@ class TeamsTabTest(TeamsTabBase):
self.verify_teams_present(True) self.verify_teams_present(True)
@ddt.data( @ddt.data(
'topics/{topic_id}',
'topics/{topic_id}/search',
'topics/{topic_id}/{team_id}/edit-team',
'teams/{topic_id}/{team_id}'
)
def test_unauthorized_error_message(self, route):
"""Ensure that an error message is shown to the user if they attempt
to take an action which makes an AJAX request while not signed
in.
"""
topics = self.create_topics(1)
topic = topics[0]
self.set_team_configuration({
u'max_team_size': 10,
u'topics': topics
})
team = self.create_teams(topic, 1)[0]
self.teams_page.visit()
self.browser.delete_cookie('sessionid')
url = self.browser.current_url.split('#')[0]
self.browser.get(
'{url}#{route}'.format(
url=url,
route=route.format(
topic_id=topic['id'],
team_id=team['id']
)
)
)
self.teams_page.wait_for_ajax()
self.assertEqual(
self.teams_page.warning_message,
u"Your request could not be completed. Reload the page and try again."
)
@ddt.data(
('browse', '.topics-list'), ('browse', '.topics-list'),
# TODO: find a reliable way to match the "My Teams" tab # TODO: find a reliable way to match the "My Teams" tab
# ('my-teams', 'div.teams-list'), # ('my-teams', 'div.teams-list'),
......
...@@ -4,8 +4,6 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory', ...@@ -4,8 +4,6 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory',
'use strict'; 'use strict';
describe("Teams Tab Factory", function() { describe("Teams Tab Factory", function() {
var teamsTab;
var initializeTeamsTabFactory = function() { var initializeTeamsTabFactory = function() {
TeamsTabFactory(TeamSpecHelpers.createMockContext()); TeamsTabFactory(TeamSpecHelpers.createMockContext());
}; };
...@@ -19,6 +17,11 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory', ...@@ -19,6 +17,11 @@ define(['jquery', 'backbone', 'teams/js/teams_tab_factory',
}); });
it('can render the "Teams" tab', function() { it('can render the "Teams" tab', function() {
// Hack to make sure the URL fragments from earlier
// tests don't interfere with Backbone routing by the
// teams tab view
document.location.hash = '';
initializeTeamsTabFactory(); initializeTeamsTabFactory();
expect($('.teams-content').text()).toContain('See all teams in your course, organized by topic'); expect($('.teams-content').text()).toContain('See all teams in your course, organized by topic');
}); });
......
...@@ -39,9 +39,7 @@ define([ ...@@ -39,9 +39,7 @@ define([
spyOn($.fn, 'focus'); spyOn($.fn, 'focus');
}); });
afterEach(function () { afterEach(Backbone.history.stop);
Backbone.history.stop();
});
describe('Navigation', function () { describe('Navigation', function () {
it('displays and focuses an error message when trying to navigate to a nonexistent page', function () { it('displays and focuses an error message when trying to navigate to a nonexistent page', function () {
...@@ -76,6 +74,24 @@ define([ ...@@ -76,6 +74,24 @@ define([
expectError(teamsTabView, 'The team "no_such_team" could not be found.'); expectError(teamsTabView, 'The team "no_such_team" could not be found.');
expectFocus(teamsTabView.$('.warning')); expectFocus(teamsTabView.$('.warning'));
}); });
it('displays and focuses an error message when it receives a 401 AJAX response', function () {
var requests = AjaxHelpers.requests(this),
teamsTabView = createTeamsTabView().render();
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
AjaxHelpers.respondWithError(requests, 401);
expectError(teamsTabView, "Your request could not be completed. Reload the page and try again.");
expectFocus(teamsTabView.$('.warning'));
});
it('displays and focuses an error message when it receives a 500 AJAX response', function () {
var requests = AjaxHelpers.requests(this),
teamsTabView = createTeamsTabView().render();
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
AjaxHelpers.respondWithError(requests, 500);
expectError(teamsTabView, "Your request could not be completed due to a server problem. Reload the page and try again. If the issue persists, click the Help tab to report the problem.");
expectFocus(teamsTabView.$('.warning'));
});
}); });
describe('Discussion privileges', function () { describe('Discussion privileges', function () {
......
;(function (define) { ;(function (define) {
'use strict'; 'use strict';
define(['jquery', 'teams/js/views/teams_tab'],
define(['jquery', 'underscore', 'backbone', 'teams/js/views/teams_tab'], function ($, TeamsTabView) {
function ($, _, Backbone, TeamsTabView) {
return function (options) { return function (options) {
var teamsTab = new TeamsTabView({ var teamsTab = new TeamsTabView({
el: $('.teams-content'), el: $('.teams-content'),
......
...@@ -19,11 +19,12 @@ ...@@ -19,11 +19,12 @@
'teams/js/views/topic_teams', 'teams/js/views/topic_teams',
'teams/js/views/edit_team', 'teams/js/views/edit_team',
'teams/js/views/team_profile_header_actions', 'teams/js/views/team_profile_header_actions',
'teams/js/views/team_utils',
'text!teams/templates/teams_tab.underscore'], 'text!teams/templates/teams_tab.underscore'],
function (Backbone, _, gettext, SearchFieldView, HeaderView, HeaderModel, TabbedView, function (Backbone, _, gettext, SearchFieldView, HeaderView, HeaderModel, TabbedView,
TopicModel, TopicCollection, TeamModel, TeamCollection, TeamMembershipCollection, TopicModel, TopicCollection, TeamModel, TeamCollection, TeamMembershipCollection,
TopicsView, TeamProfileView, MyTeamsView, TopicTeamsView, TeamEditView, TopicsView, TeamProfileView, MyTeamsView, TopicTeamsView, TeamEditView,
TeamProfileHeaderActionsView, teamsTemplate) { TeamProfileHeaderActionsView, TeamUtils, teamsTemplate) {
var TeamsHeaderModel = HeaderModel.extend({ var TeamsHeaderModel = HeaderModel.extend({
initialize: function () { initialize: function () {
_.extend(this.defaults, {nav_aria_label: gettext('teams')}); _.extend(this.defaults, {nav_aria_label: gettext('teams')});
...@@ -144,6 +145,15 @@ ...@@ -144,6 +145,15 @@
start: function() { start: function() {
Backbone.history.start(); Backbone.history.start();
$(document).ajaxError(function (event, xhr) {
if (xhr.status === 401) {
TeamUtils.showMessage(gettext("Your request could not be completed. Reload the page and try again."));
}
else if (xhr.status === 500) {
TeamUtils.showMessage(gettext("Your request could not be completed due to a server problem. Reload the page and try again. If the issue persists, click the Help tab to report the problem."));
}
});
// Navigate to the default page if there is no history: // Navigate to the default page if there is no history:
// 1. If the user belongs to at least one team, jump to the "My Teams" page // 1. If the user belongs to at least one team, jump to the "My Teams" page
// 2. If not, then jump to the "Browse" page // 2. If not, then jump to the "Browse" page
......
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