fields_helpers.js 11.3 KB
Newer Older
1 2 3
define(['backbone',
        'jquery',
        'underscore',
4
        'edx-ui-toolkit/js/utils/html-utils',
5 6
        'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
        'common/js/spec_helpers/template_helpers',
7 8
        'js/views/fields',
        'string_utils'],
9
    function(Backbone, $, _, HtmlUtils, AjaxHelpers, TemplateHelpers, FieldViews) {
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
        '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
        });

30
        var createFieldData = function(fieldType, fieldData) {
31 32 33 34
            var data = {
                model: fieldData.model || new UserAccountModel({}),
                title: fieldData.title || 'Field Title',
                valueAttribute: fieldData.valueAttribute,
muzaffaryousaf committed
35 36
                helpMessage: fieldData.helpMessage || 'I am a field message',
                placeholderValue: fieldData.placeholderValue || 'I am a placeholder message'
37 38 39
            };

            switch (fieldType) {
40 41 42 43 44 45 46 47 48 49
            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;
50 51 52 53 54 55 56 57
            }

            _.extend(data, fieldData);

            return data;
        };

        var createErrorMessage = function(attribute, user_message) {
58
            var field_errors = {};
59
            field_errors[attribute] = {
60
                'user_message': user_message
61
            };
62
            return {
63
                'field_errors': field_errors
64
            };
65 66
        };

67 68
        var expectTitleToContain = function(view, expectedTitle) {
            expect(view.$('.u-field-title').text().trim()).toContain(expectedTitle);
69 70
        };

71 72 73 74
        var expectDropdownSrTitleToContain = function(view, expectedTitle) {
            expect(view.$('.u-field-value .sr').text().trim()).toContain(expectedTitle);
        };

75 76 77 78
        var expectMessageContains = function(view, expectedText) {
            expect(view.$('.u-field-message').html()).toContain(expectedText);
        };

79 80 81 82 83
        var expectTitleAndMessageToContain = function(view, expectedTitle, expectedMessage) {
            expectTitleToContain(view, expectedTitle);
            expectMessageContains(view, expectedMessage);
        };

84 85 86 87 88 89
        var expectAjaxRequestWithData = function(requests, data) {
            AjaxHelpers.expectJsonRequest(
                requests, 'PATCH', API_URL, data
            );
        };

90
        var verifyMessageUpdates = function(view, data, timerCallback) {
91
            var message = 'Here to help!';
92

93
            view.showHelpMessage(message);
94 95 96 97 98 99
            expectMessageContains(view, message);

            view.showHelpMessage();
            expectMessageContains(view, view.helpMessage);

            view.showInProgressMessage();
100 101
            expectMessageContains(view, view.indicators.inProgress);
            expectMessageContains(view, view.messages.inProgress);
102 103

            view.showSuccessMessage();
104
            expectMessageContains(view, view.indicators.success);
105 106 107 108 109 110 111 112
            expectMessageContains(view, view.getMessage('success'));

            expect(timerCallback).not.toHaveBeenCalled();

            view.showErrorMessage({
                responseText: JSON.stringify(createErrorMessage(data.valueAttribute, 'Ops, try again!.')),
                status: 400
            });
113
            expectMessageContains(view, view.indicators.validationError);
114 115

            view.showErrorMessage({status: 500});
116 117
            expectMessageContains(view, view.indicators.error);
            expectMessageContains(view, view.indicators.error);
118 119
        };

120
        var verifySuccessMessageReset = function(view) {
121 122 123
            view.showHelpMessage();
            expectMessageContains(view, view.helpMessage);
            view.showSuccessMessage();
124
            expectMessageContains(view, view.indicators.success);
125
            jasmine.clock().tick(7000);
126 127 128 129
            // Message gets reset
            expectMessageContains(view, view.helpMessage);

            view.showSuccessMessage();
130
            expectMessageContains(view, view.indicators.success);
131
            // But if we change the message, it should not get reset.
132
            view.showHelpMessage('Do not reset this!');
133
            jasmine.clock().tick(7000);
134
            expectMessageContains(view, 'Do not reset this!');
135 136
        };

137
        var verifyPersistence = function(fieldClass, requests) {
muhammad-ammar committed
138 139 140 141 142 143 144 145 146 147 148 149
            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) {
150 151 152 153 154 155 156 157 158 159
            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;
muhammad-ammar committed
160 161 162 163 164
            }

            view.$(valueInputSelector).val(fieldData.validValue).change();
            expect(view.fieldValue()).toBe(fieldData.validValue);
            expectMessageContains(view, view.helpMessage);
165
            AjaxHelpers.expectNoRequests(requests);
muhammad-ammar committed
166 167
        };

168
        var verifyEditableField = function(view, data, requests) {
169 170 171
            var request_data = {};
            var url = view.model.url;

muzaffaryousaf committed
172 173
            if (data.editable === 'toggle') {
                expect(view.el).toHaveClass('mode-placeholder');
174
                expectTitleToContain(view, data.title);
175
                expectMessageContains(view, view.indicators.canEdit);
muzaffaryousaf committed
176 177
                view.$el.click();
            } else {
178
                expectTitleAndMessageToContain(view, data.title, data.helpMessage);
muzaffaryousaf committed
179 180
            }
            expect(view.el).toHaveClass('mode-edit');
181 182 183 184

            if (view.fieldValue() !== null) {
                expect(view.fieldValue()).not.toContain(data.validValue);
            }
185

muzaffaryousaf committed
186
            view.$(data.valueInputSelector).val(data.validValue).change();
187
            view.$(data.valueInputSelector).focusout();
188 189
            // When the value in the field is changed
            expect(view.fieldValue()).toBe(data.validValue);
190 191
            expectMessageContains(view, view.indicators.inProgress);
            expectMessageContains(view, view.messages.inProgress);
192 193 194 195 196 197 198
            request_data[data.valueAttribute] = data.validValue;
            AjaxHelpers.expectJsonRequest(
                requests, 'PATCH', url, request_data
            );

            AjaxHelpers.respondWithNoContent(requests);
            // When server returns success.
muzaffaryousaf committed
199 200 201 202
            if (data.editable === 'toggle') {
                expect(view.el).toHaveClass('mode-display');
                view.$el.click();
            } else {
203
                expectMessageContains(view, view.indicators.success);
muzaffaryousaf committed
204
            }
205

muzaffaryousaf committed
206
            view.$(data.valueInputSelector).val(data.invalidValue1).change();
207
            view.$(data.valueInputSelector).focusout();
208 209 210 211 212 213
            request_data[data.valueAttribute] = data.invalidValue1;
            AjaxHelpers.expectJsonRequest(
                requests, 'PATCH', url, request_data
            );
            AjaxHelpers.respondWithError(requests, 500);
            // When server returns a 500 error
214 215
            expectMessageContains(view, view.indicators.error);
            expectMessageContains(view, view.messages.error);
muzaffaryousaf committed
216
            expect(view.el).toHaveClass('mode-edit');
217

muzaffaryousaf committed
218
            view.$(data.valueInputSelector).val(data.invalidValue2).change();
219
            view.$(data.valueInputSelector).focusout();
220 221 222 223 224 225
            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
226
            expectMessageContains(view, view.indicators.validationError);
227
            expectMessageContains(view, data.validationError);
muzaffaryousaf committed
228 229 230
            expect(view.el).toHaveClass('mode-edit');

            view.$(data.valueInputSelector).val('').change();
231
            view.$(data.valueInputSelector).focusout();
muzaffaryousaf committed
232
            // When the value in the field is changed
233 234
            expect(view.fieldValue()).toBe(data.defaultValue);
            request_data[data.valueAttribute] = data.defaultValue;
muzaffaryousaf committed
235 236 237 238 239 240 241 242 243 244
            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');
            }
245 246
        };

247
        var verifyTextField = function(view, data, requests) {
248
            verifyEditableField(view, _.extend({
249 250 251
                valueSelector: '.u-field-value',
                valueInputSelector: '.u-field-value > input'
            }, data),
252
                requests);
253
        };
254

255
        var verifyDropDownField = function(view, data, requests) {
256
            verifyEditableField(view, _.extend({
257 258 259
                valueSelector: '.u-field-value',
                valueInputSelector: '.u-field-value > select'
            }, data
260
            ), requests);
261
        };
262 263 264 265 266 267

        return {
            SELECT_OPTIONS: SELECT_OPTIONS,
            UserAccountModel: UserAccountModel,
            createFieldData: createFieldData,
            createErrorMessage: createErrorMessage,
268
            expectTitleToContain: expectTitleToContain,
269
            expectDropdownSrTitleToContain: expectDropdownSrTitleToContain,
270
            expectTitleAndMessageToContain: expectTitleAndMessageToContain,
271 272 273 274 275 276
            expectMessageContains: expectMessageContains,
            expectAjaxRequestWithData: expectAjaxRequestWithData,
            verifyMessageUpdates: verifyMessageUpdates,
            verifySuccessMessageReset: verifySuccessMessageReset,
            verifyEditableField: verifyEditableField,
            verifyTextField: verifyTextField,
muhammad-ammar committed
277 278
            verifyDropDownField: verifyDropDownField,
            verifyPersistence: verifyPersistence
279 280
        };
    });