timhaley94/holdem

View on GitHub
server/src/domain/user/index.test.js

Summary

Maintainability
C
7 hrs
Test Coverage
const { Types } = require('mongoose');
const { Auth, Errors } = require('../../modules');
const { init, close } = require('../../loaders');
const User = require('./index');

describe('Domain.Users', () => {
  beforeAll(init);
  afterAll(close);

  const data = {
    secret: 'foobarbazbuq1000',
    name: 'Jim Halpert',
    avatarId: '1',
  };

  describe('.exists()', () => {
    it('does not throw if user exists', async () => {
      const { _id } = await User.create({
        secret: data.secret,
      });

      await User.exists({ id: _id.toString() });
    });

    it('throws if user does not exist', async () => {
      expect.assertions(1);

      try {
        await User.exists({
          id: Types.ObjectId().toHexString(),
        });
      } catch (e) {
        expect(e instanceof Errors.NotFound).toBeTruthy();
      }
    });
  });

  describe('.retrieve()', () => {
    it('throws on no result', async () => {
      expect.assertions(1);

      try {
        await User.retrieve({
          id: Types.ObjectId().toHexString(),
        });
      } catch (e) {
        expect(e instanceof Errors.NotFound).toBeTruthy();
      }
    });
  });

  describe('.create()', () => {
    it('requires secret', async () => {
      expect.assertions(1);

      try {
        await User.create({});
      } catch (e) {
        expect(e instanceof Errors.BadRequest).toBeTruthy();
      }
    });

    it('can create with required fields', async () => {
      const user = await User.create({
        secret: data.secret,
      });

      const id = user._id.toString();

      expect(id).toBeTruthy();
      expect(typeof id).toEqual('string');
      expect(user.secret).toEqual(data.secret);
    });

    it('can create with optional fields', async () => {
      const user = await User.create(data);

      const id = user._id.toString();

      expect(id).toBeTruthy();
      expect(typeof id).toEqual('string');
      expect(user.name).toEqual(data.name);
      expect(user.avatarId).toEqual(data.avatarId);
    });

    it('throws on bad data', async () => {
      expect.assertions(1);

      try {
        await User.create({
          secret: ['foo', 'bar'],
          name: 459,
          avatarId: false,
        });
      } catch (e) {
        expect(e instanceof Errors.BadRequest).toBeTruthy();
      }
    });

    it('persists to database', async () => {
      const { _id } = await User.create(data);
      const id = _id.toString();

      const user = await User.retrieve({ id });

      expect(id).toEqual(id);

      Object.entries(data).forEach(
        ([key, value]) => {
          expect(value).toEqual(user[key]);
        },
      );
    });

    it('throws on db error', async () => {
      const spy = jest.spyOn(User.model, 'create');

      spy.mockImplementation(() => {
        throw new Error();
      });

      expect.assertions(1);

      try {
        await User.create(data);
      } catch (e) {
        expect(e instanceof Errors.Fatal).toBeTruthy();
      }

      spy.mockRestore();
    });
  });

  describe('.auth()', () => {
    it('throws if secret is wrong', async () => {
      expect.assertions(1);

      const user = await User.create(data);

      try {
        await User.auth({
          id: user._id.toString(),
          secret: 'wrongsecret123',
        });
      } catch (e) {
        expect(e instanceof Errors.Unauthorized).toBeTruthy();
      }
    });

    it('returns token if secret is correct', async () => {
      expect.assertions(1);

      const user = await User.create(data);
      const token = await User.auth({
        id: user._id.toString(),
        secret: data.secret,
      });

      const { id } = Auth.verify(token);
      expect(id).toEqual(user._id.toString());
    });
  });

  describe('.update()', () => {
    const updateData = {
      name: 'Pam Beasley',
      avatarId: '2',
    };

    it('throws on bad data', async () => {
      expect.assertions(1);

      const user = await User.create(data);

      try {
        await User.update({
          id: user._id.toString(),
          name: [1, 2, 3],
          avatarId: false,
        });
      } catch (e) {
        expect(e instanceof Errors.BadRequest).toBeTruthy();
      }
    });

    it('hanldes and persist valid data', async () => {
      let user = await User.create(data);
      const id = user._id.toString();

      await User.update({
        id,
        ...updateData,
      });

      user = await User.retrieve({ id });

      Object.entries(updateData).forEach(
        ([key, value]) => {
          expect(value).toEqual(user[key]);
        },
      );
    });

    it('fires listener on update', async () => {
      const user = await User.create(data);
      const id = user._id.toString();

      const cb = jest.fn();
      User.listener.subscribe(id, cb);

      await User.update({
        id,
        ...updateData,
      });

      expect(cb).toBeCalled();
    });

    it('throws on db error', async () => {
      const spy = jest.spyOn(User.model, 'updateOne');

      spy.mockImplementation(() => {
        throw new Error();
      });

      expect.assertions(1);

      const user = await User.create(data);
      const id = user._id.toString();

      try {
        await User.update({
          id,
          ...updateData,
        });
      } catch (e) {
        expect(e instanceof Errors.Fatal).toBeTruthy();
      }

      spy.mockRestore();
    });
  });
});