-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A temporary solution, it should be rethought in terms of architecture and improved for the next alert task.
- Loading branch information
1 parent
49c72fc
commit 7344aee
Showing
18 changed files
with
973 additions
and
1 deletion.
There are no files selected for viewing
104 changes: 104 additions & 0 deletions
104
SensoBackend.UnitTests/Application/Modules/Account/AddDeviceToken.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
using FluentValidation; | ||
using Mapster; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Time.Testing; | ||
using SensoBackend.Application.Modules.Accounts.Contracts; | ||
using SensoBackend.Application.Modules.Accounts.CreateAccount; | ||
using SensoBackend.Domain.Enums; | ||
using SensoBackend.Domain.Exceptions; | ||
using SensoBackend.Infrastructure.Data; | ||
using SensoBackend.UnitTests.Utils; | ||
|
||
namespace SensoBackend.Tests.Application.Modules.Accounts.CreateAccount; | ||
|
||
public sealed class AddDeviceTokenHandlerTests : IDisposable | ||
{ | ||
private static readonly DateTimeOffset AddedAt = DateTimeOffset.UtcNow; | ||
|
||
private readonly AppDbContext _context = Database.CreateFixture(); | ||
|
||
private static readonly string _deviceTypeName = "Android"; | ||
private static readonly DeviceType _deviceType = DeviceType.Android; | ||
private static readonly string _deviceToken = "J3b4cDr4p4l3"; | ||
|
||
private readonly AddDeviceTokenHandler _sut; | ||
|
||
public AddDeviceTokenHandlerTests() => | ||
_sut = new AddDeviceTokenHandler(_context, new FakeTimeProvider(AddedAt)); | ||
|
||
public void Dispose() => _context.Dispose(); | ||
|
||
[Fact] | ||
public async Task Handle_ShouldAddDeviceToken() | ||
{ | ||
var account = await _context.SetUpAccount(); | ||
var dto = new AddDeviceTokenDto | ||
{ | ||
DeviceToken = _deviceToken, | ||
DeviceType = _deviceTypeName, | ||
}; | ||
|
||
var request = new AddDeviceTokenRequest { AccountId = account.Id, Dto = dto }; | ||
await _sut.Handle(request, CancellationToken.None); | ||
|
||
var device = await _context.Devices.FirstOrDefaultAsync(d => d.AccountId == account.Id); | ||
|
||
device.Should().NotBeNull(); | ||
if (device == null) | ||
return; | ||
|
||
device.Token.Should().Be(_deviceToken); | ||
device.Type.Should().Be(_deviceType); | ||
device.AddedAt.Should().Be(AddedAt); | ||
} | ||
|
||
[Fact] | ||
public async Task Handle_ShouldUpdateDeviceToken() | ||
{ | ||
var account = await _context.SetUpAccount(); | ||
await _context.SetUpDevice(account.Id, "oldToken", _deviceType); | ||
var dto = new AddDeviceTokenDto | ||
{ | ||
DeviceToken = _deviceToken, | ||
DeviceType = _deviceTypeName, | ||
}; | ||
|
||
var request = new AddDeviceTokenRequest { AccountId = account.Id, Dto = dto }; | ||
await _sut.Handle(request, CancellationToken.None); | ||
|
||
var deviceInDb = await _context.Devices.FirstOrDefaultAsync(d => d.AccountId == account.Id); | ||
|
||
deviceInDb.Should().NotBeNull(); | ||
if (deviceInDb == null) | ||
return; | ||
|
||
deviceInDb.Token.Should().Be(_deviceToken); | ||
deviceInDb.Type.Should().Be(_deviceType); | ||
deviceInDb.AddedAt.Should().Be(AddedAt); | ||
} | ||
|
||
[Fact] | ||
public async Task Handle_ShouldNotUpdateDeviceToken_WhenDeviceTokenIsTheSame() | ||
{ | ||
var account = await _context.SetUpAccount(); | ||
var device = await _context.SetUpDevice(account.Id, _deviceToken, _deviceType); | ||
var dto = new AddDeviceTokenDto | ||
{ | ||
DeviceToken = _deviceToken, | ||
DeviceType = _deviceTypeName, | ||
}; | ||
|
||
var request = new AddDeviceTokenRequest { AccountId = account.Id, Dto = dto }; | ||
await _sut.Handle(request, CancellationToken.None); | ||
|
||
var deviceInDb = await _context.Devices.FirstOrDefaultAsync(d => d.AccountId == account.Id); | ||
|
||
deviceInDb.Should().NotBeNull(); | ||
if (deviceInDb == null) | ||
return; | ||
|
||
deviceInDb.Token.Should().Be(_deviceToken); | ||
deviceInDb.Type.Should().Be(_deviceType); | ||
deviceInDb.AddedAt.Should().Be(device.AddedAt); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
SensoBackend.UnitTests/Application/Modules/Account/Utils/GetDeviceTypeTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using SensoBackend.Application.Modules.Accounts.Utils; | ||
using SensoBackend.Application.Modules.Alerts.Utils; | ||
using SensoBackend.Domain.Enums; | ||
using SensoBackend.Domain.Exceptions; | ||
|
||
namespace SensoBackend.UnitTests.Application.Modules.Alerts.Utils; | ||
|
||
public sealed class GetDeviceTypeFromNameTests | ||
{ | ||
[Theory] | ||
[InlineData("Android", DeviceType.Android)] | ||
[InlineData("Ios", DeviceType.Ios)] | ||
public void GetDeviceTypeFromName_ShouldReturnDeviceType_WhenDeviceTypeNameIsValid( | ||
string deviceTypeName, | ||
DeviceType expectedDeviceType | ||
) | ||
{ | ||
var deviceType = GetDeviceType.FromName(deviceTypeName); | ||
|
||
deviceType.Should().Be(expectedDeviceType); | ||
} | ||
|
||
[Fact] | ||
public void GetDeviceTypeFromName_ShouldThrowIncorrectDeviceTypeNameException_WhenDeviceTypeNameIsInvalid() | ||
{ | ||
var deviceTypeName = "invalidDeviceTypeName"; | ||
|
||
var action = () => GetDeviceType.FromName(deviceTypeName); | ||
|
||
action | ||
.Should() | ||
.Throw<IncorrectDeviceTypeNameException>() | ||
.WithMessage($"Device type {deviceTypeName} is incorrect"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
SensoBackend/Application/Modules/Accounts/AddDeviceToken.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using FluentValidation; | ||
using JetBrains.Annotations; | ||
using MediatR; | ||
using Microsoft.EntityFrameworkCore; | ||
using SensoBackend.Application.Modules.Accounts.Contracts; | ||
using SensoBackend.Application.Modules.Accounts.Utils; | ||
using SensoBackend.Domain.Entities; | ||
using SensoBackend.Infrastructure.Data; | ||
|
||
namespace SensoBackend.Application.Modules.Accounts.CreateAccount; | ||
|
||
public sealed record AddDeviceTokenRequest : IRequest | ||
{ | ||
public required int AccountId; | ||
public required AddDeviceTokenDto Dto; | ||
} | ||
|
||
[UsedImplicitly] | ||
public sealed class AddDeviceTokenValidator : AbstractValidator<AddDeviceTokenRequest> | ||
{ | ||
public AddDeviceTokenValidator() | ||
{ | ||
RuleFor(r => r.Dto.DeviceToken).NotEmpty().WithMessage("Device token is required"); | ||
RuleFor(r => r.Dto.DeviceType).NotEmpty().WithMessage("Device type is required"); | ||
} | ||
} | ||
|
||
[UsedImplicitly] | ||
public sealed class AddDeviceTokenHandler(AppDbContext context, TimeProvider timeProvider) | ||
: IRequestHandler<AddDeviceTokenRequest> | ||
{ | ||
public async Task Handle(AddDeviceTokenRequest request, CancellationToken ct) | ||
{ | ||
var deviceType = GetDeviceType.FromName(request.Dto.DeviceType); | ||
|
||
var deviceInDb = await context | ||
.Devices | ||
.Where(d => d.AccountId == request.AccountId && d.Type == deviceType) | ||
.FirstOrDefaultAsync(ct); | ||
|
||
if (deviceInDb is null) | ||
{ | ||
var device = new Device | ||
{ | ||
Id = default, | ||
AccountId = request.AccountId, | ||
Token = request.Dto.DeviceToken, | ||
Type = deviceType, | ||
AddedAt = timeProvider.GetUtcNow(), | ||
}; | ||
|
||
context.Devices.Add(device); | ||
await context.SaveChangesAsync(ct); | ||
return; | ||
} | ||
|
||
if (deviceInDb.Token == request.Dto.DeviceToken) | ||
{ | ||
return; | ||
} | ||
|
||
deviceInDb.Token = request.Dto.DeviceToken; | ||
deviceInDb.AddedAt = timeProvider.GetUtcNow(); | ||
await context.SaveChangesAsync(ct); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
SensoBackend/Application/Modules/Accounts/Contracts/AddDeviceTokenDto.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace SensoBackend.Application.Modules.Accounts.Contracts; | ||
|
||
public sealed record AddDeviceTokenDto | ||
{ | ||
[Required] | ||
public required string DeviceToken { get; init; } | ||
|
||
[Required] | ||
public required string DeviceType { get; init; } | ||
} |
16 changes: 16 additions & 0 deletions
16
SensoBackend/Application/Modules/Accounts/Utils/GetDeviceType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using SensoBackend.Domain.Enums; | ||
using SensoBackend.Domain.Exceptions; | ||
|
||
namespace SensoBackend.Application.Modules.Accounts.Utils; | ||
|
||
public static class GetDeviceType | ||
{ | ||
public static DeviceType FromName(string deviceTypeName) | ||
{ | ||
if (Enum.TryParse(deviceTypeName, true, out DeviceType result)) | ||
{ | ||
return result; | ||
} | ||
throw new IncorrectDeviceTypeNameException(deviceTypeName); | ||
} | ||
} |
Oops, something went wrong.