A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

65 lines
2.6 KiB

using System.Collections.Generic;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.PullToRefresh;
using Avalonia.Input;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests.PullToRefresh;
public class ScrollablePullGestureRecognizerTests : ScopedTestBase
{
// Repro for the "PointerCaptureLost doesn't clean up state" bug.
//
// PointerReleased clears _pullInProgress, _tracking, _initialPosition.
// PointerCaptureLost only raises EndPull (so the PullGestureEnded event fires)
// but leaves _pullInProgress == true and _tracking pointing at the lost pointer.
// The next gesture re-enters PointerMoved with (_pullInProgress=true, pulling=true)
// and goes straight to HandlePull, skipping BeginPull. This reuses the OLD _gestureId
// for the next PullGestureEvent - the same id that was just used in the
// PullGestureEndedEvent for the previous gesture.
[Fact]
public void Gesture_After_PointerCaptureLost_Uses_A_New_Id()
{
var scrollable = new TestScrollable();
var recognizer = new ScrollablePullGestureRecognizer(PullDirection.TopToBottom, isMouseEnabled: true);
scrollable.GestureRecognizers.Add(recognizer);
var root = new TestRoot(scrollable);
var pullIds = new List<int>();
var endedIds = new List<int>();
root.AddHandler(InputElement.PullGestureEvent, (_, e) => pullIds.Add(e.Id));
root.AddHandler(InputElement.PullGestureEndedEvent, (_, e) => endedIds.Add(e.Id));
var touch = new TouchTestHelper();
// First gesture: start pulling downwards so the recognizer begins a pull and captures the pointer.
touch.Down(scrollable, new Point(10, 20));
touch.Move(scrollable, new Point(10, 70));
Assert.Single(pullIds);
var firstGestureId = pullIds[0];
// Capture is lost (e.g. another control steals it, or the visual is detached mid-gesture)
touch.Cancel();
Assert.Equal([firstGestureId], endedIds);
// Second gesture must begin cleanly (BeginPull, not HandlePull) and therefore get a fresh id.
touch.Down(scrollable, new Point(10, 20));
touch.Move(scrollable, new Point(10, 70));
Assert.Equal(2, pullIds.Count);
Assert.NotEqual(firstGestureId, pullIds[1]);
}
private sealed class TestScrollable : Decorator, IScrollable
{
public Size Extent => new(100, 1000);
public Vector Offset { get; set; }
public Size Viewport => new(100, 100);
public bool CanHorizontallyScroll { get => false; }
public bool CanVerticallyScroll { get => true; }
}
}