Skip to content

Commit

Permalink
WIP: Add tests and update all packages to latest version (#8)
Browse files Browse the repository at this point in the history
* add github workflow file and fix compiler errors

* add deploy script

* add strict compiler flag and update packages

* successfully set up auth test and add http error models

* get some tests written and stub out the rest

* finish auth tests

* move error models; fix tslint errors

* reformat constructor

Signed-off-by: Connor Ruggles <conruggles@gmail.com>

* finish tests for logic; still need to figure out full integration tests

* update packages

* update packages

* use different process for dev runs

* get rid of deploy script, move everything over to github actions
  • Loading branch information
rugglcon authored May 4, 2020
1 parent 626a7f4 commit 11b5c42
Show file tree
Hide file tree
Showing 31 changed files with 2,234 additions and 1,597 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Deploy

on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Cache Node.js modules
uses: actions/cache@v1
with:
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.OS }}-node-
${{ runner.OS }}-
- name: npm install and build prod
run: |
npm ci
npm run ci
- name: copy files to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
source: "./dist/*"
target: ${{ secrets.SSH_DEST }}
- name: restart budgets server
run: ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} ${{ secrets.SSH_CMD }}
env:
CI: true
31 changes: 31 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: PR Actions

on:
pull_request:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Cache Node.js modules
uses: actions/cache@v1
with:
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.OS }}-node-
${{ runner.OS }}-
- name: npm install, build, and test
run: |
npm ci
npm run ci
env:
CI: true
148 changes: 148 additions & 0 deletions __tests__/auth.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { AuthLogic } from '../src/logic/auth';
import { UserLogic } from '../src/logic/users';
import { Repository } from 'typeorm';
import { User, NewUser } from '../src/data/entities/user';
import logger from '../src/util/logger';

describe('AuthLogic should', () => {
let logic: AuthLogic;
let userLogic: UserLogic;
let repo: Repository<User>;
let user: User;

beforeEach(() => {
repo = new Repository<User>();
userLogic = new UserLogic(repo);
logic = new AuthLogic(userLogic);

user = new User();
// hashed version of 'password'
user.password = '$2b$10$2f.Q.8acxtXTIvZADjtNfex9THg6gBlXrITG194IWtb1h0MeVScKK';
user.userName = 'user';
});

it('should be instantiated', () => {
expect(logic).toBeDefined();
});

describe('login', () => {
it('should return a user with loggedIn to true on successful login', async () => {
jest.spyOn(repo, 'findOne').mockImplementation(options => Promise.resolve(user));
jest.spyOn(repo, 'save').mockImplementation(item => Promise.resolve(user));
jest.spyOn(userLogic, 'get');
jest.spyOn(userLogic, 'update');

const res = await logic.login({userName: 'user', password: 'password'});

expect(res.loggedIn).toBeTruthy();
expect(res.password).toBe(user.password);
expect(res.userName).toBe(user.userName);
expect(userLogic.get).toHaveBeenCalledWith({where: {userName: user.userName}});
expect(userLogic.update).toHaveBeenCalledTimes(1);
});

it('should throw NotFoundError if user does not exist on login', done => {
jest.spyOn(repo, 'findOne').mockImplementation(options => Promise.resolve(undefined));
jest.spyOn(userLogic, 'get');
jest.spyOn(userLogic, 'update');
jest.spyOn(logger, 'error');

logic.login({userName: 'user', password: 'pass'}).catch(err => {
expect(logger.error).toHaveBeenCalledWith('Got a null user');
expect(err.message).toBe('User with username user not found.');
expect(err.status).toBe(404);
expect(userLogic.get).toHaveBeenCalledWith({where: {userName: user.userName}});
expect(userLogic.update).not.toHaveBeenCalled();
done();
});
});

it('should throw UnauthorizedError if incorrect password given to login', done => {
jest.spyOn(repo, 'findOne').mockImplementation(options => Promise.resolve(user));
jest.spyOn(userLogic, 'get');
jest.spyOn(userLogic, 'update');

logic.login({userName: 'user', password: 'porsword'}).catch(err => {
expect(err.message).toBe('Username and password do not match.');
expect(err.status).toBe(401);
expect(userLogic.get).toHaveBeenCalledWith({where: {userName: user.userName}});
expect(userLogic.update).not.toHaveBeenCalled();
done();
});
});
});

describe('logout', () => {
it('should set loggedIn to false on logout', async () => {
jest.spyOn(userLogic, 'update');
jest.spyOn(repo, 'save').mockImplementation(item => Promise.resolve(user));

await logic.logout(user);

expect(user.loggedIn).toBeFalsy();
expect(userLogic.update).toHaveBeenCalled();
});
});

describe('signup', () => {
it('should create new loggedIn user on signup', async () => {
jest.spyOn(repo, 'findOne').mockImplementationOnce(options => Promise.resolve(undefined));
jest.spyOn(repo, 'create').mockImplementation(item => user);
jest.spyOn(repo, 'save').mockImplementation(item => Promise.resolve(user));
jest.spyOn(repo, 'findOne').mockImplementationOnce(options => Promise.resolve(user));
jest.spyOn(userLogic, 'create');
jest.spyOn(userLogic, 'get');
jest.spyOn(logic, 'login');

const loggedInUser = await logic.signup({userName: 'user', password: 'password'} as NewUser);
expect(userLogic.create).toHaveBeenCalledTimes(1);
expect(userLogic.get).toHaveBeenCalledTimes(2);
expect(userLogic.get).toHaveBeenCalledWith({where: {userName: 'user'}});
expect(logic.login).toHaveBeenCalledWith({userName: 'user', password: 'password'});
expect(loggedInUser.userName).toEqual(user.userName);
expect(loggedInUser.password).toEqual(user.password);
expect(user.loggedIn).toBeTruthy();
});

it('should throw BadRequestError if duplicate username on signup', done => {
jest.spyOn(repo, 'findOne').mockImplementation(options => Promise.resolve(user));
jest.spyOn(logger, 'error');
jest.spyOn(userLogic, 'get');

logic.signup({userName: 'user', password: 'password'} as NewUser).catch(err => {
expect(logger.error).toHaveBeenCalledWith('user with username [user] already exists');
expect(repo.findOne).toHaveBeenCalledTimes(1);
expect(err.message).toBe('User with username user already exists.');
expect(err.status).toBe(400);
expect(userLogic.get).toHaveBeenCalledWith({where: {userName: 'user'}});
done();
});
});
});

describe('authenticate', () => {
it('should return valid user when trying to authenticate', async () => {
jest.spyOn(repo, 'findOne').mockImplementationOnce(options => Promise.resolve(user));
jest.spyOn(userLogic, 'get');

const ret = await logic.authenticate('user');

expect(userLogic.get).toHaveBeenCalledTimes(1);
expect(repo.findOne).toHaveBeenCalledTimes(1);
expect(ret.userName).toBe(user.userName);
expect(ret.password).toBe(user.password);
});

it('should throw NotFoundError if trying to authenticate for a user that does not exist', done => {
jest.spyOn(repo, 'findOne').mockImplementation(options => Promise.resolve(undefined));
jest.spyOn(userLogic, 'get');

logic.authenticate('user').catch(err => {
expect(err.message).toBe('User with username user not found as being logged in.');
expect(err.status).toBe(404);
expect(userLogic.get).toHaveBeenCalledTimes(1);
done();
});
});
});
});
Loading

0 comments on commit 11b5c42

Please sign in to comment.