diff --git a/package.json b/package.json index 2fee235..a16188e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "test": "jasmine" + "test": "nyc jasmine" }, "author": "", "license": "ISC", @@ -14,13 +14,13 @@ "express": "^4.18.2", "express-session": "^1.18.0", "firebase-admin": "^12.0.0", - "jasmine-node": "^1.16.0", "multer": "^1.4.5-lts.1", "request": "^2.88.2", "sinon": "^17.0.1" }, "devDependencies": { - "jasmine": "^5.1.0" + "jasmine": "^5.1.0", + "nyc": "^15.1.0" } } diff --git a/spec/auth.spec.js b/spec/auth.spec.js new file mode 100644 index 0000000..1d82831 --- /dev/null +++ b/spec/auth.spec.js @@ -0,0 +1,101 @@ +const sinon = require('sinon'); +const auth = require('../auth'); // Assuming auth.js is where signup function resides +const userManager = require('../userManager'); // Assuming userManager module is required + +describe('signup function', () => { + let getUserStub; + let addUserStub; + + beforeEach(() => { + getUserStub = sinon.stub(userManager, 'getUser'); + addUserStub = sinon.stub(userManager, 'addUser'); + }); + + afterEach(() => { + getUserStub.restore(); + if (addUserStub) addUserStub.restore(); + }); + + it('should signup a new user and redirect to browse page if user does not exist', async () => { + const req = { body: { username: 'newUser', password: 'password123' }, session: {} }; + const res = { redirect: sinon.stub() }; + getUserStub.resolves(null); + addUserStub.resolves({ id: 'fakeUserId' }); + + // Call the function + await auth.signup(req, res); + + // Assertions + expect(userManager.getUser.calledOnceWith('newUser')).toBe(true); + expect(userManager.addUser.calledOnceWith('newUser', 'password123')).toBe(true); + expect(req.session.userId).toBe('fakeUserId'); + expect(res.redirect.calledOnceWith('/browse')).toBe(true); + }); + + it('should not signup a new user if user already exists', async () => { + const req = { body: { username: 'existingUser', password: 'password123' }, session: {} }; + const res = { redirect: sinon.stub() }; + getUserStub.resolves({}); + const result = await auth.signup(req, res); + expect(userManager.getUser.calledOnceWith('existingUser')).toBe(true); + expect(result).toBe(false); + expect(res.redirect.called).toBe(false); + }); + + it('should handle errors if getUser function fails', async () => { + const req = { body: { username: 'newUser', password: 'password123' }, session: {} }; + const res = { redirect: sinon.stub() }; + getUserStub.rejects(new Error('getUser failed')); + const result = await auth.signup(req, res); + expect(result).toBe(false); + expect(res.redirect.called).toBe(false); + }); + + it('should handle invalid input if username or password is missing', async () => { + const req = { body: { username: 'missingPassword' }, session: {} }; + const res = { redirect: sinon.stub() }; + const result = await auth.signup(req, res); + expect(result).toBe(false); + expect(res.redirect.called).toBe(false); + }); +}); + +describe('signin function', () => { + let getUserStub; + let req, res; + + beforeEach(() => { + getUserStub = sinon.stub(userManager, 'getUser'); + req = { body: {}, session: {} }; + res = { redirect: sinon.stub() }; + }); + + afterEach(() => { + getUserStub.restore(); + }); + + it('should sign in a user with valid credentials and redirect to the browse page', async () => { + const username = 'validUser'; + const password = 'validPassword'; + const user = { id: 'falseUserId' }; + getUserStub.resolves(user); + req.body.username = username; + req.body.password = password; + await auth.signin(req, res); + expect(userManager.getUser.calledOnceWith(username, password)).toBe(true); + expect(req.session.userId).toBe(user.id); + expect(res.redirect.calledOnceWith('/browse')).toBe(true); + }); + + it('should not sign in a user with invalid credentials', async () => { + const username = 'invalidUser'; + const password = 'invalidPassword'; + getUserStub.resolves(null); + req.body.username = username; + req.body.password = password; + const result = await auth.signin(req, res); + expect(userManager.getUser.calledOnceWith(username, password)).toBe(true); + expect(result).toBe(false); + expect(res.redirect.called).toBe(false); + }); +}); diff --git a/spec/user.spec.js b/spec/user.spec.js index 845e5a8..e15a86f 100644 --- a/spec/user.spec.js +++ b/spec/user.spec.js @@ -1,7 +1,10 @@ const sinon = require('sinon'); const userManager = require('../userManager.js'); +const { addUser } = require('../userManager.js'); +const { getUser } = require('../userManager.js'); +const db = require('../firebase') -describe('find user(admin)', () => { +describe('getUserById', () => { it('should return the admin user given their id', async () => { // Stub the getUserById function of userManager const getUserByIdStub = sinon.stub(userManager, 'getUserById'); @@ -18,4 +21,118 @@ describe('find user(admin)', () => { // Restore the original function to avoid affecting other tests getUserByIdStub.restore(); }); -}); \ No newline at end of file + + it('should return the user with the given user ID', async () => { + const getUserByIdStub = sinon.stub(userManager, 'getUserById'); + getUserByIdStub.withArgs('J45gM6VGe6bmRdN1MCpr').resolves({ username: 'admin', userId: 'J45gM6VGe6bmRdN1MCpr' }); + const user = await userManager.getUserById('J45gM6VGe6bmRdN1MCpr'); + expect(user.userId).toBe('J45gM6VGe6bmRdN1MCpr'); + getUserByIdStub.restore(); + }); + + it('should return null if the user ID is not found', async () => { + const getUserByIdStub = sinon.stub(userManager, 'getUserById'); + getUserByIdStub.withArgs('noId').resolves(null); + const user = await userManager.getUserById('noId'); + expect(user).toBeNull(); + getUserByIdStub.restore(); + }); + + it('should return null if the DB is empty', async () => { + const getUserByIdStub = sinon.stub(userManager, 'getUserById'); + getUserByIdStub.resolves(null); + const user = await userManager.getUserById('randomID'); + expect(user).toBeNull(); + getUserByIdStub.restore(); + }); + + it('should return null if no ID is provided', async () => { + const getUserByIdStub = sinon.stub(userManager, 'getUserById'); + getUserByIdStub.withArgs('').resolves(null); + const user = await userManager.getUserById(''); + expect(user).toBeNull(); + getUserByIdStub.restore(); + }); +}); + +describe('addUser', () => { + it('should pass in testName and testPass into db', async() => { + const addUserStub = sinon.stub(userManager, 'addUser'); + addUserStub.withArgs('testName', 'testPass').resolves({username: 'testName', password: 'testPass'}); + const user = await userManager.addUser('testName', 'testPass'); + expect(user.username).toBe('testName'); + expect(user.password).toBe('testPass'); + addUserStub.restore(); + }); + + it('should pass in testName and testPass into db and expect the titles not to be swapped', async() => { + const addUserStub = sinon.stub(userManager, 'addUser'); + addUserStub.withArgs('testName', 'testPass').resolves({username: 'testName', password: 'testPass'}); + const user = await userManager.addUser('testName', 'testPass'); + expect(user.username).not.toBe('testPass'); + expect(user.password).not.toBe('testName'); + addUserStub.restore(); + }); + + it('should pass in data into db and not be empty', async() => { //potential bug if allowed + const addUserStub = sinon.stub(userManager, 'addUser'); + addUserStub.withArgs('', '').resolves({username: '', password: ''}); + const user = await userManager.addUser('', ''); + expect(user.username).toBe(''); + expect(user.password).toBe(''); + addUserStub.restore(); + }); +}); + +describe('getUser', () => { //Working incorrectly. May have something to do with how the functions interact with the db these tests are all returning null meaning none of the users are being recognized as pre-existing in the mock. + let getStub; + + beforeEach(() => { + getStub = sinon.stub(db.firestore.collection('users'), 'get'); + }); + + afterEach(() => { + getStub.restore(); + }); + + it('should return the user document if the username and password match', async () => { + const username = 'TestingTony'; + const password = 'rightPass'; + const userDoc = { data: () => ({ username: 'TestingTony', password: 'rightPass' }) }; + getStub.resolves({ docs: [userDoc] }); + + const user = await getUser(username, password); + + expect(user).toEqual(userDoc); + }); + + it('should return the user document if the username matches and no password is provided', async () => { + const username = 'TestingTony'; + const userDoc = { data: () => ({ username: 'TestingTony', password: 'rightPass' }) }; + getStub.resolves({ docs: [userDoc] }); + + const user = await getUser(username); + + expect(user).toEqual(userDoc); + }); + + it('should return null if the username does not match', async () => { + const username = 'noUser'; + getStub.resolves({ docs: [] }); + + const user = await getUser(username); + + expect(user).toBeNull(); + }); + + it('should return null if the username matches but the password does not', async () => { + const username = 'TestingTony'; + const password = 'wrongPass'; + const userDoc = { data: () => ({ username: 'TestingTony', password: 'rightPass' }) }; + getStub.resolves({ docs: [userDoc] }); + + const user = await getUser(username, password); + + expect(user).toBeNull(); + }); +});