Skip to content
Open
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
6 changes: 5 additions & 1 deletion .github/workflows/release-extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ jobs:
- **x64**: `QuickShell-Setup-${{ steps.version.outputs.VERSION }}-x64.exe`
- **ARM64**: `QuickShell-Setup-${{ steps.version.outputs.VERSION }}-arm64.exe`

### PowerToys Run plugin
Includes **Command Palette** registration and the **PowerToys Run** plugin. Restart PowerToys after install.

### PowerToys Run plugin (ZIP only)

For Store users who want Run without the full EXE:

- **x64**: `QuickShell.Run-x64.zip` → extract to `%LOCALAPPDATA%\Microsoft\PowerToys\PowerToys Run\Plugins\QuickShell\`
- **ARM64**: `QuickShell.Run-ARM64.zip`
Expand Down
102 changes: 102 additions & 0 deletions QuickShell.Core.Tests/RunQueryScoringTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using QuickShell.Models;
using QuickShell.Services;

namespace QuickShell.Core.Tests;

public sealed class RunQueryScoringTests
{
[Fact]
public void BrowseMode_ShortcutsOutrankUtilities()
{
var shortcut = new TerminalShortcut { Name = "Demo", Directory = @"C:\Demo" };
var shortcutScore = RunQueryScoring.ComputeShortcutScore(shortcut, search: string.Empty, directActivationBrowse: true);
var utilityScore = RunQueryScoring.ComputeUtilityScore(rankedScore: 2000, search: string.Empty, utilityOrder: 0);

Assert.True(shortcutScore > utilityScore);
}

[Fact]
public void BrowseMode_PinnedShortcutsRespectPinOrder()
{
var first = new TerminalShortcut { Name = "A", IsPinned = true, PinOrder = 1 };
var second = new TerminalShortcut { Name = "B", IsPinned = true, PinOrder = 2 };

var firstScore = RunQueryScoring.ComputeShortcutScore(first, string.Empty, directActivationBrowse: true);
var secondScore = RunQueryScoring.ComputeShortcutScore(second, string.Empty, directActivationBrowse: true);

Assert.True(firstScore > secondScore);
}

[Fact]
public void BrowseMode_PinOrderBeatsRecency()
{
var recentSecond = new TerminalShortcut
{
Name = "B",
IsPinned = true,
PinOrder = 2,
LastUsedUtc = new DateTime(2024, 6, 1, 12, 0, 0, DateTimeKind.Utc),
};
Comment thread
tonythethompson marked this conversation as resolved.
var olderFirst = new TerminalShortcut
{
Name = "A",
IsPinned = true,
PinOrder = 1,
LastUsedUtc = null,
};

var now = new DateTime(2024, 6, 1, 13, 0, 0, DateTimeKind.Utc);
var firstScore = RunQueryScoring.ComputeShortcutScore(olderFirst, string.Empty, directActivationBrowse: true, now);
var secondScore = RunQueryScoring.ComputeShortcutScore(recentSecond, string.Empty, directActivationBrowse: true, now);

Assert.True(firstScore > secondScore);
}

[Fact]
public void BrowseMode_UnorderedPinnedShortcutsRankBelowExplicitOrder()
{
var ordered = new TerminalShortcut { Name = "A", IsPinned = true, PinOrder = 1 };
var unordered = new TerminalShortcut { Name = "B", IsPinned = true, PinOrder = null };

var orderedScore = RunQueryScoring.ComputeShortcutScore(ordered, string.Empty, directActivationBrowse: true);
var unorderedScore = RunQueryScoring.ComputeShortcutScore(unordered, string.Empty, directActivationBrowse: true);

Assert.True(orderedScore > unorderedScore);
}

[Fact]
public void BrowseMode_UnorderedPinnedBeatsRecentUnpinned()
{
var favorite = new TerminalShortcut { Name = "Fav", IsPinned = true, PinOrder = null };
var recent = new TerminalShortcut
{
Name = "Recent",
LastUsedUtc = new DateTime(2024, 6, 1, 12, 0, 0, DateTimeKind.Utc),
};

var now = new DateTime(2024, 6, 1, 13, 0, 0, DateTimeKind.Utc);
var favoriteScore = RunQueryScoring.ComputeShortcutScore(favorite, string.Empty, directActivationBrowse: true, now);
var recentScore = RunQueryScoring.ComputeShortcutScore(recent, string.Empty, directActivationBrowse: true, now);

Assert.True(favoriteScore > recentScore);
}

[Fact]
public void BrowseMode_UtilitiesPreserveDeclarationOrder()
{
var firstUtility = RunQueryScoring.ComputeUtilityScore(2000, string.Empty, utilityOrder: 0);
var secondUtility = RunQueryScoring.ComputeUtilityScore(2000, string.Empty, utilityOrder: 1);

Assert.True(firstUtility > secondUtility);
}

[Fact]
public void SearchMode_UtilitiesKeepHighRankWhenMatched()
{
var firstUtility = RunQueryScoring.ComputeUtilityScore(2000, "export", utilityOrder: 0);
var secondUtility = RunQueryScoring.ComputeUtilityScore(2000, "export", utilityOrder: 1);

Assert.Equal(2000, firstUtility);
Assert.True(firstUtility > secondUtility);
}
}
13 changes: 4 additions & 9 deletions QuickShell.Core.Tests/ShortcutDraftStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,16 +156,11 @@ public void Dispose()

private static void WaitForDraftFile(ShortcutDraftStore store)
{
for (var attempt = 0; attempt < 50; attempt++)
{
if (File.Exists(store.DraftPath))
{
return;
}
store.FlushPendingFileIoForTests();

Thread.Sleep(20);
if (!File.Exists(store.DraftPath))
{
throw new InvalidOperationException("Draft file was not written.");
}

throw new InvalidOperationException("Draft file was not written in time.");
}
}
Loading
Loading