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
80 changes: 33 additions & 47 deletions RadialActions.Tests/Actions/ActionsSettingsViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public void SettingsWindowViewModel_SelectAction_SelectsActionTabAndForwardsSele

Assert.Equal(1, settings.SettingsTabIndex);
Assert.Same(second, viewModel.Actions.SelectedAction);
Assert.Equal(1, viewModel.Actions.SelectedActionIndex);
}

[Fact]
Expand All @@ -29,7 +28,6 @@ public void Constructor_SelectsFirstAction()
var viewModel = CreateViewModel(first, second);

Assert.Same(first, viewModel.SelectedAction);
Assert.Equal(0, viewModel.SelectedActionIndex);
Assert.Same(first, viewModel.Editor.SelectedAction);
}

Expand All @@ -43,30 +41,55 @@ public void SelectAction_SelectsMatchingAction()
viewModel.SelectAction(second);

Assert.Same(second, viewModel.SelectedAction);
Assert.Equal(1, viewModel.SelectedActionIndex);
Assert.Same(second, viewModel.Editor.SelectedAction);
}

[Fact]
public void AddAction_InsertsBlankActionAfterSelectedActionAndSelectsIt()
public void AddAction_AppendsNewActionAtEndAndSelectsIt()
{
var first = PieAction.CreateKeyAction("Mute");
var second = PieAction.CreateKeyAction("VolumeUp");
var third = PieAction.CreateKeyAction("VolumeDown");
var viewModel = CreateViewModel(first, second, third);
viewModel.SelectAction(second);
var viewModel = CreateViewModel(first, second);
viewModel.SelectAction(first);

viewModel.AddActionCommand.Execute(null);

var added = viewModel.Actions[2];
Assert.Equal([first, second, added, third], viewModel.Actions);
Assert.Equal("Blank action", added.Name);
Assert.Equal([first, second, added], viewModel.Actions);
Assert.Equal(PieAction.DefaultName, added.Name);
Assert.Equal(ActionType.None, added.Type);
Assert.Same(added, viewModel.SelectedAction);
Assert.Equal(2, viewModel.SelectedActionIndex);
Assert.Same(added, viewModel.Editor.SelectedAction);
}

[Fact]
public void DuplicateAction_InsertsCopyAfterSourceAndSelectsIt()
{
var first = PieAction.CreateScriptAction("Backup", "Get-Date", icon: "🧹", interpreter: "pwsh.exe", workingDirectory: @"C:\", runHidden: true);
first.IsEnabled = false;
first.Arguments = "/select";
var second = PieAction.CreateKeyAction("Mute");
var viewModel = CreateViewModel(first, second);
viewModel.SelectAction(first);

viewModel.DuplicateActionCommand.Execute(null);

var copy = viewModel.Actions[1];
Assert.Equal([first, copy, second], viewModel.Actions);
Assert.NotSame(first, copy);
Assert.Equal(first.Name, copy.Name);
Assert.Equal(first.Icon, copy.Icon);
Assert.Equal(first.Type, copy.Type);
Assert.Equal(first.IsEnabled, copy.IsEnabled);
Assert.Equal(first.Parameter, copy.Parameter);
Assert.Equal(first.Arguments, copy.Arguments);
Assert.Equal(first.WorkingDirectory, copy.WorkingDirectory);
Assert.Equal(first.Script, copy.Script);
Assert.Equal(first.RunHidden, copy.RunHidden);
Assert.Same(copy, viewModel.SelectedAction);
Assert.Same(copy, viewModel.Editor.SelectedAction);
}

[Fact]
public void AddDroppedTargets_InsertsAfterSelectionAndSelectsLast()
{
Expand All @@ -85,7 +108,6 @@ public void AddDroppedTargets_InsertsAfterSelectionAndSelectsLast()
Assert.Equal("https://a.com", addedA.Parameter);
Assert.Equal("https://b.com", addedB.Parameter);
Assert.Same(addedB, viewModel.SelectedAction);
Assert.Equal(3, viewModel.SelectedActionIndex);
Assert.Same(addedB, viewModel.Editor.SelectedAction);
}

Expand All @@ -99,7 +121,6 @@ public void AddDroppedTargets_WithoutSelection_AppendsAtEnd()
var added = Assert.Single(viewModel.Actions);
Assert.Equal("https://a.com", added.Parameter);
Assert.Same(added, viewModel.SelectedAction);
Assert.Equal(0, viewModel.SelectedActionIndex);
}

[Fact]
Expand All @@ -113,7 +134,6 @@ public void AddDroppedTargets_EmptyOrNull_DoesNothing()

Assert.Equal([first], viewModel.Actions);
Assert.Same(first, viewModel.SelectedAction);
Assert.Equal(0, viewModel.SelectedActionIndex);
}

[Fact]
Expand Down Expand Up @@ -170,7 +190,6 @@ public void RemoveAction_SelectsNextAvailableAction()

Assert.Equal([first, third], viewModel.Actions);
Assert.Same(third, viewModel.SelectedAction);
Assert.Equal(1, viewModel.SelectedActionIndex);
Assert.Same(third, viewModel.Editor.SelectedAction);
}

Expand All @@ -184,42 +203,9 @@ public void RemoveAction_ClearsSelectionWhenListBecomesEmpty()

Assert.Empty(viewModel.Actions);
Assert.Null(viewModel.SelectedAction);
Assert.Equal(-1, viewModel.SelectedActionIndex);
Assert.Null(viewModel.Editor.SelectedAction);
}

[Fact]
public void MoveUp_MovesSelectedActionAndKeepsSelection()
{
var first = PieAction.CreateKeyAction("Mute");
var second = PieAction.CreateKeyAction("VolumeUp");
var third = PieAction.CreateKeyAction("VolumeDown");
var viewModel = CreateViewModel(first, second, third);
viewModel.SelectAction(second);

viewModel.MoveUpCommand.Execute(null);

Assert.Equal([second, first, third], viewModel.Actions);
Assert.Same(second, viewModel.SelectedAction);
Assert.Equal(0, viewModel.SelectedActionIndex);
}

[Fact]
public void MoveDown_MovesSelectedActionAndKeepsSelection()
{
var first = PieAction.CreateKeyAction("Mute");
var second = PieAction.CreateKeyAction("VolumeUp");
var third = PieAction.CreateKeyAction("VolumeDown");
var viewModel = CreateViewModel(first, second, third);
viewModel.SelectAction(second);

viewModel.MoveDownCommand.Execute(null);

Assert.Equal([first, third, second], viewModel.Actions);
Assert.Same(second, viewModel.SelectedAction);
Assert.Equal(2, viewModel.SelectedActionIndex);
}

private static ActionsSettingsViewModel CreateViewModel(params PieAction[] actions)
{
return new ActionsSettingsViewModel(CreateSettings(actions));
Expand Down
16 changes: 15 additions & 1 deletion RadialActions.Tests/Pie/PieReorderCalculatorTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Windows;
using System.Windows;

namespace RadialActions.Tests;

Expand Down Expand Up @@ -37,6 +37,20 @@ public void GetTargetSlot_MapsRotationToSlot(int originalIndex, double rotationO
Assert.Equal(expectedSlot, slot);
}

[Theory]
[InlineData(0, 360, 0)] // a full lap over the six-slot editor ring (five slices plus the ghost) lands home
[InlineData(4, 60, 5)] // the last slice dragged one slot clockwise lands in the ghost slot, which the control clamps to the last real slot
[InlineData(0, -60, 5)] // the first slice dragged counterclockwise wraps into the ghost slot the same way
public void GetTargetSlot_WithEditModeGhostSlot_WrapsOverTheFullSlotRing(int originalIndex, double rotationOffset, int expectedSlot)
{
const double angleStep = 60;
const int slotCount = 6;

var slot = PieReorderCalculator.GetTargetSlot(originalIndex, rotationOffset, angleStep, slotCount);

Assert.Equal(expectedSlot, slot);
}

[Theory]
[InlineData(0, 288, -72)] // short way is backward
[InlineData(300, 0, 360)] // short way keeps going forward
Expand Down
16 changes: 16 additions & 0 deletions RadialActions/Actions/Action.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,22 @@ public static PieAction CreateScriptAction(string name, string script, string ic
RunHidden = runHidden
};

/// <summary>
/// Creates a copy of this action with the same configuration.
/// </summary>
public PieAction Clone() => new()
{
Name = Name,
Icon = Icon,
Type = Type,
IsEnabled = IsEnabled,
Parameter = Parameter,
Arguments = Arguments,
WorkingDirectory = WorkingDirectory,
Script = Script,
RunHidden = RunHidden,
};

/// <summary>
/// Executes the action.
/// </summary>
Expand Down
Loading