tray: --import-profile merges a profile document into the user config
RioJoy.Tray --import-profile <profile.json> merges a single-profile document (a repo's profiles/*.json) into %APPDATA%\RIOJoy\config.json via ConfigStore.ImportProfile: same-name profiles are replaced in place (FindProfile's case-insensitive convention), everything else appended, all other config content preserved. Refuses (exit 3) while a tray instance is running - a live tray rewrites the config from memory and would silently discard the import. Documents that a Name must be stated in the file itself: RioProfile defaults Name to 'Unnamed', so the import checks the raw JSON, not the deserialized object. This is the profile install story for bench machines and pods (previously: hand-paste into the Profiles array). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,87 @@ public class ConfigStoreTests
|
||||
Assert.Equal(File.ReadAllBytes(shipped), File.ReadAllBytes(reference));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportProfile_ShippedDescentFile_IntoFreshConfig()
|
||||
{
|
||||
string configPath = Path.Combine(Path.GetTempPath(), $"riojoy-import-{Guid.NewGuid():N}", "config.json");
|
||||
try
|
||||
{
|
||||
string shipped = Path.Combine(TestRepo.Root(), "profiles", "descent-d1x.json");
|
||||
ProfileImportResult result = ConfigStore.ImportProfile(configPath, shipped);
|
||||
|
||||
Assert.Equal("Descent", result.Name);
|
||||
Assert.False(result.Replaced);
|
||||
|
||||
RioProfile p = Assert.Single(ConfigStore.Load(configPath).Profiles);
|
||||
Assert.Equal("Descent", p.Name);
|
||||
// The routing must survive the import round-trip intact — this is the
|
||||
// exact payload a cabinet/bench install writes.
|
||||
Assert.NotNull(p.AxisRouting);
|
||||
Assert.Equal(new AxisRoute { Target = PadTarget.RightThumbY, Mode = AxisOutputMode.UnipolarPositive }, p.AxisRouting!.Z);
|
||||
}
|
||||
finally
|
||||
{
|
||||
string? dir = Path.GetDirectoryName(configPath);
|
||||
if (dir is not null && Directory.Exists(dir))
|
||||
Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportProfile_ReplacesSameName_PreservesEverythingElse()
|
||||
{
|
||||
string configPath = Path.Combine(Path.GetTempPath(), $"riojoy-import-{Guid.NewGuid():N}", "config.json");
|
||||
try
|
||||
{
|
||||
ConfigStore.Save(new AppConfig
|
||||
{
|
||||
DefaultRioComPort = "COM7",
|
||||
NeutralProfileName = "Desktop",
|
||||
Profiles =
|
||||
{
|
||||
new RioProfile { Name = "Desktop" },
|
||||
new RioProfile { Name = "descent", PlasmaGreeting = "STALE" }, // case-insensitive match
|
||||
},
|
||||
}, configPath);
|
||||
|
||||
string shipped = Path.Combine(TestRepo.Root(), "profiles", "descent-d1x.json");
|
||||
ProfileImportResult result = ConfigStore.ImportProfile(configPath, shipped);
|
||||
Assert.True(result.Replaced);
|
||||
|
||||
AppConfig back = ConfigStore.Load(configPath);
|
||||
Assert.Equal("COM7", back.DefaultRioComPort); // untouched settings survive
|
||||
Assert.Equal("Desktop", back.NeutralProfileName);
|
||||
Assert.Equal(2, back.Profiles.Count); // replaced in place, not appended
|
||||
RioProfile descent = Assert.IsType<RioProfile>(back.FindProfile("Descent"));
|
||||
Assert.Equal("DESCENT", descent.PlasmaGreeting); // stale profile fully overwritten
|
||||
}
|
||||
finally
|
||||
{
|
||||
string? dir = Path.GetDirectoryName(configPath);
|
||||
if (dir is not null && Directory.Exists(dir))
|
||||
Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImportProfile_NamelessProfile_Throws()
|
||||
{
|
||||
string dir = Path.Combine(Path.GetTempPath(), $"riojoy-import-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(dir);
|
||||
try
|
||||
{
|
||||
string profilePath = Path.Combine(dir, "nameless.json");
|
||||
File.WriteAllText(profilePath, "{\"PlasmaGreeting\":\"X\"}");
|
||||
Assert.Throws<Newtonsoft.Json.JsonSerializationException>(
|
||||
() => ConfigStore.ImportProfile(Path.Combine(dir, "config.json"), profilePath));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(dir, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Load_MissingFile_ReturnsDefaults()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user