Files
zulip/frontend_tests/node_tests/channel.js
Greg Price 192ec7c0f6 middleware: Use a proper error code on CSRF failure.
This allows us to reliably parse the error in code, rather than
attempt to parse the error text.  Because the error text gets
translated into the user's language, this error-handling path
wasn't functioning at all for users using Zulip in any of the
seven non-English languages for which we had a translation for
this string.

Together with 709c3b50f which fixed a similar issue in a
different error-handling path, this fixes #5598.
2017-07-25 14:02:12 -07:00

318 lines
7.9 KiB
JavaScript

var channel = require('js/channel');
set_global('$', {});
set_global('reload', {});
set_global('blueslip', {});
var default_stub_xhr = 'default-stub-xhr';
function test_with_mock_ajax(test_params) {
var ajax_called;
var ajax_options;
$.ajax = function (options) {
$.ajax = undefined;
ajax_called = true;
ajax_options = options;
var xhr = test_params.xhr || default_stub_xhr;
options.simulate_success = function (data, text_status) {
options.success(data, text_status, xhr);
};
options.simulate_error = function () {
options.error(xhr);
};
return xhr;
};
test_params.run_code();
assert(ajax_called);
test_params.check_ajax_options(ajax_options);
}
(function test_basics() {
test_with_mock_ajax({
run_code: function () {
channel.post({});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'POST');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
test_with_mock_ajax({
run_code: function () {
channel.patch({});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'POST');
assert.equal(options.data.method, 'PATCH');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
test_with_mock_ajax({
run_code: function () {
channel.put({});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'PUT');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
test_with_mock_ajax({
run_code: function () {
channel.del({});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'DELETE');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
test_with_mock_ajax({
run_code: function () {
channel.get({});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'GET');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
}());
(function test_normal_post() {
var data = {
s: 'some_string',
num: 7,
lst: [1, 2, 4, 8],
};
var orig_success_called;
var orig_error_called;
var stub_xhr = 'stub-xhr-normal-post';
test_with_mock_ajax({
xhr: stub_xhr,
run_code: function () {
channel.post({
data: data,
url: '/json/endpoint',
success: function (data, text_status, xhr) {
orig_success_called = true;
assert.equal(data, 'response data');
assert.equal(text_status, 'success');
assert.equal(xhr, stub_xhr);
},
error: function () {
orig_error_called = true;
},
});
},
check_ajax_options: function (options) {
assert.equal(options.type, 'POST');
assert.equal(options.dataType, 'json');
assert.deepEqual(options.data, data);
assert.equal(options.url, '/json/endpoint');
options.simulate_success('response data', 'success');
assert(orig_success_called);
options.simulate_error();
assert(orig_error_called);
},
});
}());
(function test_patch_with_form_data() {
var appended;
var data = {
append: function (k, v) {
assert.equal(k, 'method');
assert.equal(v, 'PATCH');
appended = true;
},
};
test_with_mock_ajax({
run_code: function () {
channel.patch({
data: data,
processData: false,
});
assert(appended);
},
check_ajax_options: function (options) {
assert.equal(options.type, 'POST');
assert.equal(options.dataType, 'json');
// Just make sure these don't explode.
options.simulate_success();
options.simulate_error();
},
});
}());
(function test_reload_on_403_error() {
test_with_mock_ajax({
xhr: {
status: 403,
responseText: '{"msg": "CSRF Fehler: etwas", "code": "CSRF_FAILED"}',
},
run_code: function () {
channel.post({});
},
check_ajax_options: function (options) {
var reload_initiated;
reload.initiate = function (options) {
reload_initiated = true;
assert.deepEqual(options, {
immediate: true,
save_pointer: true,
save_narrow: true,
save_compose: true,
});
};
options.simulate_error();
assert(reload_initiated);
},
});
}());
(function test_unexpected_403_response() {
test_with_mock_ajax({
xhr: {
status: 403,
responseText: 'unexpected',
},
run_code: function () {
channel.post({});
},
check_ajax_options: function (options) {
var has_error;
blueslip.error = function (msg) {
assert.equal(msg, 'Unexpected 403 response from server');
has_error = true;
};
options.simulate_error();
assert(has_error);
},
});
}());
(function test_retry() {
test_with_mock_ajax({
run_code: function () {
channel.post({
idempotent: true,
data: 42,
});
},
check_ajax_options: function (options) {
var logged;
blueslip.log = function (msg) {
// Our log formatting is a bit broken.
assert.equal(msg, 'Retrying idempotent[object Object]');
logged = true;
};
global.patch_builtin('setTimeout', function (f, delay) {
assert.equal(delay, 0);
f();
});
test_with_mock_ajax({
run_code: function () {
options.simulate_success();
},
check_ajax_options: function (options) {
assert.equal(options.data, 42);
},
});
assert(logged);
},
});
}());
(function test_too_many_pending() {
$.ajax = function () {
var xhr = 'stub';
return xhr;
};
var warned;
blueslip.warn = function (msg) {
assert.equal(
msg,
'The length of pending_requests is over 50. Most likely they are not being correctly removed.'
);
warned = true;
};
_.times(50, function () {
channel.post({});
});
assert(warned);
}());
(function test_xhr_error_message() {
var xhr = {
status: '200',
responseText: 'does not matter',
};
var msg = 'data added';
assert.equal(channel.xhr_error_message(msg, xhr), 'data added');
xhr = {
status: '404',
responseText: '{"msg": "file not found"}',
};
msg = 'some message';
assert.equal(channel.xhr_error_message(msg, xhr), 'some message: file not found');
}());