Convert learner_dashboard to es2015
This commit is contained in:
committed by
Michael Terry
parent
acf7de7c02
commit
c9318c3e51
@@ -1,185 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/views/program_card_view',
|
||||
'js/learner_dashboard/collections/program_collection',
|
||||
'js/learner_dashboard/views/collection_list_view',
|
||||
'js/learner_dashboard/collections/program_progress_collection'
|
||||
], function(Backbone, $, ProgramCardView, ProgramCollection, CollectionListView, ProgressCollection) {
|
||||
'use strict';
|
||||
/* jslint maxlen: 500 */
|
||||
|
||||
describe('Collection List View', function() {
|
||||
var view = null,
|
||||
programCollection,
|
||||
progressCollection,
|
||||
context = {
|
||||
programsData: [
|
||||
{
|
||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||
title: 'Food Security and Sustainability',
|
||||
subtitle: 'Learn how to feed all people in the world in a sustainable way.',
|
||||
type: 'XSeries',
|
||||
detail_url: 'https://www.edx.org/foo/bar',
|
||||
banner_image: {
|
||||
medium: {
|
||||
height: 242,
|
||||
width: 726,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.medium.jpg'
|
||||
},
|
||||
'x-small': {
|
||||
height: 116,
|
||||
width: 348,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.x-small.jpg'
|
||||
},
|
||||
small: {
|
||||
height: 145,
|
||||
width: 435,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.small.jpg'
|
||||
},
|
||||
large: {
|
||||
height: 480,
|
||||
width: 1440,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.large.jpg'
|
||||
}
|
||||
},
|
||||
authoring_organizations: [
|
||||
{
|
||||
uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22',
|
||||
key: 'WageningenX',
|
||||
name: 'Wageningen University & Research'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
uuid: '91d144d2-1bb1-4afe-90df-d5cff63fa6e2',
|
||||
title: 'edX Course Creator',
|
||||
subtitle: 'Become an expert in creating courses for the edX platform.',
|
||||
type: 'XSeries',
|
||||
detail_url: 'https://www.edx.org/foo/bar',
|
||||
banner_image: {
|
||||
medium: {
|
||||
height: 242,
|
||||
width: 726,
|
||||
url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.medium.jpg'
|
||||
},
|
||||
'x-small': {
|
||||
height: 116,
|
||||
width: 348,
|
||||
url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.x-small.jpg'
|
||||
},
|
||||
small: {
|
||||
height: 145,
|
||||
width: 435,
|
||||
url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.small.jpg'
|
||||
},
|
||||
large: {
|
||||
height: 480,
|
||||
width: 1440,
|
||||
url: 'https://example.com/91d144d2-1bb1-4afe-90df-d5cff63fa6e2.large.jpg'
|
||||
}
|
||||
},
|
||||
authoring_organizations: [
|
||||
{
|
||||
uuid: '4f8cb2c9-589b-4d1e-88c1-b01a02db3a9c',
|
||||
key: 'edX',
|
||||
name: 'edX'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
userProgress: [
|
||||
{
|
||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||
completed: 4,
|
||||
in_progress: 2,
|
||||
not_started: 4
|
||||
},
|
||||
{
|
||||
uuid: '91d144d2-1bb1-4afe-90df-d5cff63fa6e2',
|
||||
completed: 1,
|
||||
in_progress: 0,
|
||||
not_started: 3
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="program-cards-container"></div>');
|
||||
programCollection = new ProgramCollection(context.programsData);
|
||||
progressCollection = new ProgressCollection();
|
||||
progressCollection.set(context.userProgress);
|
||||
context.progressCollection = progressCollection;
|
||||
|
||||
view = new CollectionListView({
|
||||
el: '.program-cards-container',
|
||||
childView: ProgramCardView,
|
||||
collection: programCollection,
|
||||
context: context
|
||||
});
|
||||
view.render();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should load the collection items based on passed in collection', function() {
|
||||
var $cards = view.$el.find('.program-card');
|
||||
expect($cards.length).toBe(2);
|
||||
$cards.each(function(index, el) {
|
||||
// eslint-disable-next-line newline-per-chained-call
|
||||
expect($(el).find('.title').html().trim()).toEqual(context.programsData[index].title);
|
||||
});
|
||||
});
|
||||
|
||||
it('should display no item if collection is empty', function() {
|
||||
var $cards;
|
||||
view.remove();
|
||||
programCollection = new ProgramCollection([]);
|
||||
view = new CollectionListView({
|
||||
el: '.program-cards-container',
|
||||
childView: ProgramCardView,
|
||||
context: {},
|
||||
collection: programCollection
|
||||
});
|
||||
view.render();
|
||||
$cards = view.$el.find('.program-card');
|
||||
expect($cards.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should have no title when title not provided', function() {
|
||||
var $title;
|
||||
setFixtures('<div class="test-container"><div class="program-cards-container"></div></div>');
|
||||
view.remove();
|
||||
view.render();
|
||||
expect(view).toBeDefined();
|
||||
$title = view.$el.parent().find('.collection-title');
|
||||
expect($title.html()).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should display screen reader header when provided', function() {
|
||||
var titleContext = {el: 'h2', title: 'list start'},
|
||||
$title;
|
||||
|
||||
view.remove();
|
||||
setFixtures('<div class="test-container"><div class="program-cards-container"></div></div>');
|
||||
programCollection = new ProgramCollection(context.programsData);
|
||||
view = new CollectionListView({
|
||||
el: '.program-cards-container',
|
||||
childView: ProgramCardView,
|
||||
context: context,
|
||||
collection: programCollection,
|
||||
titleContext: titleContext
|
||||
});
|
||||
view.render();
|
||||
$title = view.$el.parent().find('.collection-title');
|
||||
expect($title.html()).toBe(titleContext.title);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,272 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/models/course_card_model',
|
||||
'js/learner_dashboard/views/course_card_view'
|
||||
], function(Backbone, $, CourseCardModel, CourseCardView) {
|
||||
'use strict';
|
||||
|
||||
describe('Course Card View', function() {
|
||||
var view = null,
|
||||
courseCardModel,
|
||||
course,
|
||||
startDate = 'Feb 28, 2017',
|
||||
endDate = 'May 30, 2017',
|
||||
|
||||
setupView = function(data, isEnrolled, collectionCourseStatus) {
|
||||
var programData = $.extend({}, data),
|
||||
context = {
|
||||
courseData: {
|
||||
grades: {
|
||||
'course-v1:WageningenX+FFESx+1T2017': 0.8
|
||||
}
|
||||
},
|
||||
collectionCourseStatus: collectionCourseStatus
|
||||
};
|
||||
|
||||
if (typeof collectionCourseStatus === 'undefined') {
|
||||
context.collectionCourseStatus = 'completed';
|
||||
}
|
||||
|
||||
programData.course_runs[0].is_enrolled = isEnrolled;
|
||||
setFixtures('<div class="program-course-card"></div>');
|
||||
courseCardModel = new CourseCardModel(programData);
|
||||
view = new CourseCardView({
|
||||
model: courseCardModel,
|
||||
context: context
|
||||
});
|
||||
},
|
||||
|
||||
validateCourseInfoDisplay = function() {
|
||||
// DRY validation for course card in enrolled state
|
||||
expect(view.$('.course-details .course-title-link').text().trim()).toEqual(course.title);
|
||||
expect(view.$('.course-details .course-title-link').attr('href')).toEqual(
|
||||
course.course_runs[0].marketing_url
|
||||
);
|
||||
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
||||
startDate + ' - ' + endDate
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
// NOTE: This data is redefined prior to each test case so that tests
|
||||
// can't break each other by modifying data copied by reference.
|
||||
course = {
|
||||
key: 'WageningenX+FFESx',
|
||||
uuid: '9f8562eb-f99b-45c7-b437-799fd0c15b6a',
|
||||
title: 'Systems thinking and environmental sustainability',
|
||||
course_runs: [
|
||||
{
|
||||
key: 'course-v1:WageningenX+FFESx+1T2017',
|
||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
||||
image: {
|
||||
src: 'https://example.com/9f8562eb-f99b-45c7-b437-799fd0c15b6a.jpg'
|
||||
},
|
||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability',
|
||||
start: '2017-02-28T05:00:00Z',
|
||||
end: '2017-05-30T23:00:00Z',
|
||||
enrollment_start: '2017-01-18T00:00:00Z',
|
||||
enrollment_end: null,
|
||||
type: 'verified',
|
||||
certificate_url: '',
|
||||
course_url: 'https://courses.example.com/courses/course-v1:WageningenX+FFESx+1T2017',
|
||||
enrollment_open_date: 'Jan 18, 2016',
|
||||
is_course_ended: false,
|
||||
is_enrolled: true,
|
||||
is_enrollment_open: true,
|
||||
status: 'published',
|
||||
upgrade_url: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
setupView(course, true);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render final grade if course is completed', function() {
|
||||
view.remove();
|
||||
setupView(course, true);
|
||||
expect(view.$('.grade-display').text()).toEqual('80%');
|
||||
});
|
||||
|
||||
it('should not render final grade if course has not been completed', function() {
|
||||
view.remove();
|
||||
setupView(course, true, 'in_progress');
|
||||
expect(view.$('.final-grade').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should render the course card based on the data not enrolled', function() {
|
||||
view.remove();
|
||||
setupView(course, false);
|
||||
validateCourseInfoDisplay();
|
||||
});
|
||||
|
||||
it('should update render if the course card is_enrolled updated', function() {
|
||||
setupView(course, false);
|
||||
courseCardModel.set({
|
||||
is_enrolled: true
|
||||
});
|
||||
validateCourseInfoDisplay();
|
||||
});
|
||||
|
||||
it('should show the course advertised start date', function() {
|
||||
var advertisedStart = 'A long time ago...';
|
||||
course.course_runs[0].advertised_start = advertisedStart;
|
||||
|
||||
setupView(course, false);
|
||||
|
||||
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
||||
advertisedStart + ' - ' + endDate
|
||||
);
|
||||
});
|
||||
|
||||
it('should only show certificate status section if a certificate has been earned', function() {
|
||||
var certUrl = 'sample-certificate';
|
||||
|
||||
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||
view.remove();
|
||||
|
||||
course.course_runs[0].certificate_url = certUrl;
|
||||
setupView(course, false);
|
||||
expect(view.$('.course-certificate .certificate-status').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should only show upgrade message section if an upgrade is required', function() {
|
||||
var upgradeUrl = '/path/to/upgrade';
|
||||
|
||||
expect(view.$('.upgrade-message').length).toEqual(0);
|
||||
view.remove();
|
||||
|
||||
course.course_runs[0].upgrade_url = upgradeUrl;
|
||||
setupView(course, false);
|
||||
expect(view.$('.upgrade-message').length).toEqual(1);
|
||||
expect(view.$('.upgrade-message .cta-primary').attr('href')).toEqual(upgradeUrl);
|
||||
});
|
||||
|
||||
it('should not show both the upgrade message and certificate status sections', function() {
|
||||
// Verify that no empty elements are left in the DOM.
|
||||
course.course_runs[0].upgrade_url = '';
|
||||
course.course_runs[0].certificate_url = '';
|
||||
setupView(course, false);
|
||||
expect(view.$('.upgrade-message').length).toEqual(0);
|
||||
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||
view.remove();
|
||||
|
||||
// Verify that the upgrade message takes priority.
|
||||
course.course_runs[0].upgrade_url = '/path/to/upgrade';
|
||||
course.course_runs[0].certificate_url = '/path/to/certificate';
|
||||
setupView(course, false);
|
||||
expect(view.$('.upgrade-message').length).toEqual(1);
|
||||
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should allow enrollment in future runs when the user has an expired enrollment', function() {
|
||||
var newRun = $.extend({}, course.course_runs[0]),
|
||||
newRunKey = 'course-v1:foo+bar+baz',
|
||||
advertisedStart = 'Summer';
|
||||
|
||||
newRun.key = newRunKey;
|
||||
newRun.is_enrolled = false;
|
||||
newRun.advertised_start = advertisedStart;
|
||||
course.course_runs.push(newRun);
|
||||
|
||||
course.expired = true;
|
||||
|
||||
setupView(course, true);
|
||||
|
||||
expect(courseCardModel.get('course_run_key')).toEqual(newRunKey);
|
||||
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
||||
advertisedStart + ' - ' + endDate
|
||||
);
|
||||
});
|
||||
|
||||
it('should show a message if an there is an upcoming course run', function() {
|
||||
course.course_runs[0].is_enrollment_open = false;
|
||||
|
||||
setupView(course, false);
|
||||
|
||||
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
||||
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
||||
expect(view.$('.no-action-message').text().trim()).toBe('Coming Soon');
|
||||
expect(view.$('.enrollment-open-date').text().trim()).toEqual(
|
||||
course.course_runs[0].enrollment_open_date
|
||||
);
|
||||
});
|
||||
|
||||
it('should show a message if there are no upcoming course runs', function() {
|
||||
course.course_runs[0].is_enrollment_open = false;
|
||||
course.course_runs[0].is_course_ended = true;
|
||||
|
||||
setupView(course, false);
|
||||
|
||||
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
||||
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
||||
expect(view.$('.no-action-message').text().trim()).toBe('Not Currently Available');
|
||||
expect(view.$('.enrollment-opens').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should link to the marketing site when the user is not enrolled', function() {
|
||||
setupView(course, false);
|
||||
expect(view.$('.course-title-link').attr('href')).toEqual(course.course_runs[0].marketing_url);
|
||||
});
|
||||
|
||||
it('should link to the course home when the user is enrolled', function() {
|
||||
setupView(course, true);
|
||||
expect(view.$('.course-title-link').attr('href')).toEqual(course.course_runs[0].course_url);
|
||||
});
|
||||
|
||||
it('should not link to the marketing site if the URL is not available', function() {
|
||||
course.course_runs[0].marketing_url = null;
|
||||
setupView(course, false);
|
||||
|
||||
expect(view.$('.course-title-link').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should not link to the course home if the URL is not available', function() {
|
||||
course.course_runs[0].course_url = null;
|
||||
setupView(course, true);
|
||||
|
||||
expect(view.$('.course-title-link').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should show an unfulfilled user entitlement allows you to select a session', function() {
|
||||
course.user_entitlement = {
|
||||
uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
course_uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
expiration_date: '2017-12-05 01:06:12'
|
||||
};
|
||||
setupView(course, false);
|
||||
expect(view.$('.info-expires-at').text().trim()).toContain('You must select a session by');
|
||||
});
|
||||
|
||||
it('should show a fulfilled expired user entitlement does not allow the changing of sessions', function() {
|
||||
course.user_entitlement = {
|
||||
uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
course_uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
expired_at: '2017-12-06 01:06:12',
|
||||
expiration_date: '2017-12-05 01:06:12'
|
||||
};
|
||||
setupView(course, true);
|
||||
expect(view.$('.info-expires-at').text().trim()).toContain('You can no longer change sessions.');
|
||||
});
|
||||
|
||||
it('should show a fulfilled user entitlement allows the changing of sessions', function() {
|
||||
course.user_entitlement = {
|
||||
uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
course_uuid: '99fc7414c36d4f56b37e8e30acf4c7ba',
|
||||
expiration_date: '2017-12-05 01:06:12'
|
||||
};
|
||||
setupView(course, true);
|
||||
expect(view.$('.info-expires-at').text().trim()).toContain('You can change sessions until');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,307 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/models/course_card_model',
|
||||
'js/learner_dashboard/models/course_enroll_model',
|
||||
'js/learner_dashboard/views/course_enroll_view'
|
||||
], function(Backbone, $, CourseCardModel, CourseEnrollModel, CourseEnrollView) {
|
||||
'use strict';
|
||||
|
||||
describe('Course Enroll View', function() {
|
||||
var view = null,
|
||||
courseCardModel,
|
||||
courseEnrollModel,
|
||||
urlModel,
|
||||
setupView,
|
||||
singleCourseRunList,
|
||||
multiCourseRunList,
|
||||
course = {
|
||||
key: 'WageningenX+FFESx',
|
||||
uuid: '9f8562eb-f99b-45c7-b437-799fd0c15b6a',
|
||||
title: 'Systems thinking and environmental sustainability',
|
||||
owners: [
|
||||
{
|
||||
uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22',
|
||||
key: 'WageningenX',
|
||||
name: 'Wageningen University & Research'
|
||||
}
|
||||
]
|
||||
},
|
||||
urls = {
|
||||
commerce_api_url: '/commerce',
|
||||
track_selection_url: '/select_track/course/'
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
// Stub analytics tracking
|
||||
window.analytics = jasmine.createSpyObj('analytics', ['track']);
|
||||
|
||||
// NOTE: This data is redefined prior to each test case so that tests
|
||||
// can't break each other by modifying data copied by reference.
|
||||
singleCourseRunList = [{
|
||||
key: 'course-v1:WageningenX+FFESx+1T2017',
|
||||
uuid: '2f2edf03-79e6-4e39-aef0-65436a6ee344',
|
||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
||||
image: {
|
||||
src: 'https://example.com/2f2edf03-79e6-4e39-aef0-65436a6ee344.jpg'
|
||||
},
|
||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-ffesx',
|
||||
start: '2017-02-28T05:00:00Z',
|
||||
end: '2017-05-30T23:00:00Z',
|
||||
enrollment_start: '2017-01-18T00:00:00Z',
|
||||
enrollment_end: null,
|
||||
type: 'verified',
|
||||
certificate_url: '',
|
||||
course_url: 'https://courses.example.com/courses/course-v1:edX+DemoX+Demo_Course',
|
||||
enrollment_open_date: 'Jan 18, 2016',
|
||||
is_course_ended: false,
|
||||
is_enrolled: false,
|
||||
is_enrollment_open: true,
|
||||
status: 'published',
|
||||
upgrade_url: ''
|
||||
}];
|
||||
|
||||
multiCourseRunList = [{
|
||||
key: 'course-v1:WageningenX+FFESx+2T2016',
|
||||
uuid: '9bbb7844-4848-44ab-8e20-0be6604886e9',
|
||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
||||
image: {
|
||||
src: 'https://example.com/9bbb7844-4848-44ab-8e20-0be6604886e9.jpg'
|
||||
},
|
||||
short_description: 'Learn how to apply systems thinking to improve food production systems.',
|
||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-stesx',
|
||||
start: '2016-09-08T04:00:00Z',
|
||||
end: '2016-11-11T00:00:00Z',
|
||||
enrollment_start: null,
|
||||
enrollment_end: null,
|
||||
pacing_type: 'instructor_paced',
|
||||
type: 'verified',
|
||||
certificate_url: '',
|
||||
course_url: 'https://courses.example.com/courses/course-v1:WageningenX+FFESx+2T2016',
|
||||
enrollment_open_date: 'Jan 18, 2016',
|
||||
is_course_ended: false,
|
||||
is_enrolled: false,
|
||||
is_enrollment_open: true,
|
||||
status: 'published'
|
||||
}, {
|
||||
key: 'course-v1:WageningenX+FFESx+1T2017',
|
||||
uuid: '2f2edf03-79e6-4e39-aef0-65436a6ee344',
|
||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
||||
image: {
|
||||
src: 'https://example.com/2f2edf03-79e6-4e39-aef0-65436a6ee344.jpg'
|
||||
},
|
||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-ffesx',
|
||||
start: '2017-02-28T05:00:00Z',
|
||||
end: '2017-05-30T23:00:00Z',
|
||||
enrollment_start: '2017-01-18T00:00:00Z',
|
||||
enrollment_end: null,
|
||||
type: 'verified',
|
||||
certificate_url: '',
|
||||
course_url: 'https://courses.example.com/courses/course-v1:WageningenX+FFESx+1T2017',
|
||||
enrollment_open_date: 'Jan 18, 2016',
|
||||
is_course_ended: false,
|
||||
is_enrolled: false,
|
||||
is_enrollment_open: true,
|
||||
status: 'published'
|
||||
}];
|
||||
});
|
||||
|
||||
setupView = function(courseRuns, urlMap) {
|
||||
course.course_runs = courseRuns;
|
||||
setFixtures('<div class="course-actions"></div>');
|
||||
courseCardModel = new CourseCardModel(course);
|
||||
courseEnrollModel = new CourseEnrollModel({}, {
|
||||
courseId: courseCardModel.get('course_run_key')
|
||||
});
|
||||
if (urlMap) {
|
||||
urlModel = new Backbone.Model(urlMap);
|
||||
}
|
||||
view = new CourseEnrollView({
|
||||
$parentEl: $('.course-actions'),
|
||||
model: courseCardModel,
|
||||
enrollModel: courseEnrollModel,
|
||||
urlModel: urlModel
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
urlModel = null;
|
||||
courseCardModel = null;
|
||||
courseEnrollModel = null;
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
setupView(singleCourseRunList);
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render the course enroll view when not enrolled', function() {
|
||||
setupView(singleCourseRunList);
|
||||
expect(view.$('.enroll-button').text().trim()).toEqual('Enroll Now');
|
||||
expect(view.$('.run-select').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should render the course enroll view when enrolled', function() {
|
||||
singleCourseRunList[0].is_enrolled = true;
|
||||
|
||||
setupView(singleCourseRunList);
|
||||
expect(view.$('.view-course-button').text().trim()).toEqual('View Course');
|
||||
expect(view.$('.run-select').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should not render anything if course runs are empty', function() {
|
||||
setupView([]);
|
||||
|
||||
expect(view.$('.run-select').length).toBe(0);
|
||||
expect(view.$('.enroll-button').length).toBe(0);
|
||||
});
|
||||
|
||||
it('should render run selection dropdown if multiple course runs are available', function() {
|
||||
setupView(multiCourseRunList);
|
||||
|
||||
expect(view.$('.run-select').length).toBe(1);
|
||||
expect(view.$('.run-select').val()).toEqual(multiCourseRunList[0].key);
|
||||
expect(view.$('.run-select option').length).toBe(2);
|
||||
});
|
||||
|
||||
it('should not allow enrollment in unpublished course runs', function() {
|
||||
multiCourseRunList[0].status = 'unpublished';
|
||||
|
||||
setupView(multiCourseRunList);
|
||||
expect(view.$('.run-select').length).toBe(0);
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not allow enrollment in course runs with a null status', function() {
|
||||
multiCourseRunList[0].status = null;
|
||||
|
||||
setupView(multiCourseRunList);
|
||||
expect(view.$('.run-select').length).toBe(0);
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should enroll learner when enroll button is clicked with one course run available', function() {
|
||||
setupView(singleCourseRunList);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
|
||||
spyOn(courseEnrollModel, 'save');
|
||||
|
||||
view.$('.enroll-button').click();
|
||||
|
||||
expect(courseEnrollModel.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should enroll learner when enroll button is clicked with multiple course runs available', function() {
|
||||
setupView(multiCourseRunList);
|
||||
|
||||
spyOn(courseEnrollModel, 'save');
|
||||
|
||||
view.$('.run-select').val(multiCourseRunList[1].key);
|
||||
view.$('.run-select').trigger('change');
|
||||
view.$('.enroll-button').click();
|
||||
|
||||
expect(courseEnrollModel.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should redirect to track selection when audit enrollment succeeds', function() {
|
||||
singleCourseRunList[0].is_enrolled = false;
|
||||
singleCourseRunList[0].mode_slug = 'audit';
|
||||
|
||||
setupView(singleCourseRunList, urls);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
expect(view.trackSelectionUrl).toBeDefined();
|
||||
|
||||
spyOn(view, 'redirect');
|
||||
|
||||
view.enrollSuccess();
|
||||
|
||||
expect(view.redirect).toHaveBeenCalledWith(
|
||||
view.trackSelectionUrl + courseCardModel.get('course_run_key'));
|
||||
});
|
||||
|
||||
it('should redirect to track selection when enrollment in an unspecified mode is attempted', function() {
|
||||
singleCourseRunList[0].is_enrolled = false;
|
||||
singleCourseRunList[0].mode_slug = null;
|
||||
|
||||
setupView(singleCourseRunList, urls);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
expect(view.trackSelectionUrl).toBeDefined();
|
||||
|
||||
spyOn(view, 'redirect');
|
||||
|
||||
view.enrollSuccess();
|
||||
|
||||
expect(view.redirect).toHaveBeenCalledWith(
|
||||
view.trackSelectionUrl + courseCardModel.get('course_run_key')
|
||||
);
|
||||
});
|
||||
|
||||
it('should not redirect when urls are not provided', function() {
|
||||
singleCourseRunList[0].is_enrolled = false;
|
||||
singleCourseRunList[0].mode_slug = 'verified';
|
||||
|
||||
setupView(singleCourseRunList);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
expect(view.verificationUrl).not.toBeDefined();
|
||||
expect(view.dashboardUrl).not.toBeDefined();
|
||||
expect(view.trackSelectionUrl).not.toBeDefined();
|
||||
|
||||
spyOn(view, 'redirect');
|
||||
|
||||
view.enrollSuccess();
|
||||
|
||||
expect(view.redirect).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should redirect to track selection on error', function() {
|
||||
setupView(singleCourseRunList, urls);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
expect(view.trackSelectionUrl).toBeDefined();
|
||||
|
||||
spyOn(view, 'redirect');
|
||||
|
||||
view.enrollError(courseEnrollModel, {status: 500});
|
||||
expect(view.redirect).toHaveBeenCalledWith(
|
||||
view.trackSelectionUrl + courseCardModel.get('course_run_key')
|
||||
);
|
||||
});
|
||||
|
||||
it('should redirect to login on 403 error', function() {
|
||||
var response = {
|
||||
status: 403,
|
||||
responseJSON: {
|
||||
user_message_url: 'redirect/to/this'
|
||||
}
|
||||
};
|
||||
|
||||
setupView(singleCourseRunList, urls);
|
||||
|
||||
expect(view.$('.enroll-button').length).toBe(1);
|
||||
expect(view.trackSelectionUrl).toBeDefined();
|
||||
|
||||
spyOn(view, 'redirect');
|
||||
|
||||
view.enrollError(courseEnrollModel, response);
|
||||
|
||||
expect(view.redirect).toHaveBeenCalledWith(
|
||||
response.responseJSON.user_message_url
|
||||
);
|
||||
});
|
||||
|
||||
it('sends analytics event when enrollment succeeds', function() {
|
||||
setupView(singleCourseRunList, urls);
|
||||
spyOn(view, 'redirect');
|
||||
view.enrollSuccess();
|
||||
expect(window.analytics.track).toHaveBeenCalledWith(
|
||||
'edx.bi.user.program-details.enrollment'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,188 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'underscore',
|
||||
'jquery',
|
||||
'js/learner_dashboard/models/course_entitlement_model',
|
||||
'js/learner_dashboard/views/course_entitlement_view'
|
||||
], function(Backbone, _, $, CourseEntitlementModel, CourseEntitlementView) {
|
||||
'use strict';
|
||||
|
||||
describe('Course Entitlement View', function() {
|
||||
var view = null,
|
||||
setupView,
|
||||
sessionIndex,
|
||||
selectOptions,
|
||||
entitlementAvailableSessions,
|
||||
initialSessionId,
|
||||
alreadyEnrolled,
|
||||
hasSessions,
|
||||
entitlementUUID = 'a9aiuw76a4ijs43u18',
|
||||
testSessionIds = ['test_session_id_1', 'test_session_id_2'];
|
||||
|
||||
setupView = function(isAlreadyEnrolled, hasAvailableSessions, specificSessionIndex) {
|
||||
setFixtures('<div class="course-entitlement-selection-container"></div>');
|
||||
alreadyEnrolled = (typeof isAlreadyEnrolled !== 'undefined') ? isAlreadyEnrolled : true;
|
||||
hasSessions = (typeof hasAvailableSessions !== 'undefined') ? hasAvailableSessions : true;
|
||||
sessionIndex = (typeof specificSessionIndex !== 'undefined') ? specificSessionIndex : 0;
|
||||
|
||||
initialSessionId = alreadyEnrolled ? testSessionIds[sessionIndex] : '';
|
||||
entitlementAvailableSessions = [];
|
||||
if (hasSessions) {
|
||||
entitlementAvailableSessions = [{
|
||||
enrollment_end: null,
|
||||
start: '2016-02-05T05:00:00+00:00',
|
||||
pacing_type: 'instructor_paced',
|
||||
session_id: testSessionIds[0],
|
||||
end: null
|
||||
}, {
|
||||
enrollment_end: '2019-12-22T03:30:00Z',
|
||||
start: '2020-01-03T13:00:00+00:00',
|
||||
pacing_type: 'self_paced',
|
||||
session_id: testSessionIds[1],
|
||||
end: '2020-03-09T21:30:00+00:00'
|
||||
}];
|
||||
}
|
||||
|
||||
view = new CourseEntitlementView({
|
||||
el: '.course-entitlement-selection-container',
|
||||
triggerOpenBtn: '#course-card-0 .change-session',
|
||||
courseCardMessages: '#course-card-0 .messages-list > .message',
|
||||
courseTitleLink: '#course-card-0 .course-title a',
|
||||
courseImageLink: '#course-card-0 .wrapper-course-image > a',
|
||||
dateDisplayField: '#course-card-0 .info-date-block',
|
||||
enterCourseBtn: '#course-card-0 .enter-course',
|
||||
availableSessions: JSON.stringify(entitlementAvailableSessions),
|
||||
entitlementUUID: entitlementUUID,
|
||||
currentSessionId: initialSessionId,
|
||||
userId: '1',
|
||||
enrollUrl: '/api/enrollment/v1/enrollment',
|
||||
courseHomeUrl: '/courses/course-v1:edX+DemoX+Demo_Course/course/'
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(function() {
|
||||
if (view) view.remove();
|
||||
});
|
||||
|
||||
describe('Initialization of view', function() {
|
||||
it('Should create a entitlement view element', function() {
|
||||
setupView(false);
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Available Sessions Select - Unfulfilled Entitlement', function() {
|
||||
beforeEach(function() {
|
||||
setupView(false);
|
||||
selectOptions = view.$('.session-select').find('option');
|
||||
});
|
||||
|
||||
it('Select session dropdown should show all available course runs and a coming soon option.', function() {
|
||||
expect(selectOptions.length).toEqual(entitlementAvailableSessions.length + 1);
|
||||
});
|
||||
|
||||
it('Self paced courses should have visual indication in the selection option.', function() {
|
||||
var selfPacedOptionIndex = _.findIndex(entitlementAvailableSessions, function(session) {
|
||||
return session.pacing_type === 'self_paced';
|
||||
});
|
||||
var selfPacedOption = selectOptions[selfPacedOptionIndex];
|
||||
expect(selfPacedOption && selfPacedOption.text.includes('(Self-paced)')).toBe(true);
|
||||
});
|
||||
|
||||
it('Courses with an an enroll by date should indicate so on the selection option.', function() {
|
||||
var enrollEndSetOptionIndex = _.findIndex(entitlementAvailableSessions, function(session) {
|
||||
return session.enrollment_end !== null;
|
||||
});
|
||||
var enrollEndSetOption = selectOptions[enrollEndSetOptionIndex];
|
||||
expect(enrollEndSetOption && enrollEndSetOption.text.includes('Open until')).toBe(true);
|
||||
});
|
||||
|
||||
it('Title element should correctly indicate the expected behavior.', function() {
|
||||
expect(view.$('.action-header').text().includes(
|
||||
'To access the course, select a session.'
|
||||
)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Available Sessions Select - Unfulfilled Entitlement without available sessions', function() {
|
||||
beforeEach(function() {
|
||||
setupView(false, false);
|
||||
});
|
||||
|
||||
it('Should notify user that more sessions are coming soon if none available.', function() {
|
||||
expect(view.$('.action-header').text().includes('More sessions coming soon.')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Available Sessions Select - Fulfilled Entitlement', function() {
|
||||
beforeEach(function() {
|
||||
setupView(true);
|
||||
selectOptions = view.$('.session-select').find('option');
|
||||
});
|
||||
|
||||
it('Select session dropdown should show available course runs, coming soon and leave options.', function() {
|
||||
expect(selectOptions.length).toEqual(entitlementAvailableSessions.length + 2);
|
||||
});
|
||||
|
||||
it('Select session dropdown should allow user to leave the current session.', function() {
|
||||
var leaveSessionOption = selectOptions[selectOptions.length - 1];
|
||||
expect(leaveSessionOption.text.includes('Leave the current session and decide later')).toBe(true);
|
||||
});
|
||||
|
||||
it('Currently selected session should be specified in the dropdown options.', function() {
|
||||
var selectedSessionIndex = _.findIndex(entitlementAvailableSessions, function(session) {
|
||||
return initialSessionId === session.session_id;
|
||||
});
|
||||
expect(selectOptions[selectedSessionIndex].text.includes('Currently Selected')).toBe(true);
|
||||
});
|
||||
|
||||
it('Title element should correctly indicate the expected behavior.', function() {
|
||||
expect(view.$('.action-header').text().includes(
|
||||
'Change to a different session or leave the current session.'
|
||||
)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Available Sessions Select - Fulfilled Entitlement (session in the future)', function() {
|
||||
beforeEach(function() {
|
||||
setupView(true, true, 1);
|
||||
});
|
||||
|
||||
it('Currently selected session should initialize to selected in the dropdown options.', function() {
|
||||
var selectedOption = view.$('.session-select').find('option:selected');
|
||||
expect(selectedOption.data('session_id')).toEqual(testSessionIds[1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Select Session Action Button and popover behavior - Unfulfilled Entitlement', function() {
|
||||
beforeEach(function() {
|
||||
setupView(false);
|
||||
});
|
||||
|
||||
it('Change session button should have the correct text.', function() {
|
||||
expect(view.$('.enroll-btn-initial').text() === 'Select Session').toBe(true);
|
||||
});
|
||||
|
||||
it('Select session button should show popover when clicked.', function() {
|
||||
view.$('.enroll-btn-initial').click();
|
||||
expect(view.$('.verification-modal').length > 0).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Change Session Action Button and popover behavior - Fulfilled Entitlement', function() {
|
||||
beforeEach(function() {
|
||||
setupView(true);
|
||||
selectOptions = view.$('.session-select').find('option');
|
||||
});
|
||||
|
||||
it('Change session button should show correct text.', function() {
|
||||
expect(view.$('.enroll-btn-initial').text().trim() === 'Change Session').toBe(true);
|
||||
});
|
||||
|
||||
it('Switch session button should be disabled when on the currently enrolled session.', function() {
|
||||
expect(view.$('.enroll-btn-initial')).toHaveClass('disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,193 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/views/entitlement_unenrollment_view'
|
||||
], function(Backbone, $, EntitlementUnenrollmentView) {
|
||||
'use strict';
|
||||
|
||||
describe('EntitlementUnenrollmentView', function() {
|
||||
var view = null,
|
||||
options = {
|
||||
dashboardPath: '/dashboard',
|
||||
signInPath: '/login'
|
||||
},
|
||||
|
||||
initView = function() {
|
||||
return new EntitlementUnenrollmentView(options);
|
||||
},
|
||||
|
||||
modalHtml = '<a id="link1" class="js-entitlement-action-unenroll" ' +
|
||||
' data-course-name="Test Course 1" ' +
|
||||
' data-course-number="test1" ' +
|
||||
' data-entitlement-api-endpoint="/test/api/endpoint/1">Unenroll</a> ' +
|
||||
'<a id="link2" class="js-entitlement-action-unenroll" ' +
|
||||
' data-course-name="Test Course 2" ' +
|
||||
' data-course-number="test2" ' +
|
||||
' data-entitlement-api-endpoint="/test/api/endpoint/2">Unenroll</a> ' +
|
||||
'<div class="js-entitlement-unenrollment-modal"> ' +
|
||||
' <span class="js-entitlement-unenrollment-modal-header-text"></span> ' +
|
||||
' <span class="js-entitlement-unenrollment-modal-error-text"></span> ' +
|
||||
' <button class="js-entitlement-unenrollment-modal-submit">Unenroll</button> ' +
|
||||
'</div> ';
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures(modalHtml);
|
||||
view = initView();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
describe('when an unenroll link is clicked', function() {
|
||||
it('should reset the modal and set the correct values for header/submit', function() {
|
||||
var $link1 = $('#link1'),
|
||||
$link2 = $('#link2'),
|
||||
$headerTxt = $('.js-entitlement-unenrollment-modal-header-text'),
|
||||
$errorTxt = $('.js-entitlement-unenrollment-modal-error-text'),
|
||||
$submitBtn = $('.js-entitlement-unenrollment-modal-submit');
|
||||
|
||||
$link1.trigger('click');
|
||||
expect($headerTxt.html().startsWith('Are you sure you want to unenroll from Test Course 1')).toBe(true);
|
||||
expect($submitBtn.data()).toEqual({entitlementApiEndpoint: '/test/api/endpoint/1'});
|
||||
expect($submitBtn.prop('disabled')).toBe(false);
|
||||
expect($errorTxt.html()).toEqual('');
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(false);
|
||||
|
||||
// Set an error so that we can see that the modal is reset properly when clicked again
|
||||
view.setError('This is an error');
|
||||
expect($errorTxt.html()).toEqual('This is an error');
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(true);
|
||||
expect($submitBtn.prop('disabled')).toBe(true);
|
||||
|
||||
$link2.trigger('click');
|
||||
expect($headerTxt.html().startsWith('Are you sure you want to unenroll from Test Course 2')).toBe(true);
|
||||
expect($submitBtn.data()).toEqual({entitlementApiEndpoint: '/test/api/endpoint/2'});
|
||||
expect($submitBtn.prop('disabled')).toBe(false);
|
||||
expect($errorTxt.html()).toEqual('');
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the unenroll submit button is clicked', function() {
|
||||
it('should send a DELETE request to the configured apiEndpoint', function() {
|
||||
var $submitBtn = $('.js-entitlement-unenrollment-modal-submit'),
|
||||
apiEndpoint = '/test/api/endpoint/1';
|
||||
|
||||
view.setSubmitData(apiEndpoint);
|
||||
|
||||
spyOn($, 'ajax').and.callFake(function(opts) {
|
||||
expect(opts.url).toEqual(apiEndpoint);
|
||||
expect(opts.method).toEqual('DELETE');
|
||||
expect(opts.complete).toBeTruthy();
|
||||
});
|
||||
|
||||
$submitBtn.trigger('click');
|
||||
expect($.ajax).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set an error and disable submit if the apiEndpoint has not been properly set', function() {
|
||||
var $errorTxt = $('.js-entitlement-unenrollment-modal-error-text'),
|
||||
$submitBtn = $('.js-entitlement-unenrollment-modal-submit');
|
||||
|
||||
expect($submitBtn.data()).toEqual({});
|
||||
expect($submitBtn.prop('disabled')).toBe(false);
|
||||
expect($errorTxt.html()).toEqual('');
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(false);
|
||||
|
||||
spyOn($, 'ajax');
|
||||
$submitBtn.trigger('click');
|
||||
expect($.ajax).not.toHaveBeenCalled();
|
||||
|
||||
expect($submitBtn.data()).toEqual({});
|
||||
expect($submitBtn.prop('disabled')).toBe(true);
|
||||
expect($errorTxt.html()).toEqual(view.genericErrorMsg);
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(true);
|
||||
});
|
||||
|
||||
describe('when the unenroll request is complete', function() {
|
||||
it('should redirect to the dashboard if the request was successful', function() {
|
||||
var $submitBtn = $('.js-entitlement-unenrollment-modal-submit'),
|
||||
apiEndpoint = '/test/api/endpoint/1';
|
||||
|
||||
view.setSubmitData(apiEndpoint);
|
||||
|
||||
spyOn($, 'ajax').and.callFake(function(opts) {
|
||||
expect(opts.url).toEqual(apiEndpoint);
|
||||
expect(opts.method).toEqual('DELETE');
|
||||
expect(opts.complete).toBeTruthy();
|
||||
|
||||
opts.complete({
|
||||
status: 204,
|
||||
responseJSON: {detail: 'success'}
|
||||
});
|
||||
});
|
||||
spyOn(view, 'redirectTo');
|
||||
|
||||
$submitBtn.trigger('click');
|
||||
expect($.ajax).toHaveBeenCalled();
|
||||
expect(view.redirectTo).toHaveBeenCalledWith(view.dashboardPath);
|
||||
});
|
||||
|
||||
it('should redirect to the login page if the request failed with an auth error', function() {
|
||||
var $submitBtn = $('.js-entitlement-unenrollment-modal-submit'),
|
||||
apiEndpoint = '/test/api/endpoint/1';
|
||||
|
||||
view.setSubmitData(apiEndpoint);
|
||||
|
||||
spyOn($, 'ajax').and.callFake(function(opts) {
|
||||
expect(opts.url).toEqual(apiEndpoint);
|
||||
expect(opts.method).toEqual('DELETE');
|
||||
expect(opts.complete).toBeTruthy();
|
||||
|
||||
opts.complete({
|
||||
status: 401,
|
||||
responseJSON: {detail: 'Authentication credentials were not provided.'}
|
||||
});
|
||||
});
|
||||
spyOn(view, 'redirectTo');
|
||||
|
||||
$submitBtn.trigger('click');
|
||||
expect($.ajax).toHaveBeenCalled();
|
||||
expect(view.redirectTo).toHaveBeenCalledWith(
|
||||
view.signInPath + '?next=' + encodeURIComponent(view.dashboardPath)
|
||||
);
|
||||
});
|
||||
|
||||
it('should set an error and disable submit if a non-auth error occurs', function() {
|
||||
var $errorTxt = $('.js-entitlement-unenrollment-modal-error-text'),
|
||||
$submitBtn = $('.js-entitlement-unenrollment-modal-submit'),
|
||||
apiEndpoint = '/test/api/endpoint/1';
|
||||
|
||||
view.setSubmitData(apiEndpoint);
|
||||
|
||||
spyOn($, 'ajax').and.callFake(function(opts) {
|
||||
expect(opts.url).toEqual(apiEndpoint);
|
||||
expect(opts.method).toEqual('DELETE');
|
||||
expect(opts.complete).toBeTruthy();
|
||||
|
||||
opts.complete({
|
||||
status: 400,
|
||||
responseJSON: {detail: 'Bad request.'}
|
||||
});
|
||||
});
|
||||
spyOn(view, 'redirectTo');
|
||||
|
||||
expect($submitBtn.prop('disabled')).toBe(false);
|
||||
expect($errorTxt.html()).toEqual('');
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(false);
|
||||
|
||||
$submitBtn.trigger('click');
|
||||
|
||||
expect($submitBtn.prop('disabled')).toBe(true);
|
||||
expect($errorTxt.html()).toEqual(view.genericErrorMsg);
|
||||
expect($errorTxt.hasClass('entitlement-unenrollment-modal-error-text-visible')).toBe(true);
|
||||
|
||||
expect($.ajax).toHaveBeenCalled();
|
||||
expect(view.redirectTo).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,137 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'underscore',
|
||||
'jquery',
|
||||
'js/learner_dashboard/collections/program_progress_collection',
|
||||
'js/learner_dashboard/models/program_model',
|
||||
'js/learner_dashboard/views/program_card_view'
|
||||
], function(Backbone, _, $, ProgressCollection, ProgramModel, ProgramCardView) {
|
||||
'use strict';
|
||||
/* jslint maxlen: 500 */
|
||||
|
||||
describe('Program card View', function() {
|
||||
var view = null,
|
||||
programModel,
|
||||
program = {
|
||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||
title: 'Food Security and Sustainability',
|
||||
subtitle: 'Learn how to feed all people in the world in a sustainable way.',
|
||||
type: 'XSeries',
|
||||
detail_url: 'https://www.edx.org/foo/bar',
|
||||
banner_image: {
|
||||
medium: {
|
||||
height: 242,
|
||||
width: 726,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.medium.jpg'
|
||||
},
|
||||
'x-small': {
|
||||
height: 116,
|
||||
width: 348,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.x-small.jpg'
|
||||
},
|
||||
small: {
|
||||
height: 145,
|
||||
width: 435,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.small.jpg'
|
||||
},
|
||||
large: {
|
||||
height: 480,
|
||||
width: 1440,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.large.jpg'
|
||||
}
|
||||
},
|
||||
authoring_organizations: [
|
||||
{
|
||||
uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22',
|
||||
key: 'WageningenX',
|
||||
name: 'Wageningen University & Research'
|
||||
}
|
||||
]
|
||||
},
|
||||
userProgress = [
|
||||
{
|
||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||
completed: 4,
|
||||
in_progress: 2,
|
||||
not_started: 4
|
||||
},
|
||||
{
|
||||
uuid: '91d144d2-1bb1-4afe-90df-d5cff63fa6e2',
|
||||
completed: 1,
|
||||
in_progress: 0,
|
||||
not_started: 3
|
||||
}
|
||||
],
|
||||
progressCollection = new ProgressCollection(),
|
||||
cardRenders = function($card) {
|
||||
expect($card).toBeDefined();
|
||||
expect($card.find('.title').html().trim()).toEqual(program.title);
|
||||
expect($card.find('.category span').html().trim()).toEqual(program.type);
|
||||
expect($card.find('.organization').html().trim()).toEqual(program.authoring_organizations[0].key);
|
||||
expect($card.find('.card-link').attr('href')).toEqual(program.detail_url);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="program-card"></div>');
|
||||
programModel = new ProgramModel(program);
|
||||
progressCollection.set(userProgress);
|
||||
view = new ProgramCardView({
|
||||
model: programModel,
|
||||
context: {
|
||||
progressCollection: progressCollection
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should load the program-card based on passed in context', function() {
|
||||
cardRenders(view.$el);
|
||||
});
|
||||
|
||||
it('should call reEvaluatePicture if reLoadBannerImage is called', function() {
|
||||
spyOn(view, 'reEvaluatePicture');
|
||||
view.reLoadBannerImage();
|
||||
expect(view.reEvaluatePicture).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle exceptions from reEvaluatePicture', function() {
|
||||
var message = 'Picturefill had exceptions';
|
||||
|
||||
spyOn(view, 'reEvaluatePicture').and.callFake(function() {
|
||||
var error = {name: message};
|
||||
|
||||
throw error;
|
||||
});
|
||||
view.reLoadBannerImage();
|
||||
expect(view.reEvaluatePicture).toHaveBeenCalled();
|
||||
expect(view.reLoadBannerImage).not.toThrow(message);
|
||||
});
|
||||
|
||||
it('should show the right number of progress bar segments', function() {
|
||||
expect(view.$('.progress-bar .completed').length).toEqual(4);
|
||||
expect(view.$('.progress-bar .enrolled').length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should display the correct course status numbers', function() {
|
||||
expect(view.$('.number-circle').text()).toEqual('424');
|
||||
});
|
||||
|
||||
it('should render cards if there is no progressData', function() {
|
||||
view.remove();
|
||||
view = new ProgramCardView({
|
||||
model: programModel,
|
||||
context: {}
|
||||
});
|
||||
cardRenders(view.$el);
|
||||
expect(view.$('.progress').length).toEqual(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,77 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/views/program_header_view'
|
||||
], function(Backbone, $, ProgramHeaderView) {
|
||||
'use strict';
|
||||
|
||||
describe('Program Details Header View', function() {
|
||||
var view = null,
|
||||
context = {
|
||||
programData: {
|
||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||
title: 'Food Security and Sustainability',
|
||||
subtitle: 'Learn how to feed all people in the world in a sustainable way.',
|
||||
type: 'XSeries',
|
||||
detail_url: 'https://www.edx.org/foo/bar',
|
||||
banner_image: {
|
||||
medium: {
|
||||
height: 242,
|
||||
width: 726,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.medium.jpg'
|
||||
},
|
||||
'x-small': {
|
||||
height: 116,
|
||||
width: 348,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.x-small.jpg'
|
||||
},
|
||||
small: {
|
||||
height: 145,
|
||||
width: 435,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.small.jpg'
|
||||
},
|
||||
large: {
|
||||
height: 480,
|
||||
width: 1440,
|
||||
url: 'https://example.com/a87e5eac-3c93-45a1-a8e1-4c79ca8401c8.large.jpg'
|
||||
}
|
||||
},
|
||||
authoring_organizations: [
|
||||
{
|
||||
uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22',
|
||||
key: 'WageningenX',
|
||||
name: 'Wageningen University & Research',
|
||||
certificate_logo_image_url: 'https://example.com/org-certificate-logo.jpg',
|
||||
logo_image_url: 'https://example.com/org-logo.jpg'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="js-program-header"></div>');
|
||||
view = new ProgramHeaderView({
|
||||
model: new Backbone.Model(context)
|
||||
});
|
||||
view.render();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render the header based on the passed in model', function() {
|
||||
expect(view.$('.program-title').html()).toEqual(context.programData.title);
|
||||
expect(view.$('.org-logo').length).toEqual(context.programData.authoring_organizations.length);
|
||||
expect(view.$('.org-logo').attr('src'))
|
||||
.toEqual(context.programData.authoring_organizations[0].certificate_logo_image_url);
|
||||
expect(view.$('.org-logo').attr('alt'))
|
||||
.toEqual(context.programData.authoring_organizations[0].name + '\'s logo');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
File diff suppressed because one or more lines are too long
@@ -1,632 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/views/program_details_view'
|
||||
], function(Backbone, $, ProgramDetailsView) {
|
||||
'use strict';
|
||||
|
||||
describe('Program Details Header View', function() {
|
||||
var view = null,
|
||||
options = {
|
||||
programData: {
|
||||
subtitle: '',
|
||||
overview: '',
|
||||
weeks_to_complete: null,
|
||||
corporate_endorsements: [],
|
||||
video: null,
|
||||
type: 'Test',
|
||||
max_hours_effort_per_week: null,
|
||||
transcript_languages: [
|
||||
'en-us'
|
||||
],
|
||||
expected_learning_items: [],
|
||||
uuid: '0ffff5d6-0177-4690-9a48-aa2fecf94610',
|
||||
title: 'Test Course Title',
|
||||
languages: [
|
||||
'en-us'
|
||||
],
|
||||
subjects: [],
|
||||
individual_endorsements: [],
|
||||
staff: [
|
||||
{
|
||||
family_name: 'Tester',
|
||||
uuid: '11ee1afb-5750-4185-8434-c9ae8297f0f1',
|
||||
bio: 'Dr. Tester, PhD, RD, is an Associate Professor at the School of Nutrition.',
|
||||
profile_image: {},
|
||||
profile_image_url: 'some image',
|
||||
given_name: 'Bob',
|
||||
urls: {
|
||||
blog: null,
|
||||
twitter: null,
|
||||
facebook: null
|
||||
},
|
||||
position: {
|
||||
organization_name: 'Test University',
|
||||
title: 'Associate Professor of Nutrition'
|
||||
},
|
||||
works: [],
|
||||
slug: 'dr-tester'
|
||||
}
|
||||
],
|
||||
marketing_slug: 'testing',
|
||||
marketing_url: 'someurl',
|
||||
status: 'active',
|
||||
credit_redemption_overview: '',
|
||||
discount_data: {
|
||||
currency: 'USD',
|
||||
discount_value: 0,
|
||||
is_discounted: false,
|
||||
total_incl_tax: 300,
|
||||
total_incl_tax_excl_discounts: 300
|
||||
},
|
||||
full_program_price: 300,
|
||||
card_image_url: 'some image',
|
||||
faq: [],
|
||||
price_ranges: [
|
||||
{
|
||||
max: 378,
|
||||
total: 109,
|
||||
min: 10,
|
||||
currency: 'USD'
|
||||
}
|
||||
],
|
||||
banner_image: {
|
||||
large: {
|
||||
url: 'someurl',
|
||||
width: 1440,
|
||||
height: 480
|
||||
},
|
||||
small: {
|
||||
url: 'someurl',
|
||||
width: 435,
|
||||
height: 145
|
||||
},
|
||||
medium: {
|
||||
url: 'someurl',
|
||||
width: 726,
|
||||
height: 242
|
||||
},
|
||||
'x-small': {
|
||||
url: 'someurl',
|
||||
width: 348,
|
||||
height: 116
|
||||
}
|
||||
},
|
||||
authoring_organizations: [
|
||||
{
|
||||
description: '<p>Learning University is home to leading creators, entrepreneurs.</p>',
|
||||
tags: [
|
||||
'contributor'
|
||||
],
|
||||
name: 'Learning University',
|
||||
homepage_url: null,
|
||||
key: 'LearnX',
|
||||
certificate_logo_image_url: null,
|
||||
marketing_url: 'someurl',
|
||||
logo_image_url: 'https://stage.edx.org/sites/default/files/school/image/logo/learnx.png',
|
||||
uuid: 'de3e9ff0-477d-4496-8cfa-a98f902e5830'
|
||||
},
|
||||
{
|
||||
description: '<p>The Test University was chartered in 1868.</p>',
|
||||
tags: [
|
||||
'charter',
|
||||
'contributor'
|
||||
],
|
||||
name: 'Test University',
|
||||
homepage_url: null,
|
||||
key: 'TestX',
|
||||
certificate_logo_image_url: null,
|
||||
marketing_url: 'someurl',
|
||||
logo_image_url: 'https://stage.edx.org/sites/default/files/school/image/logo/ritx.png',
|
||||
uuid: '54bc81cb-b736-4505-aa51-dd2b18c61d84'
|
||||
}
|
||||
],
|
||||
job_outlook_items: [],
|
||||
credit_backing_organizations: [],
|
||||
weeks_to_complete_min: 8,
|
||||
weeks_to_complete_max: 8,
|
||||
min_hours_effort_per_week: null,
|
||||
is_learner_eligible_for_one_click_purchase: false
|
||||
},
|
||||
courseData: {
|
||||
completed: [
|
||||
{
|
||||
owners: [
|
||||
{
|
||||
uuid: '766a3716-f962-425b-b56e-e214c019b229',
|
||||
key: 'Testx',
|
||||
name: 'Test University'
|
||||
}
|
||||
],
|
||||
uuid: '4be8dceb-3454-4fbf-8993-17d563ab41d4',
|
||||
title: 'Who let the dogs out',
|
||||
image: null,
|
||||
key: 'Testx+DOGx002',
|
||||
course_runs: [
|
||||
{
|
||||
upgrade_url: null,
|
||||
image: {
|
||||
src: 'someurl',
|
||||
width: null,
|
||||
description: null,
|
||||
height: null
|
||||
},
|
||||
max_effort: null,
|
||||
is_enrollment_open: true,
|
||||
course: 'Testx+DOGx002',
|
||||
content_language: null,
|
||||
eligible_for_financial_aid: true,
|
||||
seats: [
|
||||
{
|
||||
sku: '4250900',
|
||||
credit_hours: null,
|
||||
price: '89.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: '',
|
||||
type: 'verified'
|
||||
}
|
||||
],
|
||||
course_url: '/courses/course-v1:Testx+DOGx002+1T2016/',
|
||||
availability: 'Archived',
|
||||
transcript_languages: [],
|
||||
staff: [],
|
||||
announcement: null,
|
||||
end: '2016-10-01T23:59:00Z',
|
||||
uuid: 'f0ac45f5-f0d6-44bc-aeb9-a14e36e963a5',
|
||||
title: 'Who let the dogs out',
|
||||
certificate_url: '/certificates/1730700d89434b718d0d91f8b5d339bf',
|
||||
enrollment_start: null,
|
||||
start: '2017-03-21T22:18:15Z',
|
||||
min_effort: null,
|
||||
short_description: null,
|
||||
hidden: false,
|
||||
level_type: null,
|
||||
type: 'verified',
|
||||
enrollment_open_date: 'Jan 01, 1900',
|
||||
marketing_url: null,
|
||||
is_course_ended: false,
|
||||
instructors: [],
|
||||
full_description: null,
|
||||
key: 'course-v1:Testx+DOGx002+1T2016',
|
||||
enrollment_end: null,
|
||||
reporting_type: 'mooc',
|
||||
advertised_start: null,
|
||||
mobile_available: false,
|
||||
modified: '2017-03-24T14:22:15.609907Z',
|
||||
is_enrolled: true,
|
||||
pacing_type: 'self_paced',
|
||||
video: null,
|
||||
status: 'published'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
in_progress: [
|
||||
{
|
||||
owners: [
|
||||
{
|
||||
uuid: 'c484a523-d396-4aff-90f4-bb7e82e16bf6',
|
||||
key: 'LearnX',
|
||||
name: 'Learning University'
|
||||
}
|
||||
],
|
||||
uuid: '872ec14c-3b7d-44b8-9cf2-9fa62182e1dd',
|
||||
title: 'Star Trek: The Next Generation',
|
||||
image: null,
|
||||
key: 'LearnX+NGIx',
|
||||
course_runs: [
|
||||
{
|
||||
upgrade_url: 'someurl',
|
||||
image: {
|
||||
src: '',
|
||||
width: null,
|
||||
description: null,
|
||||
height: null
|
||||
},
|
||||
max_effort: null,
|
||||
is_enrollment_open: true,
|
||||
course: 'LearnX+NGx',
|
||||
content_language: null,
|
||||
eligible_for_financial_aid: true,
|
||||
seats: [
|
||||
{
|
||||
sku: '44EEB26',
|
||||
credit_hours: null,
|
||||
price: '0.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: null,
|
||||
type: 'audit'
|
||||
},
|
||||
{
|
||||
sku: '64AAFBA',
|
||||
credit_hours: null,
|
||||
price: '10.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: '2017-04-29T00:00:00Z',
|
||||
credit_provider: null,
|
||||
type: 'verified'
|
||||
}
|
||||
],
|
||||
course_url: 'someurl',
|
||||
availability: 'Current',
|
||||
transcript_languages: [],
|
||||
staff: [],
|
||||
announcement: null,
|
||||
end: '2017-03-31T12:00:00Z',
|
||||
uuid: 'ce841f5b-f5a9-428f-b187-e6372b532266',
|
||||
title: 'Star Trek: The Next Generation',
|
||||
certificate_url: null,
|
||||
enrollment_start: '2014-03-31T20:00:00Z',
|
||||
start: '2017-03-20T20:50:14Z',
|
||||
min_effort: null,
|
||||
short_description: null,
|
||||
hidden: false,
|
||||
level_type: null,
|
||||
type: 'verified',
|
||||
enrollment_open_date: 'Jan 01, 1900',
|
||||
marketing_url: 'someurl',
|
||||
is_course_ended: false,
|
||||
instructors: [],
|
||||
full_description: null,
|
||||
key: 'course-v1:LearnX+NGIx+3T2016',
|
||||
enrollment_end: null,
|
||||
reporting_type: 'mooc',
|
||||
advertised_start: null,
|
||||
mobile_available: false,
|
||||
modified: '2017-03-24T14:16:47.547643Z',
|
||||
is_enrolled: true,
|
||||
pacing_type: 'instructor_paced',
|
||||
video: null,
|
||||
status: 'published'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
uuid: '0ffff5d6-0177-4690-9a48-aa2fecf94610',
|
||||
not_started: [
|
||||
{
|
||||
owners: [
|
||||
{
|
||||
uuid: '766a3716-f962-425b-b56e-e214c019b229',
|
||||
key: 'Testx',
|
||||
name: 'Test University'
|
||||
}
|
||||
],
|
||||
uuid: '88da08e4-e9ef-406e-95d7-7a178f9f9695',
|
||||
title: 'Introduction to Health and Wellness',
|
||||
image: null,
|
||||
key: 'Testx+EXW100x',
|
||||
course_runs: [
|
||||
{
|
||||
upgrade_url: null,
|
||||
image: {
|
||||
src: 'someurl',
|
||||
width: null,
|
||||
description: null,
|
||||
height: null
|
||||
},
|
||||
max_effort: null,
|
||||
is_enrollment_open: true,
|
||||
course: 'Testx+EXW100x',
|
||||
content_language: 'en-us',
|
||||
eligible_for_financial_aid: true,
|
||||
seats: [
|
||||
{
|
||||
sku: '',
|
||||
credit_hours: null,
|
||||
price: '0.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: '',
|
||||
type: 'audit'
|
||||
},
|
||||
{
|
||||
sku: '',
|
||||
credit_hours: null,
|
||||
price: '10.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: '',
|
||||
type: 'verified'
|
||||
}
|
||||
],
|
||||
course_url: 'someurl',
|
||||
availability: 'Archived',
|
||||
transcript_languages: [
|
||||
'en-us'
|
||||
],
|
||||
staff: [
|
||||
{
|
||||
family_name: 'Tester',
|
||||
uuid: '11ee1afb-5750-4185-8434-c9ae8297f0f1',
|
||||
bio: 'Dr. Tester, PhD, RD, is a Professor at the School of Nutrition.',
|
||||
profile_image: {},
|
||||
profile_image_url: 'someimage.jpg',
|
||||
given_name: 'Bob',
|
||||
urls: {
|
||||
blog: null,
|
||||
twitter: null,
|
||||
facebook: null
|
||||
},
|
||||
position: {
|
||||
organization_name: 'Test University',
|
||||
title: 'Associate Professor of Nutrition'
|
||||
},
|
||||
works: [],
|
||||
slug: 'dr-tester'
|
||||
}
|
||||
],
|
||||
announcement: null,
|
||||
end: '2017-03-25T22:18:33Z',
|
||||
uuid: 'a36efd39-6637-11e6-a8e3-22000bdde520',
|
||||
title: 'Introduction to Jedi',
|
||||
certificate_url: null,
|
||||
enrollment_start: null,
|
||||
start: '2016-01-11T05:00:00Z',
|
||||
min_effort: null,
|
||||
short_description: null,
|
||||
hidden: false,
|
||||
level_type: null,
|
||||
type: 'verified',
|
||||
enrollment_open_date: 'Jan 01, 1900',
|
||||
marketing_url: 'someurl',
|
||||
is_course_ended: false,
|
||||
instructors: [],
|
||||
full_description: null,
|
||||
key: 'course-v1:Testx+EXW100x+1T2016',
|
||||
enrollment_end: null,
|
||||
reporting_type: 'mooc',
|
||||
advertised_start: null,
|
||||
mobile_available: true,
|
||||
modified: '2017-03-24T14:18:08.693748Z',
|
||||
is_enrolled: false,
|
||||
pacing_type: 'instructor_paced',
|
||||
video: null,
|
||||
status: 'published'
|
||||
},
|
||||
{
|
||||
upgrade_url: null,
|
||||
image: {
|
||||
src: 'someurl',
|
||||
width: null,
|
||||
description: null,
|
||||
height: null
|
||||
},
|
||||
max_effort: null,
|
||||
is_enrollment_open: true,
|
||||
course: 'Testx+EXW100x',
|
||||
content_language: null,
|
||||
eligible_for_financial_aid: true,
|
||||
seats: [
|
||||
{
|
||||
sku: '77AA8F2',
|
||||
credit_hours: null,
|
||||
price: '0.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: null,
|
||||
type: 'audit'
|
||||
},
|
||||
{
|
||||
sku: '7EC7BB0',
|
||||
credit_hours: null,
|
||||
price: '100.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: null,
|
||||
type: 'verified'
|
||||
},
|
||||
{
|
||||
sku: 'BD436CC',
|
||||
credit_hours: 10,
|
||||
price: '378.00',
|
||||
currency: 'USD',
|
||||
upgrade_deadline: null,
|
||||
credit_provider: 'asu',
|
||||
type: 'credit'
|
||||
}
|
||||
],
|
||||
course_url: 'someurl',
|
||||
availability: 'Archived',
|
||||
transcript_languages: [],
|
||||
staff: [],
|
||||
announcement: null,
|
||||
end: '2016-07-29T00:00:00Z',
|
||||
uuid: '03b34748-19b1-4732-9ea2-e68da95024e6',
|
||||
title: 'Introduction to Jedi',
|
||||
certificate_url: null,
|
||||
enrollment_start: null,
|
||||
start: '2017-03-22T18:10:39Z',
|
||||
min_effort: null,
|
||||
short_description: null,
|
||||
hidden: false,
|
||||
level_type: null,
|
||||
type: 'credit',
|
||||
enrollment_open_date: 'Jan 01, 1900',
|
||||
marketing_url: null,
|
||||
is_course_ended: false,
|
||||
instructors: [],
|
||||
full_description: null,
|
||||
key: 'course-v1:Testx+EXW100x+2164C',
|
||||
enrollment_end: '2016-06-18T19:00:00Z',
|
||||
reporting_type: 'mooc',
|
||||
advertised_start: null,
|
||||
mobile_available: false,
|
||||
modified: '2017-03-23T16:47:37.108260Z',
|
||||
is_enrolled: false,
|
||||
pacing_type: 'self_paced',
|
||||
video: null,
|
||||
status: 'published'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
grades: {
|
||||
'course-v1:Testx+DOGx002+1T2016': 0.9
|
||||
}
|
||||
},
|
||||
urls: {
|
||||
program_listing_url: '/dashboard/programs/',
|
||||
commerce_api_url: '/api/commerce/v0/baskets/',
|
||||
track_selection_url: '/course_modes/choose/'
|
||||
},
|
||||
userPreferences: {
|
||||
'pref-lang': 'en'
|
||||
}
|
||||
},
|
||||
data = options.programData,
|
||||
initView;
|
||||
|
||||
initView = function(updates) {
|
||||
var viewOptions = $.extend({}, options, updates);
|
||||
|
||||
return new ProgramDetailsView(viewOptions);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="js-program-details-wrapper"></div>');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should render the header', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect(view.$('.js-program-header h2').html()).toEqual(data.title);
|
||||
expect(view.$('.js-program-header .org-logo')[0].src).toEqual(
|
||||
data.authoring_organizations[0].logo_image_url
|
||||
);
|
||||
expect(view.$('.js-program-header .org-logo')[1].src).toEqual(
|
||||
data.authoring_organizations[1].logo_image_url
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the program heading program journey message if program not completed', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect(view.$('.program-heading-title').text()).toEqual('Your Program Journey');
|
||||
expect(view.$('.program-heading-message').text().trim()
|
||||
.replace(/\s+/g, ' ')).toEqual(
|
||||
'Track and plan your progress through the 3 courses in this program. ' +
|
||||
'To complete the program, you must earn a verified certificate for each course.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the program heading congratulations message if all courses completed', function() {
|
||||
view = initView({
|
||||
// Remove remaining courses so all courses are complete
|
||||
courseData: $.extend({}, options.courseData, {
|
||||
in_progress: [],
|
||||
not_started: []
|
||||
})
|
||||
});
|
||||
view.render();
|
||||
|
||||
expect(view.$('.program-heading-title').text()).toEqual('Congratulations!');
|
||||
expect(view.$('.program-heading-message').text().trim()
|
||||
.replace(/\s+/g, ' ')).toEqual(
|
||||
'You have successfully completed all the requirements for the Test Course Title Test.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the course list headings', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect(view.$('.course-list-heading .status').text()).toEqual(
|
||||
'COURSES IN PROGRESSREMAINING COURSESCOMPLETED COURSES'
|
||||
);
|
||||
expect(view.$('.course-list-heading .count').text()).toEqual('111');
|
||||
});
|
||||
|
||||
it('should render the basic course card information', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect($(view.$('.course-title')[0]).text().trim()).toEqual('Star Trek: The Next Generation');
|
||||
expect($(view.$('.enrolled')[0]).text().trim()).toEqual('Enrolled:');
|
||||
expect($(view.$('.run-period')[0]).text().trim()).toEqual('Mar 20, 2017 - Mar 31, 2017');
|
||||
});
|
||||
|
||||
it('should render certificate information', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect($(view.$('.upgrade-message .card-msg')).text().trim()).toEqual('Certificate Status:');
|
||||
expect($(view.$('.upgrade-message .price')).text().trim()).toEqual('$10.00');
|
||||
expect($(view.$('.upgrade-button.single-course-run')[0]).text().trim()).toEqual('Upgrade to Verified');
|
||||
});
|
||||
|
||||
it('should render full program purchase link', function() {
|
||||
view = initView({
|
||||
programData: $.extend({}, options.programData, {
|
||||
is_learner_eligible_for_one_click_purchase: true
|
||||
})
|
||||
});
|
||||
view.render();
|
||||
expect($(view.$('.upgrade-button.complete-program')).text().trim().
|
||||
replace(/\s+/g, ' ')).
|
||||
toEqual(
|
||||
'Upgrade All Remaining Courses ( $300.00 USD )'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render partial program purchase link', function() {
|
||||
view = initView({
|
||||
programData: $.extend({}, options.programData, {
|
||||
is_learner_eligible_for_one_click_purchase: true,
|
||||
discount_data: {
|
||||
currency: 'USD',
|
||||
discount_value: 30,
|
||||
is_discounted: true,
|
||||
total_incl_tax: 300,
|
||||
total_incl_tax_excl_discounts: 270
|
||||
}
|
||||
})
|
||||
});
|
||||
view.render();
|
||||
expect($(view.$('.upgrade-button.complete-program')).text().trim().
|
||||
replace(/\s+/g, ' ')).
|
||||
toEqual(
|
||||
'Upgrade All Remaining Courses ( $270.00 $300.00 USD )'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render enrollment information', function() {
|
||||
view = initView();
|
||||
view.render();
|
||||
expect(view.$('.run-select')[0].options.length).toEqual(2);
|
||||
expect($(view.$('.select-choice')[0]).attr('for')).toEqual($(view.$('.run-select')[0]).attr('id'));
|
||||
expect($(view.$('.enroll-button button')[0]).text().trim()).toEqual('Enroll Now');
|
||||
});
|
||||
|
||||
it('should send analytic event when purchase button clicked', function() {
|
||||
var properties = {
|
||||
category: 'partial bundle',
|
||||
label: 'Test Course Title',
|
||||
uuid: '0ffff5d6-0177-4690-9a48-aa2fecf94610'
|
||||
};
|
||||
view = initView({
|
||||
programData: $.extend({}, options.programData, {
|
||||
is_learner_eligible_for_one_click_purchase: true,
|
||||
variant: 'partial'
|
||||
})
|
||||
});
|
||||
view.render();
|
||||
$('.complete-program').click();
|
||||
// Verify that analytics event fires when the purchase button is clicked.
|
||||
expect(window.analytics.track).toHaveBeenCalledWith(
|
||||
'edx.bi.user.dashboard.program.purchase',
|
||||
properties
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,53 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'jquery',
|
||||
'js/learner_dashboard/views/sidebar_view'
|
||||
], function(Backbone, $, SidebarView) {
|
||||
'use strict';
|
||||
/* jslint maxlen: 500 */
|
||||
|
||||
describe('Sidebar View', function() {
|
||||
var view = null,
|
||||
context = {
|
||||
marketingUrl: 'https://www.example.org/programs'
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="sidebar"></div>');
|
||||
|
||||
view = new SidebarView({
|
||||
el: '.sidebar',
|
||||
context: context
|
||||
});
|
||||
view.render();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('should load the exploration panel given a marketing URL', function() {
|
||||
var $sidebar = view.$el;
|
||||
expect($sidebar.find('.program-advertise .advertise-message').html().trim())
|
||||
.toEqual('Browse recently launched courses and see what\'s new in your favorite subjects');
|
||||
expect($sidebar.find('.program-advertise .ad-link a').attr('href')).toEqual(context.marketingUrl);
|
||||
});
|
||||
|
||||
it('should not load the advertising panel if no marketing URL is provided', function() {
|
||||
var $ad;
|
||||
view.remove();
|
||||
view = new SidebarView({
|
||||
el: '.sidebar',
|
||||
context: {}
|
||||
});
|
||||
view.render();
|
||||
$ad = view.$el.find('.program-advertise');
|
||||
expect($ad.length).toBe(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,46 +0,0 @@
|
||||
define([
|
||||
'backbone',
|
||||
'js/learner_dashboard/views/unenroll_view'
|
||||
], function(Backbone, UnenrollView) {
|
||||
'use strict';
|
||||
|
||||
describe('Unenroll View', function() {
|
||||
var view = null,
|
||||
options = {
|
||||
urls: {
|
||||
dashboard: '/dashboard',
|
||||
browseCourses: '/courses'
|
||||
},
|
||||
isEdx: true
|
||||
},
|
||||
initView;
|
||||
|
||||
initView = function() {
|
||||
return new UnenrollView(options);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div class="unenroll-modal"><div class="wrapper-action-more" data-course-key="course-v1:edX+DemoX+Demo_Course"> <button type="button" class="action action-more" id="actions-dropdown-link-0" aria-haspopup="true" aria-expanded="true" aria-controls="actions-dropdown-0" data-course-number="DemoX" data-course-name="edX Demonstration Course" data-dashboard-index="0"> <span class="sr">Course options for</span> <span class="sr"> edX Demonstration Course </span> <span class="fa fa-cog" aria-hidden="true"></span> </button> <div class="actions-dropdown is-visible" id="actions-dropdown-0" tabindex="-1"> <ul class="actions-dropdown-list" id="actions-dropdown-list-0" aria-label="Available Actions" role="menu"> <div class="reasons_survey"> <div class="slide1 hidden"> <h3>We\'re sorry to see you go! Please share your main reason for unenrolling.</h3><br> <ul class="options"> <li><label class="option"><input type="radio" name="reason" val="I don\'t have enough support">I don\'t have enough support</label></li><li><label class="option"><input type="radio" name="reason" val="I don’t have the academic or language prerequisites">I don\'t have the academic or language prerequisites</label></li><li><label class="option"><input type="radio" name="reason" val="Something was broken">Something was broken</label></li><li><label class="option"><input type="radio" name="reason" val="I just wanted to browse the material">I just wanted to browse the material</label></li><li><label class="option"><input type="radio" name="reason" val="This won’t help me reach my goals">This won\'t help me reach my goals</label></li><li><label class="option"><input type="radio" name="reason" val="I am not happy with the quality of the content">I am not happy with the quality of the content</label></li><li><label class="option"><input type="radio" name="reason" val="The course material was too hard">The course material was too hard</label></li><li><label class="option"><input type="radio" name="reason" val="I don\'t have the time">I don\'t have the time</label></li><li><label class="option"><input type="radio" name="reason" val="The course material was too easy">The course material was too easy</label></li><li><label class="option"><input class="other_radio" type="radio" name="reason" val="Other">Other <input type="text" class="other_text"></label></li></ul> <button class="submit_reasons">Submit</button> </div> </div> <div class="slide2 hidden"> Thank you for sharing your reasons for unenrolling.<br> You are unenrolled from edX Demonstration Course. <a class="button survey_button return_to_dashboard"> Return To Dashboard </a> <a class="button survey_button browse_courses"> Browse Courses </a> </div> <li class="actions-item" id="actions-item-unenroll-0"> <a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="course-v1:edX+DemoX+Demo_Course" data-course-number="DemoX" data-course-name="edX Demonstration Course" data-dashboard-index="0" data-track-info="Are you sure you want to unenroll from %(course_name)s (%(course_number)s)?" id="unenroll-0"> Unenroll </a> </li> <li class="actions-item" id="actions-item-email-settings-0"> </li> </ul> </div> </div></div>'); // eslint-disable-line max-len
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
it('should exist', function() {
|
||||
view = initView();
|
||||
expect(view).toBeDefined();
|
||||
});
|
||||
|
||||
it('switch between slides', function() {
|
||||
view = initView();
|
||||
expect($('.slide1').hasClass('hidden')).toEqual(true);
|
||||
view.switchToSlideOne();
|
||||
expect($('.slide1').hasClass('hidden')).toEqual(false);
|
||||
expect($('.slide2').hasClass('hidden')).toEqual(true);
|
||||
view.switchToSlideTwo();
|
||||
expect($('.slide2').hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -97,7 +97,7 @@ define([
|
||||
};
|
||||
StaffDebug.doInstructorDashAction(action);
|
||||
AjaxHelpers.respondWithTextError(requests);
|
||||
expect($('#idash_msg').text()).toBe('Failed to reset attempts for user. ');
|
||||
expect($('#idash_msg').text()).toBe('Failed to reset attempts for user. Unknown Error Occurred.');
|
||||
$('#result_' + locationName).remove();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user