brisket/brisket

View on GitHub
spec/client/client/ClientAjaxSpec.js

Summary

Maintainability
D
1 day
Test Coverage
"use strict";

describe("ClientAjax", function() {
    var ClientAjax = require("../../../lib/client/ClientAjax");
    var ClientTestable = require("../../../lib/client/ClientTestable");
    var Promise = require("bluebird");
    var Backbone = require("backbone");
    var _ = require("underscore");

    var bootstrappedData;
    var appRoot;
    var successCallback;
    var errorCallback;
    var ajaxConfig;
    var error;

    beforeEach(function() {
        bootstrappedData = {
            "/api/from/bootstrappedData%7B%22param%22%3A%22value%22%7D": {
                "from": "bootstrappedData"
            }
        };

        successCallback = jasmine.createSpy();
        errorCallback = jasmine.createSpy();
    });

    afterEach(function() {
        ClientAjax.reset();
    });

    describe("when there is NO appRoot", function() {

        beforeEach(function() {
            appRoot = "";

            ClientAjax.setup(bootstrappedData, appRoot);
        });

        it("makes ajax call with config passed to it", function(done) {
            givenAjaxCallWillSucceed();

            Backbone.ajax(supportedAjaxConfig())
                .then(function() {
                    expect(ClientTestable.BackboneNativeAjax).toHaveBeenCalledWith(jasmine.objectContaining({
                        url: "/api/url",
                        type: "GET",
                        data: {
                            "param": "value"
                        },
                        headers: {
                            "x-my-custom-header": "some value",
                        }
                    }));
                })
                .finally(done);
        });

        it("does NOT make ajax call when data for url in bootstrappedData", function(done) {
            ajaxConfig = supportedAjaxConfig({
                url: "/api/from/bootstrappedData"
            });

            Backbone.ajax(ajaxConfig)
                .then(function(data) {
                    expect(data).toEqual({
                        "from": "bootstrappedData"
                    });
                })
                .finally(done);
        });

        it("calls success callback when data for url in bootstrappedData", function(done) {
            ajaxConfig = supportedAjaxConfig({
                url: "/api/from/bootstrappedData",
                success: successCallback,
                error: errorCallback
            });

            Backbone.ajax(ajaxConfig)
                .then(function() {
                    expect(successCallback).toHaveBeenCalledWith({
                        from: "bootstrappedData"
                    });
                    expect(errorCallback).not.toHaveBeenCalled();
                })
                .finally(done);
        });

        it("rejects with error when success callback has an error when data for url in bootstrappedData", function(done) {
            error = new Error();

            successCallback.and.throwError(error);

            ajaxConfig = supportedAjaxConfig({
                url: "/api/from/bootstrappedData",
                success: successCallback,
                error: errorCallback
            });

            Backbone.ajax(ajaxConfig)
                .catch(function(reason) {
                    expect(reason).toBe(error);
                })
                .finally(done);
        });

        it("bubbles error from success callback", function(done) {
            givenAjaxCallWillSucceed();

            error = new Error();

            successCallback.and.throwError(error);

            ajaxConfig = supportedAjaxConfig({
                url: "/api/path/to/data",
                success: successCallback,
                error: errorCallback
            });

            Backbone.ajax(ajaxConfig)
                .catch(function(reason) {
                    expect(reason).toBe(error);
                })
                .finally(done);
        });

        it("bubbles error from error callback", function(done) {
            givenAjaxCallWillFail();

            error = new Error();

            errorCallback.and.throwError(error);

            ajaxConfig = supportedAjaxConfig({
                url: "/api/path/to/data",
                success: successCallback,
                error: errorCallback
            });

            Backbone.ajax(ajaxConfig)
                .catch(function(reason) {
                    expect(reason).toBe(error);
                })
                .finally(done);
        });

    });

    describe("when there is an appRoot", function() {

        beforeEach(function() {
            appRoot = "/root";

            ClientAjax.setup(bootstrappedData, appRoot);
        });

        it("makes ajax call with appRoot", function(done) {
            givenAjaxCallWillSucceed();

            ajaxConfig = supportedAjaxConfig();

            Backbone.ajax(ajaxConfig)
                .then(function() {
                    expect(ClientTestable.BackboneNativeAjax).toHaveBeenCalledWith(jasmine.objectContaining({
                        url: "/root/api/url",
                        type: "GET",
                        data: {
                            "param": "value"
                        },
                        headers: {
                            "x-my-custom-header": "some value",
                        }
                    }));
                })
                .finally(done);
        });

    });

    function supportedAjaxConfig(extra) {
        return _.extend({
            url: "/api/url",
            type: "GET",
            data: {
                "param": "value"
            },
            headers: {
                "x-my-custom-header": "some value",
            }
        }, extra);
    }

    function givenAjaxCallWillSucceed() {
        spyOn(ClientTestable, "BackboneNativeAjax").and.callFake(function(ajaxConfig) {
            if (ajaxConfig.success) {
                ajaxConfig.success();
            }

            return Promise.resolve({
                some: "data"
            });
        });
    }

    function givenAjaxCallWillFail() {
        spyOn(ClientTestable, "BackboneNativeAjax").and.callFake(function(ajaxConfig) {
            if (ajaxConfig.error) {
                ajaxConfig.error();
            }

            return Promise.reject({
                error: "reason"
            });
        });
    }

});