-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Add tests and update all packages to latest version (#8)
* 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
Showing
31 changed files
with
2,234 additions
and
1,597 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.