Files
Wino-Mail/Wino.Mail.ViewModels.Tests/Data/MailItemViewModelUpdateTests.cs
T

174 lines
5.3 KiB
C#

using FluentAssertions;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Mail.ViewModels.Collections;
using Wino.Mail.ViewModels.Data;
using Xunit;
namespace Wino.Mail.ViewModels.Tests.Data;
public class MailItemViewModelUpdateTests
{
[Fact]
public void UpdateFrom_ShouldNotifyOnlyReadState_WhenSameInstanceAndHintProvided()
{
var mailCopy = CreateMailCopy("thread-1", DateTime.UtcNow);
var sut = new MailItemViewModel(mailCopy);
var raisedProperties = new List<string>();
sut.PropertyChanged += (_, e) =>
{
if (!string.IsNullOrEmpty(e.PropertyName))
{
raisedProperties.Add(e.PropertyName);
}
};
mailCopy.IsRead = true;
sut.UpdateFrom(mailCopy, MailCopyChangeFlags.IsRead);
raisedProperties.Should().Equal(nameof(MailItemViewModel.IsRead));
}
[Fact]
public void UpdateFrom_ShouldNotifyAddressAndDependentSenderFields_WhenFromAddressChanges()
{
var original = CreateMailCopy("thread-1", DateTime.UtcNow);
original.FromName = string.Empty;
var updated = CloneMailCopy(original);
updated.FromAddress = "updated@wino.dev";
var sut = new MailItemViewModel(original);
var raisedProperties = new List<string>();
sut.PropertyChanged += (_, e) =>
{
if (!string.IsNullOrEmpty(e.PropertyName))
{
raisedProperties.Add(e.PropertyName);
}
};
sut.UpdateFrom(updated);
raisedProperties.Should().Equal(
nameof(MailItemViewModel.FromAddress),
nameof(MailItemViewModel.FromName),
nameof(MailItemViewModel.SortingName));
}
[Fact]
public async Task UpdateMailCopy_ShouldNotifyThreadOnlyForReadState_WhenReadStateChanges()
{
var collection = new WinoMailCollection
{
CoreDispatcher = new ImmediateDispatcher()
};
var older = CreateMailCopy("thread-1", DateTime.UtcNow.AddMinutes(-5));
var latest = CreateMailCopy("thread-1", DateTime.UtcNow);
await collection.AddAsync(older);
await collection.AddAsync(latest);
ThreadMailItemViewModel? threadItem = null;
foreach (var group in collection.MailItems)
{
foreach (var item in group)
{
if (item is ThreadMailItemViewModel thread)
{
threadItem = thread;
break;
}
}
if (threadItem != null)
break;
}
threadItem.Should().NotBeNull();
var raisedProperties = new List<string>();
threadItem!.PropertyChanged += (_, e) =>
{
if (!string.IsNullOrEmpty(e.PropertyName))
{
raisedProperties.Add(e.PropertyName);
}
};
latest.IsRead = true;
await collection.UpdateMailCopy(latest, MailUpdateSource.ClientUpdated, MailCopyChangeFlags.IsRead);
raisedProperties.Should().Equal(nameof(ThreadMailItemViewModel.IsRead));
}
private static MailCopy CreateMailCopy(string threadId, DateTime creationDate)
=> new()
{
UniqueId = Guid.NewGuid(),
Id = Guid.NewGuid().ToString("N"),
FolderId = Guid.NewGuid(),
ThreadId = threadId,
MessageId = $"message-{Guid.NewGuid():N}",
References = string.Empty,
InReplyTo = string.Empty,
FromName = "Sender",
FromAddress = "sender@wino.dev",
Subject = "Subject",
PreviewText = "Preview",
CreationDate = creationDate,
Importance = MailImportance.Normal,
IsRead = false,
IsFlagged = false,
IsFocused = false,
HasAttachments = false,
ItemType = MailItemType.Mail,
DraftId = string.Empty,
IsDraft = false,
FileId = Guid.NewGuid()
};
private static MailCopy CloneMailCopy(MailCopy source)
=> new()
{
UniqueId = source.UniqueId,
Id = source.Id,
FolderId = source.FolderId,
ThreadId = source.ThreadId,
MessageId = source.MessageId,
References = source.References,
InReplyTo = source.InReplyTo,
FromName = source.FromName,
FromAddress = source.FromAddress,
Subject = source.Subject,
PreviewText = source.PreviewText,
CreationDate = source.CreationDate,
Importance = source.Importance,
IsRead = source.IsRead,
IsFlagged = source.IsFlagged,
IsFocused = source.IsFocused,
HasAttachments = source.HasAttachments,
ItemType = source.ItemType,
DraftId = source.DraftId,
IsDraft = source.IsDraft,
FileId = source.FileId,
SenderContact = source.SenderContact,
AssignedAccount = source.AssignedAccount,
AssignedFolder = source.AssignedFolder
};
private sealed class ImmediateDispatcher : IDispatcher
{
public Task ExecuteOnUIThread(Action action)
{
action();
return Task.CompletedTask;
}
}
}