I've changed the logic so that AjaxHelpers keeps track of which requests have not yet had mock responses sent. This ensures that every response is handled before moving on to the next one, rather than always handling the last request. My intention is that this won't allow bugs to creep in where a request isn't fired and instead the test responds to an old request. It also should ensure that extra events aren't accidentally fired.
268 lines
11 KiB
JavaScript
268 lines
11 KiB
JavaScript
define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers', 'common/js/spec_helpers/template_helpers',
|
|
'js/views/fields',
|
|
'string_utils'],
|
|
function (Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViews) {
|
|
'use strict';
|
|
|
|
var API_URL = '/api/end_point/v1';
|
|
|
|
var USERNAME = 'Legolas',
|
|
FULLNAME = 'Legolas Thranduil',
|
|
EMAIL = 'legolas@woodland.middlearth',
|
|
SELECT_OPTIONS = [['si', 'sindarin'], ['el', 'elvish'], ['na', 'nandor']];
|
|
|
|
var UserAccountModel = Backbone.Model.extend({
|
|
idAttribute: 'username',
|
|
defaults: {
|
|
username: USERNAME,
|
|
name: FULLNAME,
|
|
email: EMAIL,
|
|
language: SELECT_OPTIONS[0][0]
|
|
},
|
|
url: API_URL
|
|
});
|
|
|
|
var createFieldData = function (fieldType, fieldData) {
|
|
var data = {
|
|
model: fieldData.model || new UserAccountModel({}),
|
|
title: fieldData.title || 'Field Title',
|
|
valueAttribute: fieldData.valueAttribute,
|
|
helpMessage: fieldData.helpMessage || 'I am a field message',
|
|
placeholderValue: fieldData.placeholderValue || 'I am a placeholder message'
|
|
};
|
|
|
|
switch (fieldType) {
|
|
case FieldViews.DropdownFieldView:
|
|
data['required'] = fieldData.required || false;
|
|
data['options'] = fieldData.options || SELECT_OPTIONS;
|
|
break;
|
|
case FieldViews.LinkFieldView:
|
|
case FieldViews.PasswordFieldView:
|
|
data['linkTitle'] = fieldData.linkTitle || "Link Title";
|
|
data['linkHref'] = fieldData.linkHref || "/path/to/resource";
|
|
data['emailAttribute'] = 'email';
|
|
break;
|
|
}
|
|
|
|
_.extend(data, fieldData);
|
|
|
|
return data;
|
|
};
|
|
|
|
var createErrorMessage = function(attribute, user_message) {
|
|
var field_errors = {};
|
|
field_errors[attribute] = {
|
|
"user_message": user_message
|
|
};
|
|
return {
|
|
"field_errors": field_errors
|
|
};
|
|
};
|
|
|
|
var expectTitleToContain = function(view, expectedTitle) {
|
|
expect(view.$('.u-field-title').text().trim()).toContain(expectedTitle);
|
|
};
|
|
|
|
var expectMessageContains = function(view, expectedText) {
|
|
expect(view.$('.u-field-message').html()).toContain(expectedText);
|
|
};
|
|
|
|
var expectTitleAndMessageToContain = function(view, expectedTitle, expectedMessage) {
|
|
expectTitleToContain(view, expectedTitle);
|
|
expectMessageContains(view, expectedMessage);
|
|
};
|
|
|
|
var expectAjaxRequestWithData = function(requests, data) {
|
|
AjaxHelpers.expectJsonRequest(
|
|
requests, 'PATCH', API_URL, data
|
|
);
|
|
};
|
|
|
|
var verifyMessageUpdates = function (view, data, timerCallback) {
|
|
|
|
var message = 'Here to help!';
|
|
|
|
view.showHelpMessage(message);
|
|
expectMessageContains(view, message);
|
|
|
|
view.showHelpMessage();
|
|
expectMessageContains(view, view.helpMessage);
|
|
|
|
view.showInProgressMessage();
|
|
expectMessageContains(view, view.indicators.inProgress);
|
|
expectMessageContains(view, view.messages.inProgress);
|
|
|
|
view.showSuccessMessage();
|
|
expectMessageContains(view, view.indicators.success);
|
|
expectMessageContains(view, view.getMessage('success'));
|
|
|
|
expect(timerCallback).not.toHaveBeenCalled();
|
|
|
|
view.showErrorMessage({
|
|
responseText: JSON.stringify(createErrorMessage(data.valueAttribute, 'Ops, try again!.')),
|
|
status: 400
|
|
});
|
|
expectMessageContains(view, view.indicators.validationError);
|
|
|
|
view.showErrorMessage({status: 500});
|
|
expectMessageContains(view, view.indicators.error);
|
|
expectMessageContains(view, view.indicators.error);
|
|
};
|
|
|
|
var verifySuccessMessageReset = function (view) {
|
|
view.showHelpMessage();
|
|
expectMessageContains(view, view.helpMessage);
|
|
view.showSuccessMessage();
|
|
expectMessageContains(view, view.indicators.success);
|
|
jasmine.Clock.tick(7000);
|
|
// Message gets reset
|
|
expectMessageContains(view, view.helpMessage);
|
|
|
|
view.showSuccessMessage();
|
|
expectMessageContains(view, view.indicators.success);
|
|
// But if we change the message, it should not get reset.
|
|
view.showHelpMessage("Do not reset this!");
|
|
jasmine.Clock.tick(7000);
|
|
expectMessageContains(view, "Do not reset this!");
|
|
};
|
|
|
|
var verifyPersistence = function (fieldClass, requests) {
|
|
var fieldData = createFieldData(fieldClass, {
|
|
title: 'Username',
|
|
valueAttribute: 'username',
|
|
helpMessage: 'The username that you use to sign in to edX.',
|
|
validValue: 'My Name',
|
|
persistChanges: false,
|
|
messagePosition: 'header'
|
|
});
|
|
var view = new fieldClass(fieldData).render();
|
|
var valueInputSelector;
|
|
|
|
switch (fieldClass) {
|
|
case FieldViews.TextFieldView:
|
|
valueInputSelector = '.u-field-value > input';
|
|
break;
|
|
case FieldViews.DropdownFieldView:
|
|
valueInputSelector = '.u-field-value > select';
|
|
_.extend(fieldData, {validValue: SELECT_OPTIONS[0][0]});
|
|
break;
|
|
case FieldViews.TextareaFieldView:
|
|
valueInputSelector = '.u-field-value > textarea';
|
|
break;
|
|
}
|
|
|
|
view.$(valueInputSelector).val(fieldData.validValue).change();
|
|
expect(view.fieldValue()).toBe(fieldData.validValue);
|
|
expectMessageContains(view, view.helpMessage);
|
|
AjaxHelpers.expectNoRequests(requests);
|
|
};
|
|
|
|
var verifyEditableField = function (view, data, requests) {
|
|
var request_data = {};
|
|
var url = view.model.url;
|
|
|
|
if (data.editable === 'toggle') {
|
|
expect(view.el).toHaveClass('mode-placeholder');
|
|
expectTitleToContain(view, data.title);
|
|
expectMessageContains(view, view.indicators.canEdit);
|
|
view.$el.click();
|
|
} else {
|
|
expectTitleAndMessageToContain(view, data.title, data.helpMessage, false);
|
|
}
|
|
expect(view.el).toHaveClass('mode-edit');
|
|
|
|
if (view.fieldValue() !== null) {
|
|
expect(view.fieldValue()).not.toContain(data.validValue);
|
|
}
|
|
|
|
view.$(data.valueInputSelector).val(data.validValue).change();
|
|
// When the value in the field is changed
|
|
expect(view.fieldValue()).toBe(data.validValue);
|
|
expectMessageContains(view, view.indicators.inProgress);
|
|
expectMessageContains(view, view.messages.inProgress);
|
|
request_data[data.valueAttribute] = data.validValue;
|
|
AjaxHelpers.expectJsonRequest(
|
|
requests, 'PATCH', url, request_data
|
|
);
|
|
|
|
AjaxHelpers.respondWithNoContent(requests);
|
|
// When server returns success.
|
|
if (data.editable === 'toggle') {
|
|
expect(view.el).toHaveClass('mode-display');
|
|
view.$el.click();
|
|
} else {
|
|
expectMessageContains(view, view.indicators.success);
|
|
}
|
|
|
|
view.$(data.valueInputSelector).val(data.invalidValue1).change();
|
|
request_data[data.valueAttribute] = data.invalidValue1;
|
|
AjaxHelpers.expectJsonRequest(
|
|
requests, 'PATCH', url, request_data
|
|
);
|
|
AjaxHelpers.respondWithError(requests, 500);
|
|
// When server returns a 500 error
|
|
expectMessageContains(view, view.indicators.error);
|
|
expectMessageContains(view, view.messages.error);
|
|
expect(view.el).toHaveClass('mode-edit');
|
|
|
|
view.$(data.valueInputSelector).val(data.invalidValue2).change();
|
|
request_data[data.valueAttribute] = data.invalidValue2;
|
|
AjaxHelpers.expectJsonRequest(
|
|
requests, 'PATCH', url, request_data
|
|
);
|
|
AjaxHelpers.respondWithError(requests, 400, createErrorMessage(data.valueAttribute, data.validationError));
|
|
// When server returns a validation error
|
|
expectMessageContains(view, view.indicators.validationError);
|
|
expectMessageContains(view, data.validationError);
|
|
expect(view.el).toHaveClass('mode-edit');
|
|
|
|
view.$(data.valueInputSelector).val('').change();
|
|
// When the value in the field is changed
|
|
expect(view.fieldValue()).toBe(data.defaultValue);
|
|
request_data[data.valueAttribute] = data.defaultValue;
|
|
AjaxHelpers.expectJsonRequest(
|
|
requests, 'PATCH', url, request_data
|
|
);
|
|
AjaxHelpers.respondWithNoContent(requests);
|
|
// When server returns success.
|
|
if (data.editable === 'toggle') {
|
|
expect(view.el).toHaveClass('mode-placeholder');
|
|
} else {
|
|
expect(view.el).toHaveClass('mode-edit');
|
|
}
|
|
};
|
|
|
|
var verifyTextField = function (view, data, requests) {
|
|
verifyEditableField(view, _.extend({
|
|
valueSelector: '.u-field-value',
|
|
valueInputSelector: '.u-field-value > input'
|
|
}, data
|
|
), requests);
|
|
};
|
|
|
|
var verifyDropDownField = function (view, data, requests) {
|
|
verifyEditableField(view, _.extend({
|
|
valueSelector: '.u-field-value',
|
|
valueInputSelector: '.u-field-value > select'
|
|
}, data
|
|
), requests);
|
|
};
|
|
|
|
return {
|
|
SELECT_OPTIONS: SELECT_OPTIONS,
|
|
UserAccountModel: UserAccountModel,
|
|
createFieldData: createFieldData,
|
|
createErrorMessage: createErrorMessage,
|
|
expectTitleToContain: expectTitleToContain,
|
|
expectTitleAndMessageToContain: expectTitleAndMessageToContain,
|
|
expectMessageContains: expectMessageContains,
|
|
expectAjaxRequestWithData: expectAjaxRequestWithData,
|
|
verifyMessageUpdates: verifyMessageUpdates,
|
|
verifySuccessMessageReset: verifySuccessMessageReset,
|
|
verifyEditableField: verifyEditableField,
|
|
verifyTextField: verifyTextField,
|
|
verifyDropDownField: verifyDropDownField,
|
|
verifyPersistence: verifyPersistence
|
|
};
|
|
});
|