Files
SongTidy/SongTidy.Tests/FilenameParserTests.cs
T

253 lines
8.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using SongTidy.Services;
namespace SongTidy.Tests;
/// <summary>
/// Contains tests for <see cref="FilenameParser"/>.
/// </summary>
[TestClass]
public sealed class FilenameParserTests {
#region Successful parsing
/// <summary>
/// Verifies the documented example with one English and one Chinese bracket group.
/// </summary>
[TestMethod]
public void ParsesSpecificationExample() {
AssertParse("A - B (Live - Tokyo)(修正版)", "A", "B", "Live - Tokyo 修正版");
}
/// <summary>
/// Verifies that multiple comment groups are joined with a single half-width space.
/// </summary>
[TestMethod]
public void ParsesMultipleCommentGroups() {
AssertParse("A - B (Live)(Remix)", "A", "B", "Live Remix");
}
/// <summary>
/// Verifies that Chinese bracket groups are extracted like English bracket groups.
/// </summary>
[TestMethod]
public void ParsesChineseBracketComment() {
AssertParse("歌手 - 歌名(现场)", "歌手", "歌名", "现场");
}
/// <summary>
/// Verifies that all comment groups are removed from the text used for artist and title.
/// </summary>
[TestMethod]
public void RemovesAllCommentGroupsFromSource() {
AssertParse("A - B (Live) (Tokyo)", "A", "B", "Live Tokyo");
}
/// <summary>
/// Verifies that nested brackets stay as literal text inside the comment.
/// </summary>
[TestMethod]
public void KeepsNestedBracketsInsideComment() {
AssertParse("A - B (Live (Tokyo) Mix)", "A", "B", "Live (Tokyo) Mix");
}
/// <summary>
/// Verifies that nested full-width brackets stay as literal text inside an English comment.
/// </summary>
[TestMethod]
public void PreservesFullWidthNestedBrackets() {
AssertParse("A - B (Live(东京))", "A", "B", "Live(东京)");
}
/// <summary>
/// Verifies that only the outermost pair of a nested group is treated as the comment.
/// </summary>
[TestMethod]
public void TreatsOnlyOutermostBracketGroupAsComment() {
AssertParse("A - B ((Live))", "A", "B", "(Live)");
}
/// <summary>
/// Verifies that a comment can be extracted from a name without a hyphen.
/// </summary>
[TestMethod]
public void ParsesCommentWithoutArtistSeparator() {
AssertParse("Song (Live)", string.Empty, "Song", "Live");
}
#endregion
#region Invalid bracket structures
/// <summary>
/// Verifies that an unmatched opening bracket disables comment extraction entirely.
/// </summary>
[TestMethod]
public void AbandonsExtractionForUnmatchedOpeningBracket() {
AssertParse("A - B (Live", "A", "B (Live", string.Empty);
}
/// <summary>
/// Verifies that an unmatched closing bracket disables comment extraction entirely.
/// </summary>
[TestMethod]
public void AbandonsExtractionForUnmatchedClosingBracket() {
AssertParse("A - B Live)", "A", "B Live)", string.Empty);
}
/// <summary>
/// Verifies that opening and closing brackets of different types cannot pair.
/// </summary>
[TestMethod]
public void AbandonsExtractionForMismatchedBracketTypes() {
AssertParse("A - B (Live)", "A", "B (Live)", string.Empty);
}
/// <summary>
/// Verifies that an extra closing bracket after a valid pair disables extraction entirely.
/// </summary>
[TestMethod]
public void AbandonsExtractionForExtraClosingBracket() {
AssertParse("A - B (Live))", "A", "B (Live))", string.Empty);
}
/// <summary>
/// Verifies that an extra opening bracket after a valid pair disables extraction entirely.
/// </summary>
[TestMethod]
public void AbandonsExtractionForExtraOpeningBracket() {
AssertParse("A - B (Live) (", "A", "B (Live) (", string.Empty);
}
/// <summary>
/// Verifies that an unclosed outer bracket invalidates otherwise complete nested brackets.
/// </summary>
[TestMethod]
public void AbandonsExtractionForUnclosedOuterBracket() {
AssertParse("A - B (Live (Tokyo)", "A", "B (Live (Tokyo)", string.Empty);
}
/// <summary>
/// Verifies that crossing bracket groups are treated as an invalid structure.
/// </summary>
[TestMethod]
public void AbandonsExtractionForCrossingBracketGroups() {
AssertParse("(a(b))", string.Empty, "(a(b))", string.Empty);
}
#endregion
#region Hyphen handling
/// <summary>
/// Verifies that a single half-width hyphen separates artist from title.
/// </summary>
[TestMethod]
public void SplitsSingleHalfWidthHyphen() {
AssertParse("A - B", "A", "B", string.Empty);
}
/// <summary>
/// Verifies that multiple half-width hyphens make the whole remaining text the title.
/// </summary>
[TestMethod]
public void TreatsMultipleHyphensAsTitleOnly() {
AssertParse("A - B - C", string.Empty, "A - B - C", string.Empty);
}
/// <summary>
/// Verifies that hyphens inside a removed comment do not count when applying the multiple-hyphen rule.
/// </summary>
[TestMethod]
public void IgnoresHyphensInsideCommentsWhenSplitting() {
AssertParse("A - B (Live - Tokyo - Mix)", "A", "B", "Live - Tokyo - Mix");
}
/// <summary>
/// Verifies that a full-width hyphen is not treated as a separator.
/// </summary>
[TestMethod]
public void DoesNotSplitOnFullWidthHyphen() {
AssertParse("A - B", string.Empty, "A - B", string.Empty);
}
/// <summary>
/// Verifies that an em dash is not treated as a separator.
/// </summary>
[TestMethod]
public void DoesNotSplitOnEmDash() {
AssertParse("A — B", string.Empty, "A — B", string.Empty);
}
/// <summary>
/// Verifies that a name without a hyphen produces an empty artist and a full title.
/// </summary>
[TestMethod]
public void ReturnsEmptyArtistWhenNoHyphenExists() {
AssertParse("Song Title", string.Empty, "Song Title", string.Empty);
}
/// <summary>
/// Verifies that an empty input produces three empty fields.
/// </summary>
[TestMethod]
public void ReturnsEmptyFieldsForEmptyInput() {
AssertParse(string.Empty, string.Empty, string.Empty, string.Empty);
}
#endregion
#region Whitespace handling
/// <summary>
/// Verifies that standard whitespace around the artist and title is removed.
/// </summary>
[TestMethod]
public void TrimsStandardWhitespaceAroundArtistAndTitle() {
AssertParse(" A - B ", "A", "B", string.Empty);
}
/// <summary>
/// Verifies that standard whitespace around extracted comment text is removed.
/// </summary>
[TestMethod]
public void TrimsStandardWhitespaceInsideComments() {
AssertParse("A - B ( Live )", "A", "B", "Live");
}
/// <summary>
/// Verifies that full-width spaces inside comment text are preserved.
/// </summary>
[TestMethod]
public void PreservesFullWidthSpacesInsideComments() {
AssertParse("A - B (\u3000Live\u3000)", "A", "B", "\u3000Live\u3000");
}
/// <summary>
/// Verifies that full-width spaces around artist and title are preserved.
/// </summary>
[TestMethod]
public void PreservesFullWidthSpacesAroundFields() {
AssertParse("A\u3000-\u3000B", "A\u3000", "\u3000B", string.Empty);
}
#endregion
/// <summary>
/// Parses the input and asserts all three resulting fields.
/// </summary>
/// <param name="input">The file name to parse.</param>
/// <param name="expectedArtist">The expected artist value.</param>
/// <param name="expectedTitle">The expected title value.</param>
/// <param name="expectedComment">The expected comment value.</param>
private static void AssertParse(
string input,
string expectedArtist,
string expectedTitle,
string expectedComment) {
FilenameParseResult result = FilenameParser.Parse(input);
Assert.AreEqual(expectedArtist, result.Artist, "Artist mismatch.");
Assert.AreEqual(expectedTitle, result.Title, "Title mismatch.");
Assert.AreEqual(expectedComment, result.Comment, "Comment mismatch.");
}
}