Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions Keybinding.Test/CommandCategoryFilterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2023-2026 ktsu-dev contributors

namespace ktsu.Keybinding.Test;

using ktsu.Keybinding.Core.Models;
using ktsu.Keybinding.Core.Services;

[TestClass]
public class CommandCategoryFilterTests
{
private static readonly string[] UncategorizedIds = ["file.save"];
private static readonly string[] EditIds = ["edit.copy"];

private CommandRegistry _registry = null!;

[TestInitialize]
public void Setup()
{
_registry = new CommandRegistry();
_registry.RegisterCommand(new Command("file.save", "Save"));
_registry.RegisterCommand(new Command("edit.copy", "Copy", null, "Edit"));
}

[TestMethod]
[DataRow(null)]
[DataRow("")]
[DataRow(" ")]
public void GetCommandsByCategory_BlankCategory_ReturnsOnlyUncategorizedCommands(string? category)
{
string[] ids = [.. _registry.GetCommandsByCategory(category).Select(c => (string)c.Id)];

CollectionAssert.AreEquivalent(UncategorizedIds, ids);

Check warning on line 32 in Keybinding.Test/CommandCategoryFilterTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.AreSequenceEqual' instead of 'CollectionAssert.AreEquivalent'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Keybinding&issues=AaDwXl_DnAunJMVScS7O&open=AaDwXl_DnAunJMVScS7O&pullRequest=158
}

[TestMethod]
[DataRow("Edit")]
[DataRow("edit")]
[DataRow(" Edit ")]
public void GetCommandsByCategory_NamedCategory_ReturnsOnlyThatCategory(string category)
{
string[] ids = [.. _registry.GetCommandsByCategory(category).Select(c => (string)c.Id)];

CollectionAssert.AreEquivalent(EditIds, ids);

Check warning on line 43 in Keybinding.Test/CommandCategoryFilterTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.AreSequenceEqual' instead of 'CollectionAssert.AreEquivalent'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Keybinding&issues=AaDwXl_DnAunJMVScS7P&open=AaDwXl_DnAunJMVScS7P&pullRequest=158
}

[TestMethod]
public void GetCommandsByCategory_PassingACommandsOwnCategoryBack_FindsThatCommand()
{
foreach (Command command in _registry.GetAllCommands())
{
Assert.IsTrue(
_registry.GetCommandsByCategory(command.Category).Contains(command),
$"{command.Id} should be in the group for its own category.");

Check warning on line 53 in Keybinding.Test/CommandCategoryFilterTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.Contains' instead of 'Assert.IsTrue'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Keybinding&issues=AaDwXl_DnAunJMVScS7Q&open=AaDwXl_DnAunJMVScS7Q&pullRequest=158
}
}
}
2 changes: 1 addition & 1 deletion Keybinding/Contracts/ICommandRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public interface ICommandRegistry
/// <summary>
/// Gets commands by category
/// </summary>
/// <param name="category">The category to filter by</param>
/// <param name="category">The category to filter by, compared case-insensitively. Null, empty or whitespace selects the uncategorized commands.</param>
/// <returns>Collection of commands in the specified category</returns>
public IReadOnlyCollection<Command> GetCommandsByCategory(string? category);

Expand Down
8 changes: 6 additions & 2 deletions Keybinding/Services/CommandRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
{
return string.IsNullOrWhiteSpace(commandId)
? throw new ArgumentException("Command ID cannot be null or whitespace", nameof(commandId))
: _commands.TryGetValue(commandId.Trim(), out Command? command) ? command : null;

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.

Check warning on line 43 in Keybinding/Services/CommandRegistry.cs

View workflow job for this annotation

GitHub Actions / ci / .NET / Analyze & Release

Extract this nested ternary operation into an independent statement.
}

/// <inheritdoc/>
Expand All @@ -57,9 +57,13 @@
{
lock (_lock)
{
string? normalizedCategory = category?.Trim();
// Compare explicitly: a null CommandCategory converts to "" rather than null, so passing
// it straight to string.Equals made null find nothing while "" found the uncategorized commands.
string? wanted = string.IsNullOrWhiteSpace(category) ? null : category.Trim();
return _commands.Values
.Where(c => string.Equals(c.Category, normalizedCategory, StringComparison.OrdinalIgnoreCase))
.Where(c => wanted is null
? string.IsNullOrWhiteSpace(c.Category)
: string.Equals(c.Category?.ToString(), wanted, StringComparison.OrdinalIgnoreCase))
.ToList()
.AsReadOnly();
}
Expand Down
Loading