diff --git a/Keybinding.Test/BlankNoteNameTests.cs b/Keybinding.Test/BlankNoteNameTests.cs new file mode 100644 index 0000000..8ac1504 --- /dev/null +++ b/Keybinding.Test/BlankNoteNameTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2023-2026 ktsu-dev contributors + +namespace ktsu.Keybinding.Test; + +using ktsu.Keybinding.Core.Models; + +[TestClass] +public class BlankNoteNameTests +{ + [TestMethod] + [DataRow("")] + [DataRow(" ")] + [DataRow("\t")] + public void NoteFromBlankNoteName_ThrowsArgumentException(string key) + { + // The string constructor already refused a blank key; the NoteName one built an empty note that + // displayed as "Ctrl+", executed, and was then dropped when the profile was loaded again (#212). + NoteName name = NoteName.Create(key); + ArgumentException exception = Assert.ThrowsExactly(() => new Note(name)); + Assert.AreEqual("key", exception.ParamName); + Assert.StartsWith("Key cannot be null or whitespace", exception.Message); + } + + [TestMethod] + [DataRow("")] + [DataRow(" ")] + [DataRow("\t")] + public void NoteFromBlankString_ThrowsTheSameArgumentException(string key) + { + ArgumentException exception = Assert.ThrowsExactly(() => new Note(key)); + Assert.AreEqual("key", exception.ParamName); + Assert.StartsWith("Key cannot be null or whitespace", exception.Message); + } +} diff --git a/Keybinding/Models/MusicalTypes.cs b/Keybinding/Models/MusicalTypes.cs index 7cfc33c..762a9ad 100644 --- a/Keybinding/Models/MusicalTypes.cs +++ b/Keybinding/Models/MusicalTypes.cs @@ -19,6 +19,11 @@ public sealed class Note : IEquatable public Note(NoteName key) { Ensure.NotNull(key); + if (string.IsNullOrWhiteSpace(key.ToString())) + { + throw new ArgumentException("Key cannot be null or whitespace", nameof(key)); + } + string canonical = NormalizeKey(key.ToString()); Key = canonical == key.ToString() ? key : NoteName.Create(canonical); }