spec-js/observables/dom/ajax-spec.js
"use strict";
var chai_1 = require('chai');
var sinon = require('sinon');
var Rx = require('../../../dist/cjs/Rx');
var root_1 = require('../../../dist/cjs/util/root');
var ajax_helper_1 = require('../../helpers/ajax-helper');
/** @test {ajax} */
describe('Observable.ajax', function () {
var gXHR;
var rXHR;
var sandbox;
beforeEach(function () {
sandbox = sinon.sandbox.create();
gXHR = global.XMLHttpRequest;
rXHR = root_1.root.XMLHttpRequest;
global.XMLHttpRequest = ajax_helper_1.MockXMLHttpRequest;
root_1.root.XMLHttpRequest = ajax_helper_1.MockXMLHttpRequest;
});
afterEach(function () {
sandbox.restore();
ajax_helper_1.MockXMLHttpRequest.clearRequest();
global.XMLHttpRequest = gXHR;
root_1.root.XMLHttpRequest = rXHR;
root_1.root.XDomainRequest = null;
root_1.root.ActiveXObject = null;
});
it('should create default XMLHttpRequest for non CORS', function () {
var obj = {
url: '/',
method: ''
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.withCredentials).to.be.false;
});
it('should try to create AXObject for XHR in old version of IE', function () {
var axObjectStub = sandbox.stub();
axObjectStub.returns(sinon.stub(new ajax_helper_1.MockXMLHttpRequest()));
root_1.root.ActiveXObject = axObjectStub;
root_1.root.XMLHttpRequest = null;
var obj = {
url: '/',
method: ''
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(axObjectStub).to.have.been.called;
});
it('should throw if not able to create XMLHttpRequest', function () {
root_1.root.XMLHttpRequest = null;
root_1.root.ActiveXObject = null;
var obj = {
url: '/',
method: ''
};
chai_1.expect(function () {
Rx.Observable.ajax(obj).subscribe();
}).to.throw();
});
it('should create XMLHttpRequest for CORS', function () {
var obj = {
url: '/',
method: '',
crossDomain: true,
withCredentials: true
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.withCredentials).to.be.true;
});
it('should try to create XDomainRequest for CORS if XMLHttpRequest is not available', function () {
var xDomainStub = sandbox.stub();
xDomainStub.returns(sinon.stub(new ajax_helper_1.MockXMLHttpRequest()));
root_1.root.XDomainRequest = xDomainStub;
root_1.root.XMLHttpRequest = null;
var obj = {
url: '/',
method: '',
crossDomain: true,
withCredentials: true
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(xDomainStub).to.have.been.called;
});
it('should throw if not able to create CORS request', function () {
root_1.root.XMLHttpRequest = null;
root_1.root.XDomainRequest = null;
var obj = {
url: '/',
method: '',
crossDomain: true,
withCredentials: true
};
chai_1.expect(function () {
Rx.Observable.ajax(obj).subscribe();
}).to.throw();
});
it('should set headers', function () {
var obj = {
url: '/talk-to-me-goose',
headers: {
'Content-Type': 'kenny/loggins',
'Fly-Into-The': 'Dangah Zone!',
'Take-A-Ride-Into-The': 'Danger ZoooOoone!'
},
method: ''
};
Rx.Observable.ajax(obj).subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.url).to.equal('/talk-to-me-goose');
chai_1.expect(request.requestHeaders).to.deep.equal({
'Content-Type': 'kenny/loggins',
'Fly-Into-The': 'Dangah Zone!',
'Take-A-Ride-Into-The': 'Danger ZoooOoone!',
'X-Requested-With': 'XMLHttpRequest'
});
});
it('should not set default Content-Type header when no body is sent', function () {
var obj = {
url: '/talk-to-me-goose',
method: 'GET'
};
Rx.Observable.ajax(obj).subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.url).to.equal('/talk-to-me-goose');
chai_1.expect(request.requestHeaders).to.not.have.keys('Content-Type');
});
it('should error if createXHR throws', function () {
var error;
var obj = {
url: '/flibbertyJibbet',
responseType: 'text',
createXHR: function () {
throw new Error('wokka wokka');
}
};
Rx.Observable.ajax(obj)
.subscribe(function (x) {
throw 'should not next';
}, function (err) {
error = err;
}, function () {
throw 'should not complete';
});
chai_1.expect(error).to.be.an('error', 'wokka wokka');
});
it('should succeed on 200', function () {
var expected = { foo: 'bar' };
var result;
var complete = false;
var obj = {
url: '/flibbertyJibbet',
responseType: 'text',
method: ''
};
Rx.Observable.ajax(obj)
.subscribe(function (x) {
result = x;
}, null, function () {
complete = true;
});
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
ajax_helper_1.MockXMLHttpRequest.mostRecent.respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': JSON.stringify(expected)
});
chai_1.expect(result.xhr).exist;
chai_1.expect(result.response).to.deep.equal(JSON.stringify({ foo: 'bar' }));
chai_1.expect(complete).to.be.true;
});
it('should fail on 404', function () {
var error;
var obj = {
url: '/flibbertyJibbet',
normalizeError: function (e, xhr, type) {
return xhr.response || xhr.responseText;
},
responseType: 'text',
method: ''
};
Rx.Observable.ajax(obj)
.subscribe(function (x) {
throw 'should not next';
}, function (err) {
error = err;
}, function () {
throw 'should not complete';
});
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
ajax_helper_1.MockXMLHttpRequest.mostRecent.respondWith({
'status': 404,
'contentType': 'text/plain',
'responseText': 'Wee! I am text!'
});
chai_1.expect(error instanceof Rx.AjaxError).to.be.true;
chai_1.expect(error.message).to.equal('ajax error 404');
chai_1.expect(error.status).to.equal(404);
});
it('should fail on 404', function () {
var error;
var obj = {
url: '/flibbertyJibbet',
normalizeError: function (e, xhr, type) {
return xhr.response || xhr.responseText;
},
responseType: 'text',
method: ''
};
Rx.Observable.ajax(obj).subscribe(function (x) {
throw 'should not next';
}, function (err) {
error = err;
}, function () {
throw 'should not complete';
});
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
ajax_helper_1.MockXMLHttpRequest.mostRecent.respondWith({
'status': 300,
'contentType': 'text/plain',
'responseText': 'Wee! I am text!'
});
chai_1.expect(error instanceof Rx.AjaxError).to.be.true;
chai_1.expect(error.message).to.equal('ajax error 300');
chai_1.expect(error.status).to.equal(300);
});
it('should succeed no settings', function () {
var expected = JSON.stringify({ foo: 'bar' });
Rx.Observable.ajax('/flibbertyJibbet')
.subscribe(function (x) {
chai_1.expect(x.status).to.equal(200);
chai_1.expect(x.xhr.method).to.equal('GET');
chai_1.expect(x.xhr.responseText).to.equal(expected);
}, function () {
throw 'should not have been called';
});
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
ajax_helper_1.MockXMLHttpRequest.mostRecent.respondWith({
'status': 200,
'contentType': 'text/plain',
'responseText': expected
});
});
it('should fail no settings', function () {
var expected = JSON.stringify({ foo: 'bar' });
Rx.Observable.ajax('/flibbertyJibbet')
.subscribe(function () {
throw 'should not have been called';
}, function (x) {
chai_1.expect(x.status).to.equal(500);
chai_1.expect(x.xhr.method).to.equal('GET');
chai_1.expect(x.xhr.responseText).to.equal(expected);
}, function () {
throw 'should not have been called';
});
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
ajax_helper_1.MockXMLHttpRequest.mostRecent.respondWith({
'status': 500,
'contentType': 'text/plain',
'responseText': expected
});
});
describe('ajax request body', function () {
var rFormData;
beforeEach(function () {
rFormData = root_1.root.FormData;
root_1.root.FormData = root_1.root.FormData || (function () {
function class_1() {
}
return class_1;
}());
});
afterEach(function () {
root_1.root.FormData = rFormData;
});
it('can take string body', function () {
var obj = {
url: '/flibbertyJibbet',
method: '',
body: 'foobar'
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.data).to.equal('foobar');
});
it('can take FormData body', function () {
var body = new root_1.root.FormData();
var obj = {
url: '/flibbertyJibbet',
method: '',
body: body
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.data).to.deep.equal(body);
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.requestHeaders).to.deep.equal({
'X-Requested-With': 'XMLHttpRequest',
});
});
it('should not fail when FormData is undefined', function () {
root_1.root.FormData = void 0;
var obj = {
url: '/flibbertyJibbet',
method: '',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: { '🌟': '🚀' }
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
});
it('should send by form-urlencoded format', function () {
var body = {
'🌟': '🚀'
};
var obj = {
url: '/flibbertyJibbet',
method: '',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.data).to.equal('%F0%9F%8C%9F=%F0%9F%9A%80');
});
it('should send by JSON', function () {
var body = {
'🌟': '🚀'
};
var obj = {
url: '/flibbertyJibbet',
method: '',
headers: {
'Content-Type': 'application/json'
},
body: body
};
Rx.Observable.ajax(obj).subscribe();
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');
chai_1.expect(ajax_helper_1.MockXMLHttpRequest.mostRecent.data).to.equal('{"🌟":"🚀"}');
});
});
describe('ajax.get', function () {
it('should succeed on 200', function () {
var expected = { foo: 'bar' };
var result;
var complete = false;
Rx.Observable
.ajax.get('/flibbertyJibbet')
.subscribe(function (x) {
result = x.response;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
request.respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': JSON.stringify(expected)
});
chai_1.expect(result).to.deep.equal(expected);
chai_1.expect(complete).to.be.true;
});
it('should succeed on 204 No Content', function () {
var expected = null;
var result;
var complete = false;
Rx.Observable
.ajax.get('/flibbertyJibbet')
.subscribe(function (x) {
result = x.response;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
request.respondWith({
'status': 204,
'contentType': 'application/json',
'responseText': expected
});
chai_1.expect(result).to.deep.equal(expected);
chai_1.expect(complete).to.be.true;
});
it('should able to select json response via getJSON', function () {
var expected = { foo: 'bar' };
var result;
var complete = false;
Rx.Observable
.ajax.getJSON('/flibbertyJibbet')
.subscribe(function (x) {
result = x;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
request.respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': JSON.stringify(expected)
});
chai_1.expect(result).to.deep.equal(expected);
chai_1.expect(complete).to.be.true;
});
});
describe('ajax.post', function () {
it('should succeed on 200', function () {
var expected = { foo: 'bar', hi: 'there you' };
var result;
var complete = false;
Rx.Observable
.ajax.post('/flibbertyJibbet', expected)
.subscribe(function (x) {
result = x;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.method).to.equal('POST');
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
chai_1.expect(request.requestHeaders).to.deep.equal({
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
});
request.respondWith({
'status': 200,
'contentType': 'application/json',
'responseText': JSON.stringify(expected)
});
chai_1.expect(request.data).to.equal('foo=bar&hi=there%20you');
chai_1.expect(result.response).to.deep.equal(expected);
chai_1.expect(complete).to.be.true;
});
it('should succeed on 204 No Content', function () {
var expected = null;
var result;
var complete = false;
Rx.Observable
.ajax.post('/flibbertyJibbet', expected)
.subscribe(function (x) {
result = x;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.method).to.equal('POST');
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
chai_1.expect(request.requestHeaders).to.deep.equal({
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
});
request.respondWith({
'status': 204,
'contentType': 'application/json',
'responseType': 'json',
'responseText': expected
});
chai_1.expect(result.response).to.equal(expected);
chai_1.expect(complete).to.be.true;
});
it('should succeed in IE on 204 No Content', function () {
var expected = null;
var result;
var complete = false;
root_1.root.XMLHttpRequest = ajax_helper_1.MockXMLHttpRequestInternetExplorer;
Rx.Observable
.ajax.post('/flibbertyJibbet', expected)
.subscribe(function (x) {
result = x;
}, null, function () {
complete = true;
});
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(request.method).to.equal('POST');
chai_1.expect(request.url).to.equal('/flibbertyJibbet');
chai_1.expect(request.requestHeaders).to.deep.equal({
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
});
//IE behavior: IE does not provide the a responseText property, so also exercise the code which handles this.
request.respondWith({
'status': 204,
'contentType': 'application/json'
});
chai_1.expect(result.response).to.equal(expected);
chai_1.expect(complete).to.be.true;
});
});
it('should work fine when XMLHttpRequest onreadystatechange property is monkey patched', function () {
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'onreadystatechange', {
set: function (fn) {
var _this = this;
var wrapFn = function (ev) {
var result = fn.call(_this, ev);
if (result === false) {
ev.preventDefault();
}
};
this['_onreadystatechange'] = wrapFn;
},
get: function () {
return this['_onreadystatechange'];
},
configurable: true
});
Rx.Observable.ajax({
url: '/flibbertyJibbet'
})
.subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(function () {
request.onreadystatechange('onreadystatechange');
}).not.throw();
delete root_1.root.XMLHttpRequest.prototype.onreadystatechange;
});
it('should work fine when XMLHttpRequest ontimeout property is monkey patched', function () {
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'ontimeout', {
set: function (fn) {
var _this = this;
var wrapFn = function (ev) {
var result = fn.call(_this, ev);
if (result === false) {
ev.preventDefault();
}
};
this['_ontimeout'] = wrapFn;
},
get: function () {
return this['_ontimeout'];
},
configurable: true
});
var ajaxRequest = {
url: '/flibbertyJibbet'
};
Rx.Observable.ajax(ajaxRequest)
.subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
try {
request.ontimeout('ontimeout');
}
catch (e) {
chai_1.expect(e.message).to.equal(new Rx.AjaxTimeoutError(request, ajaxRequest).message);
}
delete root_1.root.XMLHttpRequest.prototype.ontimeout;
});
it('should work fine when XMLHttpRequest onprogress property is monkey patched', function () {
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'onprogress', {
set: function (fn) {
var _this = this;
var wrapFn = function (ev) {
var result = fn.call(_this, ev);
if (result === false) {
ev.preventDefault();
}
};
this['_onprogress'] = wrapFn;
},
get: function () {
return this['_onprogress'];
},
configurable: true
});
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'upload', {
get: function () {
return true;
},
configurable: true
});
// mock for onprogress
root_1.root.XDomainRequest = true;
Rx.Observable.ajax({
url: '/flibbertyJibbet',
progressSubscriber: {
next: function () {
// noop
},
error: function () {
// noop
},
complete: function () {
// noop
}
}
})
.subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
chai_1.expect(function () {
request.onprogress('onprogress');
}).not.throw();
delete root_1.root.XMLHttpRequest.prototype.onprogress;
delete root_1.root.XMLHttpRequest.prototype.upload;
delete root_1.root.XDomainRequest;
});
it('should work fine when XMLHttpRequest onerror property is monkey patched', function () {
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'onerror', {
set: function (fn) {
var _this = this;
var wrapFn = function (ev) {
var result = fn.call(_this, ev);
if (result === false) {
ev.preventDefault();
}
};
this['_onerror'] = wrapFn;
},
get: function () {
return this['_onerror'];
},
configurable: true
});
Object.defineProperty(root_1.root.XMLHttpRequest.prototype, 'upload', {
get: function () {
return true;
},
configurable: true
});
// mock for onprogress
root_1.root.XDomainRequest = true;
Rx.Observable.ajax({
url: '/flibbertyJibbet'
})
.subscribe();
var request = ajax_helper_1.MockXMLHttpRequest.mostRecent;
try {
request.onerror('onerror');
}
catch (e) {
chai_1.expect(e.message).to.equal('ajax error');
}
delete root_1.root.XMLHttpRequest.prototype.onerror;
delete root_1.root.XMLHttpRequest.prototype.upload;
delete root_1.root.XDomainRequest;
});
});
//# sourceMappingURL=ajax-spec.js.map