using Avalonia; using Omika.App.Controls; using Xunit; namespace Omika.Tests.Controls; /// /// Tests de la machine à états du tracé de signature (mono-pointeur). La logique /// est extraite du contrôle visuel pour être testable /// sans plateforme de rendu Avalonia (environnement headless). /// public sealed class SignatureStrokeTrackerTests { [Fact] public void TryBeginStroke_PremierPointeur_ActiveLeTrait() { var tracker = new SignatureStrokeTracker(); bool started = tracker.TryBeginStroke(pointerId: 1, new Point(5, 5)); Assert.True(started); Assert.True(tracker.IsDrawing); Assert.Equal(1, tracker.ActivePointerId); Assert.Single(tracker.Points); Assert.Equal(new Point(5, 5), tracker.Points[0]); } [Fact] public void TryBeginStroke_SecondPointeurPendantTrait_EstIgnore() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(5, 5)); bool started = tracker.TryBeginStroke(pointerId: 2, new Point(99, 99)); Assert.False(started); Assert.Equal(1, tracker.ActivePointerId); Assert.Single(tracker.Points); Assert.Equal(new Point(5, 5), tracker.Points[0]); } [Fact] public void TryAddPoint_PointeurActif_AjoutePointEtRetournePrecedent() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(0, 0)); Point? previous = tracker.TryAddPoint(pointerId: 1, new Point(10, 20)); Assert.True(previous.HasValue); Assert.Equal(new Point(0, 0), previous!.Value); Assert.Equal(2, tracker.Points.Count); Assert.Equal(new Point(10, 20), tracker.Points[1]); } [Fact] public void TryAddPoint_PointeurNonActif_EstIgnore() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(0, 0)); Point? previous = tracker.TryAddPoint(pointerId: 2, new Point(99, 99)); Assert.Null(previous); Assert.Single(tracker.Points); } [Fact] public void EndStroke_ReinitialiseEtatComplet() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(0, 0)); tracker.TryAddPoint(pointerId: 1, new Point(10, 10)); tracker.EndStroke(); Assert.False(tracker.IsDrawing); Assert.Null(tracker.ActivePointerId); Assert.Empty(tracker.Points); } [Fact] public void NouveauTraitApresEndStroke_Fonctionne() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(0, 0)); tracker.EndStroke(); bool started = tracker.TryBeginStroke(pointerId: 3, new Point(7, 7)); Assert.True(started); Assert.Equal(3, tracker.ActivePointerId); Assert.Single(tracker.Points); Assert.Equal(new Point(7, 7), tracker.Points[0]); } [Fact] public void IsActivePointer_MauvaisPointeur_NeTerminePasLeTraitActif() { var tracker = new SignatureStrokeTracker(); tracker.TryBeginStroke(pointerId: 1, new Point(0, 0)); // Le relâchement d'un mauvais PointerId (second doigt) ne doit pas être // interprété comme la fin du trait actif. Assert.True(tracker.IsActivePointer(1)); Assert.False(tracker.IsActivePointer(2)); Assert.True(tracker.IsDrawing); } [Fact] public void TryAddPoint_SansTraitActif_RetourneNull() { var tracker = new SignatureStrokeTracker(); Point? previous = tracker.TryAddPoint(pointerId: 1, new Point(10, 10)); Assert.Null(previous); Assert.False(tracker.IsDrawing); } }