| @@ -1,10 +1,4 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public static class PaginationExtension | |||
| @@ -196,5 +196,19 @@ | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| return ad; | |||
| } | |||
| public async Task<Ad> GetByIdEntityAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| return ad; | |||
| } | |||
| } | |||
| } | |||
| @@ -9,23 +9,18 @@ namespace Diligent.WebAPI.Business.Services | |||
| private readonly ILogger<ApplicantService> _logger; | |||
| private readonly IUserService _userService; | |||
| private readonly IFileService _fileService; | |||
| private readonly IAdService _adService; | |||
| public ApplicantService(DatabaseContext context, IMapper mapper, ILogger<ApplicantService> logger, | |||
| IUserService userService,IFileService fileService) | |||
| IUserService userService,IFileService fileService,IAdService adService) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| _userService = userService; | |||
| _fileService = fileService; | |||
| _adService = adService; | |||
| } | |||
| public ApplicantService(DatabaseContext context, IMapper mapper, ILogger<ApplicantService> logger) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| } | |||
| public async Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| _logger.LogInformation("Start getting filtered applicants"); | |||
| @@ -79,14 +74,19 @@ namespace Diligent.WebAPI.Business.Services | |||
| public async Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {id}"); | |||
| var applicant = await _context.Applicants | |||
| .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.SelectionLevel) | |||
| .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.Scheduler) | |||
| .FirstOrDefaultAsync(a => a.ApplicantId == id); | |||
| if (applicant is null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {id} not found"); | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| } | |||
| _logger.LogInformation($"Applicant with id = {id} mapped successfully"); | |||
| return _mapper.Map<ApplicantViewDto>(applicant); | |||
| } | |||
| @@ -129,11 +129,14 @@ namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| string fileName = string.Format(@"{0}.pdf", DateTime.Now.Ticks); | |||
| _logger.LogInformation($"Start uploading CV of applicant on Azure Blob storage"); | |||
| await _fileService.UploadCV(fileName, request.PdfFile); | |||
| _logger.LogInformation($"CV uploaded on Azure Blob storage"); | |||
| _logger.LogInformation("Start applying for ad"); | |||
| _logger.LogInformation("Find ad by id"); | |||
| var ad = await _context.Ads.Where(x => x.Id == request.AdId).FirstOrDefaultAsync(); | |||
| var ad = await _adService.GetByIdEntityAsync(request.AdId); | |||
| if (ad == null) | |||
| { | |||
| @@ -189,7 +192,9 @@ namespace Diligent.WebAPI.Business.Services | |||
| _logger.LogInformation($"Create applicant instance with sent data"); | |||
| var res = new List<Applicant>(); | |||
| _logger.LogInformation($"Get first user from database"); | |||
| var user = await _userService.GetFirst(); | |||
| _logger.LogInformation($"User succesufully fetched from database"); | |||
| foreach (var request in requests) { | |||
| Applicant applicant = new Applicant | |||
| { | |||
| @@ -222,28 +227,34 @@ namespace Diligent.WebAPI.Business.Services | |||
| res.Add(applicant); | |||
| } | |||
| _logger.LogInformation($"Saving applicants in database"); | |||
| await _context.AddRangeAsync(res); | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Saving applicant in database"); | |||
| _logger.LogInformation($"Applicant saved in database"); | |||
| _logger.LogInformation($"Applicants saved in database"); | |||
| } | |||
| public async Task<List<ApplicantOptionsDTO>> GetOptions() | |||
| { | |||
| _logger.LogInformation($"Start getting all applicants from database"); | |||
| var res = await _context.Applicants.ToListAsync(); | |||
| _logger.LogInformation($"Got {res.Count} applicants"); | |||
| return _mapper.Map<List<ApplicantOptionsDTO>>(res); | |||
| } | |||
| public async Task<ServiceResponseDTO<object>> InitializeProcess(ApplicantProcessRequestDTO model) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {model.ApplicantId}"); | |||
| var applicant = await _context.Applicants.Include(n => n.SelectionProcesses).Where(n=> n.ApplicantId ==model.ApplicantId).FirstOrDefaultAsync(); | |||
| if (applicant == null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {model.ApplicantId} not found"); | |||
| return new ServiceResponseDTO<object> | |||
| { | |||
| IsError = true, | |||
| ErrorMessage = "Applicant does not exist." | |||
| }; | |||
| } | |||
| applicant.SelectionProcesses.Add(new SelectionProcess | |||
| { | |||
| @@ -254,7 +265,9 @@ namespace Diligent.WebAPI.Business.Services | |||
| Date = model.Appointment | |||
| }); | |||
| _logger.LogInformation($"Saving selection processes in database"); | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Selecetion processes saved in database"); | |||
| return new ServiceResponseDTO<object> | |||
| { | |||
| @@ -22,5 +22,6 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task ArchiveAdAsync(int id); | |||
| Task DeleteAsync(int id); | |||
| Task<Ad> GetByIdEntityAsync(int id); | |||
| } | |||
| } | |||
| @@ -10,7 +10,7 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task<ApplicantViewDto> GetById(int id); | |||
| Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id); | |||
| Task ApplyForAd(ApplyForAdRequestDto request); | |||
| Task DeleteApplicant(int id); | |||
| Task DeleteApplicant(int id); | |||
| Task<List<ApplicantOptionsDTO>> GetOptions(); | |||
| Task<ServiceResponseDTO<object>> InitializeProcess(ApplicantProcessRequestDTO model); | |||
| Task ImportApplicant(List<ApplicantImportDto> request); | |||
| @@ -20,7 +20,7 @@ | |||
| public async Task<TechnologyResponseDto> GetByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| _logger.LogInformation($"Start searching Techology with id = {id}"); | |||
| var technology = await _context.Technologies.FindAsync(id); | |||
| if (technology is null) | |||
| @@ -42,40 +42,29 @@ namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| [Authorize] | |||
| [HttpGet("processes/{id}")] | |||
| public async Task<IActionResult> GetProcesses(int id) | |||
| { | |||
| return Ok(await _applicantService.GetApplicantWithSelectionProcessesById(id)); | |||
| } | |||
| public async Task<IActionResult> GetProcesses(int id) => | |||
| Ok(await _applicantService.GetApplicantWithSelectionProcessesById(id)); | |||
| [Authorize] | |||
| [HttpGet("options")] | |||
| public async Task<IActionResult> GetOptions() | |||
| { | |||
| return Ok(await _applicantService.GetOptions()); | |||
| } | |||
| public async Task<IActionResult> GetOptions() => | |||
| Ok(await _applicantService.GetOptions()); | |||
| [Authorize] | |||
| [HttpPost("selection-init")] | |||
| public async Task<IActionResult> InitSelection(ApplicantProcessRequestDTO model) | |||
| { | |||
| await _applicantService.InitializeProcess(model); | |||
| return Ok(); | |||
| } | |||
| public async Task<IActionResult> InitSelection(ApplicantProcessRequestDTO model) => | |||
| Ok(await _applicantService.InitializeProcess(model)); | |||
| [Authorize] | |||
| [HttpPost("apply-for-ad")] | |||
| public async Task<IActionResult> ApplyForAd([FromForm]ApplyForAdRequestDto request) | |||
| { | |||
| await _applicantService.ApplyForAd(request); | |||
| return Ok(); | |||
| } | |||
| [HttpGet("get-CV")] | |||
| public async Task<IActionResult> GetCandidateCV(string fileName) | |||
| { | |||
| var res = await _fileService.GetCV(fileName); | |||
| return Ok(res); | |||
| } | |||
| public async Task<IActionResult> GetApplicantCV(string fileName) => | |||
| Ok(await _fileService.GetCV(fileName)); | |||
| } | |||
| } | |||
| @@ -9,7 +9,9 @@ namespace Diligent.WebAPI.Tests.Controllers | |||
| public class ApplicantsControllerTests | |||
| { | |||
| private readonly IApplicantService _applicantService = Substitute.For<IApplicantService>(); | |||
| private readonly IFileService _fileService = Substitute.For<IFileService>(); | |||
| private readonly ApplicantViewDto _applicant; | |||
| private readonly List<Contracts.DTOs.Ad.AdApplicantsViewDto> _adApplicants; | |||
| public ApplicantsControllerTests() | |||
| { | |||
| _applicant = new ApplicantViewDto | |||
| @@ -34,13 +36,112 @@ namespace Diligent.WebAPI.Tests.Controllers | |||
| new SelectionProcessResposneWithoutApplicantDto{ Status = ""} | |||
| } | |||
| }; | |||
| _adApplicants = new List<Contracts.DTOs.Ad.AdApplicantsViewDto> | |||
| { | |||
| new Contracts.DTOs.Ad.AdApplicantsViewDto | |||
| { | |||
| Applicants = new List<AdApplicantViewDto>{ new AdApplicantViewDto { | |||
| ApplicantId = 1, | |||
| CV = "link", | |||
| DateOfApplication = DateTime.Now, | |||
| Experience = 3, | |||
| FirstName = "Dzenis", | |||
| LastName = "Hadzifdejzovic", | |||
| TechnologyApplicants = new List<Contracts.DTOs.Technology.TechnologyViewDto>()} | |||
| }, | |||
| Id = 1, | |||
| Title = "some title" | |||
| } | |||
| }; | |||
| } | |||
| [Fact] | |||
| public async Task GetFilteredApplicants_ShouldReturn_200OK_Always() | |||
| { | |||
| var applicants = new List<ApplicantViewDto> | |||
| { | |||
| _applicant | |||
| }; | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| CurrentPage = 1, | |||
| PageSize = 4 | |||
| }; | |||
| _applicantService.GetFilteredApplicants(filterDto).Returns(new QueryResultDto<ApplicantViewDto> | |||
| { | |||
| Items = applicants, | |||
| Total = applicants.Count | |||
| }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.GetFilteredApplicants(filterDto); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldThrowEntityNotFoundException_WhenApplicantDoesNotExist() | |||
| { | |||
| _applicantService.When(x => x.GetById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetById(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldReturn_200OK_WhenApplicantExist() | |||
| { | |||
| _applicantService.GetById(Arg.Any<int>()).Returns(_applicant); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.GetById(1); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetAllAdsApplicants_ShouldReturn_200OK_Always() | |||
| { | |||
| _applicantService.GetAllAdsApplicants(Arg.Any<ApplicantFilterDto>()).Returns(_adApplicants); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.GetAllAdsApplicants(new ApplicantFilterDto { }); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task DeleteApplicant_ShouldThrowEntityNotFoundException_WhenApplicantDoesNotExist() | |||
| { | |||
| _applicantService.When(x => x.DeleteApplicant(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.DeleteApplicant(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task DeleteApplicant_ShouldReturn_200OK_WhenApplicantExist() | |||
| { | |||
| _applicantService.When(x => x.DeleteApplicant(Arg.Any<int>())).Do(x => { }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.DeleteApplicant(1000); | |||
| (result as StatusCodeResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetProcesses_ShouldReturn_200OK_WhenApplicantExists() | |||
| { | |||
| _applicantService.GetApplicantWithSelectionProcessesById(Arg.Any<int>()).Returns(_applicant); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| ApplicantsController applicantsController = new(_applicantService,_fileService); | |||
| var result = await applicantsController.GetProcesses(1); | |||
| @@ -48,57 +149,63 @@ namespace Diligent.WebAPI.Tests.Controllers | |||
| } | |||
| [Fact] | |||
| public async Task GetProcesses_ShouldThrowEntityNotFooundException_WhenApplicantDoesnotExist() | |||
| public async Task GetProcesses_ShouldThrowEntityNotFoundException_WhenApplicantDoesnotExist() | |||
| { | |||
| _applicantService.When(x => x.GetApplicantWithSelectionProcessesById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetProcesses(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldReturn_200OK_WhenApplicantExist() | |||
| public async Task GetOptions_ShouldReturn_200OK_Always() | |||
| { | |||
| _applicantService.GetById(Arg.Any<int>()).Returns(_applicant); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| _applicantService.GetOptions().Returns(new List<ApplicantOptionsDTO>()); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.GetById(1); | |||
| var result = await applicantsController.GetOptions(); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldThrowEntityNotFooundException_WhenApplicantDontExist() | |||
| public async Task InitSelecetion_ShouldReturnError_WhenApplicantDoesNotExist() | |||
| { | |||
| _applicantService.When(x => x.GetById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| _applicantService.InitializeProcess(Arg.Any<ApplicantProcessRequestDTO>()).Returns(new ServiceResponseDTO<object>()); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetById(1000)); | |||
| var result = await applicantsController.InitSelection(Arg.Any<ApplicantProcessRequestDTO>()); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetFilteredApplicants_ShouldReturn_200OK_Always() | |||
| public async Task ApplyForAd_ShouldThrowEntityNotFoundException_WhenAdDoesNotExist() | |||
| { | |||
| var applicants = new List<ApplicantViewDto> | |||
| { | |||
| _applicant | |||
| }; | |||
| _applicantService.When(x => x.ApplyForAd(Arg.Any<ApplyForAdRequestDto>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| CurrentPage = 1, | |||
| PageSize = 4 | |||
| }; | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.ApplyForAd(new ApplyForAdRequestDto())); | |||
| } | |||
| _applicantService.GetFilteredApplicants(filterDto).Returns(new QueryResultDto<ApplicantViewDto> | |||
| { | |||
| Items = applicants, | |||
| Total = applicants.Count | |||
| }); | |||
| [Fact] | |||
| public async Task ApplyForAd_ShouldReturn_200OK_WhenAdExist() | |||
| { | |||
| _applicantService.When(x => x.ApplyForAd(Arg.Any<ApplyForAdRequestDto>())).Do(x => { }); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| var result = await applicantsController.ApplyForAd(new ApplyForAdRequestDto()); | |||
| var result = await applicantsController.GetFilteredApplicants(filterDto); | |||
| (result as StatusCodeResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetApplicantCV_ShouldReturn_200OK_Always() | |||
| { | |||
| _fileService.GetCV(Arg.Any<string>()).Returns("some string"); | |||
| ApplicantsController applicantsController = new(_applicantService, _fileService); | |||
| var result = await applicantsController.GetOptions(); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| @@ -1,6 +1,5 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Data.Entities; | |||
| using static Diligent.WebAPI.Data.Entities.Applicant; | |||
| namespace Diligent.WebAPI.Tests | |||
| { | |||
| @@ -16,7 +15,7 @@ namespace Diligent.WebAPI.Tests | |||
| } | |||
| public static List<Applicant> GetListOfApplicants() | |||
| { | |||
| var applicant = new Applicant | |||
| var applicant1 = new Applicant | |||
| { | |||
| ApplicantId = 1, | |||
| ApplicationChannel = "Instagram", | |||
| @@ -39,9 +38,35 @@ namespace Diligent.WebAPI.Tests | |||
| new SelectionProcess{ Status = "", Name = ""} | |||
| } | |||
| }; | |||
| var applicant2 = new Applicant | |||
| { | |||
| ApplicantId = 2, | |||
| ApplicationChannel = "Instagram", | |||
| BitBucketLink = null, | |||
| CV = "link", | |||
| DateOfApplication = DateTime.Now, | |||
| Email = "some@mail.com", | |||
| Experience = 3, | |||
| FirstName = "Ermin", | |||
| LastName = "Bronja", | |||
| GithubLink = null, | |||
| LinkedlnLink = null, | |||
| PhoneNumber = "432424", | |||
| Position = ".NET Developer", | |||
| TypeOfEmployment = Applicant.TypesOfEmployment.Posao, | |||
| SelectionProcesses = new List<SelectionProcess> | |||
| { | |||
| new SelectionProcess{ Status = "", Name = ""}, | |||
| new SelectionProcess{ Status = "", Name = ""}, | |||
| new SelectionProcess{ Status = "", Name = ""} | |||
| } | |||
| }; | |||
| var applicants = new List<Applicant> | |||
| { | |||
| applicant | |||
| applicant1, | |||
| applicant2 | |||
| }; | |||
| return applicants; | |||
| @@ -71,6 +96,7 @@ namespace Diligent.WebAPI.Tests | |||
| { | |||
| var ad = new Ad | |||
| { | |||
| Id = 1, | |||
| Applicants = GetListOfApplicants(), | |||
| CreatedAt = DateTime.Now, | |||
| ExpiredAt = DateTime.Now.AddDays(5), | |||
| @@ -124,5 +150,37 @@ namespace Diligent.WebAPI.Tests | |||
| return comments; | |||
| } | |||
| public static List<Technology> GetListOfTechnologies() | |||
| { | |||
| var technology = new Technology | |||
| { | |||
| Name = ".NET", | |||
| TechnologyType = TechnologyTypes.Backend, | |||
| Ads = new List<Ad>(), | |||
| TechnologyApplicants = new List<TechnologyApplicant>() | |||
| }; | |||
| var techologies = new List<Technology> | |||
| { | |||
| technology | |||
| }; | |||
| return techologies; | |||
| } | |||
| public static List<ApplicantOptionsDTO> GetOptions() | |||
| { | |||
| var option1 = new ApplicantOptionsDTO | |||
| { | |||
| ApplicantId = GetListOfApplicants()[0].ApplicantId, | |||
| FirstName = "Option1", | |||
| LastName = "Optioon2" | |||
| }; | |||
| var options = new List<ApplicantOptionsDTO> { option1 }; | |||
| return options; | |||
| } | |||
| } | |||
| } | |||
| @@ -5,11 +5,6 @@ using Diligent.WebAPI.Contracts.DTOs.Ad; | |||
| using Diligent.WebAPI.Contracts.Exceptions; | |||
| using Diligent.WebAPI.Data.Entities; | |||
| using Microsoft.Extensions.Logging; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Tests.Services | |||
| { | |||
| @@ -5,6 +5,7 @@ using Diligent.WebAPI.Contracts.DTOs.Ad; | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.Exceptions; | |||
| using Diligent.WebAPI.Data.Entities; | |||
| using Microsoft.AspNetCore.Http; | |||
| using Microsoft.Extensions.Logging; | |||
| namespace Diligent.WebAPI.Tests.Services | |||
| @@ -13,13 +14,18 @@ namespace Diligent.WebAPI.Tests.Services | |||
| { | |||
| private readonly IMapper _mapper; | |||
| private ILogger<ApplicantService> _logger = Substitute.For<ILogger<ApplicantService>>(); | |||
| private readonly IUserService _userService = Substitute.For<IUserService>(); | |||
| private readonly IFileService _fileService = Substitute.For<IFileService>(); | |||
| private readonly IAdService _adService = Substitute.For<IAdService>(); | |||
| private readonly List<Applicant> _applicants; | |||
| private readonly List<Ad> _ads; | |||
| private readonly List<User> _users; | |||
| public ApplicantServiceTests() | |||
| { | |||
| // mock data | |||
| _applicants = MockData.GetListOfApplicants(); | |||
| _ads = MockData.GetListOfAds(); | |||
| _users = MockData.GetListOfUsers(); | |||
| // configure mapper | |||
| var configuration = new MapperConfiguration(cfg => cfg.AddProfiles( | |||
| @@ -33,79 +39,157 @@ namespace Diligent.WebAPI.Tests.Services | |||
| } | |||
| [Fact] | |||
| public async Task GetFilteredApplicants_ShouldReturnListOfApplicants_Always() | |||
| public async Task GetFilteredApplicants_ShouldReturnOneApplicant_Always() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var filterDto = new ApplicantFilterDto(); | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| MinExperience = 2, | |||
| MaxExperience = 4 | |||
| }; | |||
| var result = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Equal(_applicants.Count,result.Total); | |||
| Assert.Equal(1,result.Total); | |||
| } | |||
| [Fact] | |||
| public async Task GetAllAdsApplicants_ShouldReturnAllApplicants_Always() | |||
| { | |||
| var databaseContext = await Helpers<Ad>.GetDatabaseContext(_ads); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var filterDto = MockData.GetApplicantFilters(); | |||
| var result = await applicantService.GetAllAdsApplicants(filterDto); | |||
| result.Should().BeEquivalentTo(_mapper.Map<List<AdApplicantsViewDto>>(_ads)); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldReturnApplicant_WhenApplicantExist() | |||
| { | |||
| var fileInBase64Format = "some string"; | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| _fileService.GetCV(Arg.Any<string>()).Returns(fileInBase64Format); | |||
| var result = await applicantService.GetById(1); | |||
| _applicants[0].CV = fileInBase64Format; | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicants[0])); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldThrowEntityNotFooundException_WhenApplicantDontExist() | |||
| public async Task GetById_ShouldThrowEntityNotFoundException_WhenApplicantDoesNotExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(async () => await applicantService.GetById(1000)); | |||
| } | |||
| //[Fact] | |||
| //public async Task CreateApplicant_ShouldAddEntityIntoDatabase_Always() | |||
| //{ | |||
| // var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| // ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| // ApplicantCreateDto applicantCreateDto = new() | |||
| // { | |||
| // ApplicationChannel = "Facebook", | |||
| // BitBucketLink = null, | |||
| // CV = "link", | |||
| // Email = "some@mail.com", | |||
| // Experience = 1, | |||
| // FirstName = "Meris", | |||
| // LastName = "Ahmatovic", | |||
| // GithubLink = null, | |||
| // LinkedlnLink = null, | |||
| // PhoneNumber = "432424", | |||
| // Position = ".NET Developer", | |||
| // TypeOfEmployment = TypesOfEmployment.Intership.ToString() | |||
| // }; | |||
| // await applicantService.CreateApplicant(applicantCreateDto); | |||
| // var filterDto = new ApplicantFilterDto | |||
| // { | |||
| // CurrentPage = 1, | |||
| // PageSize = 4 | |||
| // }; | |||
| // var result = await applicantService.GetFilteredApplicants(filterDto); | |||
| // Assert.Equal(2, result.Total); | |||
| //} | |||
| [Fact] | |||
| public async Task GetApplicantWithSelectionProcessesById_ShouldReturnApplicant_WhenApplicantExists() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var result = await applicantService.GetApplicantWithSelectionProcessesById(1); | |||
| var processes = result.SelectionProcesses; | |||
| processes.Should().HaveCount(3); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicants[0])); | |||
| } | |||
| [Fact] | |||
| public async Task GetApplicantWithSelectionProcessesById_ShouldThrowEntityNotFoundException_WhenApplicantDoesNotExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(async () => await | |||
| applicantService.GetApplicantWithSelectionProcessesById(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task ApplyForAd_ShouldThrowEntityNotFooundException_WhenAdIsNotFound() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| ApplyForAdRequestDto applyForAdRequestDto = new() | |||
| { | |||
| AdId = 1, | |||
| BitBucketLink = "", | |||
| CoverLetter = "saddadas", | |||
| DateOfBirth = new DateTime(1980, 10, 10), | |||
| Email = "meris@gmail.com", | |||
| Experience = 3, | |||
| FirstName = "Meris", | |||
| LastName = "Ahmatovic", | |||
| GithubLink = "", | |||
| LinkedinLink = "", | |||
| PdfFile = null, | |||
| PhoneNumber = "32312321", | |||
| TechnologiesIds = new int[] { 1 }, | |||
| }; | |||
| _fileService.When(x => x.UploadCV(Arg.Any<string>(), Arg.Any<IFormFile>())).Do(x => { }); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(async () => await | |||
| applicantService.ApplyForAd(applyForAdRequestDto)); | |||
| } | |||
| [Fact] | |||
| public async Task ApplyForAd_ApplicantShouldBeCreated_Always() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| ApplyForAdRequestDto applyForAdRequestDto = new() | |||
| { | |||
| AdId = 1, | |||
| BitBucketLink = "", | |||
| CoverLetter = "saddadas", | |||
| DateOfBirth = new DateTime(1980, 10, 10), | |||
| Email = "meris@gmail.com", | |||
| Experience = 3, | |||
| FirstName = "Meris", | |||
| LastName = "Ahmatovic", | |||
| GithubLink = "", | |||
| LinkedinLink = "", | |||
| PdfFile = null, | |||
| PhoneNumber = "32312321", | |||
| TechnologiesIds = new int[] { 1 }, | |||
| }; | |||
| _fileService.When(x => x.UploadCV(Arg.Any<string>(), Arg.Any<IFormFile>())).Do(x => { }); | |||
| _adService.GetByIdEntityAsync(Arg.Any<int>()).Returns(new Ad | |||
| { | |||
| Id = 10, | |||
| Applicants = new List<Applicant>(), | |||
| CreatedAt = DateTime.Now, | |||
| ExpiredAt = DateTime.Now.AddDays(5), | |||
| MinimumExperience = 1, | |||
| Title = ".NET Intern", | |||
| KeyResponsibilities = "dasdadas", | |||
| Offer = "dsadsada", | |||
| Requirements = "dsadsadas" | |||
| }); | |||
| await applicantService.ApplyForAd(applyForAdRequestDto); | |||
| var filterDto = MockData.GetApplicantFilters(); | |||
| var result = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Equal(3, result.Total); | |||
| } | |||
| [Fact] | |||
| public async Task DeleteApplicant_ShouldDeleteApplicant_WhenApplicantExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| await applicantService.DeleteApplicant(1); | |||
| @@ -113,71 +197,106 @@ namespace Diligent.WebAPI.Tests.Services | |||
| var applicants = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Empty(applicants.Items); | |||
| Assert.Equal(1,applicants.Total); | |||
| } | |||
| [Fact] | |||
| public async Task DeleteApplicant_ShouldThrowEntityNotFooundException_WhenApplicantDontExist() | |||
| public async Task DeleteApplicant_ShouldThrowEntityNotFooundException_WhenApplicantDoesNotExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(async () => await applicantService.DeleteApplicant(1000)); | |||
| } | |||
| //[Fact] | |||
| //public async Task UpdateApplicant_ShouldUpdateApplicant_WhenApplicantExist() | |||
| //{ | |||
| // var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| // ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| // ApplicantUpdateDto applicantUpdateDto = new() | |||
| // { | |||
| // ApplicationChannel = "Instagram", | |||
| // BitBucketLink = null, | |||
| // CV = "link", | |||
| // Email = "some@mail.com", | |||
| // Experience = 1, | |||
| // FirstName = "Dzenis", | |||
| // LastName = "Hadzifejzovic", | |||
| // GithubLink = null, | |||
| // LinkedlnLink = null, | |||
| // PhoneNumber = "432424", | |||
| // Position = "React Developer" | |||
| // }; | |||
| // await applicantService.UpdateApplicant(1, applicantUpdateDto); | |||
| // var applicant = await applicantService.GetById(1); | |||
| // Assert.Equal(applicant.Position, applicantUpdateDto.Position); | |||
| //} | |||
| [Fact] | |||
| public async Task GetAllAdsApplicants_ShouldReturnListOfAdApplicants_Always() | |||
| public async Task GetOptions_ShouldReturnAllOptions_Always() | |||
| { | |||
| var databaseContext = await Helpers<Ad>.GetDatabaseContext(_ads); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var filterDto = MockData.GetApplicantFilters(); | |||
| var res = await applicantService.GetOptions(); | |||
| Assert.Equal(2, res.Count); | |||
| } | |||
| var result = await applicantService.GetAllAdsApplicants(filterDto); | |||
| [Fact] | |||
| public async Task InitializeProcess_ShouldReturnError_WhenApplicantDoesNotExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var res = await applicantService.InitializeProcess(new ApplicantProcessRequestDTO | |||
| { | |||
| ApplicantId = 1000, | |||
| Appointment = DateTime.Now, | |||
| SchedulerId = 1000 | |||
| }); | |||
| result.Should().BeEquivalentTo(_mapper.Map<List<AdApplicantsViewDto>>(_ads)); | |||
| Assert.True(res.IsError); | |||
| } | |||
| [Fact] | |||
| public async Task GetApplicantWithSelectionProcessesById_ShouldReturnApplicant_WhenApplicantExists() | |||
| public async Task InitializeProcess_SelectionProcessShouldBeCreated_WhenApplicantExist() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| var res = await applicantService.InitializeProcess(new ApplicantProcessRequestDTO | |||
| { | |||
| ApplicantId = 1, | |||
| Appointment = DateTime.Now, | |||
| SchedulerId = 1 | |||
| }); | |||
| // before creating new selection process total number of selection proceesses was 6 | |||
| Assert.Equal(7, databaseContext.SelectionProcesses.Count()); | |||
| Assert.False(res.IsError); | |||
| } | |||
| var result = await applicantService.GetApplicantWithSelectionProcessesById(1); | |||
| var processes = result.SelectionProcesses; | |||
| [Fact] | |||
| public async Task ImportApplicant_ShouldCreateApplicant_Always() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| _userService.GetFirst().Returns(_users[0]); | |||
| ApplicantService applicantService = new(databaseContext, _mapper, _logger, _userService, _fileService, _adService); | |||
| processes.Should().HaveCount(3); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicants[0])); | |||
| var ad = new Ad | |||
| { | |||
| Id = 2, | |||
| Applicants = _applicants, | |||
| CreatedAt = DateTime.Now, | |||
| ExpiredAt = DateTime.Now.AddDays(5), | |||
| MinimumExperience = 1, | |||
| Title = ".NET Intern", | |||
| KeyResponsibilities = "dasdadas", | |||
| Offer = "dsadsada", | |||
| Requirements = "dsadsadas" | |||
| }; | |||
| await applicantService.ImportApplicant(new List<ApplicantImportDto> | |||
| { | |||
| new ApplicantImportDto | |||
| { | |||
| Ad = ad, | |||
| ApplicationChannel = "Facebook", | |||
| BitBucketLink = "", | |||
| Comment = "some comment", | |||
| CV = "name of CV", | |||
| DateOfApplication = DateTime.Now, | |||
| Email = "somemail@gmail.com", | |||
| Experience = 3, | |||
| FirstName = "Dzenis", | |||
| LastName = "Hadzifejzovic", | |||
| GithubLink = "", | |||
| LinkedlnLink = "", | |||
| PhoneNumber = "2321312", | |||
| Position = "some position", | |||
| TypeOfEmployment = "Intership" | |||
| } | |||
| }); | |||
| Assert.Equal(3, databaseContext.Applicants.Count()); | |||
| } | |||
| } | |||
| } | |||
| @@ -15,10 +15,11 @@ namespace Diligent.WebAPI.Tests.Services | |||
| private readonly IMapper _mapper; | |||
| private readonly List<Comment> _comments; | |||
| private readonly List<Applicant> _applicants; | |||
| private ILogger<CommentService> _logger = Substitute.For<ILogger<CommentService>>(); | |||
| private readonly ILogger<CommentService> _logger = Substitute.For<ILogger<CommentService>>(); | |||
| private readonly List<User> _users; | |||
| public CommentServiceTests() | |||
| { | |||
| // mock data | |||
| _applicants = MockData.GetListOfApplicants(); | |||
| _comments = MockData.GetListOfComments(); | |||
| _users = MockData.GetListOfUsers(); | |||
| @@ -33,13 +34,45 @@ namespace Diligent.WebAPI.Tests.Services | |||
| } | |||
| [Fact] | |||
| public async Task CreateComment_ShouldUpdatedListOfComments_Always() | |||
| public async Task CreateComment_ShouldSendMailAndCreateComments_WhenThereIsUserToNotify() | |||
| { | |||
| var databaseContext = await Helpers<Comment>.GetDatabaseContext(_comments); | |||
| var frontSettings = Substitute.For<IOptions<FrontEndSettings>>(); | |||
| var frontSettings = Options.Create(new FrontEndSettings | |||
| { | |||
| BaseUrl = "some url" | |||
| }); | |||
| var mailer = Substitute.For<IEmailer>(); | |||
| mailer.When(x => x.SendEmailAsync(Arg.Any<List<string>>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>())).Do(x => { }); | |||
| CommentService commentService = new(frontSettings,databaseContext, _mapper, _logger, mailer); | |||
| var commentCreateDto = new CommentCreateDto | |||
| { | |||
| ApplicantId = _applicants[0].ApplicantId, | |||
| Content = "dsadasd", | |||
| UserId = _users[0].Id, | |||
| UsersToNotify = new List<string> { "dzenis@dilig.net" } | |||
| }; | |||
| await commentService.CreateComment(commentCreateDto); | |||
| var comments = await databaseContext.Comments.ToListAsync(); | |||
| Assert.Equal(2, comments.Count); | |||
| await mailer.Received().SendEmailAsync(Arg.Any<List<string>>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>()); | |||
| } | |||
| [Fact] | |||
| public async Task CreateComment_ShouldCreateComments_WhenThereIsNoUserToNotify() | |||
| { | |||
| var databaseContext = await Helpers<Comment>.GetDatabaseContext(_comments); | |||
| var frontSettings = Options.Create(new FrontEndSettings | |||
| { | |||
| BaseUrl = "some url" | |||
| }); | |||
| var mailer = Substitute.For<IEmailer>(); | |||
| mailer.When(x => x.SendEmailAsync(Arg.Any<List<string>>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>())).Do(x => { }); | |||
| CommentService applicantService = new(frontSettings,databaseContext, _mapper, _logger, mailer); | |||
| CommentService commentService = new(frontSettings, databaseContext, _mapper, _logger, mailer); | |||
| var commentCreateDto = new CommentCreateDto | |||
| { | |||
| @@ -49,10 +82,11 @@ namespace Diligent.WebAPI.Tests.Services | |||
| UsersToNotify = new List<string>() | |||
| }; | |||
| await applicantService.CreateComment(commentCreateDto); | |||
| await commentService.CreateComment(commentCreateDto); | |||
| var comments = await databaseContext.Comments.ToListAsync(); | |||
| Assert.Equal(2, comments.Count); | |||
| await mailer.DidNotReceive().SendEmailAsync(Arg.Any<List<string>>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>()); | |||
| } | |||
| } | |||
| } | |||
| @@ -41,7 +41,7 @@ namespace Diligent.WebAPI.Tests.Services | |||
| } | |||
| [Fact] | |||
| public async Task GetAll_ShouldReturnListOfTechnologies_WhenCalled() | |||
| public async Task GetAll_ShouldReturnListOfTechnologies_Always() | |||
| { | |||
| var databaseContext = await Helpers<Technology>.GetDatabaseContext(_technologies); | |||
| TechnologyService tehnologyService = new(_mapper, databaseContext, _logger); | |||
| @@ -63,7 +63,7 @@ namespace Diligent.WebAPI.Tests.Services | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldThrowEntityNotFoundException_WhenTechnologyDontExists() | |||
| public async Task GetById_ShouldThrowEntityNotFoundException_WhenTechnologyDoesNotExists() | |||
| { | |||
| var databaseContext = await Helpers<Technology>.GetDatabaseContext(_technologies); | |||
| TechnologyService tehnologyService = new(_mapper, databaseContext, _logger); | |||
| @@ -83,7 +83,7 @@ namespace Diligent.WebAPI.Tests.Services | |||
| } | |||
| [Fact] | |||
| public async Task GetEntityById_ShouldThrowEntityNotFoundException_WhenTechnologyDontExists() | |||
| public async Task GetEntityById_ShouldThrowEntityNotFoundException_WhenTechnologyDoesNotExists() | |||
| { | |||
| var databaseContext = await Helpers<Technology>.GetDatabaseContext(_technologies); | |||
| TechnologyService tehnologyService = new(_mapper, databaseContext, _logger); | |||