121 lines
4.5 KiB
C#
121 lines
4.5 KiB
C#
using System.Reactive.Linq;
|
|
using System.Reactive.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NSubstitute;
|
|
using PLib.Application.Library;
|
|
using PLib.Desktop.Services;
|
|
using PLib.Desktop.Settings;
|
|
using PLib.Desktop.ViewModels;
|
|
using Shouldly;
|
|
|
|
namespace PLib.Tests.Settings;
|
|
|
|
public sealed class SettingsViewModelTests
|
|
{
|
|
private readonly IAppSettingsStore _store = Substitute.For<IAppSettingsStore>();
|
|
|
|
[Fact]
|
|
public async Task Opening_and_saving_without_touching_anything_changes_nothing()
|
|
{
|
|
// Both of these are displayed in a lossier unit than they are stored in: 65 536 bytes
|
|
// shows as 0,06 MB. Converting the untouched field back used to yield 62 915, which
|
|
// silently rewrote the setting and forced a full rescan on every visit to the panel.
|
|
var options = new LibraryOptions
|
|
{
|
|
Folders = [@"C:\videos"],
|
|
MinimumFileSizeInBytes = 65_536,
|
|
ThumbnailPositionRatio = 0.15,
|
|
};
|
|
|
|
var (viewModel, outcome) = await SaveAsync(options);
|
|
|
|
outcome.RescanRequired.ShouldBeFalse();
|
|
Written.MinimumFileSizeInBytes.ShouldBe(65_536);
|
|
Written.ThumbnailPositionRatio.ShouldBe(0.15);
|
|
viewModel.HasFolders.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Editing_the_minimum_size_does_write_the_new_value()
|
|
{
|
|
var (_, outcome) = await SaveAsync(
|
|
new LibraryOptions { Folders = [@"C:\videos"], MinimumFileSizeInBytes = 65_536 },
|
|
viewModel => viewModel.MinimumFileSizeMegabytes = 4);
|
|
|
|
Written.MinimumFileSizeInBytes.ShouldBe(4 * 1024 * 1024);
|
|
outcome.RescanRequired.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Removing_a_folder_is_carried_into_the_saved_settings()
|
|
{
|
|
var (_, outcome) = await SaveAsync(
|
|
new LibraryOptions { Folders = [@"C:\a", @"C:\b"] },
|
|
viewModel => viewModel.Folders[0].RemoveCommand.Execute().Subscribe());
|
|
|
|
Written.Folders.ShouldBe([@"C:\b"]);
|
|
outcome.RescanRequired.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Saving_the_panel_keeps_the_settings_it_does_not_edit()
|
|
{
|
|
// The panel writes the whole file, so anything outside its own screens — the
|
|
// playback volume, for one — has to be carried through untouched.
|
|
await SaveAsync(
|
|
new LibraryOptions { Folders = [@"C:ideos"] },
|
|
viewModel => viewModel.ThumbnailWidth = 720,
|
|
new PlaybackOptions { Volume = 0.42, IsMuted = true });
|
|
|
|
Written.ThumbnailWidth.ShouldBe(720);
|
|
Written.Volume.ShouldBe(0.42);
|
|
Written.IsMuted.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Cancelling_writes_nothing()
|
|
{
|
|
var viewModel = Create(new LibraryOptions { Folders = [@"C:\videos"] });
|
|
var closed = viewModel.Closed.FirstAsync().ToTask();
|
|
|
|
viewModel.MinimumFileSizeMegabytes = 999;
|
|
await viewModel.CancelCommand.Execute().FirstAsync().ToTask(TestContext.Current.CancellationToken);
|
|
|
|
(await closed).Saved.ShouldBeFalse();
|
|
_store.ReceivedCalls().ShouldNotContain(call => call.GetMethodInfo().Name == nameof(IAppSettingsStore.SaveAsync));
|
|
}
|
|
|
|
private AppSettings Written =>
|
|
(AppSettings)_store.ReceivedCalls()
|
|
.Single(call => call.GetMethodInfo().Name == nameof(IAppSettingsStore.SaveAsync))
|
|
.GetArguments()[0]!;
|
|
|
|
private async Task<(SettingsViewModel ViewModel, SettingsDialogOutcome Outcome)> SaveAsync(
|
|
LibraryOptions options,
|
|
Action<SettingsViewModel>? edit = null,
|
|
PlaybackOptions? playback = null)
|
|
{
|
|
var viewModel = Create(options, playback);
|
|
var closed = viewModel.Closed.FirstAsync().ToTask();
|
|
|
|
edit?.Invoke(viewModel);
|
|
await viewModel.SaveCommand.Execute().FirstAsync().ToTask(TestContext.Current.CancellationToken);
|
|
|
|
return (viewModel, await closed);
|
|
}
|
|
|
|
private SettingsViewModel Create(LibraryOptions options, PlaybackOptions? playback = null)
|
|
{
|
|
_store.Current.Returns(
|
|
AppSettings.From(options, new AppearanceOptions(), playback ?? new PlaybackOptions()));
|
|
|
|
return new SettingsViewModel(
|
|
Substitute.For<IServiceScopeFactory>(),
|
|
_store,
|
|
Substitute.For<IFolderPicker>(),
|
|
Substitute.For<IThemeService>(),
|
|
NullLogger<SettingsViewModel>.Instance);
|
|
}
|
|
}
|