define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/js/spec_helpers/template_helpers', 'js/discussions_management/views/discussions', 'js/discussions_management/models/course_discussions_detail', 'js/discussions_management/models/course_discussions_settings' ], function(Backbone, $, AjaxHelpers, TemplateHelpers, DiscussionsView, CourseDiscussionTopicDetailsModel, CourseDiscussionsSettingsModel) { 'use strict'; describe('Discussions View', function() { var createMockDiscussionsSettingsJson, createDiscussionsView, discussionsView, requests, verifyMessage, createMockDiscussionsSettings, createMockDiscussionsJson, createMockDiscussions, showAndAssertDiscussionTopics; // Selectors var inlineDiscussionsFormCss = '.cohort-inline-discussions-form', courseWideDiscussionsFormCss = '.cohort-course-wide-discussions-form', courseWideDiscussionsSaveButtonCss = '.cohort-course-wide-discussions-form .action-save', inlineDiscussionsSaveButtonCss = '.cohort-inline-discussions-form .action-save'; createMockDiscussionsSettingsJson = function(dividedInlineDiscussions, dividedCourseWideDiscussions, alwaysDivideInlineDiscussions, availableDivisionSchemes) { return { id: 0, divided_inline_discussions: dividedInlineDiscussions || [], divided_course_wide_discussions: dividedCourseWideDiscussions || [], always_divide_inline_discussions: alwaysDivideInlineDiscussions || false, available_division_schemes: availableDivisionSchemes || ['cohort'] }; }; createMockDiscussionsSettings = function(dividedInlineDiscussions, dividedCourseWideDiscussions, alwaysDivideInlineDiscussions, availableDivisionSchemes) { return new CourseDiscussionsSettingsModel( createMockDiscussionsSettingsJson(dividedInlineDiscussions, dividedCourseWideDiscussions, alwaysDivideInlineDiscussions, availableDivisionSchemes) ); }; createMockDiscussionsJson = function(allDivided) { return { course_wide_discussions: { children: [['Topic_C_1', 'entry'], ['Topic_C_2', 'entry']], entries: { Topic_C_1: { sort_key: null, is_divided: true, id: 'Topic_C_1' }, Topic_C_2: { sort_key: null, is_divided: false, id: 'Topic_C_2' } } }, inline_discussions: { subcategories: { Topic_I_1: { subcategories: {}, children: [['Inline_Discussion_1', 'entry'], ['Inline_Discussion_2', 'entry']], entries: { Inline_Discussion_1: { sort_key: null, is_divided: true, id: 'Inline_Discussion_1' }, Inline_Discussion_2: { sort_key: null, is_divided: allDivided || false, id: 'Inline_Discussion_2' } } } }, children: [['Topic_I_1', 'subcategory']] } }; }; createMockDiscussions = function(allDivided) { return new CourseDiscussionTopicDetailsModel( createMockDiscussionsJson(allDivided) ); }; verifyMessage = function(expectedTitle, expectedMessageType, expectedAction, hasDetails) { expect(discussionsView.$('.message-title').text().trim()).toBe(expectedTitle); expect(discussionsView.$('div.message')).toHaveClass('message-' + expectedMessageType); if (expectedAction) { expect(discussionsView.$('.message-actions .action-primary').text().trim()).toBe(expectedAction); } else { expect(discussionsView.$('.message-actions .action-primary').length).toBe(0); } if (!hasDetails) { expect(discussionsView.$('.summary-items').length).toBe(0); } }; createDiscussionsView = function(test, options) { var discussionSettings, dividedDiscussions, discussionOptions; discussionOptions = options || {}; discussionSettings = discussionOptions.cohortSettings || createMockDiscussionsSettings(); discussionSettings.url = '/mock_service/discussions/settings'; dividedDiscussions = discussionOptions.dividedDiscussions || createMockDiscussions(); dividedDiscussions.url = '/mock_service/discussion/topics'; requests = AjaxHelpers.requests(test); discussionsView = new DiscussionsView({ el: $('.discussions-management'), discussionSettings: discussionSettings, context: { courseDiscussionTopicDetailsModel: dividedDiscussions } }); discussionsView.render(); }; showAndAssertDiscussionTopics = function() { var $courseWideDiscussionsForm, $inlineDiscussionsForm; $courseWideDiscussionsForm = discussionsView.$(courseWideDiscussionsFormCss); $inlineDiscussionsForm = discussionsView.$(inlineDiscussionsFormCss); // Discussions form should not be visible. expect($inlineDiscussionsForm.length).toBe(1); expect($courseWideDiscussionsForm.length).toBe(1); expect($courseWideDiscussionsForm.text()) .toContain('Course-Wide Discussion Topics'); expect($courseWideDiscussionsForm.text()) .toContain('Select the course-wide discussion topics that you want to divide.'); // Should see the inline discussions form and its content expect($inlineDiscussionsForm.length).toBe(1); expect($inlineDiscussionsForm.text()) .toContain('Content-Specific Discussion Topics'); expect($inlineDiscussionsForm.text()) .toContain('Specify whether content-specific discussion topics are divided.'); }; beforeEach(function() { setFixtures('
' + '
'); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/discussions'); TemplateHelpers.installTemplate( 'templates/instructor/instructor_dashboard_2/divided-discussions-course-wide' ); TemplateHelpers.installTemplate( 'templates/instructor/instructor_dashboard_2/divided-discussions-inline' ); TemplateHelpers.installTemplate( 'templates/instructor/instructor_dashboard_2/cohort-discussions-category' ); TemplateHelpers.installTemplate( 'templates/instructor/instructor_dashboard_2/cohort-discussions-subcategory' ); TemplateHelpers.installTemplate('templates/instructor/instructor_dashboard_2/notification'); }); describe('Discussion Topics', function() { var courseWideView, assertDividedTopics; assertDividedTopics = function(view, type) { expect($('.check-discussion-subcategory-' + type).length).toBe(2); expect($('.check-discussion-subcategory-' + type + ':checked').length).toBe(1); }; it('renders the view properly', function() { createDiscussionsView(this); showAndAssertDiscussionTopics(this); }); describe('Course Wide', function() { it('shows the "Save" button as disabled initially', function() { createDiscussionsView(this); expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeTruthy(); }); it('has one divided and one non-divided topic', function() { createDiscussionsView(this); assertDividedTopics(courseWideView, 'course-wide'); expect($('.course-wide-discussion-topics .divided-discussion-text').length).toBe(2); expect($('.course-wide-discussion-topics .divided-discussion-text.hidden').length).toBe(1); }); it('enables the "Save" button after changing checkbox', function() { createDiscussionsView(this); // save button is disabled. expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeTruthy(); $($('.check-discussion-subcategory-course-wide')[0]).prop('checked', false).change(); // save button is enabled. expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeFalsy(); }); it('saves the topic successfully', function() { createDiscussionsView(this); $($('.check-discussion-subcategory-course-wide')[1]).prop('checked', 'checked').change(); expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeFalsy(); // Save the updated settings $('#cohort-course-wide-discussions-form .action-save').click(); // fake requests for discussions settings with PATCH method. AjaxHelpers.expectJsonRequest( requests, 'PATCH', '/mock_service/discussions/settings', {divided_course_wide_discussions: ['Topic_C_1', 'Topic_C_2']} ); AjaxHelpers.respondWithJson( requests, {divided_course_wide_discussions: ['Topic_C_1', 'Topic_C_2']} ); // fake request for discussion/topics with GET method. AjaxHelpers.expectJsonRequest( requests, 'GET', '/mock_service/discussion/topics' ); AjaxHelpers.respondWithJson( requests, createMockDiscussions() ); // verify the success message. expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeTruthy(); verifyMessage('Your changes have been saved.', 'confirmation'); }); it('shows an appropriate message when subsequent "GET" returns HTTP500', function() { var expectedTitle; createDiscussionsView(this); $($('.check-discussion-subcategory-course-wide')[1]).prop('checked', 'checked').change(); expect($(courseWideDiscussionsSaveButtonCss).prop('disabled')).toBeFalsy(); // Save the updated settings $('#cohort-course-wide-discussions-form .action-save').click(); // fake requests for discussion settings with PATCH method. AjaxHelpers.expectJsonRequest( requests, 'PATCH', '/mock_service/discussions/settings', {divided_course_wide_discussions: ['Topic_C_1', 'Topic_C_2']} ); AjaxHelpers.respondWithJson( requests, {divided_course_wide_discussions: ['Topic_C_1', 'Topic_C_2']} ); // fake request for discussion/topics with GET method. AjaxHelpers.expectJsonRequest( requests, 'GET', '/mock_service/discussion/topics' ); AjaxHelpers.respondWithError(requests, 500); expectedTitle = "We've encountered an error. Refresh your browser and then try again."; expect($('.message-title').text().trim()).toBe(expectedTitle); }); it('shows an appropriate error message for HTTP500', function() { var expectedTitle; createDiscussionsView(this); $($('.check-discussion-subcategory-course-wide')[1]).prop('checked', 'checked').change(); $('.action-save').click(); AjaxHelpers.respondWithError(requests, 500); expectedTitle = "We've encountered an error. Refresh your browser and then try again."; expect($('.message-title').text().trim()).toBe(expectedTitle); }); }); describe('Inline', function() { var enableSaveButton, mockGetRequest, verifySuccess, mockPatchRequest; enableSaveButton = function() { // enable the inline discussion topics. $('.check-cohort-inline-discussions').prop('checked', 'checked').change(); $($('.check-discussion-subcategory-inline')[0]).prop('checked', 'checked').change(); expect($(inlineDiscussionsSaveButtonCss).prop('disabled')).toBeFalsy(); }; verifySuccess = function() { // verify the success message. expect($(inlineDiscussionsSaveButtonCss).prop('disabled')).toBeTruthy(); verifyMessage('Your changes have been saved.', 'confirmation'); }; mockPatchRequest = function(dividededInlineDiscussions) { AjaxHelpers.expectJsonRequest( requests, 'PATCH', '/mock_service/discussions/settings', { divided_inline_discussions: dividededInlineDiscussions, always_divide_inline_discussions: false } ); AjaxHelpers.respondWithJson( requests, { divided_inline_discussions: dividededInlineDiscussions, always_divide_inline_discussions: false } ); }; mockGetRequest = function(alldivided) { // fake request for discussion/topics with GET method. AjaxHelpers.expectJsonRequest( requests, 'GET', '/mock_service/discussion/topics' ); AjaxHelpers.respondWithJson( requests, createMockDiscussions(alldivided) ); }; it('shows the "Save" button as disabled initially', function() { createDiscussionsView(this); expect($(inlineDiscussionsSaveButtonCss).prop('disabled')).toBeTruthy(); }); it('shows always divide radio button as selected', function() { createDiscussionsView(this); $('.check-all-inline-discussions').prop('checked', 'checked').change(); // verify always divide inline discussions is being selected. expect($('.check-all-inline-discussions').prop('checked')).toBeTruthy(); // verify that inline topics are disabled expect($('.check-discussion-subcategory-inline').prop('disabled')).toBeTruthy(); expect($('.check-discussion-category').prop('disabled')).toBeTruthy(); // verify that divide some topics are not being selected. expect($('.check-cohort-inline-discussions').prop('checked')).toBeFalsy(); }); it('shows divide some topics radio button as selected', function() { createDiscussionsView(this); $('.check-cohort-inline-discussions').prop('checked', 'checked').change(); // verify some divide inline discussions radio is being selected. expect($('.check-cohort-inline-discussions').prop('checked')).toBeTruthy(); // verify always divide radio is not selected. expect($('.check-all-inline-discussions').prop('checked')).toBeFalsy(); // verify that inline topics are enabled expect($('.check-discussion-subcategory-inline').prop('disabled')).toBeFalsy(); expect($('.check-discussion-category').prop('disabled')).toBeFalsy(); }); it('has divided and non-divided topics', function() { createDiscussionsView(this); enableSaveButton(); assertDividedTopics(this, 'inline'); }); it('enables "Save" button after changing from always inline option', function() { createDiscussionsView(this); enableSaveButton(); }); it('saves the topic', function() { createDiscussionsView(this); enableSaveButton(); // Save the updated settings $('.action-save').click(); mockPatchRequest(['Inline_Discussion_1']); mockGetRequest(); verifySuccess(); }); it('selects the parent category when all children are selected', function() { createDiscussionsView(this); enableSaveButton(); // parent category should be indeterminate. expect($('.check-discussion-category:checked').length).toBe(0); expect($('.check-discussion-category:indeterminate').length).toBe(1); $('.check-discussion-subcategory-inline').prop('checked', 'checked').change(); // parent should be checked as we checked all children expect($('.check-discussion-category:checked').length).toBe(1); }); it('selects/deselects all children when a parent category is selected/deselected', function() { createDiscussionsView(this); enableSaveButton(); expect($('.check-discussion-category:checked').length).toBe(0); $('.check-discussion-category').prop('checked', 'checked').change(); expect($('.check-discussion-category:checked').length).toBe(1); expect($('.check-discussion-subcategory-inline:checked').length).toBe(2); // un-check the parent, all children should be unchecd. $('.check-discussion-category').prop('checked', false).change(); expect($('.check-discussion-category:checked').length).toBe(0); expect($('.check-discussion-subcategory-inline:checked').length).toBe(0); }); it('saves correctly when a subset of topics are selected within a category', function() { createDiscussionsView(this); enableSaveButton(); // parent category should be indeterminate. expect($('.check-discussion-category:checked').length).toBe(0); expect($('.check-discussion-category:indeterminate').length).toBe(1); // Save the updated settings $('#cohort-inline-discussions-form .action-save').click(); mockPatchRequest(['Inline_Discussion_1']); mockGetRequest(); verifySuccess(); // parent category should be indeterminate. expect($('.check-discussion-category:indeterminate').length).toBe(1); }); it('saves correctly when all child topics are selected within a category', function() { createDiscussionsView(this); enableSaveButton(); // parent category should be indeterminate. expect($('.check-discussion-category:checked').length).toBe(0); expect($('.check-discussion-category:indeterminate').length).toBe(1); $('.check-discussion-subcategory-inline').prop('checked', 'checked').change(); // Save the updated settings $('#cohort-inline-discussions-form .action-save').click(); mockPatchRequest(['Inline_Discussion_1', 'Inline_Discussion_2']); mockGetRequest(true); verifySuccess(); // parent category should be checked. expect($('.check-discussion-category:checked').length).toBe(1); }); it('shows an appropriate message when no inline topics exist', function() { var topicsJson, options, expectedTitle; topicsJson = { course_wide_discussions: { children: [['Topic_C_1', 'entry']], entries: { Topic_C_1: { sort_key: null, is_divided: true, id: 'Topic_C_1' } } }, inline_discussions: { subcategories: {}, children: [] } }; options = {dividedDiscussions: new CourseDiscussionTopicDetailsModel(topicsJson)}; createDiscussionsView(this, options); expectedTitle = 'No content-specific discussion topics exist.'; expect($('.no-topics').text().trim()).toBe(expectedTitle); }); it('shows an appropriate message when subsequent "GET" returns HTTP500', function() { var expectedTitle; createDiscussionsView(this); enableSaveButton(); // Save the updated settings $('#cohort-inline-discussions-form .action-save').click(); mockPatchRequest(['Inline_Discussion_1']); // fake request for discussion/topics with GET method. AjaxHelpers.expectJsonRequest( requests, 'GET', '/mock_service/discussion/topics' ); AjaxHelpers.respondWithError(requests, 500); expectedTitle = "We've encountered an error. Refresh your browser and then try again."; expect($('.message-title').text().trim()).toBe(expectedTitle); }); it('shows an appropriate error message for HTTP500', function() { var expectedTitle; createDiscussionsView(this); enableSaveButton(); $($('.check-discussion-subcategory-inline')[1]).prop('checked', 'checked').change(); $('#cohort-inline-discussions-form .action-save').click(); AjaxHelpers.respondWithError(requests, 500); expectedTitle = "We've encountered an error. Refresh your browser and then try again."; expect($('.message-title').text().trim()).toBe(expectedTitle); }); }); }); }); });