Files
riojoy/tests/RioJoy.Core.Tests/Editing/CockpitPanelTests.cs
T
CydandClaude Opus 4.8 4994ab699f Editor cockpit rework + dormant-by-default serial port use
Profile editor:
- Cockpit-style encoder gauges centered over the Upper Middle MFD: Z left,
  X/Y right, and L/R/Rz arranged as a big "U".
- [JoyStick] section surfaced as a vertical "Axis" toggle column (6 inverts
  + ZR mix), written back to the profile's calibration.
- Tighten the panel layout (close gaps, trim empty border columns); colour the
  Secondary/Screen columns yellow; rename the "Joystick / Hat" board to
  "Joystick"; add an "Import .ini..." tray entry.
- "RIO commands (live)" button group (all RioCommandCodes) fired at the live RIO.

Serial-port handling:
- Start dormant; only take the COM port for a profiled game (auto-switch) or
  while editing, so the native games can open the port without clashing.
- Editor sessions hold the port but route keyboard/mouse/joystick to no-op
  sinks (NullInputSink), so button function can be checked without injecting
  input; RioRuntime.ButtonActivity drives a live cyan press indicator and
  lamp feedback still applies.
- AutoSwitchWatcher.Reset() re-syncs the watcher after an editor session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 22:55:53 -05:00

69 lines
2.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using RioJoy.Core.Editing;
using RioJoy.Core.Mapping;
using Xunit;
namespace RioJoy.Core.Tests.Editing;
public class CockpitPanelTests
{
[Fact]
public void Covers_EveryValidAddress_ExactlyOnce()
{
List<int> addrs = CockpitPanel.Buttons().Select(b => b.Address).ToList();
// 0x000x47 buttons + 0x500x6F keypads = 104 valid addresses; 0x480x4F don't exist.
var expected = Enumerable.Range(0x00, 0x48).Concat(Enumerable.Range(0x50, 0x20)).ToHashSet();
Assert.Equal(expected.Count, addrs.Count); // no duplicates / no extras
Assert.Equal(expected, addrs.ToHashSet()); // exactly the valid set
Assert.DoesNotContain(0x48, addrs); // gap excluded
}
[Theory]
[InlineData(0x2F, "Upper Left MFD")]
[InlineData(0x20, "Upper Middle MFD")]
[InlineData(0x37, "Upper Right MFD")]
[InlineData(0x00, "Lower Right MFD")]
[InlineData(0x0F, "Lower Left MFD")]
[InlineData(0x38, "Throttle")]
[InlineData(0x10, "Secondary")]
[InlineData(0x18, "Screen")]
[InlineData(0x40, "Joystick")]
[InlineData(0x50, "Internal Keypad")]
[InlineData(0x6F, "External Keypad")]
public void Address_LandsInExpectedGroup(int address, string group)
{
PanelButton b = CockpitPanel.Buttons().Single(x => x.Address == address);
Assert.Equal(group, b.Group.Title);
}
[Fact]
public void Keypads_AreNotLampCapable()
{
foreach (PanelButton b in CockpitPanel.Buttons().Where(x => x.Group.Kind == PanelGroupKind.Keypad))
Assert.False(b.LampCapable);
// ...and everything else is.
foreach (PanelButton b in CockpitPanel.Buttons().Where(x => x.Group.Kind != PanelGroupKind.Keypad))
Assert.True(b.LampCapable);
}
[Fact]
public void Keypad_PhysicalLayout_MapsDigitsToAddresses()
{
// Internal keypad: top-left "1" -> 0x51, bottom-middle "0" -> 0x50, "C" -> 0x5C.
IReadOnlyList<PanelButton> all = CockpitPanel.Buttons();
PanelGroup pad = CockpitPanel.Groups.Single(g => g.Title == "Internal Keypad");
Assert.Equal(0x51, pad.Addresses[0]); // row0 col0 = "1"
Assert.Equal(0x5C, pad.Addresses[3]); // row0 col3 = "C"
Assert.Equal(0x50, pad.Addresses[13]); // row3 col1 = "0"
Assert.Equal(0x5F, pad.Addresses[15]); // row3 col3 = "F"
}
[Fact]
public void AllAddresses_AreValidRioAddresses()
{
foreach (PanelButton b in CockpitPanel.Buttons())
Assert.InRange(b.Address, 0, RioAddress.MaxAddress);
}
}