Skip to content
Open
49 changes: 49 additions & 0 deletions Mixter.Domain.Tests/Core/Messages/Handlers/UpdateTimelineTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mixter.Domain.Core.Messages;
using Mixter.Domain.Core.Messages.Events;
using Mixter.Domain.Core.Messages.Handlers;
using Mixter.Domain.Identity;
using Mixter.Infrastructure;
using NFluent;

namespace Mixter.Domain.Tests.Core.Messages.Handlers
{
[TestClass]
public class UpdateTimelineTest
{
private const string Content = "Hello";

private static readonly UserId Author = new UserId("author@mixit.fr");
private static readonly MessageId MessageId = MessageId.Generate();

private TimelineMessagesRepository _repository;
private UpdateTimeline _handler;

[TestInitialize]
public void Initialize()
{
_repository = new TimelineMessagesRepository();
_handler = new UpdateTimeline(_repository);
}

[TestMethod]
public void WhenHandleMessagePublishedThenSaveTimelineMessageProjectionForAuthor()
{
_handler.Handle(new MessagePublished(MessageId, Author, Content));

Check.That(_repository.GetMessagesOfUser(Author))
.ContainsExactly(new TimelineMessageProjection(Author, Author, Content, MessageId));
}

[TestMethod]
public void WhenHandleMessageRepliedThenSaveTimelineMessageProjectionForReplier()
{
var parentMessageId = MessageId.Generate();
var replier = new UserId("author@mixit.fr");
_handler.Handle(new ReplyMessagePublished(MessageId, replier, Content, parentMessageId));

Check.That(_repository.GetMessagesOfUser(replier))
.ContainsExactly(new TimelineMessageProjection(replier, replier, Content, MessageId));
}
}
}
171 changes: 148 additions & 23 deletions Mixter.Domain.Tests/Core/Messages/MessageTest.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mixter.Domain.Core.Messages;
using Mixter.Domain.Core.Messages.Events;
using Mixter.Domain.Identity;
using Mixter.Infrastructure;
using Mixter.Infrastructure.Tests.Infrastructure;
using Mixter.Infrastructure.Tests;
using NFluent;

namespace Mixter.Domain.Tests.Core.Messages
Expand All @@ -17,6 +18,7 @@ public class MessageTest

private static readonly UserId Author = new UserId("pierre@mixit.fr");
private static readonly UserId Republisher = new UserId("alfred@mixit.fr");
private static readonly MessageId MessageId = MessageId.Generate();
private static readonly UserId Replier = new UserId("jean@mixit.fr");

private EventPublisherFake _eventPublisher;
Expand All @@ -39,46 +41,169 @@ public void WhenPublishMessageThenRaiseUserMessagePublished()
[TestMethod]
public void WhenRepublishMessageThenRaiseMessageRepublished()
{
var message = Message.Publish(new EventPublisher(), Author, MessageContent);
message.Republish(_eventPublisher, Republisher);
Check.That(_eventPublisher.Events).ContainsExactly(new MessageRepublished(message.GetId(), Republisher));
Given(new MessagePublished(MessageId, Author, MessageContent))
.When(o => o.Republish(_eventPublisher, Republisher))
.ThenHas(new MessageRepublished(MessageId, Republisher));
}

[TestMethod]
public void WhenRepublishMyOwnMessageThenDoNotRaiseMessageRepublished()
{
var message = Message.Publish(new EventPublisher(), Author, MessageContent);
message.Republish(_eventPublisher, Author);
Check.That(_eventPublisher.Events).IsEmpty();
Given(new MessagePublished(MessageId, Author, MessageContent))
.When(o => o.Republish(_eventPublisher, Author))
.ThenNothing();
}

[TestMethod]
public void WhenRepublishTwoTimesSameMessageThenDoNotRaiseMessageRepublished()
{
var message = Message.Publish(new EventPublisher(), Author, MessageContent);
message.Republish(_eventPublisher, Republisher);
message.Republish(_eventPublisher, Republisher);
Check.That(_eventPublisher.Events).ContainsExactly(new MessageRepublished(message.GetId(), Republisher));
Given(new MessagePublished(MessageId, Author, MessageContent))
.And(new MessageRepublished(MessageId, Republisher))
.When(o => o.Republish(_eventPublisher, Republisher))
.ThenNothing();
}

[TestMethod]
public void WhenReplyThenRaiseReplyMessagePublished()
{
var message = Message.Publish(_eventPublisher, Author, MessageContent);
message.Reply(_eventPublisher, Replier, ReplyContent);
var replyEvent = _eventPublisher.Events.OfType<ReplyMessagePublished>().First();
Check.That(replyEvent.ParentId).IsEqualTo(message.GetId());
Check.That(replyEvent.ReplyContent).IsEqualTo(ReplyContent);
Check.That(replyEvent.Replier).IsEqualTo(Replier);
Check.That(replyEvent.ReplyId).IsNotEqualTo(message.GetId());
Given(new MessagePublished(MessageId, Author, MessageContent))
.When(o => o.Reply(_eventPublisher, Replier, ReplyContent))
.ThenHasEvent<ReplyMessagePublished>(evt =>
{
Check.That(evt.ParentId).IsEqualTo(MessageId);
Check.That(evt.ReplyContent).IsEqualTo(ReplyContent);
Check.That(evt.Replier).IsEqualTo(Replier);
Check.That(evt.ReplyId).IsNotEqualTo(MessageId);
});
}

[TestMethod]
public void WhenDeleteThenRaiseMessageDeleted()
{
var message = Message.Publish(new EventPublisher(), Author, MessageContent);
message.Delete(_eventPublisher, Author);
Check.That(_eventPublisher.Events).ContainsExactly(new MessageDeleted(message.GetId()));
Given(new MessagePublished(MessageId, Author, MessageContent))
.When(o => o.Delete(_eventPublisher, Author))
.ThenHasOnly(new MessageDeleted(MessageId));
}

[TestMethod]
public void WhenDeleteBySomeoneElseThanAuthorThenDoNotRaiseMessageDeleted()
{
Given(new MessagePublished(MessageId, Author, MessageContent))
.When(o => o.Delete(_eventPublisher, new UserId("clement@mix-it.fr")))
.ThenNothing();
}

[TestMethod]
public void GivenIsRepublishedWhenDeleteByRepublisherThenDoNotRaiseMessageDeleted()
{
Given(new MessagePublished(MessageId, Author, MessageContent))
.And(new MessageRepublished(MessageId, Republisher))
.When(o => o.Delete(_eventPublisher, Republisher))
.ThenNothing();
}

[TestMethod]
public void GiveDeletedMessageWhenDeleteThenNothing()
{
Given(new MessagePublished(MessageId, Author, MessageContent))
.And(new MessageDeleted(MessageId))
.When(o => o.Delete(_eventPublisher, Author))
.ThenNothing();
}

[TestMethod]
public void GivenReplyMessageWhenGetIdHasReplayMessageId()
{
var replyMessageId = MessageId.Generate();
var message = CreateMessage(new ReplyMessagePublished(replyMessageId, Replier, ReplyContent, MessageId));

Check.That(message.GetId()).IsEqualTo(replyMessageId);
}

[TestMethod]
public void GivenADeletedMessageWhenReplyThenDoNotRaiseMessageDeleted()
{
Given(new MessagePublished(MessageId, Author, MessageContent))
.And(new MessageDeleted(MessageId))
.When(o => o.Reply(_eventPublisher, Replier, ReplyContent))
.ThenNothing();
}

[TestMethod]
public void GivenDeletedMessageWhenRepublishThenDoNotRaiseMessageRepublished()
{
Given(new MessagePublished(MessageId, Author, MessageContent))
.And(new MessageDeleted(MessageId))
.When(o => o.Republish(_eventPublisher, Republisher))
.ThenNothing();
}

private Message CreateMessage(params IDomainEvent[] events)
{
return new Message(events);
}

private GivenFactory Given(IDomainEvent evt)
{
return new GivenFactory(evt, _eventPublisher);
}

private class GivenFactory
{
private readonly IList<IDomainEvent> _events = new List<IDomainEvent>();
private readonly EventPublisherFake _eventPublisherFake;

public GivenFactory(IDomainEvent evt, EventPublisherFake eventPublisherFake)
{
_events.Add(evt);
_eventPublisherFake = eventPublisherFake;
}

public GivenFactory And(IDomainEvent evt)
{
_events.Add(evt);

return this;
}

public ThenFactory When(Action<Message> when)
{
var message = new Message(_events);
when(message);

return new ThenFactory(_eventPublisherFake);
}

public class ThenFactory
{
private readonly EventPublisherFake _eventPublisherFake;

public ThenFactory(EventPublisherFake eventPublisherFake)
{
_eventPublisherFake = eventPublisherFake;
}

public void ThenHas(IDomainEvent domainEvent)
{
Check.That(_eventPublisherFake.Events).Contains(domainEvent);
}

public void ThenNothing()
{
Check.That(_eventPublisherFake.Events).IsEmpty();
}

public void ThenHasEvent<TEvent>(Action<TEvent> then)
{
var evt = _eventPublisherFake.Events.OfType<TEvent>().First();
then(evt);
}

public void ThenHasOnly(IDomainEvent domainEvent)
{
Check.That(_eventPublisherFake.Events).ContainsExactly(domainEvent);
}
}
}
}
}
34 changes: 34 additions & 0 deletions Mixter.Domain.Tests/Core/Subscriptions/SubscriptionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mixter.Domain.Core.Messages;
using Mixter.Domain.Core.Subscriptions;
using Mixter.Domain.Core.Subscriptions.Events;
using Mixter.Domain.Identity;
using Mixter.Infrastructure.Tests;
using NFluent;

namespace Mixter.Domain.Tests.Core.Subscriptions
{
[TestClass]
public class SubscriptionTest
{
private static readonly UserId Follower = new UserId("emilien@mixit.fr");
private static readonly UserId Followee = new UserId("florent@mixit.fr");
private static readonly SubscriptionId SubscriptionId = new SubscriptionId(Follower, Followee);

private EventPublisherFake _eventPublisher;

[TestInitialize]
public void Initialize()
{
_eventPublisher = new EventPublisherFake();
}

[TestMethod]
public void WhenFollowThenUserFollowedIsRaised()
{
Subscription.FollowUser(_eventPublisher, Follower, Followee);

Check.That(_eventPublisher.Events).Contains(new UserFollowed(SubscriptionId));
}
}
}
22 changes: 22 additions & 0 deletions Mixter.Domain/Core/Messages/Handlers/UpdateTimeline.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Mixter.Domain.Core.Messages.Events;

namespace Mixter.Domain.Core.Messages.Handlers
{
public class UpdateTimeline : IEventHandler<MessagePublished>, IEventHandler<ReplyMessagePublished>
{
private readonly ITimelineMessagesRepository _timelineMessagesRepository;

public UpdateTimeline(ITimelineMessagesRepository timelineMessagesRepository)
{
_timelineMessagesRepository = timelineMessagesRepository;
}

public void Handle(MessagePublished evt)
{
}

public void Handle(ReplyMessagePublished evt)
{
}
}
}
9 changes: 3 additions & 6 deletions Mixter.Domain/Core/Messages/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static Message Publish(IEventPublisher eventPublisher, UserId author, str

public void Republish(IEventPublisher eventPublisher, UserId republisher)
{
if (!_projection.Publishers.Contains(republisher) && !_projection.IsDeleted)
if (!_projection.Publishers.Contains(republisher))
{
var evt = new MessageRepublished(GetId(), republisher);
PublishEvent(eventPublisher, evt);
Expand All @@ -45,11 +45,8 @@ private void PublishEvent<TEvent>(IEventPublisher eventPublisher, TEvent evt) wh

public void Reply(IEventPublisher eventPublisher, UserId replier, string replyContent)
{
if (!_projection.IsDeleted)
{
var evt = new ReplyMessagePublished(MessageId.Generate(), replier, replyContent, _projection.Id);
eventPublisher.Publish(evt);
}
var evt = new ReplyMessagePublished(MessageId.Generate(), replier, replyContent, _projection.Id);
eventPublisher.Publish(evt);
}

public void Delete(IEventPublisher eventPublisher, UserId deleter)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Mixter.Domain.Core.Messages;

namespace Mixter.Domain.Core.Subscriptions.Events
{
public struct FolloweeMessagePublished : IDomainEvent
{
public SubscriptionId SubscriptionId { get; private set; }

public MessageId MessageId { get; private set; }

public FolloweeMessagePublished(SubscriptionId subscriptionId, MessageId messageId)
: this()
{
SubscriptionId = subscriptionId;
MessageId = messageId;
}

public object GetAggregateId()
{
return SubscriptionId;
}
}
}
18 changes: 18 additions & 0 deletions Mixter.Domain/Core/Subscriptions/Events/UserFollowed.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Mixter.Domain.Core.Subscriptions.Events
{
public struct UserFollowed : IDomainEvent
{
public SubscriptionId SubscriptionId { get; private set; }

public UserFollowed(SubscriptionId subscriptionId)
: this()
{
SubscriptionId = subscriptionId;
}

public object GetAggregateId()
{
return SubscriptionId;
}
}
}
Loading