Skip to content

Commit

Permalink
Merge dev into staging (hngprojects#377)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexindevs authored Aug 31, 2024
2 parents f2da8a3 + e4bf5e5 commit cf020a8
Show file tree
Hide file tree
Showing 49 changed files with 3,731 additions and 53 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/c-sharp-postman-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: C-sharp Run Postman Tests Every 15 Minutes

on:
workflow_dispatch:
schedule:
- cron: "*/15 * * * *" # Every 15 minutes

jobs:
run-postman-tests:
runs-on: self-hosted

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install Newman
run: npm install -g newman

- name: Run Newman tests
id: newman
run: |
newman run status/postman/telex_postmancollection_v1.json --reporters cli,json --reporter-json-export report.json
- name: Upload newman report to API
run: |
curl -X POST "${{ vars.API_URL }}/api/v1/api-status" \
-H "Content-Type: multipart/form-data" \
-F "[email protected]"
9 changes: 8 additions & 1 deletion Hng.Csharp.Web.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hng.Application", "src\Hng.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hng.Web", "src\Hng.Web\Hng.Web.csproj", "{9774A8A9-24E7-4DF0-99FE-28377C71A396}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hng.Application.Test", "src\Hng.Application.Test\Hng.Application.Test.csproj", "{D4B9422C-9838-4E41-B817-882A53C2B7A9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hng.Application.Test", "src\Hng.Application.Test\Hng.Application.Test.csproj", "{D4B9422C-9838-4E41-B817-882A53C2B7A9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hng.Graphql", "src\Hng.Graphql\Hng.Graphql.csproj", "{BBD35442-B803-4B17-A5B7-B5147350D616}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -41,6 +43,10 @@ Global
{D4B9422C-9838-4E41-B817-882A53C2B7A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4B9422C-9838-4E41-B817-882A53C2B7A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4B9422C-9838-4E41-B817-882A53C2B7A9}.Release|Any CPU.Build.0 = Release|Any CPU
{BBD35442-B803-4B17-A5B7-B5147350D616}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBD35442-B803-4B17-A5B7-B5147350D616}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBD35442-B803-4B17-A5B7-B5147350D616}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBD35442-B803-4B17-A5B7-B5147350D616}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -51,6 +57,7 @@ Global
{D0791DB0-B0F8-441E-9063-B898C0A10F75} = {7DBA9FEC-56C1-4474-A496-42135E7C1431}
{9774A8A9-24E7-4DF0-99FE-28377C71A396} = {7DBA9FEC-56C1-4474-A496-42135E7C1431}
{D4B9422C-9838-4E41-B817-882A53C2B7A9} = {7DBA9FEC-56C1-4474-A496-42135E7C1431}
{BBD35442-B803-4B17-A5B7-B5147350D616} = {7DBA9FEC-56C1-4474-A496-42135E7C1431}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {27B33D62-0FC6-4073-BEAB-76CFE688568E}
Expand Down
67 changes: 67 additions & 0 deletions src/Hng.Application.Test/Features/Squeeze/CreateSqueezeShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using AutoMapper;
using Hng.Application.Features.Squeeze.Commands;
using Hng.Application.Features.Squeeze.Dtos;
using Hng.Application.Features.Squeeze.Handlers;
using Hng.Application.Features.Squeeze.Mappers;
using Hng.Infrastructure.Repository.Interface;
using Microsoft.AspNetCore.Http;
using Moq;
using Xunit;

namespace Hng.Application.Test.Features.Squeeze;

public class CreateSqueezeShould
{
private readonly Mock<IRepository<Domain.Entities.Squeeze>> _repositoryMock;
private readonly CreateSqueezeCommandHandler _handler;

public CreateSqueezeShould()
{
var mappingProfile = new SqueezeMapperProfile();
var configuration = new MapperConfiguration(cfg => cfg.AddProfile(mappingProfile));
IMapper mapper = new Mapper(configuration);

_repositoryMock = new Mock<IRepository<Domain.Entities.Squeeze>>();
_handler = new CreateSqueezeCommandHandler(_repositoryMock.Object, mapper);
}

[Fact]
public async Task Handle_ShouldReturnCreatedSqueeze()
{
var expectedId = Guid.NewGuid();
var createDto = new CreateSqueezeRequestDto()
{
FirstName = "Test First Name",
LastName = "Test Last Name",
Email = "[email protected]",
};

var squeeze = new Domain.Entities.Squeeze
{
Id = expectedId,
FirstName = createDto.FirstName,
LastName = createDto.LastName,
Email = createDto.Email,
};

_repositoryMock.Setup(r => r.AddAsync(It.IsAny<Domain.Entities.Squeeze>()))
.ReturnsAsync((Domain.Entities.Squeeze org) =>
{
org.Id = expectedId;
return org;
});

var command = new CreateSqueezeCommand(createDto);

var result = await _handler.Handle(command, default);

Assert.NotNull(result);
Assert.Equal(StatusCodes.Status201Created, result.StatusCode);
Assert.Equal("Squeeze Created Successfully", result.Message);
Assert.NotNull(result.Data);
Assert.Equal(expectedId, result.Data.Id);
Assert.Equal(createDto.FirstName, result.Data.FirstName);
Assert.Equal(createDto.LastName, result.Data.LastName);
Assert.Equal(createDto.Email, result.Data.Email);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using AutoMapper;
using Hng.Application.Features.WaitLists.Commands;
using Hng.Application.Features.WaitLists.Dtos;
using Hng.Application.Features.WaitLists.Handlers;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Moq;
using System.Linq.Expressions;
using Xunit;

namespace Hng.Application.Test.Features.WaitLists
{
public class CreateWaitlistCommandHandlerShould
{
private readonly Mock<IRepository<Waitlist>> _mockWaitlistRepository;
private readonly Mock<IMapper> _mockMapper;
private readonly CreateWaitlistCommandHandler _handler;

public CreateWaitlistCommandHandlerShould()
{
_mockWaitlistRepository = new Mock<IRepository<Waitlist>>();
_mockMapper = new Mock<IMapper>();
_handler = new CreateWaitlistCommandHandler(
_mockWaitlistRepository.Object,
_mockMapper.Object
);
}

[Fact]
public async Task Handle_ShouldCreateNewWaitlistWhenEmailDoesNotExist()
{
// Arrange
var waitListDto = new WaitListDto
{
Name = "John Doe",
Email = "[email protected]"
};

var command = new CreateWaitlistCommand(waitListDto);
var newWaitlist = new Waitlist
{
Id = Guid.NewGuid(),
Name = waitListDto.Name,
Email = waitListDto.Email
};

_mockWaitlistRepository.Setup(r => r.GetBySpec(It.IsAny<Expression<Func<Waitlist, bool>>>()))
.ReturnsAsync((Waitlist)null);
_mockMapper.Setup(m => m.Map<Waitlist>(waitListDto))
.Returns(newWaitlist);
_mockWaitlistRepository.Setup(r => r.AddAsync(It.IsAny<Waitlist>()))
.ReturnsAsync(newWaitlist);
_mockWaitlistRepository.Setup(r => r.SaveChanges())
.Returns(Task.CompletedTask);

// Act
var result = await _handler.Handle(command, CancellationToken.None);

// Assert
Assert.NotNull(result);
Assert.Equal(waitListDto.Name, result.Name);
Assert.Equal(waitListDto.Email, result.Email);

_mockWaitlistRepository.Verify(r => r.GetBySpec(It.IsAny<Expression<Func<Waitlist, bool>>>()), Times.Once);
_mockMapper.Verify(m => m.Map<Waitlist>(waitListDto), Times.Once);
_mockWaitlistRepository.Verify(r => r.AddAsync(It.IsAny<Waitlist>()), Times.Once);
_mockWaitlistRepository.Verify(r => r.SaveChanges(), Times.Once);
}

[Fact]
public async Task Handle_ShouldReturnNullWhenEmailAlreadyExists()
{
// Arrange
var existingEmail = "[email protected]";
var waitListDto = new WaitListDto
{
Name = "John Doe",
Email = existingEmail
};
var command = new CreateWaitlistCommand(waitListDto);
var existingWaitlist = new Waitlist
{
Id = Guid.NewGuid(),
Email = existingEmail
};

_mockWaitlistRepository.Setup(r => r.GetBySpec(It.IsAny<Expression<Func<Waitlist, bool>>>()))
.ReturnsAsync(existingWaitlist);

// Act
var result = await _handler.Handle(command, CancellationToken.None);

// Assert
Assert.Null(result);

_mockWaitlistRepository.Verify(r => r.GetBySpec(It.IsAny<Expression<Func<Waitlist, bool>>>()), Times.Once);
_mockMapper.Verify(m => m.Map<Waitlist>(It.IsAny<WaitListDto>()), Times.Never);
_mockWaitlistRepository.Verify(r => r.AddAsync(It.IsAny<Waitlist>()), Times.Never);
_mockWaitlistRepository.Verify(r => r.SaveChanges(), Times.Never);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using AutoMapper;
using Hng.Application.Features.WaitLists.Commands;
using Hng.Application.Features.WaitLists.Handlers;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Moq;
using Xunit;

namespace Hng.Application.Test.Features.WaitLists
{
public class DeleteWaitlistByIdCommandHandlerShould
{
private readonly Mock<IRepository<Waitlist>> _mockWaitlistRepository;
private readonly Mock<IMapper> _mockMapper;
private readonly DeleteWaitlistByIdCommandHandler _handler;

public DeleteWaitlistByIdCommandHandlerShould()
{
_mockWaitlistRepository = new Mock<IRepository<Waitlist>>();
_mockMapper = new Mock<IMapper>();
_handler = new DeleteWaitlistByIdCommandHandler(
_mockWaitlistRepository.Object,
_mockMapper.Object
);
}

[Fact]
public async Task Handle_ShouldDeleteWaitlistWhenExists()
{
// Arrange
var waitlistId = Guid.NewGuid();
var existingWaitlist = new Waitlist { Id = waitlistId, Email = "[email protected]" };

_mockWaitlistRepository.Setup(r => r.GetAsync(waitlistId))
.ReturnsAsync(existingWaitlist);
_mockWaitlistRepository.Setup(r => r.DeleteAsync(existingWaitlist))
.ReturnsAsync(existingWaitlist);
_mockWaitlistRepository.Setup(r => r.SaveChanges())
.Returns(Task.CompletedTask);

var command = new DeleteWaitlistByIdCommand(waitlistId);

// Act
var result = await _handler.Handle(command, CancellationToken.None);

// Assert
Assert.NotNull(result);
Assert.Equal(existingWaitlist, result);

_mockWaitlistRepository.Verify(r => r.GetAsync(waitlistId), Times.Once);
_mockWaitlistRepository.Verify(r => r.DeleteAsync(existingWaitlist), Times.Once);
_mockWaitlistRepository.Verify(r => r.SaveChanges(), Times.Once);
}

[Fact]
public async Task Handle_ShouldReturnNullWhenWaitlistDoesNotExist()
{
// Arrange
var nonExistentWaitlistId = Guid.NewGuid();

_mockWaitlistRepository.Setup(r => r.GetAsync(nonExistentWaitlistId))
.ReturnsAsync((Waitlist)null);

var command = new DeleteWaitlistByIdCommand(nonExistentWaitlistId);

// Act
var result = await _handler.Handle(command, CancellationToken.None);

// Assert
Assert.Null(result);

_mockWaitlistRepository.Verify(r => r.GetAsync(nonExistentWaitlistId), Times.Once);
_mockWaitlistRepository.Verify(r => r.DeleteAsync(It.IsAny<Waitlist>()), Times.Never);
_mockWaitlistRepository.Verify(r => r.SaveChanges(), Times.Never);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using AutoMapper;
using Hng.Application.Features.WaitLists.Handlers;
using Hng.Application.Features.WaitLists.Queries;
using Hng.Domain.Entities;
using Hng.Infrastructure.Repository.Interface;
using Moq;
using Xunit;

namespace Hng.Application.Test.Features.WaitLists
{
public class GetAllWaitlistQueryHandlerShould
{
private readonly Mock<IRepository<Waitlist>> _mockWaitlistRepository;
private readonly Mock<IMapper> _mockMapper;
private readonly GetAllWaitlistQueryHandler _handler;

public GetAllWaitlistQueryHandlerShould()
{
_mockWaitlistRepository = new Mock<IRepository<Waitlist>>();
_mockMapper = new Mock<IMapper>();
_handler = new GetAllWaitlistQueryHandler(
_mockWaitlistRepository.Object,
_mockMapper.Object
);
}

[Fact]
public async Task Handle_ShouldReturnAllWaitlists()
{
// Arrange
var waitlists = new List<Waitlist>
{
new Waitlist { Id = Guid.NewGuid(), Email = "[email protected]" },
new Waitlist { Id = Guid.NewGuid(), Email = "[email protected]" }
};

_mockWaitlistRepository.Setup(r => r.GetAllAsync())
.ReturnsAsync(waitlists);

var query = new GetAllWaitlistQuery();

// Act
var result = await _handler.Handle(query, CancellationToken.None);

// Assert
Assert.NotNull(result);
Assert.Equal(2, result.Count);
Assert.Equal(waitlists, result);

_mockWaitlistRepository.Verify(r => r.GetAllAsync(), Times.Once);
}

[Fact]
public async Task Handle_ShouldReturnEmptyListWhenNoWaitlists()
{
// Arrange
var emptyList = new List<Waitlist>();

_mockWaitlistRepository.Setup(r => r.GetAllAsync())
.ReturnsAsync(emptyList);

var query = new GetAllWaitlistQuery();

// Act
var result = await _handler.Handle(query, CancellationToken.None);

// Assert
Assert.NotNull(result);
Assert.Empty(result);

_mockWaitlistRepository.Verify(r => r.GetAllAsync(), Times.Once);
}
}
}
Loading

0 comments on commit cf020a8

Please sign in to comment.