Home Manual Reference Source Test Repository

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