using Microsoft.Extensions.Options; using Novelly.Api.Imports; namespace Novelly.Api.Tests; [TestFixture] public class ImportBrowseServiceTests { private string _root = null!; private ImportBrowseService _browse = null!; [SetUp] public void SetUp() { _root = Directory.CreateTempSubdirectory("novelly-browse-test-").FullName; _browse = new ImportBrowseService( Options.Create(new ImportOptions { RootPath = _root }), new CapturingLogger()); } [TearDown] public void TearDown() { if (Directory.Exists(_root)) { Directory.Delete(_root, recursive: true); } } [Test] public void Listing_the_root_returns_directories_before_files_ordered_by_name() { File.WriteAllText(Path.Combine(_root, "notes.md"), "# Notes"); Directory.CreateDirectory(Path.Combine(_root, "zeta")); Directory.CreateDirectory(Path.Combine(_root, "alpha")); var listing = _browse.List(null); Assert.That(listing.Entries.Select(e => e.Name), Is.EqualTo(new[] { "alpha", "zeta", "notes.md" })); } [Test] public void A_folder_with_an_outline_file_is_flagged_importable() { var folder = Path.Combine(_root, "my-novel"); Directory.CreateDirectory(folder); File.WriteAllText(Path.Combine(folder, "outline.md"), "# My Novel"); var listing = _browse.List(null); Assert.That(listing.Entries.Single(e => e.Name == "my-novel").LooksImportable, Is.True); } [Test] public void An_empty_folder_is_not_flagged_importable() { Directory.CreateDirectory(Path.Combine(_root, "empty")); var listing = _browse.List(null); Assert.That(listing.Entries.Single(e => e.Name == "empty").LooksImportable, Is.False); } [Test] public void The_staging_folder_is_hidden_from_listings() { Directory.CreateDirectory(Path.Combine(_root, ".novelly-staging")); Directory.CreateDirectory(Path.Combine(_root, "visible")); var listing = _browse.List(null); Assert.That(listing.Entries.Select(e => e.Name), Is.EqualTo(new[] { "visible" })); } [Test] public void Escaping_the_import_root_is_rejected() { Assert.That(() => _browse.List(".."), Throws.TypeOf()); } [Test] public void Browsing_without_a_configured_root_fails() { var unconfigured = new ImportBrowseService( Options.Create(new ImportOptions()), new CapturingLogger()); Assert.That(() => unconfigured.List(null), Throws.TypeOf()); } [Test] public void Listing_a_subfolder_reports_its_parent() { Directory.CreateDirectory(Path.Combine(_root, "child")); var listing = _browse.List("child"); Assert.That(listing.ParentRelativePath, Is.EqualTo("")); } }