diff --git a/.github/workflows/testCoveralls.yml b/.github/workflows/testCoveralls.yml index 1d12740a..339ba535 100644 --- a/.github/workflows/testCoveralls.yml +++ b/.github/workflows/testCoveralls.yml @@ -16,10 +16,11 @@ jobs: with: node-version: 16.x - - name: npm install, make test-coverage + - name: run tests run: | npm install - make test-coverage + cd Backend + npm run test:cov - name: Coveralls uses: coverallsapp/github-action@v2 diff --git a/Backend/src/app.module.spec.ts b/Backend/src/app.module.spec.ts new file mode 100644 index 00000000..6e6458ef --- /dev/null +++ b/Backend/src/app.module.spec.ts @@ -0,0 +1,47 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MongooseModule } from '@nestjs/mongoose'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { AppModule } from './app.module'; +import { UserModule } from './user/user.module'; +import { Logger } from '@nestjs/common'; + +describe('AppModule', () => { + let module: TestingModule; + + beforeEach(async () => { + const mockConfigService = { + get: jest.fn().mockReturnValue('mongodb://localhost/test'), + }; + + module = await Test.createTestingModule({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + }), + MongooseModule.forRootAsync({ + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => { + Logger.log('Factory function called', 'Database'); + const uri = configService.get('MONGODB_URI'); + Logger.log(`MongoDB URI: ${uri}`, 'Database'); + return { uri }; + }, + inject: [ConfigService], + }), + UserModule, + ], + }) + .overrideProvider(ConfigService) + .useValue(mockConfigService) + .compile(); + }); + + it('should compile the module', () => { + expect(module).toBeDefined(); + }); + + it('should use the correct MongoDB URI', () => { + const configService = module.get(ConfigService); + expect(configService.get('MONGODB_URI')).toBe('mongodb://localhost/test'); + }); +}); diff --git a/Backend/src/auth/auth.module.spec.ts b/Backend/src/auth/auth.module.spec.ts new file mode 100644 index 00000000..a3fc37e5 --- /dev/null +++ b/Backend/src/auth/auth.module.spec.ts @@ -0,0 +1,28 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthModule } from './auth.module'; +import { AuthService } from './auth.service'; +import { AuthController } from './auth.controller'; + +describe('AuthModule', () => { + let module: TestingModule; + + beforeEach(async () => { + module = await Test.createTestingModule({ + imports: [AuthModule], + }).compile(); + }); + + it('should compile the module', () => { + expect(module).toBeDefined(); + }); + + it('should provide AuthService', () => { + const authService = module.get(AuthService); + expect(authService).toBeDefined(); + }); + + it('should provide AuthController', () => { + const authController = module.get(AuthController); + expect(authController).toBeDefined(); + }); +}); diff --git a/Backend/src/user/user.service.spec.ts b/Backend/src/user/user.service.spec.ts index 35c3deb6..f0168b32 100644 --- a/Backend/src/user/user.service.spec.ts +++ b/Backend/src/user/user.service.spec.ts @@ -2,6 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getModelToken } from '@nestjs/mongoose'; import { UserService } from './user.service'; import { User, UserDocument } from './user.schema'; +import * as bcrypt from 'bcryptjs'; import { Model } from 'mongoose'; describe('UserService', () => { @@ -35,4 +36,62 @@ describe('UserService', () => { expect(service).toBeDefined(); }); + describe('findOne', () => { + it('should return a user if found', async () => { + const user = { username: 'testUser', password: 'hashedPassword' } as UserDocument; + mockUserModel.findOne.mockReturnValue({ + exec: jest.fn().mockResolvedValue(user), + }); + + expect(await service.findOne('testUser')).toEqual(user); + }); + + it('should return an error if user not found', async () => { + mockUserModel.findOne.mockReturnValue({ + exec: jest.fn().mockResolvedValue(null), + }); + + expect(await service.findOne('nonexistentUser')).toEqual({ + error: 'User not found', + message: 'The user with the provided username does not exist', + }); + }); + }); + + describe('validateUser', () => { + it('should return a user if validation is successful', async () => { + const user = { + username: 'testUser', + password: 'hashedPassword' + } as UserDocument; + jest.spyOn(service, 'findOne').mockResolvedValue(user); + + const compareSpy = jest.spyOn(bcrypt, 'compare') as unknown as jest.MockInstance< + Promise, + [string, string] + >; + + compareSpy.mockResolvedValue(true); + + expect(await service.validateUser('testUser', 'plainPassword')).toEqual({ message: 'Login successful', user: { username: 'testUser' } }); + }); + + it('should return an error if validation fails', async () => { + const user = { username: 'testUser', password: 'hashedPassword' } as UserDocument; + jest.spyOn(service, 'findOne').mockResolvedValue(null); + + const compareSpy = jest.spyOn(bcrypt, 'compare') as unknown as jest.MockInstance< + Promise, + [string, string] + >; + + compareSpy.mockResolvedValue(false); + + expect(await service.validateUser('testUser', 'wrongPassword')).toEqual({ + error: 'Login failed', + message: 'Invalid username or password', + }); + }); + }); + }); diff --git a/Backend/src/user/user.service.ts b/Backend/src/user/user.service.ts index f5301b8b..53162fa6 100644 --- a/Backend/src/user/user.service.ts +++ b/Backend/src/user/user.service.ts @@ -12,7 +12,7 @@ export class UserService { } async findOne(username: string): Promise { - var user = this.userModel.findOne({username}).exec(); + var user = await this.userModel.findOne({ username }).exec(); if (user) { return user; @@ -26,7 +26,12 @@ export class UserService { async create(email: string, username: string, password: string): Promise { const hashedPassword = await bcrypt.hash(password, 10); - const newUser = new this.userModel({username, password: hashedPassword, email, spotifyConnected: false}); + const newUser = new this.userModel({ + username, + password: hashedPassword, + email, + spotifyConnected: false + }); await newUser.save(); return {message:'Creation successful,', user: newUser}; diff --git a/Frontend/src/app/pages/home/home.component.ts b/Frontend/src/app/pages/home/home.component.ts index c24b806c..85ce7a0c 100644 --- a/Frontend/src/app/pages/home/home.component.ts +++ b/Frontend/src/app/pages/home/home.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import {SongRecommendationComponent} from "../../shared/song-recommendation/song-recommendation.component"; import { NavbarComponent } from '../../shared/navbar/navbar.component'; import { ThemeService } from './../../services/theme.service'; -import { MatSidenav} from '@angular/material/sidenav'; +import { MatSidenav } from '@angular/material/sidenav'; import { MatCard, MatCardContent } from '@angular/material/card'; import { NgClass, NgForOf, NgIf } from '@angular/common'; import { SideBarComponent} from '../../shared/side-bar/side-bar.component';