Initial commit

This commit is contained in:
zavolo
2026-06-05 00:53:35 +03:00
commit e59e4424a4
7686 changed files with 352420 additions and 0 deletions
@@ -0,0 +1,238 @@
using Shouldly;
namespace MyTelegram.Domain.Tests.UnitTests.Aggregates.AppCode;
public class AppCodeAggregateTests : TestsFor<AppCodeAggregate>
{
private readonly string _inValidPhoneCodeHash = "2";
private readonly int _maxFailedCount = 5;
private readonly string _phoneNumber = "0";
private readonly string _validPhoneCodeHash = "1";
public AppCodeAggregateTests()
{
Fixture.Customize<AppCodeId>(c => c.FromFactory(() => AppCodeId.Create(_phoneNumber, _validPhoneCodeHash)));
}
[Fact]
public void Cancel_AppCode_Success()
{
CreateAppCodeAggregate();
Sut.CancelCode(A<RequestInfo>(), _phoneNumber, _validPhoneCodeHash);
Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<AppCodeCanceledEvent>();
}
//[Fact]
//public void CheckSignInCode_Exceeded_Max_Failed_Count_Throws_Exception()
//{
// CreateAppCodeAggregate();
// var aggregateEvent = new CheckSignInCodeCompletedEvent(A<RequestInfo>(), false, 1);
// var aggregateEvents = Enumerable.Repeat(aggregateEvent, _maxFailedCount + 1);
// var domainEvents = aggregateEvents.Select((p,
// index) => ADomainEvent<AppCodeAggregate, AppCodeId, CheckSignInCodeCompletedEvent>(p, Sut.Version + index + 1))
// .ToList();
// Sut.ApplyEvents(domainEvents);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignInCode(A<RequestInfo>(), _validPhoneCodeHash, A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.PhoneCodeInvalid.Message);
//}
//[Fact]
//public void CheckSignInCode_With_Canceled_Code_Throws_Exception()
//{
// CreateAppCodeAggregate();
// var domainEvent = ADomainEvent<AppCodeAggregate, AppCodeId, AppCodeCanceledEvent>(Sut.Version + 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignInCode(A<RequestInfo>(), _validPhoneCodeHash, A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.PhoneCodeExpired.Message);
//}
[Fact]
public void CheckSignInCode_With_Correct_PhoneCode()
{
CreateAppCodeAggregate();
Sut.CheckSignInCode(A<RequestInfo>(), _validPhoneCodeHash, A<long>());
Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckSignInCodeCompletedEvent>();
}
//[Fact]
//public void CheckSignInCode_With_Empty_PhoneCode_Throws_Exception()
//{
// CreateAppCodeAggregate(expireMinutes: -5);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignInCode(A<RequestInfo>(), string.Empty, A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.PhoneCodeEmpty.Message);
//}
//[Fact]
//public void CheckSignInCode_With_Expire_PhoneCode_Throws_Exception()
//{
// CreateAppCodeAggregate(expireMinutes: -5);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignInCode(A<RequestInfo>(), _validPhoneCodeHash, A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.PhoneCodeExpired.Message);
//}
[Fact]
public void CheckSignInCode_With_Invalid_PhoneCode()
{
CreateAppCodeAggregate();
Sut.CheckSignInCode(A<RequestInfo>(), _inValidPhoneCodeHash, A<long>());
var checkSignUpCodeCompletedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckSignInCodeCompletedEvent>();
checkSignUpCodeCompletedEvent.IsCodeValid.ShouldBeFalse();
}
//[Fact]
//public void CheckSignUpCode_Exceeded_Max_Failed_Count_Throws_Exception()
//{
// CreateAppCodeAggregate();
// var aggregateEvent = new CheckSignUpCodeCompletedEvent(A<RequestInfo>(), false, 1, 0, "0", "0", null, Guid.Empty);
// var aggregateEvents = Enumerable.Repeat(aggregateEvent, _maxFailedCount + 1);
// var domainEvents = aggregateEvents.Select((p,
// index) => ADomainEvent<AppCodeAggregate, AppCodeId, CheckSignUpCodeCompletedEvent>(p, Sut.Version + index + 1))
// .ToList();
// Sut.ApplyEvents(domainEvents);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignUpCode(A<RequestInfo>(),
// 0,
// _validPhoneCodeHash,
// 0,
// _phoneNumber,
// "0",
// null,
// Guid.Empty));
// exception.Message.ShouldBe(RpcErrorMessages.PhoneCodeInvalid);
//}
//[Fact]
//public void CheckSignUpCode_With_Canceled_Code_Throws_Exception()
//{
// CreateAppCodeAggregate();
// var domainEvent = ADomainEvent<AppCodeAggregate, AppCodeId, AppCodeCanceledEvent>(Sut.Version + 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignUpCode(A<RequestInfo>(),
// 0,
// _validPhoneCodeHash,
// 0,
// _phoneNumber,
// "0",
// null,
// Guid.Empty));
// exception.Message.ShouldBe(RpcErrorMessages.PhoneCodeExpired);
//}
[Fact]
public void CheckSignUpCode_With_Correct_PhoneCode_For_New_User()
{
CreateAppCodeAggregate();
Sut.CheckSignUpCode(
A<RequestInfo>(),
0, _validPhoneCodeHash, 0, _phoneNumber, "0", null);
//Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<SignUpRequiredEvent>();
var uncommittedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckSignUpCodeCompletedEvent>();
uncommittedEvent.IsCodeValid.ShouldBeTrue();
}
[Fact]
public void CheckSignUpCode_With_Correct_PhoneCode_For_Old_User()
{
var oldUid = 1;
CreateAppCodeAggregate(oldUid);
Sut.CheckSignUpCode(A<RequestInfo>(), oldUid, _validPhoneCodeHash, 0, _phoneNumber, "0", null);
var checkSignUpCodeCompletedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckSignUpCodeCompletedEvent>();
checkSignUpCodeCompletedEvent.IsCodeValid.ShouldBeTrue();
checkSignUpCodeCompletedEvent.UserId.ShouldBe(oldUid);
checkSignUpCodeCompletedEvent.PhoneNumber.ShouldBe(_phoneNumber);
}
//[Fact]
//public void CheckSignUpCode_With_Empty_PhoneCode_Throws_Exception()
//{
// CreateAppCodeAggregate(expireMinutes: -5);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignUpCode(A<RequestInfo>(),
// 0,
// string.Empty,
// 0,
// _phoneNumber,
// "0",
// null,
// Guid.Empty));
// exception.Message.ShouldBe(RpcErrorMessages.PhoneCodeEmpty);
//}
//[Fact]
//public void CheckSignUpCode_With_Expire_PhoneCode_Throws_Exception()
//{
// CreateAppCodeAggregate(expireMinutes: -5);
// var exception = Assert.Throws<UserFriendlyException>(() => Sut.CheckSignUpCode(A<RequestInfo>(),
// 0,
// _validPhoneCodeHash,
// 0,
// _phoneNumber,
// "0",
// null,
// Guid.Empty));
// exception.Message.ShouldBe(RpcErrorMessages.PhoneCodeExpired);
//}
//[Fact]
//public void CheckSignUpCode_With_Invalid_PhoneCode()
//{
// CreateAppCodeAggregate();
// Sut.CheckSignUpCode(A<RequestInfo>(), 0, _inValidPhoneCodeHash, 0, _phoneNumber, "0", null, Guid.Empty);
// var checkSignUpCodeCompletedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckSignUpCodeCompletedEvent>();
// checkSignUpCodeCompletedEvent.IsCodeValid.ShouldBeFalse();
//}
//[Fact]
//public void CreateAppCode_Success()
//{
// Sut.Create(A<RequestInfo>(), A<long>(), A<string>(), A<string>(), A<int>(), A<string>(), A<long>());
// Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<AppCodeCreatedEvent>();
//}
private void CreateAppCodeAggregate(long uid = 0, int expireMinutes = 5)
{
var aggregateId = A<AppCodeId>();
var appCodeCreatedEvent = new AppCodeCreatedEvent(A<RequestInfo>(),
uid,
_phoneNumber,
"0",
DateTime.UtcNow.AddMinutes(expireMinutes).ToTimestamp(),
_validPhoneCodeHash,
0);
Sut.ApplyEvents(new IDomainEvent[]
{
new DomainEvent<AppCodeAggregate, AppCodeId, AppCodeCreatedEvent>(appCodeCreatedEvent,
Metadata.Empty,
DateTimeOffset.UtcNow,
aggregateId,
1)
});
}
}
@@ -0,0 +1,235 @@
using MyTelegram.Schema;
namespace MyTelegram.Domain.Tests.UnitTests.Aggregates.Channel;
public class ChannelAggregateTests : TestsFor<ChannelAggregate>
{
public ChannelAggregateTests()
{
Fixture.Customize<ChannelId>(x => x.FromFactory(() => ChannelId.Create(MyTelegramConsts.ChannelInitId + 1)));
}
[Fact]
public void EditAbout_For_Not_Exists_Channel_Throws_Exception()
{
Assert.Throws<DomainError>(() => Sut.EditAbout(A<RequestInfo>(), 1, "test"));
}
[Fact]
public void EditAbout_Success_Test()
{
var about = "test about";
var aggregateEvent = A<ChannelCreatedEvent>();
var channelCreatedEvent = ADomainEvent<ChannelAggregate, ChannelId, ChannelCreatedEvent>(aggregateEvent, 1);
Sut.ApplyEvents(new IDomainEvent[] { channelCreatedEvent });
var requestInfo = A<RequestInfo>() with { UserId = aggregateEvent.CreatorId };
Sut.EditAbout(requestInfo, aggregateEvent.CreatorId, about);
var uncommittedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<ChannelAboutEditedEvent>();
uncommittedEvent.About.ShouldBe(about);
}
[Fact]
public void EditAbout_With_Text_Length_GreaterThan_ChatAbout_Max_Length_Throws_Exception()
{
var longAbout = string.Join("", Enumerable.Repeat("a", MyTelegramConsts.ChatAboutMaxLength + 1));
var aggregateEvent = A<ChannelCreatedEvent>();
var channelCreatedEvent = ADomainEvent<ChannelAggregate, ChannelId, ChannelCreatedEvent>(aggregateEvent, 1);
Sut.ApplyEvents(new IDomainEvent[] { channelCreatedEvent });
var requestInfo = A<RequestInfo>() with { UserId = aggregateEvent.CreatorId };
var exception = Assert.Throws<RpcException>(() => Sut.EditAbout(requestInfo, aggregateEvent.CreatorId, longAbout));
exception.Message.ShouldBe(RpcErrors.RpcErrors400.ChatAboutTooLong.Message);
}
[Fact]
public void Non_Admin_EditAbout_Throws_Exception()
{
var about = "test about";
var aggregateEvent = A<ChannelCreatedEvent>();
var channelCreatedEvent = ADomainEvent<ChannelAggregate, ChannelId, ChannelCreatedEvent>(aggregateEvent, 1);
Sut.ApplyEvents(new IDomainEvent[] { channelCreatedEvent });
var exception = Assert.Throws<RpcException>(() => Sut.EditAbout(A<RequestInfo>(), aggregateEvent.CreatorId + 1, about));
exception.Message.ShouldBe(RpcErrors.RpcErrors400.ChatAdminRequired.Message);
}
[Fact]
public void CheckChannelState_For_Not_Exists_Channel_Throws_Exception()
{
Assert.Throws<DomainError>(() => Sut.CheckChannelState(A<RequestInfo>(),
1,
1,
0,
MessageSubType.Normal));
}
[Fact]
public void CheckChannelState_For_Broadcast_Channel_With_Non_Creator_Throws_Exception()
{
//var aggregateEvent = A<ChannelCreatedEvent>();
//var domainEvent = ADomainEvent<ChannelAggregate, ChannelId, ChannelCreatedEvent>(aggregateEvent, 1);
//Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
var creatorId = 1;
var senderPeerId = 2;
Sut.Create(A<RequestInfo>(),
1,
creatorId,
true,
false,
"test",
null,
null,
null,
0,
1,
1,
new TMessageActionChatCreate
{
Title = "test",
Users = []
},
0,
false,
null,
null,
null,
false,
false, [], []);
var exception = Assert.Throws<RpcException>(() =>
Sut.CheckChannelState(A<RequestInfo>(), senderPeerId,
1,
1,
MessageSubType.Normal));
exception.RpcError.ShouldBe(RpcErrors.RpcErrors403.ChatWriteForbidden);
}
[Fact]
public void CheckChannelState_For_Banned_SendMessage_Rights_MegaGroup_Throws_Exception()
{
var creatorId = 1;
var senderPeerId = 2;
var requestInfo = A<RequestInfo>() with { UserId = creatorId };
Sut.Create(requestInfo,
1,
creatorId,
false,
true,
"test",
null,
null,
null,
1,
1,
1,
new TMessageActionChatCreate
{
Title = "test",
Users = []
},
0, false, null, null, null,
false, false, [], []);
var bannedWriteMessageRights = new ChatBannedRights(false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true, true, true, true, true, true, true, true,
int.MaxValue);
Sut.EditChatDefaultBannedRights(requestInfo, bannedWriteMessageRights, creatorId);
var exception = Assert.Throws<RpcException>(() =>
Sut.CheckChannelState(A<RequestInfo>(), senderPeerId,
1,
1,
MessageSubType.Normal));
exception.RpcError.ShouldBe(RpcErrors.RpcErrors403.ChatWriteForbidden);
}
[Fact]
public void CheckChannelState_For_Enabled_Slow_Mode_Test()
{
var creatorId = 1;
var senderPeerId = 2;
Sut.Create(A<RequestInfo>(),
1,
creatorId,
false,
true,
"test",
null,
null,
null,
1,
1,
1,
new TMessageActionChatCreate
{
Title = "test",
Users = []
},
0,
false, null, null, null,
false, false, [], []);
Sut.ToggleSlowMode(A<RequestInfo>(), 60, 1);
var checkStateCompletedEvent = new CheckChannelStateCompletedEvent(
A<RequestInfo>(),
senderPeerId,
1,
DateTime.UtcNow.ToTimestamp(),
false,
null,
new List<long>(),
null);
var domainEvent = ADomainEvent<ChannelAggregate, ChannelId, CheckChannelStateCompletedEvent>(checkStateCompletedEvent, 3);
Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
var exception = Assert.Throws<RpcException>(() => Sut.CheckChannelState(A<RequestInfo>(), senderPeerId, 2, DateTime.UtcNow.ToTimestamp(), MessageSubType.Normal));
exception.RpcError.Message.ShouldStartWith("SLOWMODE_WAIT_");
}
[Fact]
public void CheckChannelState_Test()
{
var creatorId = 1;
var senderPeerId = 2;
var aggregateEvent = new ChannelCreatedEvent(A<RequestInfo>(),
1,
creatorId,
"test",
false,
true,
null,
null,
null,
1,
1,
1,
new TMessageActionChatCreate
{
Title = "test",
Users = []
},
0, false, null, null, null,
false, false, [], []);
Sut.ApplyEvents([ADomainEvent<ChannelAggregate, ChannelId, ChannelCreatedEvent>(aggregateEvent, 1)]);
Sut.CheckChannelState(A<RequestInfo>(), senderPeerId, 1, DateTime.UtcNow.ToTimestamp(), MessageSubType.Normal);
Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<CheckChannelStateCompletedEvent>();
}
}
@@ -0,0 +1,122 @@
//namespace MyTelegram.Domain.Tests.UnitTests.Aggregates.Chat;
//public class ChatAggregateTests : TestsFor<ChatAggregate>
//{
// public ChatAggregateTests()
// {
// Fixture.Customize<ChatId>(x => x.FromFactory(() => ChatId.Create(MyTelegramConsts.ChatIdInitId + 1)));
// }
// [Fact]
// public void CreateChat_With_TooMany_Members_Throws_Exception()
// {
// var members = Enumerable.Range(1, MyTelegramConsts.ChatMemberMaxCount + 1).Select(p => (long)p).ToList();
// var creatorId = MyTelegramConsts.ChatMemberMaxCount + 1;
// var exception = Assert.Throws<RpcException>(() => Sut.Create(A<RequestInfo>(),
// A<long>(),
// creatorId,
// A<string>(),
// members,
// A<int>(),
// A<long>(),
// A<string>(), 0));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.UsersTooMuch.Message);
// }
// [Fact]
// public void AddChatUser_Success()
// {
// var aggregateEvent = A<ChatCreatedEvent>();
// var domainEvent = ADomainEvent<ChatAggregate, ChatId, ChatCreatedEvent>(aggregateEvent, 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var inviterId = aggregateEvent.CreatorUid;
// var userId = A<long>();
// Sut.AddChatUser(A<RequestInfo>() with { UserId = inviterId },
// inviterId,
// userId,
// A<int>(),
// A<string>(),
// A<long>());
// var uncommittedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<ChatMemberAddedEvent>();
// uncommittedEvent.ChatMember.UserId.ShouldBe(userId);
// }
// [Fact]
// public void Non_Admin_AddChatUser_Throws_Exception()
// {
// var aggregateEvent = A<ChatCreatedEvent>();
// var domainEvent = ADomainEvent<ChatAggregate, ChatId, ChatCreatedEvent>(aggregateEvent, 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var inviterId = aggregateEvent.CreatorUid + 1;
// var requestInfo = A<RequestInfo>() with { UserId = inviterId };
// var exception = Assert.Throws<RpcException>(() => Sut.AddChatUser(requestInfo,
// inviterId,
// A<int>(),
// A<int>(),
// A<string>(),
// A<long>()));
// exception.RpcError.ShouldBe(RpcErrors.RpcErrors400.ChatAdminRequired);
// }
// [Fact]
// public void AddChatUser_Exceeded_Max_Count_Throws_Exception()
// {
// var aggregateEvent = A<ChatCreatedEvent>();
// var domainEvent = ADomainEvent<ChatAggregate, ChatId, ChatCreatedEvent>(aggregateEvent, 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var inviterId = aggregateEvent.CreatorUid;
// var requestInfo = A<RequestInfo>() with { UserId = aggregateEvent.CreatorUid };
// var members = Enumerable.Range((int)inviterId + 1, MyTelegramConsts.ChatMemberMaxCount);
// var aggregateEvents = members.Select(p => new ChatMemberAddedEvent(
// requestInfo,
// aggregateEvent.ChatId,
// new ChatMember(p, aggregateEvent.CreatorUid, A<int>()),
// A<string>(),
// A<long>(), new List<long>()));
// var domainEvents = aggregateEvents.Select((p,
// index) => ADomainEvent<ChatAggregate, ChatId, ChatMemberAddedEvent>(p, Sut.Version + index + 1)).ToList();
// Sut.ApplyEvents(domainEvents);
// var exception = Assert.Throws<RpcException>(() => Sut.AddChatUser(requestInfo,
// inviterId,
// A<int>(),
// A<int>(),
// A<string>(),
// A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.UsersTooMuch.Message);
// }
// [Fact]
// public void AddChatUser_For_Exists_Member_Throws_Exception()
// {
// var aggregateEvent = A<ChatCreatedEvent>();
// var domainEvent = ADomainEvent<ChatAggregate, ChatId, ChatCreatedEvent>(aggregateEvent, 1);
// Sut.ApplyEvents(new IDomainEvent[] { domainEvent });
// var memberAddedAggregateEvent = new ChatMemberAddedEvent(A<RequestInfo>(),
// aggregateEvent.ChatId,
// new ChatMember(A<long>(),
// aggregateEvent.CreatorUid,
// A<int>()),
// A<string>(),
// A<long>(), Many<long>());
// var memberAddedDomainEvent =
// ADomainEvent<ChatAggregate, ChatId, ChatMemberAddedEvent>(memberAddedAggregateEvent, Sut.Version + 1);
// Sut.ApplyEvents(new IDomainEvent[] { memberAddedDomainEvent });
// var requestInfo = A<RequestInfo>() with { UserId = aggregateEvent.CreatorUid };
// var exception = Assert.Throws<RpcException>(() => Sut.AddChatUser(requestInfo,
// aggregateEvent.CreatorUid,
// memberAddedAggregateEvent.ChatMember.UserId,
// A<int>(),
// A<string>(),
// A<long>()));
// exception.Message.ShouldBe(RpcErrors.RpcErrors400.UserAlreadyParticipant.Message);
// }
//}
@@ -0,0 +1,103 @@
using Shouldly;
namespace MyTelegram.Domain.Tests.UnitTests.Aggregates.Messaging;
public class MessageAggregateTests : TestsFor<MessageAggregate>
{
private int _messageId = 1;
public MessageAggregateTests()
{
Fixture.Customize<MessageId>(c => c.FromFactory(() => MessageId.Create(1, 1)));
}
[Fact]
public void Edit_Message_Success()
{
var messageId = 1;
var newMessage = "new message";
CreateMessage(DateTime.UtcNow.ToTimestamp());
Sut.EditOutboxMessage(A<RequestInfo>(),
messageId,
newMessage,
DateTime.UtcNow.ToTimestamp(),
null,
null,
null,
false,
null
);
var uncommittedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<OutboxMessageEditedEvent>();
uncommittedEvent.NewMessage.ShouldBe(newMessage);
}
[Fact]
public void Edit_Out_Of_Date_Message_Throws_Exception()
{
var newMessage = "new message";
var creationTime = DateTime.UtcNow.ToTimestamp() - MyTelegramConsts.EditTimeLimit - 1000;
CreateMessage(creationTime);
var exception = Assert.Throws<RpcException>(() =>
Sut.EditOutboxMessage(A<RequestInfo>(),
_messageId,
newMessage,
DateTime.UtcNow.ToTimestamp(),
null,
null,
null,
false,
null
));
exception.Message.ShouldBe(RpcErrors.RpcErrors400.MessageEditTimeExpired.Message);
}
[Fact(DisplayName = "Only message author can edit message")]
public void Edit_Inbox_Message_Throws_Exception()
{
var newMessage = "new message";
CreateMessage(DateTime.UtcNow.ToTimestamp(), false);
var exception = Assert.Throws<RpcException>(() =>
Sut.EditOutboxMessage(A<RequestInfo>(),
_messageId,
newMessage,
DateTime.UtcNow.ToTimestamp(),
null,
null,
null,
false, null));
exception.Message.ShouldBe(RpcErrors.RpcErrors403.MessageAuthorRequired.Message);
}
private MessageItem CreateMessage(int creationDate, bool isOut = true)
{
var ownerPeerId = 1;
var toPeerUserId = A<long>();
//var aggregateId = MessageId.Create(ownerPeerId, _messageId);
var messageItem = new MessageItem(
new Peer(PeerType.User, ownerPeerId),
new Peer(PeerType.User, toPeerUserId),
new Peer(PeerType.User, ownerPeerId),
ownerPeerId,
_messageId,
"test message",
creationDate,
1,
isOut
);
var outboxMessageCreatedEvent = new OutboxMessageCreatedEvent(A<RequestInfo>(),
messageItem,
null, null,
true,
1,
null, null);
Sut.ApplyEvents([ADomainEvent<MessageAggregate, MessageId, OutboxMessageCreatedEvent>(outboxMessageCreatedEvent, 1)
]);
return messageItem;
}
}
@@ -0,0 +1,55 @@
namespace MyTelegram.Domain.Tests.UnitTests.Aggregates.User;
public class UserAggregateTests : TestsFor<UserAggregate>
{
public UserAggregateTests()
{
Fixture.Customize<UserId>(c => c.FromFactory(() => UserId.Create(1)));
}
[Fact]
public void Create_User_With_Exists_PhoneNumber_Throws_Exception()
{
var aggregateEvent = A<UserCreatedEvent>();
var domainEvent = ADomainEvent<UserAggregate, UserId, UserCreatedEvent>(aggregateEvent, 1);
Sut.ApplyEvents(new[] { domainEvent });
Assert.Throws<DomainError>(() => Sut.Create(A<RequestInfo>(),
1,
0,
aggregateEvent.PhoneNumber,
"0"));
}
[Fact]
public void Create_New_User_Success()
{
var phoneNumber = "0";
var firstName = "0";
var userId = 1;
var accessHash = 1;
Sut.Create(A<RequestInfo>(), userId, accessHash, phoneNumber, firstName);
Sut.Version.ShouldBe(1);
Sut.UncommittedEvents.Count().ShouldBe(1);
var uncommittedEvent = Sut.UncommittedEvents.Single();
var userCreatedEvent = uncommittedEvent.AggregateEvent.ShouldBeOfType<UserCreatedEvent>();
userCreatedEvent.PhoneNumber.ShouldBe(phoneNumber);
userCreatedEvent.UserId.ShouldBe(userId);
userCreatedEvent.FirstName.ShouldBe(firstName);
userCreatedEvent.AccessHash.ShouldBe(accessHash);
userCreatedEvent.Bot.ShouldBeFalse();
}
[Fact]
public void Create_User_With_Empty_FirstName_Throws_Exception()
{
Assert.Throws<DomainError>(() => Sut.Create(A<RequestInfo>(),
1,
0,
"0",
string.Empty));
}
}
@@ -0,0 +1,85 @@
//namespace MyTelegram.Domain.Tests.UnitTests.Sagas;
//public class MessageSagaTests : TestsFor<MessageSaga>
//{
// //private Mock<ICommandBus> _commandBus;
// private readonly Mock<ISagaContext> _sagaContext;
// private readonly int _messageId = 1;
// public MessageSagaTests()
// {
// Fixture.Customize<MessageSagaId>(c => c.FromFactory(() => new MessageSagaId($"messagesaga-{Guid.Empty}")));
// //_commandBus = InjectMock<ICommandBus>();
// _sagaContext = InjectMock<ISagaContext>();
// }
// [Theory]
// [MemberData(nameof(GetSendMessageData))]
// public async Task SendMessage_Started_Test(Peer fromPeer, Peer toPeer)
// {
// var aggregateId = MessageId.Create(fromPeer.PeerId, _messageId);
// var messageItem = new MessageItem(
// fromPeer,
// toPeer,
// fromPeer,
// _messageId,
// "test message",
// A<int>(),
// A<long>(),
// true);
// var aggregateEvent = new SendMessageStartedEvent(A<RequestInfo>(),
// messageItem,
// true,
// 1,
// false,
// Guid.NewGuid()
// );
// var domainEvent = ADomainEvent<MessageAggregate, MessageId, SendMessageStartedEvent>(aggregateEvent, aggregateId, 1);
// await Sut.HandleAsync(domainEvent, _sagaContext.Object, CancellationToken.None);
// var uncommittedEvent = Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<MessageSagaStartedEvent>();
// uncommittedEvent.MessageItem.ToPeer.ShouldBe(toPeer);
// }
// //[Fact]
// //public async Task SendMessage_To_User_Peer_Started_Test()
// //{
// // var fromPeer = new Peer(PeerType.User, 1);
// // var toPeer = new Peer(PeerType.User, 2);
// // var aggregateId = MessageId.Create(fromPeer.PeerId, _messageId);
// // var messageItem = new MessageItem(aggregateId,
// // fromPeer,
// // toPeer,
// // fromPeer,
// // _messageId,
// // "test message",
// // A<int>(),
// // A<long>(),
// // true);
// // var aggregateEvent = new SendMessageStartedEvent(A<RequestInfo>(),
// // messageItem,
// // true,
// // 1,
// // Guid.NewGuid()
// // );
// // var domainEvent = ADomainEvent<MessageAggregate, MessageId, SendMessageStartedEvent>(aggregateEvent, aggregateId, 1);
// // _commandBus.Setup(c => c.PublishAsync(It.IsAny<ICommand<UserAggregate, UserId, IExecutionResult>>(),
// // It.IsAny<CancellationToken>())).Returns(() => Task.FromResult(ExecutionResult.Success()));
// // await Sut.HandleAsync(domainEvent, _sagaContext.Object, CancellationToken.None);
// // await Sut.PublishAsync(_commandBus.Object, CancellationToken.None);
// // Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<MessageSagaStartedEvent>();
// // _commandBus.Verify(c => c.PublishAsync(It.IsAny<ICommand<UserAggregate, UserId, IExecutionResult>>(),
// // It.IsAny<CancellationToken>()), Times.Once);
// //}
// public static IEnumerable<object[]> GetSendMessageData()
// {
// yield return new object[] { new Peer(PeerType.User, 1), new Peer(PeerType.User, 2) };
// yield return new object[] { new Peer(PeerType.User, 1), new Peer(PeerType.Chat, 2) };
// yield return new object[] { new Peer(PeerType.User, 1), new Peer(PeerType.Channel, 2) };
// }
//}
@@ -0,0 +1,41 @@
using MyTelegram.Domain.Sagas.Events;
namespace MyTelegram.Domain.Tests.UnitTests.Sagas;
public class UserSignInSagaTests : TestsFor<SignInSaga>
{
private readonly Mock<ISagaContext> _sagaContext;
public UserSignInSagaTests()
{
Fixture.Customize<AppCodeId>(c => c.FromFactory(() => AppCodeId.Create("0", "0")));
Fixture.Customize<SignInSagaId>(c => c.FromFactory(() => new SignInSagaId($"signinsagaid-{Guid.Empty}")));
_sagaContext = InjectMock<ISagaContext>();
//var idGenerator = InjectMock<IIdGenerator>();
//IdGeneratorFactory.SetDefaultIdGenerator(idGenerator.Object);
}
[Fact]
public async Task SignIn_With_Invalid_PhoneCode_Throws_Exception()
{
var aggregateEvent = new CheckSignInCodeCompletedEvent(A<RequestInfo>(), false, 1);
var domainEvent =
ADomainEvent<AppCodeAggregate, AppCodeId, CheckSignInCodeCompletedEvent>(aggregateEvent, A<AppCodeId>(), 1);
var exception = await Assert.ThrowsAsync<RpcException>(async () => await Sut.HandleAsync(domainEvent, _sagaContext.Object, CancellationToken.None).ConfigureAwait(false));
exception.RpcError.ShouldBe(RpcErrors.RpcErrors400.PhoneCodeInvalid);
}
[Fact]
public async Task SignIn_With_Correct_PhoneCode_Success()
{
var aggregateEvent = new CheckSignInCodeCompletedEvent(A<RequestInfo>(), true, 1);
var domainEvent =
ADomainEvent<AppCodeAggregate, AppCodeId, CheckSignInCodeCompletedEvent>(aggregateEvent, A<AppCodeId>(), 1);
await Sut.HandleAsync(domainEvent, _sagaContext.Object, CancellationToken.None).ConfigureAwait(false);
Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<SignInStartedSagaEvent>();
}
}
@@ -0,0 +1,32 @@
using MyTelegram.Domain.Sagas.Events;
namespace MyTelegram.Domain.Tests.UnitTests.Sagas;
public class UserSignUpSagaTests : TestsFor<UserSignUpSaga>
{
private readonly Mock<ISagaContext> _sagaContext;
public UserSignUpSagaTests()
{
Fixture.Customize<AppCodeId>(c => c.FromFactory(() => AppCodeId.Create("0", "0")));
Fixture.Customize<UserSignUpSagaId>(c => c.FromFactory(() => new UserSignUpSagaId($"usersignupsagaid-{Guid.Empty}")));
_sagaContext = InjectMock<ISagaContext>();
//var idGenerator = InjectMock<IIdGenerator>();
//IdGeneratorFactory.SetDefaultIdGenerator(idGenerator.Object);
}
[Fact]
public async Task SignUp_For_New_User_Success()
{
var aggregateEvent = new CheckSignUpCodeCompletedEvent(A<RequestInfo>(), true, 0, 0, "0", "0", null);
var domainEvent = new DomainEvent<AppCodeAggregate, AppCodeId, CheckSignUpCodeCompletedEvent>(aggregateEvent,
Metadata.Empty,
A<DateTimeOffset>(),
A<AppCodeId>(),
1);
await Sut.HandleAsync(domainEvent, _sagaContext.Object, CancellationToken.None).ConfigureAwait(false);
Sut.UncommittedEvents.Single().AggregateEvent.ShouldBeOfType<UserSignUpSuccessSagaEvent>();
}
}
@@ -0,0 +1,19 @@
namespace MyTelegram.Domain.Tests.UnitTests;
public class SimpleInMemoryIdGeneratorTests : TestsFor<SimpleInMemoryIdGenerator>
{
[Theory]
[InlineData(1)]
[InlineData(10)]
[InlineData(100)]
public async Task SequenceId_Should_Increment_By_Step(int step)
{
var id1 = await Sut.NextLongIdAsync(IdType.MessageId, 1, step).ConfigureAwait(false);
var id2 = await Sut.NextLongIdAsync(IdType.MessageId, 1, step).ConfigureAwait(false);
var id3 = await Sut.NextLongIdAsync(IdType.MessageId, 1, step).ConfigureAwait(false);
id1.ShouldBe(step);
id2.ShouldBe(id1 + step);
id3.ShouldBe(id2 + step);
}
}
@@ -0,0 +1,56 @@
using MyTelegram.Domain.Specifications;
namespace MyTelegram.Domain.Tests.UnitTests.Specifications;
public class IsEmailAddressSpecificationTests : TestsFor<IsEmailAddressSpecification>
{
[Theory]
[InlineData("email@example.com", true)]
//[InlineData("firstname.lastname@example.com", true)]
[InlineData("email@subdomain.example.com", true)]
//[InlineData("firstname+lastname@example.com", true)]
[InlineData("email@123.123.123.123", true)]
//[InlineData("email@[123.123.123.123]", true)]
//[InlineData("\"email\"@example.com", true)]
[InlineData("1234567890@example.com", true)]
[InlineData("email@example-one.com", true)]
//[InlineData("_______@example.com", true)]
[InlineData("email@example.name", true)]
[InlineData("email@example.web", true)]
[InlineData("email@example.museum", true)]
[InlineData("email@example.co.jp", true)]
//[InlineData("firstname-lastname@example.com", true)]
//[InlineData("much.”more\\ unusual”@example.com", true)]
//[InlineData("very.unusual.”@”.unusual.com@example.com", true)]
//[InlineData("very.”(),:;<>[]”.VERY.”very@\\ \"very”.unusual@strange.example.com", true)]
[InlineData("#@%^%#$@#$@#.com", false)]
[InlineData("@example.com", false)]
[InlineData("Joe Smith <email@example.com>", false)]
[InlineData("email.example.com", false)]
[InlineData("email@example@example.com", false)]
[InlineData(".email@example.com", false)]
[InlineData("email.@example.com", false)]
[InlineData("email..email@example.com", false)]
[InlineData("あいうえお@example.com", false)]
[InlineData("email@example.com (Joe Smith)", false)]
[InlineData("email@example", false)]
//[InlineData("email@-example.com", false)]
//[InlineData("email@111.222.333.44444", false)]
[InlineData("email@example..com", false)]
[InlineData("Abc..123@example.com", false)]
[InlineData("”(),:;<>[\\]@example.com", false)]
[InlineData("just”not”right@example.com", false)]
[InlineData("this\\ is\\\"really\\\"not\\allowed@example.com", false)]
public void IsEmail_Valid_Test(string email,
bool isValid)
{
// Act
var isSatisfied = Sut.IsSatisfiedBy(email);
// Assert
isSatisfied.ShouldBe(isValid);
}
}