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
2 changes: 1 addition & 1 deletion .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: dotnet build --configuration Release -warnaserror

- name: Run unit tests
run: dotnet test --no-build --verbosity normal
run: dotnet test --configuration Release --verbosity normal

- name: Validate mapping JSON files
run: |
Expand Down
47 changes: 47 additions & 0 deletions drum-midi-remapper.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Managers", "src\Managers\Ma
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLI", "src\CLI\CLI.csproj", "{36E27E57-4986-4178-98F8-3B4F6D985E2C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Managers.Tests", "tests\Managers.Tests\Managers.Tests.csproj", "{04A8B018-1954-48B8-BAAF-E17385114845}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models.Tests", "tests\Models.Tests\Models.Tests.csproj", "{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Services.Tests", "tests\Services.Tests\Services.Tests.csproj", "{3CECB972-EFFD-422B-9109-4D0D5AB6441E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -71,6 +79,42 @@ Global
{36E27E57-4986-4178-98F8-3B4F6D985E2C}.Release|x64.Build.0 = Release|Any CPU
{36E27E57-4986-4178-98F8-3B4F6D985E2C}.Release|x86.ActiveCfg = Release|Any CPU
{36E27E57-4986-4178-98F8-3B4F6D985E2C}.Release|x86.Build.0 = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|Any CPU.Build.0 = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|x64.ActiveCfg = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|x64.Build.0 = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|x86.ActiveCfg = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Debug|x86.Build.0 = Debug|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|Any CPU.ActiveCfg = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|Any CPU.Build.0 = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|x64.ActiveCfg = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|x64.Build.0 = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|x86.ActiveCfg = Release|Any CPU
{04A8B018-1954-48B8-BAAF-E17385114845}.Release|x86.Build.0 = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|x64.ActiveCfg = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|x64.Build.0 = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Debug|x86.Build.0 = Debug|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|Any CPU.Build.0 = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|x64.ActiveCfg = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|x64.Build.0 = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|x86.ActiveCfg = Release|Any CPU
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4}.Release|x86.Build.0 = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|x64.ActiveCfg = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|x64.Build.0 = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|x86.ActiveCfg = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Debug|x86.Build.0 = Debug|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|Any CPU.Build.0 = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|x64.ActiveCfg = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|x64.Build.0 = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|x86.ActiveCfg = Release|Any CPU
{3CECB972-EFFD-422B-9109-4D0D5AB6441E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -80,5 +124,8 @@ Global
{E5A71B17-7DDC-452E-AE20-141AFDAE906A} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{92335A36-F5AE-45AA-B691-5054C217E33A} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{36E27E57-4986-4178-98F8-3B4F6D985E2C} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{04A8B018-1954-48B8-BAAF-E17385114845} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{C3C581BD-E5DE-4CC4-B9A5-9F76602C69A4} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{3CECB972-EFFD-422B-9109-4D0D5AB6441E} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
EndGlobalSection
EndGlobal
50 changes: 50 additions & 0 deletions tests/Managers.Tests/Implementations/CliArgumentManagerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Models;

namespace Managers.Tests.Implementations
{
public class CliArgumentManagerTest
{
[Fact]
public async Task Execute_ValidArguments_ReturnsRemapVariables()
{
var manager = new CliArgumentManager();
var args = new[] { "GuitarPro", "LogicPro", "test.mid" };

var result = await manager.Execute(args);

Assert.Equal(DrumMapType.GuitarPro, result.SourceMapType);
Assert.Equal(DrumMapType.LogicPro, result.TargetMapType);
Assert.Equal("test.mid", result.MidiPath);
}

[Fact]
public async Task Execute_InsufficientArguments_ThrowsNullReferenceException()
{
var manager = new CliArgumentManager();
var args = new[] { "GuitarPro", "LogicPro" };

var ex = await Assert.ThrowsAsync<NullReferenceException>(() => manager.Execute(args));
Assert.Contains("Insufficient arguments", ex.Message);
}

[Fact]
public async Task Execute_InvalidSourceMap_ThrowsArgumentException()
{
var manager = new CliArgumentManager();
var args = new[] { "InvalidMap", "LogicPro", "test.mid" };

var ex = await Assert.ThrowsAsync<ArgumentException>(() => manager.Execute(args));
Assert.Contains("Invalid source map", ex.Message);
}

[Fact]
public async Task Execute_InvalidTargetMap_ThrowsArgumentException()
{
var manager = new CliArgumentManager();
var args = new[] { "GuitarPro", "InvalidMap", "test.mid" };

var ex = await Assert.ThrowsAsync<ArgumentException>(() => manager.Execute(args));
Assert.Contains("Invalid target map", ex.Message);
}
}
}
43 changes: 43 additions & 0 deletions tests/Managers.Tests/Implementations/MidiMapManagerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Moq;
using Services.Contracts;
using Models;

namespace Managers.Tests.Implementations;

public class MidiMapManagerTest
{
private const DrumMapType SOURCE = DrumMapType.GuitarPro;
private const DrumMapType TARGET = DrumMapType.StevenSlate;
private const string FILENAME = "test.mid";

[Fact]
public async Task RemapMidi_CallsServicesWithCorrectParameters()
{
// Arrange
var mockMapLoader = new Mock<IMapLoaderService>();
var mockMidiFileService = new Mock<IMidiFileService>();

var sourceMap = new DrumMap();
var targetMap = new DrumMap();

var variables = new RemapVariables
{
SourceMapType = SOURCE,
TargetMapType = TARGET,
MidiPath = FILENAME
};

mockMapLoader.Setup(m => m.LoadAsync(SOURCE)).ReturnsAsync(sourceMap);
mockMapLoader.Setup(m => m.LoadAsync(TARGET)).ReturnsAsync(targetMap);

var manager = new MidiMapManager(mockMapLoader.Object, mockMidiFileService.Object);

// Act
await manager.RemapMidi(variables);

// Assert
mockMapLoader.Verify(m => m.LoadAsync(SOURCE), Times.Once);
mockMapLoader.Verify(m => m.LoadAsync(TARGET), Times.Once);
mockMidiFileService.Verify(m => m.RemapAsync(sourceMap, targetMap, "test.mid"), Times.Once);
}
}
27 changes: 27 additions & 0 deletions tests/Managers.Tests/Managers.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
<Using Include="Managers.Implementations" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Managers\Managers.csproj" />
</ItemGroup>

</Project>
59 changes: 59 additions & 0 deletions tests/Models.Tests/DrumMapTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace Models.Tests;

public class DrumMapTest
{
[Fact]
public void DrumMap_DefaultConstructor_InitializesProperties()
{
var drumMap = new DrumMap();

Assert.NotNull(drumMap.Name);
Assert.Equal(string.Empty, drumMap.Name);
Assert.NotNull(drumMap.Mapping);
Assert.Empty(drumMap.Mapping);
}

[Fact]
public void DrumMap_CanSetName()
{
var drumMap = new DrumMap
{
Name = "My Drum Map"
};

Assert.Equal("My Drum Map", drumMap.Name);
}

[Fact]
public void DrumMap_CanAddMapping()
{
var drumMap = new DrumMap();
drumMap.Mapping["Kick"] = 36;
drumMap.Mapping["Snare"] = 38;

Assert.Equal(2, drumMap.Mapping.Count);
Assert.Equal(36, drumMap.Mapping["Kick"]);
Assert.Equal(38, drumMap.Mapping["Snare"]);
}

[Fact]
public void DrumMap_CanUpdateMapping()
{
var drumMap = new DrumMap();
drumMap.Mapping["Kick"] = 36;
drumMap.Mapping["Kick"] = 35;

Assert.Single(drumMap.Mapping);
Assert.Equal(35, drumMap.Mapping["Kick"]);
}

[Fact]
public void DrumMap_CanRemoveMapping()
{
var drumMap = new DrumMap();
drumMap.Mapping["Kick"] = 36;
drumMap.Mapping.Remove("Kick");

Assert.Empty(drumMap.Mapping);
}
}
34 changes: 34 additions & 0 deletions tests/Models.Tests/DrumMapTypeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace Models.Tests;

public class DrumMapTypeTest
{
[Fact]
public void DrumMapType_ContainsExpectedValues()
{
Assert.Equal(0, (int)DrumMapType.StevenSlate);
Assert.Equal(1, (int)DrumMapType.GuitarPro);
Assert.Equal(2, (int)DrumMapType.LogicPro);
Assert.Equal(3, (int)DrumMapType.ProTools);
}

[Theory]
[InlineData(DrumMapType.StevenSlate)]
[InlineData(DrumMapType.GuitarPro)]
[InlineData(DrumMapType.LogicPro)]
[InlineData(DrumMapType.ProTools)]
public void DrumMapType_IsDefined(DrumMapType type)
{
Assert.True(Enum.IsDefined(type));
}

[Theory]
[InlineData("StevenSlate", DrumMapType.StevenSlate)]
[InlineData("GuitarPro", DrumMapType.GuitarPro)]
[InlineData("LogicPro", DrumMapType.LogicPro)]
[InlineData("ProTools", DrumMapType.ProTools)]
public void DrumMapType_ParseString_ReturnsCorrectEnum(string name, DrumMapType expected)
{
var parsed = (DrumMapType)Enum.Parse(typeof(DrumMapType), name);
Assert.Equal(expected, parsed);
}
}
25 changes: 25 additions & 0 deletions tests/Models.Tests/Models.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Models\Models.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
<Using Include="Models" />
</ItemGroup>
</Project>
64 changes: 64 additions & 0 deletions tests/Models.Tests/RemapVariablesTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
namespace Models.Tests;

public class RemapVariablesTest
{
[Fact]
public void RemapVariables_DefaultConstructor_InitializesProperties()
{
var remapVariables = new RemapVariables
{
SourceMapType = DrumMapType.GuitarPro,
TargetMapType = DrumMapType.LogicPro,
MidiPath = "test.mid"
};

Assert.Equal(DrumMapType.GuitarPro, remapVariables.SourceMapType);
Assert.Equal(DrumMapType.LogicPro, remapVariables.TargetMapType);
Assert.Equal("test.mid", remapVariables.MidiPath);
}

[Fact]
public void RemapVariables_CanSetSourceMapType()
{
var remapVariables = new RemapVariables
{
SourceMapType = DrumMapType.LogicPro,
TargetMapType = DrumMapType.GuitarPro,
MidiPath = "file.mid"
};

remapVariables.SourceMapType = DrumMapType.GuitarPro;

Assert.Equal(DrumMapType.GuitarPro, remapVariables.SourceMapType);
}

[Fact]
public void RemapVariables_CanSetTargetMapType()
{
var remapVariables = new RemapVariables
{
SourceMapType = DrumMapType.GuitarPro,
TargetMapType = DrumMapType.LogicPro,
MidiPath = "file.mid"
};

remapVariables.TargetMapType = DrumMapType.GuitarPro;

Assert.Equal(DrumMapType.GuitarPro, remapVariables.TargetMapType);
}

[Fact]
public void RemapVariables_CanSetMidiPath()
{
var remapVariables = new RemapVariables
{
SourceMapType = DrumMapType.GuitarPro,
TargetMapType = DrumMapType.LogicPro,
MidiPath = "old.mid"
};

remapVariables.MidiPath = "new.mid";

Assert.Equal("new.mid", remapVariables.MidiPath);
}
}
Loading