junction/tests/Junction.Tests/Unit/DataItemRowViewModelTests.cs
dtrentin 54f8b3be25 feat: history & trends (v0.6)
Time-series history persisted + per-item trend sparklines in detail view.

Data (Domain+Persistence): HistoryPoint model; IMachineRepository +Append/
Get/Prune history; snapshot_history table (append-only) + index; DeleteAsync
cascades history. Port purity kept (Result/Cancelled, no throw).

Core: MachineMonitor.PersistAsync appends history on Connected snapshots +
throttled retention prune (7-day window, <=1/hour via Interlocked-CAS), never
blocks/undoes latest-snapshot save.

App: custom Sparkline Control (StreamGeometry polyline, min/max-scaled,
net48-safe, no charting dep); DataItemRowViewModel observable +Trend/HasTrend +
pure TryParseNumeric; MachineDetailViewModel loads per-item history (1h window,
60 pts) on load + each snapshot, parses numeric, sets Trend on UI thread;
detail view Trend column.

Projects: Domain, Persistence, Core, App, Tests (+31: 196 pass + 2 skip).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 08:57:52 +02:00

39 lines
1.2 KiB
C#

using Junction.App.ViewModels;
using Xunit;
namespace Junction.Tests.Unit
{
/// <summary>
/// Data-level tests for the culture-invariant numeric parse that decides whether a datum can
/// feed the trend sparkline. Pure static helper — no Avalonia platform required.
/// </summary>
public class DataItemRowViewModelTests
{
[Theory]
[InlineData("12.5", 12.5)]
[InlineData(" 3 ", 3)]
[InlineData("1000", 1000)]
[InlineData("-4.25", -4.25)]
public void TryParseNumeric_Numeric_ReturnsTrueWithInvariantValue(string input, double expected)
{
var ok = DataItemRowViewModel.TryParseNumeric(input, out var result);
Assert.True(ok);
Assert.Equal(expected, result);
}
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData("abc")]
[InlineData("ON")]
[InlineData("AVAILABLE")]
[InlineData(null)]
public void TryParseNumeric_NonNumeric_ReturnsFalse(string? input)
{
var ok = DataItemRowViewModel.TryParseNumeric(input, out _);
Assert.False(ok);
}
}
}