Asymmetrik/node-rest-starter

View on GitHub
src/app/core/user/user.controller.spec.ts

Summary

Maintainability
F
3 days
Test Coverage
import { assert, createSandbox } from 'sinon';

import userAuthorizationService from './auth/user-authorization.service';
import * as userController from './user.controller';
import { User } from './user.model';
import userService from './user.service';
import { auditService, config } from '../../../dependencies';
import { getResponseSpy } from '../../../spec/helpers';
import {
    BadRequestError,
    ForbiddenError,
    UnauthorizedError
} from '../../common/errors';

/**
 * Unit tests
 */
describe('User Profile Controller:', () => {
    let res;
    let sandbox;

    beforeEach(() => {
        sandbox = createSandbox();
        res = getResponseSpy();
    });

    afterEach(() => {
        sandbox.restore();
    });

    describe('getCurrentUser', () => {
        it('user is logged in (user attached to request)', async () => {
            const req = {
                body: {},
                user: new User()
            };

            sandbox.stub(userAuthorizationService, 'updateRoles').resolves();

            await userController.getCurrentUser(req, res);

            assert.calledOnce(userAuthorizationService.updateRoles);

            assert.calledWith(res.status, 200);
            assert.called(res.json);
        });

        it('user is not logged in (user not attached to request)', async () => {
            const req = {
                body: {}
            };

            sandbox.stub(userAuthorizationService, 'updateRoles').resolves();

            await userController
                .getCurrentUser(req, res)
                .should.be.rejectedWith(new UnauthorizedError('User is not logged in'));

            assert.notCalled(userAuthorizationService.updateRoles);
        });
    });

    describe('updateCurrentUser', () => {
        it('user is logged in; success', async () => {
            const user = new User();
            user.save = () => Promise.resolve(user);
            const req = {
                body: {},
                user: user,
                login: (u, callback) => {
                    callback();
                }
            };

            sandbox.stub(userService, 'read').resolves(user);
            sandbox.stub(auditService, 'audit').resolves();

            await userController.updateCurrentUser(req, res);

            assert.calledWith(res.status, 200);
            assert.calledWithMatch(res.json, { id: user.id });

            assert.calledWithMatch(auditService.audit, 'user updated');
        });

        it('user is logged in; success w/ password change', async () => {
            const user = new User();
            user.password = 'oldPassword';
            user.save = () => Promise.resolve(user);
            const req = {
                body: {
                    currentPassword: 'oldPassword',
                    password: 'newPassword'
                },
                user: user,
                login: (u, callback) => {
                    callback();
                }
            };
            user.auditCopy();

            sandbox.stub(userService, 'read').resolves(user);
            sandbox.stub(auditService, 'audit').resolves();

            await userController.updateCurrentUser(req, res);

            assert.calledWith(res.status, 200);
            assert.calledWithMatch(res.json, {});

            assert.calledWithMatch(auditService.audit, 'user updated');
        });

        it('user is logged in; changing password, currentPassword incorrect', async () => {
            const user = new User();
            user.password = 'differentPassword';

            const req = {
                body: {
                    currentPassword: 'oldPassword',
                    password: 'newPassword'
                },
                user: user
            };

            sandbox.stub(userService, 'read').resolves(user);
            sandbox.stub(auditService, 'audit').resolves();

            await userController
                .updateCurrentUser(req, res)
                .should.be.rejectedWith(
                    new BadRequestError('Current password invalid')
                );

            assert.calledWithMatch(
                auditService.audit,
                'user update authentication failed'
            );
        });

        it('user is logged in; login returns error', async () => {
            const user = new User();
            user.password = 'oldPassword';
            user.save = () => Promise.resolve(user);
            const req = {
                body: {
                    currentPassword: 'oldPassword',
                    password: 'newPassword'
                },
                user: user,
                login: (u, callback) => {
                    callback('error');
                }
            };

            sandbox.stub(userService, 'read').resolves(user);
            sandbox.stub(auditService, 'audit').resolves();

            await userController.updateCurrentUser(req, res);

            assert.calledWith(res.status, 400);
            assert.calledWithMatch(res.json, 'error');

            assert.calledWithMatch(auditService.audit, 'user updated');
        });

        it('user is not logged in', async () => {
            const req = {
                body: {}
            };

            await userController
                .updateCurrentUser(req, res)
                .should.be.rejectedWith(new BadRequestError('User is not logged in'));
        });
    });

    describe('updatePreferences', () => {
        it('user is logged in (user attached to request)', async () => {
            const req = {
                body: {},
                user: new User()
            };

            sandbox.stub(userService, 'updatePreferences').resolves();

            await userController.updatePreferences(req, res);

            assert.calledOnce(userService.updatePreferences);

            assert.calledWith(res.status, 200);
            assert.called(res.json);
        });
    });

    describe('updateRequiredOrgs', () => {
        it('user is logged in (user attached to request)', async () => {
            const req = {
                body: {},
                user: new User()
            };

            sandbox.stub(userService, 'updateRequiredOrgs').resolves();

            await userController.updateRequiredOrgs(req, res);

            assert.calledOnce(userService.updateRequiredOrgs);

            assert.calledWith(res.status, 200);
            assert.called(res.json);
        });
    });

    describe('getUserById', () => {
        it('user is found', async () => {
            const req = {
                body: {},
                userParam: new User()
            };

            await userController.getUserById(req, res);

            assert.calledWith(res.status, 200);
            assert.called(res.json);
        });
    });

    describe('searchUsers', () => {
        let req;
        beforeEach(() => {
            req = {
                body: {},
                user: new User()
            };
        });

        it('search returns successfully', async () => {
            sandbox.stub(userService, 'searchUsers').resolves({
                elements: []
            });

            await userController.searchUsers(req, res);

            assert.calledOnce(userService.searchUsers);
            assert.calledWith(res.status, 200);
            assert.calledOnce(res.json);
        });
    });

    describe('matchUsers', () => {
        let req;
        beforeEach(() => {
            req = {
                body: {},
                user: new User()
            };
        });

        it('search returns successfully', async () => {
            sandbox.stub(userService, 'searchUsers').resolves({
                elements: []
            });

            await userController.matchUsers(req, res);

            assert.calledOnce(userService.searchUsers);
            assert.calledWith(res.status, 200);
            assert.calledOnce(res.json);
        });
    });

    describe('canEditProfile', () => {
        it('local auth and undef bypass should be able to edit', () => {
            const _user = new User();
            const result = userController.canEditProfile('local', _user);
            result.should.equal(true);
        });

        it('local auth and no bypass should be able to edit', () => {
            const _user = new User({ bypassAccessCheck: false });
            const result = userController.canEditProfile('local', _user);
            result.should.equal(true);
        });

        it('local auth and bypass should be able to edit', () => {
            const _user = new User({ bypassAccessCheck: true });
            const result = userController.canEditProfile('local', _user);
            result.should.equal(true);
        });

        it('proxy-pki auth and undef bypass should not be able to edit', () => {
            const _user = new User({});
            const result = userController.canEditProfile('proxy-pki', _user);
            result.should.equal(false);
        });

        it('proxy-pki auth and no bypass should not be able to edit', () => {
            const _user = new User({ bypassAccessCheck: false });
            const result = userController.canEditProfile('proxy-pki', _user);
            result.should.equal(false);
        });

        it('proxy-pki auth and bypass should be able to edit', () => {
            const _user = new User({ bypassAccessCheck: true });
            const result = userController.canEditProfile('proxy-pki', _user);
            result.should.equal(true);
        });
    });

    describe('hasEdit', () => {
        it('user has edit', async () => {
            const configGetStub = sandbox.stub(config, 'get');
            configGetStub.withArgs('auth.strategy').returns('proxy-pki');
            const req = {
                body: {},
                user: { bypassAccessCheck: true }
            };

            await userController.hasEdit(req).should.not.be.rejected();
        });

        it('user does not have edit', async () => {
            const configGetStub = sandbox.stub(config, 'get');
            configGetStub.withArgs('auth.strategy').returns('proxy-pki');
            const req = {
                body: {},
                user: { bypassAccessCheck: false }
            };

            await userController
                .hasEdit(req)
                .should.be.rejectedWith(
                    new ForbiddenError('User not authorized to edit their profile')
                );
        });
    });
});