Fixing double root folder creation.
This commit is contained in:
@@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Wino.Core.Domain.Entities.Mail;
|
||||||
|
using Wino.Core.Domain.Entities.Shared;
|
||||||
|
using Wino.Core.Domain.Enums;
|
||||||
|
using Wino.Core.Domain.Interfaces;
|
||||||
|
using Wino.Core.Domain.Models.MailItem;
|
||||||
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
|
using Wino.Core.Requests.Folder;
|
||||||
|
using Wino.Core.Synchronizers;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Wino.Core.Tests.Synchronizers;
|
||||||
|
|
||||||
|
public sealed class WinoSynchronizerMailRequestTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task FoldersOnly_sync_should_not_execute_queued_folder_requests()
|
||||||
|
{
|
||||||
|
var synchronizer = new TestMailSynchronizer();
|
||||||
|
var request = new CreateRootFolderRequest(
|
||||||
|
new MailItemFolder { Id = Guid.NewGuid(), MailAccountId = synchronizer.Account.Id },
|
||||||
|
"test");
|
||||||
|
|
||||||
|
synchronizer.QueueRequest(request);
|
||||||
|
|
||||||
|
var foldersOnlyResult = await synchronizer.SynchronizeMailsAsync(new MailSynchronizationOptions
|
||||||
|
{
|
||||||
|
AccountId = synchronizer.Account.Id,
|
||||||
|
Type = MailSynchronizationType.FoldersOnly
|
||||||
|
});
|
||||||
|
|
||||||
|
foldersOnlyResult.CompletedState.Should().Be(SynchronizationCompletedState.Success);
|
||||||
|
synchronizer.CreateRootFolderInvocationCount.Should().Be(0);
|
||||||
|
synchronizer.ExecuteNativeRequestsInvocationCount.Should().Be(0);
|
||||||
|
|
||||||
|
var executeRequestsResult = await synchronizer.SynchronizeMailsAsync(new MailSynchronizationOptions
|
||||||
|
{
|
||||||
|
AccountId = synchronizer.Account.Id,
|
||||||
|
Type = MailSynchronizationType.ExecuteRequests
|
||||||
|
});
|
||||||
|
|
||||||
|
executeRequestsResult.CompletedState.Should().Be(SynchronizationCompletedState.Success);
|
||||||
|
synchronizer.CreateRootFolderInvocationCount.Should().Be(1);
|
||||||
|
synchronizer.ExecuteNativeRequestsInvocationCount.Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class TestMailSynchronizer
|
||||||
|
: WinoSynchronizer<object, object, object>
|
||||||
|
{
|
||||||
|
public TestMailSynchronizer()
|
||||||
|
: base(new MailAccount { Id = Guid.NewGuid(), Name = "Test account" }, WeakReferenceMessenger.Default)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override uint BatchModificationSize => 1;
|
||||||
|
public override uint InitialMessageDownloadCountPerFolder => 0;
|
||||||
|
public int CreateRootFolderInvocationCount { get; private set; }
|
||||||
|
public int ExecuteNativeRequestsInvocationCount { get; private set; }
|
||||||
|
|
||||||
|
public override List<IRequestBundle<object>> CreateRootFolder(CreateRootFolderRequest request)
|
||||||
|
{
|
||||||
|
CreateRootFolderInvocationCount++;
|
||||||
|
return [new TestRequestBundle(new object(), request)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task ExecuteNativeRequestsAsync(List<IRequestBundle<object>> batchedRequests, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
ExecuteNativeRequestsInvocationCount++;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task<List<NewMailItemPackage>> CreateNewMailPackagesAsync(
|
||||||
|
object message,
|
||||||
|
MailItemFolder assignedFolder,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
=> Task.FromResult(new List<NewMailItemPackage>());
|
||||||
|
|
||||||
|
protected override Task<MailSynchronizationResult> SynchronizeMailsInternalAsync(
|
||||||
|
MailSynchronizationOptions options,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
=> Task.FromResult(MailSynchronizationResult.Empty);
|
||||||
|
|
||||||
|
protected override Task<CalendarSynchronizationResult> SynchronizeCalendarEventsInternalAsync(
|
||||||
|
CalendarSynchronizationOptions options,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
=> Task.FromResult(CalendarSynchronizationResult.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class TestRequestBundle : IRequestBundle<object>
|
||||||
|
{
|
||||||
|
public TestRequestBundle(object nativeRequest, IRequestBase request)
|
||||||
|
{
|
||||||
|
NativeRequest = nativeRequest;
|
||||||
|
Request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BundleId { get; set; } = Guid.NewGuid().ToString();
|
||||||
|
public IUIChangeRequest UIChangeRequest => Request;
|
||||||
|
public object NativeRequest { get; }
|
||||||
|
public IRequestBase Request { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -140,9 +140,10 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
|||||||
PendingSynchronizationRequest.Add(options, newCancellationTokenSource);
|
PendingSynchronizationRequest.Add(options, newCancellationTokenSource);
|
||||||
activeSynchronizationCancellationToken = newCancellationTokenSource.Token;
|
activeSynchronizationCancellationToken = newCancellationTokenSource.Token;
|
||||||
|
|
||||||
// ImapSynchronizer will send this type when an Idle client receives a notification of changes.
|
// Only explicit ExecuteRequests runs are allowed to drain the queued request list.
|
||||||
// We should not execute requests in this case.
|
// Other sync types (for example the follow-up FoldersOnly refresh after folder actions)
|
||||||
bool shouldExecuteRequests = options.Type != MailSynchronizationType.IMAPIdle;
|
// may be queued alongside ExecuteRequests and must not replay the same operations.
|
||||||
|
bool shouldExecuteRequests = options.Type == MailSynchronizationType.ExecuteRequests;
|
||||||
|
|
||||||
bool shouldDelayExecution = false;
|
bool shouldDelayExecution = false;
|
||||||
int maxExecutionDelay = 0;
|
int maxExecutionDelay = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user