diff --git a/samples/book-app-project-cs/Program.cs b/samples/book-app-project-cs/Program.cs index 54373423..c9218774 100644 --- a/samples/book-app-project-cs/Program.cs +++ b/samples/book-app-project-cs/Program.cs @@ -59,9 +59,12 @@ void HandleRemove() Console.Write("Enter the title of the book to remove: "); var title = Console.ReadLine()?.Trim() ?? ""; - collection.RemoveBook(title); + var removed = collection.RemoveBook(title); - Console.WriteLine("\nBook removed if it existed.\n"); + if (removed) + Console.WriteLine($"\n\"{title}\" has been removed.\n"); + else + Console.WriteLine($"\nNo book with title \"{title}\" was found.\n"); } void HandleFind() diff --git a/samples/book-app-project-cs/Services/BookCollection.cs b/samples/book-app-project-cs/Services/BookCollection.cs index b219ba53..87ddef03 100644 --- a/samples/book-app-project-cs/Services/BookCollection.cs +++ b/samples/book-app-project-cs/Services/BookCollection.cs @@ -54,7 +54,7 @@ public Book AddBook(string title, string author, int year) return book; } - public List ListBooks() => _books; + public List ListBooks() => _books.ToList(); public Book? FindBookByTitle(string title) { diff --git a/samples/book-app-project-cs/Tests/BookCollectionTests.cs b/samples/book-app-project-cs/Tests/BookCollectionTests.cs index 5a0aa829..b9db43b8 100644 --- a/samples/book-app-project-cs/Tests/BookCollectionTests.cs +++ b/samples/book-app-project-cs/Tests/BookCollectionTests.cs @@ -67,4 +67,102 @@ public void RemoveBook_NonexistentBook_ShouldReturnFalse() var result = _collection.RemoveBook("Nonexistent Book"); Assert.False(result); } + + [Fact] + public void ListBooks_ShouldReturnCopy_AndPreventExternalMutation() + { + _collection.AddBook("Dune", "Frank Herbert", 1965); + var books = _collection.ListBooks(); + books.Clear(); + + Assert.Single(_collection.Books); + } + + // --- FindByAuthor --- + + [Fact] + public void FindByAuthor_ExactMatch_ShouldReturnBook() + { + _collection.AddBook("Dune", "Frank Herbert", 1965); + var results = _collection.FindByAuthor("Frank Herbert"); + + Assert.Single(results); + Assert.Equal("Dune", results[0].Title); + } + + [Fact] + public void FindByAuthor_CaseInsensitive_ShouldReturnBook() + { + _collection.AddBook("Dune", "Frank Herbert", 1965); + var results = _collection.FindByAuthor("frank herbert"); + + Assert.Single(results); + Assert.Equal("Dune", results[0].Title); + } + + [Fact] + public void FindByAuthor_MultipleBooksSameAuthor_ShouldReturnAll() + { + _collection.AddBook("A Wizard of Earthsea", "Ursula K. Le Guin", 1968); + _collection.AddBook("The Tombs of Atuan", "Ursula K. Le Guin", 1971); + var results = _collection.FindByAuthor("Ursula K. Le Guin"); + + Assert.Equal(2, results.Count); + Assert.Contains(results, b => b.Title == "A Wizard of Earthsea"); + Assert.Contains(results, b => b.Title == "The Tombs of Atuan"); + } + + [Fact] + public void FindByAuthor_UnknownAuthor_ShouldReturnEmpty() + { + var results = _collection.FindByAuthor("Nobody Known"); + Assert.Empty(results); + } + + // --- Persistence round-trip --- + + [Fact] + public void AddBook_ShouldPersistAcrossReload() + { + _collection.AddBook("Neuromancer", "William Gibson", 1984); + + var reloaded = new BookCollection(_tempFile); + var book = reloaded.FindBookByTitle("Neuromancer"); + + Assert.NotNull(book); + Assert.Equal("William Gibson", book.Author); + Assert.Equal(1984, book.Year); + } + + // --- Edge cases / validation --- + + [Fact] + public void AddBook_EmptyTitle_ShouldStillAdd() + { + _collection.AddBook("", "Some Author", 2000); + + Assert.Equal(1, _collection.Books.Count); + Assert.Equal("", _collection.Books[0].Title); + Assert.Equal("Some Author", _collection.Books[0].Author); + } + + [Fact] + public void AddBook_EmptyAuthor_ShouldStillAdd() + { + _collection.AddBook("Some Title", "", 2000); + + Assert.Equal(1, _collection.Books.Count); + Assert.Equal("Some Title", _collection.Books[0].Title); + Assert.Equal("", _collection.Books[0].Author); + } + + [Fact] + public void AddBook_DuplicateTitles_ShouldAllowBoth() + { + _collection.AddBook("Same Title", "Author One", 2000); + _collection.AddBook("Same Title", "Author Two", 2001); + + var matches = _collection.Books.Where(b => b.Title == "Same Title").ToList(); + Assert.Equal(2, matches.Count); + } }