Skip to content
This repository has been archived by the owner on Jul 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #269 from habralab/fix/268-notification-fix
Browse files Browse the repository at this point in the history
 #268 Правка уведомлений
  • Loading branch information
picolino authored Nov 30, 2023
2 parents 716dc10 + 1922e09 commit 3b1a970
Show file tree
Hide file tree
Showing 45 changed files with 452 additions and 56 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Garnet.Common.AcceptanceTests.Support;
using Garnet.Common.Infrastructure.Support;
using Garnet.Notifications.Application;
using Garnet.Notifications.Application.Args;
using Garnet.Notifications.Events;
using Garnet.Notifications.Infrastructure.MongoDB;
Expand Down Expand Up @@ -31,7 +32,7 @@ public NotificationDocument Build()
{
return NotificationDocument.Create(
_id,
new NotificationCreateArgs(_title, _body, _type, _userId, _createdAt, null)
new NotificationCreateArgs(_title, _body, _type, _userId, _createdAt, null, Array.Empty<QuotedEntity>())
);
}

Expand All @@ -56,7 +57,8 @@ public static SendNotificationCommandMessage EventFromNotification(this GiveMe _
document.UserId,
document.Type,
document.CreatedAt,
document.LinkedEntityId
document.LinkedEntityId,
Array.Empty<NotificationQuotedEntity>()
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public record NotificationCreateArgs(
string Type,
string UserId,
DateTimeOffset CreatedAt,
string? LinkedEntityId
string? LinkedEntityId,
QuotedEntity[] QuotedEntities
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public record NotificationEntity(
string Type,
string UserId,
DateTimeOffset CreatedAt,
string? LinkedEntityId
string? LinkedEntityId,
QuotedEntity[] QuotedEntities
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Garnet.Notifications.Application
{
public record QuotedEntity(
string Id,
string AvatarUrl,
string Quote
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Garnet.Notifications.Events
{
public record NotificationQuotedEntity(
string Id,
string AvatarUrl,
string Quote
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public record SendNotificationCommandMessage(
string UserId,
string Type,
DateTimeOffset CreatedAt,
string? LinkedEntityId
string? LinkedEntityId,
NotificationQuotedEntity[] QuotedEntities
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public record NotificationDeletePayload(
string Type,
string UserId,
DateTimeOffset CreatedAt,
string? LinkedEntityId
) : NotificationPayload(Id, Title, Body, Type, UserId, CreatedAt, LinkedEntityId);
string? LinkedEntityId,
QuotedEntityPayload[] QuotedEntities
) : NotificationPayload(Id, Title, Body, Type, UserId, CreatedAt, LinkedEntityId, QuotedEntities);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public record NotificationPayload(
string Type,
string UserId,
DateTimeOffset CreatedAt,
string? LinkedEntityId
string? LinkedEntityId,
QuotedEntityPayload[] QuotedEntities
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Garnet.Notifications.Infrastructure.Api.NotificationGet
{
public record QuotedEntityPayload(
string Id,
string AvatarUrl,
string Quote
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Garnet.Common.Infrastructure.Support;
using Garnet.Notifications.Application.Commands;
using Garnet.Notifications.Infrastructure.Api.NotificationDelete;
using Garnet.Notifications.Infrastructure.Api.NotificationGet;
using HotChocolate.Types;

namespace Garnet.Notifications.Infrastructure.Api
Expand Down Expand Up @@ -28,7 +29,12 @@ public async Task<NotificationDeletePayload> NotificationDelete(CancellationToke
notification.Type,
notification.UserId,
notification.CreatedAt,
notification.LinkedEntityId
notification.LinkedEntityId,
notification.QuotedEntities.Select(y => new QuotedEntityPayload(
y.Id,
y.AvatarUrl,
y.Quote
)).ToArray()
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,24 @@ public async Task<NotificationGetPayload> NotificationsGetListByCurrentUser(Canc
{
var result = await _notificationGetQuery.Query(ct);

var notifications = result.Select(x => new NotificationPayload(
var notifications = result.Select(x =>
{
var quote = x.QuotedEntities.Select(y => new QuotedEntityPayload(
y.Id,
y.AvatarUrl,
y.Quote
));
return new NotificationPayload(
x.Id,
x.Title,
x.Body,
x.Type,
x.UserId,
x.CreatedAt,
x.LinkedEntityId));
x.LinkedEntityId,
quote.ToArray());
});
return new NotificationGetPayload(notifications.ToArray());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ public SendNotificationCommandMessageConsumer(INotificationRepository notificati

public async Task Consume(SendNotificationCommandMessage message)
{
var notificationQuotes = message.QuotedEntities.Select(x => new QuotedEntity(
x.Id,
x.AvatarUrl,
x.Quote));

var args = new NotificationCreateArgs(
message.Title,
message.Body,
message.Type,
message.UserId,
message.CreatedAt,
message.LinkedEntityId
message.LinkedEntityId,
notificationQuotes.ToArray()
);

await _notificationRepository.CreateNotification(CancellationToken.None, args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class NotificationDocument
public string UserId { get; init; } = null!;
public string Type { get; init; } = null!;
public string? LinkedEntityId { get; init; }
public NotificationQuoteDocument[] QuoteDocuments { get; init; } = Array.Empty<NotificationQuoteDocument>();

public static NotificationDocument Create(string id, NotificationCreateArgs args)
{
Expand All @@ -23,7 +24,8 @@ public static NotificationDocument Create(string id, NotificationCreateArgs args
UserId = args.UserId,
Type = args.Type,
CreatedAt = args.CreatedAt,
LinkedEntityId = args.LinkedEntityId
LinkedEntityId = args.LinkedEntityId,
QuoteDocuments = args.QuotedEntities.Select(x=> NotificationQuoteDocument.Create(x)).ToArray()
};
}

Expand All @@ -36,7 +38,8 @@ public static NotificationEntity ToDomain(NotificationDocument doc)
doc.Type,
doc.UserId,
doc.CreatedAt,
doc.LinkedEntityId
doc.LinkedEntityId,
doc.QuoteDocuments.Select(x => NotificationQuoteDocument.ToDomain(x)).ToArray()
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Garnet.Notifications.Application;

namespace Garnet.Notifications.Infrastructure.MongoDB
{
public class NotificationQuoteDocument
{
public string Id { get; init; } = null!;
public string AvatarUrl { get; init; } = null!;
public string Quote { get; init; } = null!;

public static QuotedEntity ToDomain(NotificationQuoteDocument doc)
{
return new QuotedEntity(
doc.Id,
doc.AvatarUrl,
doc.Quote
);
}

public static NotificationQuoteDocument Create(QuotedEntity entity)
{
return new NotificationQuoteDocument() {
Id = entity.Id,
AvatarUrl = entity.AvatarUrl,
Quote = entity.Quote
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Garnet.Common.Application.MessageBus;
using Garnet.Notifications.Events;

namespace Garnet.Projects.AcceptanceTests.FakeServices.NotificationFake
{
public class DeleteNotificationCommandMessageFakeConsumer : IMessageBusConsumer<DeleteNotificationCommandMessage>
{
public List<DeleteNotificationCommandMessage> DeletedNotifications = new();
public Task Consume(DeleteNotificationCommandMessage message)
{
DeletedNotifications.Add(message);
return Task.CompletedTask;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ public async Task ThenВПоследнемУведомленииДляПольз
var notification = _sendNotificationCommandMessageFakeConsumer.Notifications
.Last(x => x.UserId == user.Id);
var project = await Db.Projects.Find(x => x.ProjectName == projectName).FirstAsync();
notification.LinkedEntityId.Should().Be(project.Id);
notification.QuotedEntities.Should().Contain(x=> x.Id == project.Id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ public async Task ThenВПоследнемУведомленииДляПольз
var team = await Db.ProjectTeams.Find(x => x.TeamName == teamName).FirstAsync();
var notification = _sendNotificationCommandMessageFakeConsumer.Notifications
.Last(x => x.UserId == user.Id);
notification.LinkedEntityId.Should().Be(team.Id);
notification.QuotedEntities.Should().Contain(x=> x.Id == team.Id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
И количество заявок на вступление в проект 'FooBar' равно '0'
И для пользователя 'Маша' существует уведомление типа 'TeamJoinRequestDecide'
И в последнем уведомлении для пользователя 'Маша' связанной сущностью является проект 'FooBar'
И для пользователя 'Вася' нет уведомлений типа 'TeamJoinProjectRequest'
И для пользователя 'Вася' нет уведомлений со связанной сущностью командой 'DreamTeam'

Сценарий: Отклонение заявки команды на участие в проекте
Когда пользователь 'Вася' отклоняет заявку на участие от команды 'DreamTeam' в проект 'FooBar'
Тогда команда 'DreamTeam' не является участником проекта 'FooBar'
И количество заявок на вступление в проект 'FooBar' равно '0'
И для пользователя 'Маша' существует уведомление типа 'TeamJoinRequestDecide'
И в последнем уведомлении для пользователя 'Маша' связанной сущностью является проект 'FooBar'
И для пользователя 'Вася' нет уведомлений типа 'TeamJoinProjectRequest'
И для пользователя 'Вася' нет уведомлений со связанной сущностью командой 'DreamTeam'

Сценарий: Только владелец проекта может выносить вердикт по заявке на вступление команды
Когда пользователь 'Маша' принимает заявку на участие от команды 'DreamTeam' в проект 'FooBar'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using FluentAssertions;
using Garnet.Common.AcceptanceTests.Contexts;
using Garnet.Common.AcceptanceTests.Fakes;
using Garnet.Project.AcceptanceTests.FakeServices.NotificationFake;
using Garnet.Projects.AcceptanceTests.FakeServices.NotificationFake;
using Garnet.Projects.Application;
using Garnet.Projects.Infrastructure.Api.ProjectTeamJoinRequestDecide;
using Garnet.Projects.Infrastructure.MongoDb;
Expand All @@ -15,13 +17,19 @@ public class ProjectTeamJoinRequestDecideSteps : BaseSteps
{
private readonly CurrentUserProviderFake _currentUserProviderFake;
private readonly QueryExceptionsContext _queryExceptionsContext;
private readonly SendNotificationCommandMessageFakeConsumer _sendNotificationCommandMessageFakeConsumer;
private readonly DeleteNotificationCommandMessageFakeConsumer _deleteNotificationCommandMessageFakeConsumer;


public ProjectTeamJoinRequestDecideSteps(StepsArgs args, CurrentUserProviderFake currentUserProviderFake,
SendNotificationCommandMessageFakeConsumer sendNotificationCommandMessageFakeConsumer,
DeleteNotificationCommandMessageFakeConsumer deleteNotificationCommandMessageFakeConsumer,
QueryExceptionsContext queryExceptionsContext) : base(args)
{
_currentUserProviderFake = currentUserProviderFake;
_queryExceptionsContext = queryExceptionsContext;
_deleteNotificationCommandMessageFakeConsumer = deleteNotificationCommandMessageFakeConsumer;
_sendNotificationCommandMessageFakeConsumer = sendNotificationCommandMessageFakeConsumer;
}

private async Task<ProjectTeamJoinRequestDecideInput> SetJoinRequestDecision(string projectName, string teamName,
Expand Down Expand Up @@ -94,4 +102,26 @@ public async Task ThenКомандаНеЯвляетсяУчастникомПр
.Find(x => x.TeamName == teamName & x.ProjectId == project.Id).FirstOrDefaultAsync();
teamParticipant.Should().BeNull();
}

[Then(@"для пользователя '(.*)' нет уведомлений типа '(.*)'")]
public async Task ThenДляПользователяНетУведомленийТипа(string username, string eventType)
{
var user = await Db.ProjectUsers.Find(x => x.UserName == username).FirstAsync();
var message = _deleteNotificationCommandMessageFakeConsumer.DeletedNotifications
.First(x => x.UserId == user.Id);
message.Type.Should().Be(eventType);
}

[Then(@"для пользователя '(.*)' нет уведомлений со связанной сущностью командой '(.*)'")]
public async Task ThenДляПользователяНетУведомленийСоСвязаннойСущностьюКомандой(string username, string teamName)
{
var user = await Db.ProjectUsers.Find(x => x.UserName == username).FirstAsync();
var team = await Db.ProjectTeams.Find(x => x.TeamName == teamName).FirstAsync();
var requestedForDeleteNotice = _deleteNotificationCommandMessageFakeConsumer.DeletedNotifications
.First(x => x.UserId == user.Id);
var notice = _sendNotificationCommandMessageFakeConsumer.Notifications
.First(x => x.UserId == user.Id && x.QuotedEntities.Any(y => y.Id == team.Id));

requestedForDeleteNotice.LinkedEntityId.Should().Be(notice.LinkedEntityId);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using FluentAssertions;
using Garnet.Common.AcceptanceTests.Contexts;
using Garnet.Common.AcceptanceTests.Fakes;
using Garnet.Common.Infrastructure.Support;
using Garnet.Project.AcceptanceTests.FakeServices.NotificationFake;
using Garnet.Projects.AcceptanceTests.Support;
using Garnet.Projects.Infrastructure.Api.ProjectTeamJoinRequest;
using Garnet.Projects.Infrastructure.Api.ProjectTeamJoinRequestGet;
Expand All @@ -16,7 +18,8 @@ public class ProjectTeamJoinRequestGetSteps : BaseSteps
{
private readonly CurrentUserProviderFake _currentUserProviderFake;
private ProjectTeamJoinRequestGetPayload? _response;
private QueryExceptionsContext _errorStepContext = null!;
private readonly QueryExceptionsContext _errorStepContext = null!;
private readonly SendNotificationCommandMessageFakeConsumer _sendNotificationCommandMessageFakeConsumer;

private readonly FilterDefinitionBuilder<ProjectDocument> _f =
Builders<ProjectDocument>.Filter;
Expand All @@ -25,10 +28,12 @@ public class ProjectTeamJoinRequestGetSteps : BaseSteps
Builders<ProjectDocument>.Update;

public ProjectTeamJoinRequestGetSteps(StepsArgs args, CurrentUserProviderFake currentUserProviderFake,
SendNotificationCommandMessageFakeConsumer sendNotificationCommandMessageFakeConsumer,
QueryExceptionsContext errorStepContext) : base(args)
{
_currentUserProviderFake = currentUserProviderFake;
_errorStepContext = errorStepContext;
_sendNotificationCommandMessageFakeConsumer = sendNotificationCommandMessageFakeConsumer;
}

[Given(@"пользователь '([^']*)' является владельцем проекта '([^']*)'")]
Expand All @@ -44,8 +49,18 @@ public async Task GivenСуществуетЗаявкаОтКомандыНаУ
{
var project = await Db.Projects.Find(x => x.ProjectName == projectName).FirstAsync();
var team = await Db.ProjectTeams.Find(x => x.TeamName == teamName).FirstAsync();
var teamJoinRequest = GiveMe.ProjectTeamJoinRequest().WithTeamId(team.Id).WithTeamName(teamName).WithProjectId(project.Id);

var teamJoinRequestId = Uuid.NewMongo();
var teamJoinRequest = GiveMe.ProjectTeamJoinRequest().WithTeamId(team.Id).WithTeamName(teamName).WithProjectId(project.Id).WithId(teamJoinRequestId);
await Db.ProjectTeamJoinRequests.InsertOneAsync(teamJoinRequest);

_sendNotificationCommandMessageFakeConsumer.Notifications.Add(
GiveMe.SendNotificationCommandMessage()
.WithUserId(project.OwnerUserId)
.WithType("TeamJoinProjectRequest")
.WithLinkedEntityId(teamJoinRequestId)
.WithQuotedEntityIds(new[] { team.Id, project.Id })
);
}

[When(@"пользователь '([^']*)' просматривает заявки проекта '([^']*)'")]
Expand Down
Loading

0 comments on commit 3b1a970

Please sign in to comment.