diff --git a/Keybinding.Test/ModifierAliasNormalizationTests.cs b/Keybinding.Test/ModifierAliasNormalizationTests.cs index 832f06e..bdd46f0 100644 --- a/Keybinding.Test/ModifierAliasNormalizationTests.cs +++ b/Keybinding.Test/ModifierAliasNormalizationTests.cs @@ -55,6 +55,8 @@ public void EveryConstructionPath_NormalizesModifierAliases(string alias, string Chord.Parse($"{alias}+S"), new Chord([new Note(alias), new Note("S")]), new Chord([new Note(NoteName.Create(alias.ToUpperInvariant())), new Note("S")]), + new Chord([new Note(NoteName.Create(alias)), new Note(NoteName.Create("s"))]), + new Chord([new Note(NoteName.Create(alias.ToLowerInvariant())), new Note("S")]), ]; foreach (Chord chord in built) @@ -64,6 +66,23 @@ public void EveryConstructionPath_NormalizesModifierAliases(string alias, string } } + [TestMethod] + [DataRow("control")] + [DataRow("Control")] + [DataRow("ctrl")] + [DataRow("s")] + [DataRow("f5")] + [DataRow(" cmd ")] + public void NoteNameConstructor_MatchesStringConstructor(string key) + { + Note fromString = new(key); + Note fromNoteName = new(NoteName.Create(key)); + + Assert.AreEqual(fromString, fromNoteName); + Assert.AreEqual(fromString.GetHashCode(), fromNoteName.GetHashCode()); + Assert.AreEqual(fromString.Key.ToString(), fromNoteName.Key.ToString()); + } + [TestMethod] public void ParseChord_AliasAndCanonicalName_CollapseToOneNote() { diff --git a/Keybinding/Models/MusicalTypes.cs b/Keybinding/Models/MusicalTypes.cs index c7af056..83dbdce 100644 --- a/Keybinding/Models/MusicalTypes.cs +++ b/Keybinding/Models/MusicalTypes.cs @@ -18,7 +18,7 @@ public sealed class Note : IEquatable public Note(NoteName key) { Ensure.NotNull(key); - string canonical = CanonicalizeKey(key.ToString()); + string canonical = NormalizeKey(key.ToString()); Key = canonical == key.ToString() ? key : NoteName.Create(canonical); } @@ -34,9 +34,17 @@ public Note(string key) throw new ArgumentException("Key cannot be null or whitespace", nameof(key)); } - Key = NoteName.Create(CanonicalizeKey(key.Trim().ToUpperInvariant())); + Key = NoteName.Create(NormalizeKey(key)); } + /// + /// Trims, uppercases and canonicalizes a key name. Both constructors go through this, so a note + /// compares and hashes the same however it was built. + /// + /// A key name in any case + /// The canonical key name + private static string NormalizeKey(string key) => CanonicalizeKey(key.Trim().ToUpperInvariant()); + /// /// Maps a modifier alias to its canonical key name, so that every way of building a note /// (parsing, constructing directly, or loading a stored profile) compares and hashes the same.