| @@ -0,0 +1,76 @@ | |||
| using static Diligent.WebAPI.Data.Entities.Applicant; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| public static class ApplicantExtensions | |||
| { | |||
| public static async Task<IQueryable<Applicant>> FilterApplicants(this IQueryable<Applicant> query,ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| IQueryable<Applicant> resultQuery; | |||
| resultQuery = query.FilterByExperience(applicantFilterDto.MinExperience, applicantFilterDto.MaxExperience) | |||
| .FilterByEmploymentType(applicantFilterDto.EmploymentType) | |||
| .FilterByDateOfApplication(applicantFilterDto.MinDateOfApplication, applicantFilterDto.MaxDateOfApplication); | |||
| return FilterByTechnologies(await resultQuery.ToListAsync(), applicantFilterDto.Technologies); | |||
| } | |||
| public static IQueryable<Applicant> ApplyPagging(this IQueryable<Applicant> query, Pagination pagination) | |||
| { | |||
| return query.Skip((pagination.CurrentPage - 1) * pagination.PageSize) | |||
| .Take(pagination.PageSize); | |||
| } | |||
| private static IQueryable<Applicant> FilterByExperience(this IQueryable<Applicant> query, int minExperience, int maxExperience) | |||
| { | |||
| if (minExperience == 0 && maxExperience == 0 || minExperience > maxExperience) return query; | |||
| return query.Where(x => x.Experience >= minExperience && x.Experience < maxExperience); | |||
| } | |||
| private static IQueryable<Applicant> FilterByEmploymentType(this IQueryable<Applicant> query, string? employmentType) | |||
| { | |||
| if (employmentType == null) return query; | |||
| return query.Where(x => x.TypeOfEmployment == Enum.Parse<TypesOfEmployment>(employmentType)); | |||
| } | |||
| private static IQueryable<Applicant> FilterByDateOfApplication(this IQueryable<Applicant> query, DateTime? minDateOfApplication, DateTime? maxDateOfApplication) | |||
| { | |||
| if (minDateOfApplication == null) return query; | |||
| if (minDateOfApplication > maxDateOfApplication) return query; | |||
| if (maxDateOfApplication == null) return query.Where(x => x.DateOfApplication >= minDateOfApplication && x.DateOfApplication <= DateTime.Now); | |||
| return query.Where(x => x.DateOfApplication >= minDateOfApplication && x.DateOfApplication < maxDateOfApplication); | |||
| } | |||
| private static IQueryable<Applicant> FilterByTechnologies(this List<Applicant> query, string[]? technologies) | |||
| { | |||
| if (technologies is null) | |||
| { | |||
| return query.AsQueryable(); | |||
| } | |||
| List<Applicant> filteredApplicants = new(); | |||
| for (int i = 0; i < query.Count; i++) | |||
| { | |||
| for (int j = 0; j < query[i].TechnologyApplicants.Count; j++) | |||
| { | |||
| bool s = false; | |||
| for (int n = 0; n < technologies.Length; n++) | |||
| { | |||
| if (query[i].TechnologyApplicants[j].Technology.Name.ToLower() == technologies[n].ToLower()) | |||
| { | |||
| s = true; | |||
| break; | |||
| } | |||
| } | |||
| if (s) | |||
| { | |||
| filteredApplicants.Add(query[i]); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return filteredApplicants.AsQueryable(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,18 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| public static class PaginationExtension | |||
| { | |||
| public static IQueryable<T> ApplyPagging<T>(this IQueryable<T> query, Pagination pagination) | |||
| { | |||
| return query.Skip((pagination.CurrentPage - 1) * pagination.PageSize) | |||
| .Take(pagination.PageSize); | |||
| } | |||
| } | |||
| } | |||
| @@ -13,6 +13,7 @@ namespace Diligent.WebAPI.Business.MappingProfiles | |||
| #region Model to DTO | |||
| CreateMap<Ad, AdResponseDto>(); | |||
| CreateMap<Ad, AdDetailsResponseDto>(); | |||
| CreateMap<Ad, AdApplicantsViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| #region Models to DTOs | |||
| CreateMap<Applicant, ApplicantViewDto>(); | |||
| CreateMap<Applicant, AdApplicantViewDto>(); | |||
| #endregion | |||
| #region DTOs to Models | |||
| @@ -1,4 +1,5 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Business.Extensions; | |||
| using Microsoft.AspNetCore.Http; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| @@ -7,16 +8,33 @@ namespace Diligent.WebAPI.Business.Services | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public ApplicantService(DatabaseContext context,IMapper mapper) | |||
| public ApplicantService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<ApplicantViewDto>> GetAll() | |||
| public async Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| var applicants = await _context.Applicants.Include(c => c.Ads).ToListAsync(); | |||
| return _mapper.Map<List<ApplicantViewDto>>(applicants); | |||
| var allApplicants = _context.Applicants | |||
| .Include(c => c.Ads) | |||
| .Include(x => x.TechnologyApplicants) | |||
| .ThenInclude(x => x.Technology); | |||
| var filteredApplicants = await allApplicants | |||
| .FilterApplicants(applicantFilterDto); | |||
| filteredApplicants = PaginationExtension.ApplyPagging(filteredApplicants, new Pagination | |||
| { | |||
| CurrentPage = applicantFilterDto.CurrentPage, | |||
| PageSize = applicantFilterDto.PageSize | |||
| }); | |||
| return new QueryResultDto<ApplicantViewDto> | |||
| { | |||
| Items = _mapper.Map<List<ApplicantViewDto>>(filteredApplicants), | |||
| Total = allApplicants.ToList().Count | |||
| }; | |||
| } | |||
| public async Task<ApplicantViewDto> GetById(int id) | |||
| @@ -35,18 +53,6 @@ namespace Diligent.WebAPI.Business.Services | |||
| return _mapper.Map<ApplicantViewDto>(applicant); | |||
| } | |||
| public async Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int 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) | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| return _mapper.Map<ApplicantViewDto>(applicant); | |||
| } | |||
| public async Task CreateApplicant(ApplicantCreateDto applicantCreateDto) | |||
| { | |||
| var applicant = _mapper.Map<Applicant>(applicantCreateDto); | |||
| @@ -59,7 +65,7 @@ namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| var applicant = await _context.Applicants.FindAsync(id); | |||
| if(applicant is null) | |||
| if (applicant is null) | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| _context.Applicants.Remove(applicant); | |||
| @@ -77,5 +83,27 @@ namespace Diligent.WebAPI.Business.Services | |||
| _context.Entry(applicant).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task<List<AdApplicantsViewDto>> GetAllAdsApplicants() | |||
| { | |||
| var adsApplicants = await _context.Ads | |||
| .Include(a => a.Applicants) | |||
| .ThenInclude(a => a.TechnologyApplicants).ThenInclude(a => a.Technology).ToListAsync(); | |||
| return _mapper.Map<List<AdApplicantsViewDto>>(adsApplicants); | |||
| } | |||
| public async Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int 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) | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| return _mapper.Map<ApplicantViewDto>(applicant); | |||
| } | |||
| } | |||
| } | |||
| @@ -3,7 +3,8 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IApplicantService | |||
| { | |||
| Task<List<ApplicantViewDto>> GetAll(); | |||
| Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto); | |||
| Task<List<AdApplicantsViewDto>> GetAllAdsApplicants(); | |||
| Task<ApplicantViewDto> GetById(int id); | |||
| Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id); | |||
| Task CreateApplicant(ApplicantCreateDto applicantCreateDto); | |||
| @@ -0,0 +1,12 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdApplicantsViewDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public List<AdApplicantViewDto> Applicants { get; set; } | |||
| public int NubmerOfApplicants { get { return Applicants.Count; } } | |||
| } | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class AdApplicantViewDto | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfApplication { get; set; } | |||
| public string CV { get; set; } | |||
| public int Experience { get; set; } | |||
| public List<TechnologyViewDto> TechnologyApplicants { get; set; } = new(); | |||
| } | |||
| } | |||
| @@ -1,4 +1,6 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantCreateDto | |||
| { | |||
| @@ -13,5 +15,6 @@ | |||
| public string BitBucketLink { get; set; } | |||
| public int Experience { get; set; } | |||
| public string ApplicationChannel { get; set; } | |||
| public string TypeOfEmployment { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| using Diligent.WebAPI.Contracts.Models; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantFilterDto : Pagination | |||
| { | |||
| public int MinExperience { get; set; } | |||
| public int MaxExperience { get; set; } | |||
| public string[]? Technologies { get; set; } | |||
| public string? EmploymentType { get; set; } | |||
| public DateTime? MinDateOfApplication { get; set; } | |||
| public DateTime? MaxDateOfApplication { get; set; } | |||
| } | |||
| } | |||
| @@ -20,6 +20,7 @@ namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| public string BitBucketLink { get; set; } | |||
| public int Experience { get; set; } | |||
| public string ApplicationChannel { get; set; } | |||
| public string TypeOfEmployment { get; set; } | |||
| public List<TechnologyViewDto> TechnologyApplicants { get; set; } = new(); | |||
| public List<CommentViewDto> Comments { get; set; } | |||
| public List<AdResponseDto> Ads { get; set; } | |||
| @@ -0,0 +1,8 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs | |||
| { | |||
| public class QueryResultDto<T> where T : class | |||
| { | |||
| public int Total { get; set; } | |||
| public IEnumerable<T> Items { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| namespace Diligent.WebAPI.Contracts.Models | |||
| { | |||
| public class Pagination | |||
| { | |||
| public int CurrentPage { get; set; } = 1; | |||
| public int PageSize { get; set; } = 6; | |||
| } | |||
| } | |||
| @@ -17,6 +17,7 @@ namespace Diligent.WebAPI.Data.Configurations | |||
| builder.Property(c => c.GithubLink).IsRequired(false); | |||
| builder.Property(c => c.BitBucketLink).IsRequired(false); | |||
| builder.Property(c => c.ApplicationChannel).IsRequired(false); | |||
| builder.Property(c => c.TypeOfEmployment).IsRequired(true).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -2,6 +2,11 @@ | |||
| { | |||
| public class Applicant | |||
| { | |||
| public enum TypesOfEmployment | |||
| { | |||
| Posao, | |||
| Intership | |||
| }; | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| @@ -15,6 +20,7 @@ | |||
| public string BitBucketLink { get; set; } | |||
| public int Experience { get; set; } | |||
| public string ApplicationChannel { get; set; } | |||
| public TypesOfEmployment TypeOfEmployment { get; set; } | |||
| public List<TechnologyApplicant> TechnologyApplicants { get; set; } | |||
| public List<Comment> Comments { get; set; } | |||
| public List<Ad> Ads { get; set; } | |||
| @@ -34,7 +34,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("ApplicantsApplicantId"); | |||
| b.ToTable("AdApplicant"); | |||
| b.ToTable("AdApplicant", (string)null); | |||
| }); | |||
| modelBuilder.Entity("AdTechnology", b => | |||
| @@ -49,7 +49,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("TechnologiesTechnologyId"); | |||
| b.ToTable("AdTechnology"); | |||
| b.ToTable("AdTechnology", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Ad", b => | |||
| @@ -95,7 +95,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("Id"); | |||
| b.ToTable("Ads"); | |||
| b.ToTable("Ads", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Applicant", b => | |||
| @@ -155,7 +155,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("ApplicantId"); | |||
| b.ToTable("Applicants"); | |||
| b.ToTable("Applicants", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.AppRole", b => | |||
| @@ -216,7 +216,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("UserId"); | |||
| b.ToTable("Comments"); | |||
| b.ToTable("Comments", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsuranceCompany", b => | |||
| @@ -270,7 +270,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("Id"); | |||
| b.ToTable("InsuranceCompanies"); | |||
| b.ToTable("InsuranceCompanies", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.InsurancePolicy", b => | |||
| @@ -310,7 +310,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("InsurerId"); | |||
| b.ToTable("InsurancePolicies"); | |||
| b.ToTable("InsurancePolicies", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Insurer", b => | |||
| @@ -372,7 +372,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("InsuranceCompanyId"); | |||
| b.ToTable("Insurers"); | |||
| b.ToTable("Insurers", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.RefreshToken", b => | |||
| @@ -410,7 +410,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("UserId"); | |||
| b.ToTable("RefreshTokens"); | |||
| b.ToTable("RefreshTokens", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.SelectionLevel", b => | |||
| @@ -427,7 +427,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("Id"); | |||
| b.ToTable("SelectionLevels"); | |||
| b.ToTable("SelectionLevels", (string)null); | |||
| b.HasData( | |||
| new | |||
| @@ -491,7 +491,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("SelectionLevelId"); | |||
| b.ToTable("SelectionProcesses"); | |||
| b.ToTable("SelectionProcesses", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.Technology", b => | |||
| @@ -513,7 +513,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("TechnologyId"); | |||
| b.ToTable("Technologies"); | |||
| b.ToTable("Technologies", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.TechnologyApplicant", b => | |||
| @@ -536,7 +536,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("TechnologyId"); | |||
| b.ToTable("ApplicantTechnologies"); | |||
| b.ToTable("ApplicantTechnologies", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.User", b => | |||
| @@ -656,7 +656,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasKey("Id"); | |||
| b.ToTable("WebhookDefinitions"); | |||
| b.ToTable("WebhookDefinitions", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Diligent.WebAPI.Data.Entities.WebhookSubscription", b => | |||
| @@ -690,7 +690,7 @@ namespace Diligent.WebAPI.Data.Migrations | |||
| b.HasIndex("WebhookDefinitionId"); | |||
| b.ToTable("WebhookSubscriptions"); | |||
| b.ToTable("WebhookSubscriptions", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b => | |||
| @@ -1,9 +1,11 @@ | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| { | |||
| [ApiVersion("1.0")] | |||
| [Route("v{version:apiVersion}/applicants")] | |||
| [ApiController] | |||
| public class ApplicantsController:ControllerBase | |||
| public class ApplicantsController : ControllerBase | |||
| { | |||
| private readonly IApplicantService _applicantService; | |||
| @@ -12,18 +14,27 @@ | |||
| _applicantService = applicantService; | |||
| } | |||
| //[Authorize] | |||
| [HttpGet] | |||
| public async Task<IActionResult> GetAll() | |||
| { | |||
| return Ok(await _applicantService.GetAll()); | |||
| } | |||
| public async Task<IActionResult> GetFilteredApplicants([FromQuery] ApplicantFilterDto applicantFilterDto) => | |||
| Ok(await _applicantService.GetFilteredApplicants(applicantFilterDto)); | |||
| //[Authorize] | |||
| [Authorize] | |||
| [HttpGet("{id}")] | |||
| public async Task<IActionResult> GetById(int id) | |||
| public async Task<IActionResult> GetById(int id) => | |||
| Ok(await _applicantService.GetById(id)); | |||
| [Authorize] | |||
| [HttpGet("adsApplicants")] | |||
| public async Task<IActionResult> GetAllAdsApplicants() => | |||
| Ok(await _applicantService.GetAllAdsApplicants()); | |||
| [Authorize] | |||
| [HttpDelete] | |||
| public async Task<IActionResult> DeleteApplicant(int id) | |||
| { | |||
| return Ok(await _applicantService.GetById(id)); | |||
| await _applicantService.DeleteApplicant(id); | |||
| return Ok(); | |||
| } | |||
| [HttpGet("processes/{id}")] | |||
| @@ -31,5 +42,6 @@ | |||
| { | |||
| return Ok(await _applicantService.GetApplicantWithSelectionProcessesById(id)); | |||
| } | |||
| } | |||
| } | |||
| @@ -15,6 +15,7 @@ | |||
| builder.ConfigureSwagger(); | |||
| IServiceCollection services = builder.Services; | |||
| services.AddHttpContextAccessor(); | |||
| services.AddControllers(); | |||
| services.AddEndpointsApiExplorer(); | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs; | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| using Diligent.WebAPI.Contracts.Exceptions; | |||
| using NSubstitute; | |||
| @@ -36,56 +37,68 @@ namespace Diligent.WebAPI.Tests.Controllers | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldReturn_200OK_WhenApplicantExist() | |||
| public async Task GetProcesses_ShouldReturn_200OK_WhenApplicantExists() | |||
| { | |||
| _applicantService.GetById(Arg.Any<int>()).Returns(_applicant); | |||
| _applicantService.GetApplicantWithSelectionProcessesById(Arg.Any<int>()).Returns(_applicant); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| var result = await applicantsController.GetById(1); | |||
| var result = await applicantsController.GetProcesses(1); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetProcesses_ShouldReturn_200OK_WhenApplicantExists() | |||
| public async Task GetProcesses_ShouldThrowEntityNotFooundException_WhenApplicantDoesnotExist() | |||
| { | |||
| _applicantService.GetApplicantWithSelectionProcessesById(Arg.Any<int>()).Returns(_applicant); | |||
| _applicantService.When(x => x.GetApplicantWithSelectionProcessesById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| var result = await applicantsController.GetProcesses(1); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetProcesses(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task GetById_ShouldThrowEntityNotFooundException_WhenApplicantDontExist() | |||
| public async Task GetById_ShouldReturn_200OK_WhenApplicantExist() | |||
| { | |||
| _applicantService.When(x => x.GetById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| _applicantService.GetById(Arg.Any<int>()).Returns(_applicant); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetById(1000)); | |||
| var result = await applicantsController.GetById(1); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| [Fact] | |||
| public async Task GetProcesses_ShouldThrowEntityNotFooundException_WhenApplicantDoesnotExist() | |||
| public async Task GetById_ShouldThrowEntityNotFooundException_WhenApplicantDontExist() | |||
| { | |||
| _applicantService.When(x => x.GetApplicantWithSelectionProcessesById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| _applicantService.When(x => x.GetById(Arg.Any<int>())).Do(x => { throw new EntityNotFoundException(); }); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetProcesses(1000)); | |||
| await Assert.ThrowsAsync<EntityNotFoundException>(() => applicantsController.GetById(1000)); | |||
| } | |||
| [Fact] | |||
| public async Task GetAll_ShouldReturn_200OK_Always() | |||
| public async Task GetFilteredApplicants_ShouldReturn_200OK_Always() | |||
| { | |||
| var applicants = new List<ApplicantViewDto> | |||
| { | |||
| _applicant | |||
| }; | |||
| _applicantService.GetAll().Returns(applicants); | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| CurrentPage = 1, | |||
| PageSize = 4 | |||
| }; | |||
| _applicantService.GetFilteredApplicants(filterDto).Returns(new QueryResultDto<ApplicantViewDto> | |||
| { | |||
| Items = applicants, | |||
| Total = applicants.Count | |||
| }); | |||
| ApplicantsController applicantsController = new(_applicantService); | |||
| var result = await applicantsController.GetAll(); | |||
| var result = await applicantsController.GetFilteredApplicants(filterDto); | |||
| (result as OkObjectResult).StatusCode.Should().Be(200); | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| namespace Diligent.WebAPI.Tests.Controllers | |||
| { | |||
| public class CommentsControllerTests | |||
| { | |||
| private ICommentService _commentService = Substitute.For<ICommentService>(); | |||
| public CommentsControllerTests() | |||
| { | |||
| } | |||
| //[Fact] | |||
| //public async AddComment_ShouldReturn_200_Created_Always() | |||
| //{ | |||
| // _commentService.Add | |||
| //} | |||
| } | |||
| } | |||
| @@ -0,0 +1,118 @@ | |||
| using Diligent.WebAPI.Data.Entities; | |||
| namespace Diligent.WebAPI.Tests | |||
| { | |||
| public static class MockData | |||
| { | |||
| public static List<Applicant> GetListOfApplicants() | |||
| { | |||
| var applicant = new Applicant | |||
| { | |||
| ApplicantId = 1, | |||
| ApplicationChannel = "Instagram", | |||
| BitBucketLink = null, | |||
| CV = "link", | |||
| DateOfApplication = DateTime.Now, | |||
| Email = "some@mail.com", | |||
| Experience = 1, | |||
| FirstName = "Dzenis", | |||
| LastName = "Hadzifejzovic", | |||
| GithubLink = null, | |||
| LinkedlnLink = null, | |||
| PhoneNumber = "432424", | |||
| Position = ".NET Developer", | |||
| TypeOfEmployment = Applicant.TypesOfEmployment.Intership, | |||
| SelectionProcesses = new List<SelectionProcess> | |||
| { | |||
| new SelectionProcess{ Id = 1, Status = "", Name = ""}, | |||
| new SelectionProcess{ Id = 2, Status = "", Name = ""}, | |||
| new SelectionProcess{ Id = 3, Status = "", Name = ""} | |||
| } | |||
| }; | |||
| var applicants = new List<Applicant> | |||
| { | |||
| applicant | |||
| }; | |||
| return applicants; | |||
| } | |||
| public static List<SelectionProcess> GetListOfSelectionProcess() | |||
| { | |||
| var selectionProcess = new SelectionProcess | |||
| { | |||
| Applicant = GetListOfApplicants()[0], | |||
| Date = DateTime.Now, | |||
| Link = "dasda", | |||
| Name = "adsda", | |||
| SelectionLevelId = 1, | |||
| Status = "completed" | |||
| }; | |||
| var selectionProcesses = new List<SelectionProcess> | |||
| { | |||
| selectionProcess | |||
| }; | |||
| return selectionProcesses; | |||
| ; | |||
| } | |||
| public static List<Ad> GetListOfAds() | |||
| { | |||
| var ad = new Ad | |||
| { | |||
| Applicants = GetListOfApplicants(), | |||
| CreatedAt = DateTime.Now, | |||
| ExpiredAt = DateTime.Now.AddDays(5), | |||
| MinimumExperience = 1, | |||
| Title = ".NET Intern", | |||
| KeyResponsibilities = "dasdadas", | |||
| Offer = "dsadsada", | |||
| Requirements = "dsadsadas" | |||
| }; | |||
| var ads = new List<Ad> | |||
| { | |||
| ad | |||
| }; | |||
| return ads; | |||
| } | |||
| public static List<User> GetListOfUsers() | |||
| { | |||
| var user = new User | |||
| { | |||
| FirstName = "Dzenis", | |||
| Email = "dzenis@gmail.com", | |||
| LastName = "Hadzifejzovic", | |||
| UserName = "dzenis12" | |||
| }; | |||
| var users = new List<User> | |||
| { | |||
| user | |||
| }; | |||
| return users; | |||
| } | |||
| public static List<Comment> GetListOfComments() | |||
| { | |||
| var comment = new Comment | |||
| { | |||
| Applicant = GetListOfApplicants()[0], | |||
| Content = "dsadsad", | |||
| DateOfSending = DateTime.Now, | |||
| User = GetListOfUsers()[0], | |||
| }; | |||
| var comments = new List<Comment> | |||
| { | |||
| comment | |||
| }; | |||
| return comments; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,66 +1,54 @@ | |||
| using AutoMapper; | |||
| using Diligent.WebAPI.Business.Extensions; | |||
| using Diligent.WebAPI.Business.MappingProfiles; | |||
| using Diligent.WebAPI.Business.Services; | |||
| using Diligent.WebAPI.Contracts.DTOs.Ad; | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| using Diligent.WebAPI.Contracts.Exceptions; | |||
| using Diligent.WebAPI.Data.Entities; | |||
| using Microsoft.AspNetCore.Http; | |||
| using static Diligent.WebAPI.Data.Entities.Applicant; | |||
| namespace Diligent.WebAPI.Tests.Services | |||
| { | |||
| public class ApplicantServiceTests | |||
| { | |||
| private readonly IMapper _mapper; | |||
| private readonly HttpContext _httpContext; | |||
| private readonly List<Applicant> _applicants; | |||
| private readonly Applicant _applicant; | |||
| private readonly List<Ad> _ads; | |||
| private readonly List<SelectionProcess> _selectionProcesses; | |||
| public ApplicantServiceTests() | |||
| { | |||
| _applicant = new Applicant | |||
| { | |||
| ApplicantId = 1, | |||
| ApplicationChannel = "Instagram", | |||
| BitBucketLink = null, | |||
| CV = "link", | |||
| DateOfApplication = DateTime.Now, | |||
| Email = "some@mail.com", | |||
| Experience = 1, | |||
| FirstName = "Dzenis", | |||
| LastName = "Hadzifejzovic", | |||
| GithubLink = null, | |||
| LinkedlnLink = null, | |||
| PhoneNumber = "432424", | |||
| Position = ".NET Developer", | |||
| SelectionProcesses = new List<SelectionProcess> | |||
| { | |||
| new SelectionProcess{ Id = 1, Status = "", Name = ""}, | |||
| new SelectionProcess{ Id = 2, Status = "", Name = ""}, | |||
| new SelectionProcess{ Id = 3, Status = "", Name = ""} | |||
| } | |||
| }; | |||
| _applicants = new List<Applicant> | |||
| { | |||
| _applicant | |||
| }; | |||
| _applicants = MockData.GetListOfApplicants(); | |||
| _ads = MockData.GetListOfAds(); | |||
| // configure mapper | |||
| var configuration = new MapperConfiguration(cfg => cfg.AddProfiles( | |||
| new List<Profile> | |||
| { | |||
| new ApplicantMappingProfile(), | |||
| new SelectionProcessMappingProfile(), | |||
| new AdMappingProfile(), | |||
| new SelectionProcessMappingProfile() | |||
| })); | |||
| _mapper = new Mapper(configuration); | |||
| _httpContext = new DefaultHttpContext(); | |||
| } | |||
| [Fact] | |||
| public async Task GetAll_ShouldReturnListOfApplicants_Always() | |||
| public async Task GetFilteredApplicants_ShouldReturnListOfApplicants_Always() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper); | |||
| var result = await applicantService.GetAll(); | |||
| var filterDto = new ApplicantFilterDto(); | |||
| result.Should().BeEquivalentTo(_mapper.Map<List<ApplicantViewDto>>(_applicants)); | |||
| var result = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Equal(_applicants.Count,result.Total); | |||
| } | |||
| [Fact] | |||
| @@ -71,20 +59,7 @@ namespace Diligent.WebAPI.Tests.Services | |||
| var result = await applicantService.GetById(1); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicant)); | |||
| } | |||
| [Fact] | |||
| public async Task GetApplicantWithSelectionProcessesById_ShouldReturnApplicant_WhenApplicantExists() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper); | |||
| var result = await applicantService.GetApplicantWithSelectionProcessesById(1); | |||
| var processes = result.SelectionProcesses; | |||
| processes.Should().HaveCount(3); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicant)); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicants[0])); | |||
| } | |||
| [Fact] | |||
| @@ -114,14 +89,21 @@ namespace Diligent.WebAPI.Tests.Services | |||
| GithubLink = null, | |||
| LinkedlnLink = null, | |||
| PhoneNumber = "432424", | |||
| Position = ".NET Developer" | |||
| Position = ".NET Developer", | |||
| TypeOfEmployment = TypesOfEmployment.Intership.ToString() | |||
| }; | |||
| await applicantService.CreateApplicant(applicantCreateDto); | |||
| var applicants = await applicantService.GetAll(); | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| CurrentPage = 1, | |||
| PageSize = 4 | |||
| }; | |||
| var result = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Equal(2, applicants.Count); | |||
| Assert.Equal(2, result.Total); | |||
| } | |||
| [Fact] | |||
| @@ -131,9 +113,16 @@ namespace Diligent.WebAPI.Tests.Services | |||
| ApplicantService applicantService = new(databaseContext, _mapper); | |||
| await applicantService.DeleteApplicant(1); | |||
| var applicants = await applicantService.GetAll(); | |||
| Assert.Empty(applicants); | |||
| var filterDto = new ApplicantFilterDto | |||
| { | |||
| CurrentPage = 1, | |||
| PageSize = 4 | |||
| }; | |||
| var applicants = await applicantService.GetFilteredApplicants(filterDto); | |||
| Assert.Empty(applicants.Items); | |||
| } | |||
| [Fact] | |||
| @@ -166,10 +155,36 @@ namespace Diligent.WebAPI.Tests.Services | |||
| Position = "React Developer" | |||
| }; | |||
| await applicantService.UpdateApplicant(1,applicantUpdateDto); | |||
| await applicantService.UpdateApplicant(1, applicantUpdateDto); | |||
| var applicant = await applicantService.GetById(1); | |||
| Assert.Equal(applicant.Position,applicantUpdateDto.Position); | |||
| Assert.Equal(applicant.Position, applicantUpdateDto.Position); | |||
| } | |||
| [Fact] | |||
| public async Task GetAllAdsApplicants_ShouldReturnListOfAdApplicants_Always() | |||
| { | |||
| var databaseContext = await Helpers<Ad>.GetDatabaseContext(_ads); | |||
| ApplicantService applicantService = new(databaseContext, _mapper); | |||
| var result = await applicantService.GetAllAdsApplicants(); | |||
| result.Should().BeEquivalentTo(_mapper.Map<List<AdApplicantsViewDto>>(_ads)); | |||
| } | |||
| [Fact] | |||
| public async Task GetApplicantWithSelectionProcessesById_ShouldReturnApplicant_WhenApplicantExists() | |||
| { | |||
| var databaseContext = await Helpers<Applicant>.GetDatabaseContext(_applicants); | |||
| ApplicantService applicantService = new(databaseContext, _mapper); | |||
| var result = await applicantService.GetApplicantWithSelectionProcessesById(1); | |||
| var processes = result.SelectionProcesses; | |||
| processes.Should().HaveCount(3); | |||
| result.Should().BeEquivalentTo(_mapper.Map<ApplicantViewDto>(_applicants[0])); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| using AutoMapper; | |||
| using Diligent.WebAPI.Business.MappingProfiles; | |||
| using Diligent.WebAPI.Business.Services; | |||
| using Diligent.WebAPI.Contracts.DTOs.Comment; | |||
| using Diligent.WebAPI.Data.Entities; | |||
| using Microsoft.EntityFrameworkCore; | |||
| namespace Diligent.WebAPI.Tests.Services | |||
| { | |||
| public class CommentServiceTests | |||
| { | |||
| private readonly IMapper _mapper; | |||
| private readonly List<Comment> _comments; | |||
| private readonly List<Applicant> _applicants; | |||
| private readonly List<User> _users; | |||
| public CommentServiceTests() | |||
| { | |||
| _applicants = MockData.GetListOfApplicants(); | |||
| _comments = MockData.GetListOfComments(); | |||
| _users = MockData.GetListOfUsers(); | |||
| // configure mapper | |||
| var configuration = new MapperConfiguration(cfg => cfg.AddProfiles( | |||
| new List<Profile> | |||
| { | |||
| new CommentMappingProfile() | |||
| })); | |||
| _mapper = new Mapper(configuration); | |||
| } | |||
| [Fact] | |||
| public async Task CreateComment_ShouldUpdatedListOfComments_Always() | |||
| { | |||
| var databaseContext = await Helpers<Comment>.GetDatabaseContext(_comments); | |||
| CommentService applicantService = new(databaseContext, _mapper); | |||
| var commentCreateDto = new CommentCreateDto | |||
| { | |||
| ApplicantId = _applicants[0].ApplicantId, | |||
| Content = "dsadasd", | |||
| UserId = _users[0].Id | |||
| }; | |||
| await applicantService.CreateComment(commentCreateDto); | |||
| var comments = await databaseContext.Comments.ToListAsync(); | |||
| Assert.Equal(2, comments.Count); | |||
| } | |||
| } | |||
| } | |||