farneman/abstrax

View on GitHub
src/index.test.js

Summary

Maintainability
A
0 mins
Test Coverage
import jQuery from 'jquery';
import abstrax from '../src/index.js';

describe('abstrax', () => {
  let myModel = null;

  const ajaxArgsFromCall = () => jQuery.ajax.calls.mostRecent().args[0];
  const expectFakeHeader = (request, value) => {
    myModel[request]();

    expect(ajaxArgsFromCall().headers['Fake-Header']).toEqual(value);
  };

  beforeEach(() => {
    myModel = abstrax({
      requests: {
        getThings: {
          url: '/api/things',
          headers: {
            'Fake-Header': 'bar'
          }
        },
        getUsers: {
          url: '/api/users'
        },
        createUser: {
          url: '/api/users',
          method: 'POST'
        },
        getUser: {
          url: '/api/users/${userId}'
        },
        updateUser: {
          url: '/api/users/${userId}',
          method: 'PATCH'
        }
      },
      defaults: {
        headers: {
          'Fake-Header': 'foo'
        }
      }
    });
  });

  it('loads the function', () => expect(abstrax).toBeDefined());

  it('defines the request methods', () => {
    expect(myModel.getThings).toBeDefined();
    expect(myModel.getUsers).toBeDefined();
    expect(myModel.createUser).toBeDefined();
    expect(myModel.getUser).toBeDefined();
    expect(myModel.updateUser).toBeDefined();
  });

  it('requires a url for each request definition', () => {
    const badModel = abstrax({
      requests: {
        getSomething: {
          method: 'GET'
        },
        getElse: {
          url: '/else'
        }
      }
    });

    expect(badModel.getSomething).toBeUndefined();
    expect(typeof badModel.getElse).toBeDefined();
  });

  describe('calling a request method', () => {
    beforeEach(() => {
      const responseData = {
          status: 200,
          contentType: 'application/json',
          responseText: 'JSON user list'
        },
        ajaxFake = () => {
          const d = jQuery.Deferred();

          d.resolve(responseData.responseText, responseData.status, responseData);

          return d.promise();
        };

      spyOn(jQuery, 'ajax').and.callFake(ajaxFake);
    });

    it('uses the global default settings', () => {
      expectFakeHeader('getUsers', 'foo');
    });

    it('overrides the global settings with settings defined per request', () => {
      expectFakeHeader('getThings', 'bar');
    });

    it('returns the ajax request object', (done) => {
      const request = myModel.getUsers(),
        mostRecentArgs = ajaxArgsFromCall();

      expect(mostRecentArgs.url).toEqual('/api/users');
      expect(mostRecentArgs.method).toEqual('GET');
      request.then((data) => {
        expect(data).toEqual('JSON user list');
        done();
      });
    });

    describe('with a payload', () => {
      it('calls jQuery.ajax with the correct data value', () => {
        const payload = {
          email: 'john@example.com',
          password: 'abcd1234'
        };

        myModel.createUser(payload);

        const mostRecentArgs = ajaxArgsFromCall();

        expect(mostRecentArgs.url).toEqual('/api/users');
        expect(mostRecentArgs.method).toEqual('POST');
        expect(mostRecentArgs.data).toEqual(JSON.stringify(payload));
      });
    });

    describe('without necessary url keys', () => {
      it('throws an error', () => {
        expect(myModel.getUser).toThrow(new Error('Must supply url keys before calling fulfill'));
      });
    });

    describe('with url keys', () => {
      it('calls jQuery.ajax with the correctly keyed url', () => {
        myModel.getUser.for({userId: '123'})();

        const mostRecentArgs = ajaxArgsFromCall();

        expect(mostRecentArgs.url).toEqual('/api/users/123');
        expect(mostRecentArgs.method).toEqual('GET');
      });
    });

    describe('with unnecessary url keys', () => {
      it('calls jQuery.ajax with the correct url', () => {
        myModel.getThings.for({
          someKey: '1',
          anotherKey: 'abc'
        })();

        const mostRecentArgs = ajaxArgsFromCall();

        expect(mostRecentArgs.url).toEqual('/api/things');
        expect(mostRecentArgs.method).toEqual('GET');
      });
    });

    describe('with url keys and payload', () => {
      it('calls jQuery.ajax with the correct data value', () => {
        const payload = {
          email: 'john@example.com',
          password: 'abcd1234'
        };

        myModel.updateUser.for({ userId: '123'})(payload);

        const mostRecentArgs = ajaxArgsFromCall();

        expect(mostRecentArgs.url).toEqual('/api/users/123');
        expect(mostRecentArgs.method).toEqual('PATCH');
        expect(mostRecentArgs.data).toEqual(JSON.stringify(payload));
      });
    });
  });
});