Files
PLib/tests/PLib.Tests/Domain/VideoItemTests.cs
T

102 lines
3.7 KiB
C#

using PLib.Domain.Videos;
using Shouldly;
namespace PLib.Tests.Domain;
public sealed class VideoItemTests
{
private static VideoItem CreateIndexedItem()
{
var item = new VideoItem(@"C:\videos\clip.mp4", "clip", 1_000, DateTimeOffset.UnixEpoch);
item.ApplyTechnicalInfo(new VideoTechnicalInfo(TimeSpan.FromMinutes(3), 1920, 1080, "h264"));
item.AttachThumbnail(@"C:\cache\clip.jpg");
item.AttachPreview(@"C:\cache\clip.strip.jpg", 12);
item.ApplyPerceptualHash(0xDEADBEEF);
return item;
}
[Fact]
public void An_item_is_indexed_once_it_has_a_duration_and_a_poster_frame()
{
var item = new VideoItem(@"C:\videos\clip.mp4", "clip", 1_000, DateTimeOffset.UnixEpoch);
item.IsIndexed.ShouldBeFalse();
item.ApplyTechnicalInfo(new VideoTechnicalInfo(TimeSpan.FromMinutes(1), 1280, 720, "h264"));
item.IsIndexed.ShouldBeFalse();
item.AttachThumbnail(@"C:\cache\clip.jpg");
// Neither the animated preview nor the hash is part of this: both belong to later
// passes, and the grid is usable long before either exists.
item.IsIndexed.ShouldBeTrue();
item.NeedsAnimatedPreview.ShouldBeTrue();
item.NeedsPerceptualHash.ShouldBeTrue();
item.AttachPreview(@"C:\cache\clip.strip.jpg", 12);
item.NeedsAnimatedPreview.ShouldBeFalse();
item.ApplyPerceptualHash(1);
item.NeedsPerceptualHash.ShouldBeFalse();
}
[Fact]
public void The_later_passes_cannot_be_asked_for_before_the_duration_is_known()
{
var item = new VideoItem(@"C:\videos\clip.mp4", "clip", 1_000, DateTimeOffset.UnixEpoch);
// Both sample frames across the running time, so there is nothing to sample yet.
item.NeedsAnimatedPreview.ShouldBeFalse();
item.NeedsPerceptualHash.ShouldBeFalse();
}
[Fact]
public void A_preview_of_a_single_frame_is_not_an_animation()
{
var item = new VideoItem(@"C:\videos\clip.mp4", "clip", 1_000, DateTimeOffset.UnixEpoch);
Should.Throw<ArgumentOutOfRangeException>(() => item.AttachPreview(@"C:\cache\clip.jpg", 1));
}
[Fact]
public void Refreshing_an_unchanged_file_keeps_everything_that_was_derived_from_it()
{
var item = CreateIndexedItem();
item.RefreshFileFacts(1_000, DateTimeOffset.UnixEpoch);
item.IsIndexed.ShouldBeTrue();
item.ThumbnailPath.ShouldNotBeNull();
item.PreviewPath.ShouldNotBeNull();
}
[Fact]
public void Refreshing_a_changed_file_invalidates_the_metadata_and_the_thumbnail()
{
var item = CreateIndexedItem();
item.RefreshFileFacts(2_000, DateTimeOffset.UnixEpoch.AddDays(1));
item.SizeInBytes.ShouldBe(2_000);
item.Duration.ShouldBeNull();
item.ThumbnailPath.ShouldBeNull();
item.PreviewPath.ShouldBeNull();
item.PreviewFrameCount.ShouldBe(0);
// The hash describes the picture, so a different file means a different hash.
item.PerceptualHash.ShouldBeNull();
item.IsIndexed.ShouldBeFalse();
}
[Theory]
[InlineData("", "title")]
[InlineData(" ", "title")]
[InlineData(@"C:\videos\clip.mp4", "")]
public void An_item_cannot_be_created_without_a_path_and_a_title(string path, string title) =>
Should.Throw<ArgumentException>(() => new VideoItem(path, title, 1, DateTimeOffset.UnixEpoch));
[Fact]
public void An_item_cannot_have_a_negative_size() =>
Should.Throw<ArgumentOutOfRangeException>(
() => new VideoItem(@"C:\videos\clip.mp4", "clip", -1, DateTimeOffset.UnixEpoch));
}