зеркало из https://github.com/DeGsoft/maui-linux.git
Speed up core UI tests and reduce flakiness (#6395)
* Speed up ViewUITests and hopefully reduce flakiness * Make focus tests work even when keyboard pops up * Move Date/Time picker tests to the end so they can't break the other bubbling tests Add delay before trying to dismiss dialogs so they can fully appear * Fix accidental triggering of Picker when removing focus from Entry * Bump up number of tests before restart
This commit is contained in:
Родитель
ca409d3d14
Коммит
3bc2e5e94b
|
@ -73,6 +73,7 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
{
|
||||
// These controls show a pop-up which we have to cancel/done out of before we can continue
|
||||
#if __ANDROID__
|
||||
System.Threading.Tasks.Task.Delay(2000).Wait(); // If we hit back before the dialog is fully up, it may not dismiss
|
||||
RunningApp.Back();
|
||||
#elif __IOS__
|
||||
var cancelButtonText = "Done";
|
||||
|
@ -200,9 +201,6 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
// We don't use 'SearchBar' here because on Android it sometimes finds the wrong control
|
||||
col1.Children.Add(MenuButton("TestSearchBar", () => new SearchBar()));
|
||||
|
||||
col2.Children.Add(MenuButton(nameof(DatePicker), () => new DatePicker()));
|
||||
col2.Children.Add(MenuButton(nameof(TimePicker), () => new TimePicker()));
|
||||
|
||||
var slider = new Slider();
|
||||
slider.On<iOS>().SetUpdateOnTap(true);
|
||||
col2.Children.Add(MenuButton(nameof(Slider), () => slider));
|
||||
|
@ -211,6 +209,9 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
col2.Children.Add(MenuButton(nameof(Stepper), () => new Stepper()));
|
||||
col2.Children.Add(MenuButton(nameof(BoxView), () => new BoxView { BackgroundColor = Color.DarkMagenta, WidthRequest = 100, HeightRequest = 100 }));
|
||||
|
||||
col2.Children.Add(MenuButton(nameof(DatePicker), () => new DatePicker()));
|
||||
col2.Children.Add(MenuButton(nameof(TimePicker), () => new TimePicker()));
|
||||
|
||||
return new ContentPage { Content = layout };
|
||||
}
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ namespace Xamarin.Forms.Controls
|
|||
}
|
||||
|
||||
static int s_testsrun;
|
||||
const int ConsecutiveTestLimit = 10;
|
||||
const int ConsecutiveTestLimit = 20;
|
||||
|
||||
// Until we get more of our memory leak issues worked out, restart the app
|
||||
// after a specified number of tests so we don't get bogged down in GC
|
||||
|
|
|
@ -1,105 +1,75 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
using System.Linq;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
|
||||
namespace Xamarin.Forms.Controls
|
||||
{
|
||||
internal class CoreGalleryPage<T> : ContentPage
|
||||
where T : View, new ()
|
||||
where T : View, new()
|
||||
{
|
||||
List<View> _views;
|
||||
List<ViewContainer<T>> _viewContainers;
|
||||
|
||||
int _currentIndex;
|
||||
Picker _picker;
|
||||
StackLayout _moveNextStack;
|
||||
|
||||
ViewContainer<T> _backgroundColorViewContainer;
|
||||
ViewContainer<T> _opacityViewContainer;
|
||||
ViewContainer<T> _rotationViewContainer;
|
||||
ViewContainer<T> _rotationXViewContainer;
|
||||
ViewContainer<T> _rotationYViewContainer;
|
||||
ViewContainer<T> _scaleViewContainer;
|
||||
ViewContainer<T> _translationXViewContainer;
|
||||
ViewContainer<T> _translationYViewContainer;
|
||||
|
||||
StateViewContainer<T> _focusStateViewContainer;
|
||||
StateViewContainer<T> _isFocusedStateViewContainer;
|
||||
StateViewContainer<T> _isVisibleStateViewContainer;
|
||||
|
||||
EventViewContainer<T> _gestureRecognizerEventViewContainer;
|
||||
EventViewContainer<T> _focusedEventViewContainer;
|
||||
EventViewContainer<T> _unfocusedEventViewContainer;
|
||||
|
||||
LayeredViewContainer<T> _inputTransparentViewContainer;
|
||||
Entry _targetEntry;
|
||||
StackLayout _layout;
|
||||
|
||||
protected StateViewContainer<T> IsEnabledStateViewContainer { get; private set; }
|
||||
|
||||
protected StackLayout Layout { get; private set; }
|
||||
|
||||
internal CoreGalleryPage ()
|
||||
internal CoreGalleryPage()
|
||||
{
|
||||
Layout = new StackLayout {
|
||||
Padding = new Thickness (20)
|
||||
Layout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(20)
|
||||
};
|
||||
|
||||
var modalDismissButton = new Button () {
|
||||
var modalDismissButton = new Button()
|
||||
{
|
||||
Text = "Dismiss Page",
|
||||
Command = new Command (async () =>
|
||||
{
|
||||
if (_picker.SelectedIndex == 0)
|
||||
await Navigation.PopAsync();
|
||||
else
|
||||
_picker.SelectedIndex--;
|
||||
})
|
||||
Command = new Command(async () =>
|
||||
{
|
||||
if (_picker.SelectedIndex == 0)
|
||||
{
|
||||
await Navigation.PopAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
_picker.SelectedIndex--;
|
||||
}
|
||||
})
|
||||
};
|
||||
Layout.Children.Add (modalDismissButton);
|
||||
Layout.Children.Add(modalDismissButton);
|
||||
|
||||
Build (Layout);
|
||||
Build(Layout);
|
||||
|
||||
Content = new ScrollView { AutomationId = "GalleryScrollView", Content = Layout };
|
||||
|
||||
}
|
||||
|
||||
protected virtual void InitializeElement (T element) {}
|
||||
protected virtual void InitializeElement(T element) { }
|
||||
|
||||
protected virtual void Build (StackLayout stackLayout)
|
||||
protected virtual void Build(StackLayout stackLayout)
|
||||
{
|
||||
var isFocusedView = new T ();
|
||||
isFocusedView.SetValueCore (IsFocusedPropertyKey, true);
|
||||
var isFocusedView = new T();
|
||||
isFocusedView.SetValueCore(IsFocusedPropertyKey, true);
|
||||
|
||||
var viewContainers = new[] {
|
||||
_isFocusedStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsFocused, isFocusedView),
|
||||
_backgroundColorViewContainer = new ViewContainer<T> (Test.VisualElement.BackgroundColor, new T { BackgroundColor = Color.Blue }),
|
||||
_focusStateViewContainer = new StateViewContainer<T> (Test.VisualElement.Focus, new T ()),
|
||||
_gestureRecognizerEventViewContainer = new EventViewContainer<T> (Test.View.GestureRecognizers, new T ()),
|
||||
_inputTransparentViewContainer = new LayeredViewContainer<T> (Test.VisualElement.InputTransparent, new T { InputTransparent = true }),
|
||||
IsEnabledStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsEnabled, new T { IsEnabled = true }),
|
||||
_focusedEventViewContainer = new EventViewContainer<T> (Test.VisualElement.Focused, new T ()),
|
||||
_unfocusedEventViewContainer = new EventViewContainer<T> (Test.VisualElement.Unfocused, new T ()),
|
||||
_isVisibleStateViewContainer = new StateViewContainer<T> (Test.VisualElement.IsVisible, new T { IsVisible = true }),
|
||||
_opacityViewContainer = new ViewContainer<T> (Test.VisualElement.Opacity, new T { Opacity = 0.5 }),
|
||||
_rotationViewContainer = new ViewContainer<T> (Test.VisualElement.Rotation, new T { Rotation = 10 }),
|
||||
_rotationXViewContainer = new ViewContainer<T> (Test.VisualElement.RotationX, new T { RotationX = 33 }),
|
||||
_rotationYViewContainer = new ViewContainer<T> (Test.VisualElement.RotationY, new T { RotationY = 10 }),
|
||||
_scaleViewContainer = new ViewContainer<T> (Test.VisualElement.Scale, new T { Scale = 0.5 }),
|
||||
_translationXViewContainer = new ViewContainer<T> (Test.VisualElement.TranslationX, new T { TranslationX = 30 }),
|
||||
_translationYViewContainer = new ViewContainer<T> (Test.VisualElement.TranslationY, new T { TranslationY = 30 }),
|
||||
};
|
||||
|
||||
// Set state
|
||||
IsEnabledStateViewContainer.StateChangeButton.Command = new Command (() => {
|
||||
IsEnabledStateViewContainer = new StateViewContainer<T>(Test.VisualElement.IsEnabled, new T { IsEnabled = true });
|
||||
IsEnabledStateViewContainer.StateChangeButton.Command = new Command(() =>
|
||||
{
|
||||
IsEnabledStateViewContainer.View.IsEnabled = !IsEnabledStateViewContainer.View.IsEnabled;
|
||||
});
|
||||
_isVisibleStateViewContainer.StateChangeButton.Command = new Command (() => {
|
||||
_isVisibleStateViewContainer.View.IsVisible = !_isVisibleStateViewContainer.View.IsVisible;
|
||||
|
||||
var isVisibleStateViewContainer = new StateViewContainer<T>(Test.VisualElement.IsVisible, new T { IsVisible = true });
|
||||
isVisibleStateViewContainer.StateChangeButton.Command = new Command(() =>
|
||||
{
|
||||
isVisibleStateViewContainer.View.IsVisible = !isVisibleStateViewContainer.View.IsVisible;
|
||||
});
|
||||
|
||||
|
||||
_isFocusedStateViewContainer.StateChangeButton.Command = new Command(() => {
|
||||
var isFocusedStateViewContainer = new StateViewContainer<T>(Test.VisualElement.IsFocused, isFocusedView);
|
||||
isFocusedStateViewContainer.StateChangeButton.Command = new Command(() =>
|
||||
{
|
||||
|
||||
if ((bool)isFocusedView.GetValue(VisualElement.IsFocusedProperty))
|
||||
{
|
||||
|
@ -111,48 +81,66 @@ namespace Xamarin.Forms.Controls
|
|||
}
|
||||
});
|
||||
|
||||
_focusStateViewContainer.StateChangeButton.Command = new Command (() => {
|
||||
if (_focusStateViewContainer.View.IsFocused) {
|
||||
_focusStateViewContainer.View.Unfocus ();
|
||||
} else {
|
||||
_focusStateViewContainer.View.Focus ();
|
||||
var focusStateViewContainer = new StateViewContainer<T>(Test.VisualElement.Focus, new T());
|
||||
focusStateViewContainer.StateChangeButton.Command = new Command(() =>
|
||||
{
|
||||
if (focusStateViewContainer.View.IsFocused)
|
||||
{
|
||||
focusStateViewContainer.View.Unfocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
focusStateViewContainer.View.Focus();
|
||||
}
|
||||
});
|
||||
|
||||
_focusedEventViewContainer.View.Focused += (sender, args) => _focusedEventViewContainer.EventFired ();
|
||||
_unfocusedEventViewContainer.View.Unfocused += (sender, args) => _unfocusedEventViewContainer.EventFired ();
|
||||
var focusedEventViewContainer = new EventViewContainer<T>(Test.VisualElement.Focused, new T());
|
||||
focusedEventViewContainer.View.Focused += (sender, args) => focusedEventViewContainer.EventFired();
|
||||
|
||||
_gestureRecognizerEventViewContainer.View.GestureRecognizers.Add (
|
||||
new TapGestureRecognizer {
|
||||
Command = new Command (() => _gestureRecognizerEventViewContainer.EventFired ())
|
||||
var unfocusedEventViewContainer = new EventViewContainer<T>(Test.VisualElement.Unfocused, new T());
|
||||
unfocusedEventViewContainer.View.Unfocused += (sender, args) => unfocusedEventViewContainer.EventFired();
|
||||
|
||||
var gestureRecognizerEventViewContainer = new EventViewContainer<T>(Test.View.GestureRecognizers, new T());
|
||||
gestureRecognizerEventViewContainer.View.GestureRecognizers.Add(
|
||||
new TapGestureRecognizer
|
||||
{
|
||||
Command = new Command(() => gestureRecognizerEventViewContainer.EventFired())
|
||||
}
|
||||
);
|
||||
|
||||
_views = new List<View> (viewContainers.Select (o => o.ContainerLayout));
|
||||
|
||||
_moveNextStack = new StackLayout ();
|
||||
var moveNextButton = new Button ();
|
||||
moveNextButton.Text = "Move Next";
|
||||
moveNextButton.AutomationId = "MoveNextButton";
|
||||
moveNextButton.Clicked += delegate (object sender, EventArgs e) {
|
||||
if (!_views.Any ())
|
||||
return;
|
||||
|
||||
if (_currentIndex + 1 >= _views.Count) {
|
||||
return;
|
||||
}
|
||||
|
||||
_currentIndex += 1;
|
||||
|
||||
_moveNextStack.Children.RemoveAt (2);
|
||||
_moveNextStack.Children.Add (_views[_currentIndex]);
|
||||
_picker.SelectedIndexChanged -= PickerSelectedIndexChanged;
|
||||
_picker.SelectedIndex = _currentIndex;
|
||||
_picker.SelectedIndexChanged += PickerSelectedIndexChanged;
|
||||
_viewContainers = new List<ViewContainer<T>> {
|
||||
isFocusedStateViewContainer,
|
||||
new ViewContainer<T> (Test.VisualElement.BackgroundColor, new T { BackgroundColor = Color.Blue }),
|
||||
focusStateViewContainer,
|
||||
gestureRecognizerEventViewContainer,
|
||||
new LayeredViewContainer<T> (Test.VisualElement.InputTransparent, new T { InputTransparent = true }),
|
||||
IsEnabledStateViewContainer,
|
||||
focusedEventViewContainer,
|
||||
unfocusedEventViewContainer,
|
||||
isVisibleStateViewContainer,
|
||||
new ViewContainer<T> (Test.VisualElement.Opacity, new T { Opacity = 0.5 }),
|
||||
new ViewContainer<T> (Test.VisualElement.Rotation, new T { Rotation = 10 }),
|
||||
new ViewContainer<T> (Test.VisualElement.RotationX, new T { RotationX = 33 }),
|
||||
new ViewContainer<T> (Test.VisualElement.RotationY, new T { RotationY = 10 }),
|
||||
new ViewContainer<T> (Test.VisualElement.Scale, new T { Scale = 0.5 }),
|
||||
new ViewContainer<T> (Test.VisualElement.TranslationX, new T { TranslationX = 30 }),
|
||||
new ViewContainer<T> (Test.VisualElement.TranslationY, new T { TranslationY = 30 }),
|
||||
};
|
||||
|
||||
_layout = new StackLayout();
|
||||
|
||||
_targetEntry = new Entry { AutomationId = "TargetViewContainer", Placeholder = "Jump To ViewContainer" };
|
||||
|
||||
var goButton = new Button
|
||||
{
|
||||
Text = "Go",
|
||||
AutomationId = "GoButton"
|
||||
};
|
||||
goButton.Clicked += GoClicked;
|
||||
|
||||
_picker = new Picker();
|
||||
foreach (var container in viewContainers) {
|
||||
foreach (var container in _viewContainers)
|
||||
{
|
||||
_picker.Items.Add(container.TitleLabel.Text);
|
||||
}
|
||||
|
||||
|
@ -160,32 +148,77 @@ namespace Xamarin.Forms.Controls
|
|||
|
||||
_picker.SelectedIndexChanged += PickerSelectedIndexChanged;
|
||||
|
||||
_moveNextStack.Children.Add (_picker);
|
||||
_moveNextStack.Children.Add (moveNextButton);
|
||||
_moveNextStack.Children.Add (_views[_currentIndex]);
|
||||
_layout.Children.Add(_picker);
|
||||
_layout.Children.Add(_targetEntry);
|
||||
_layout.Children.Add(goButton);
|
||||
_layout.Children.Add(_viewContainers[_currentIndex].ContainerLayout);
|
||||
|
||||
stackLayout.Children.Add (_moveNextStack);
|
||||
stackLayout.Children.Add(_layout);
|
||||
|
||||
if (!SupportsFocus) {
|
||||
stackLayout.Children.Remove (_focusStateViewContainer.ContainerLayout);
|
||||
stackLayout.Children.Remove (_isFocusedStateViewContainer.ContainerLayout);
|
||||
if (!SupportsFocus)
|
||||
{
|
||||
stackLayout.Children.Remove(focusStateViewContainer.ContainerLayout);
|
||||
stackLayout.Children.Remove(isFocusedStateViewContainer.ContainerLayout);
|
||||
}
|
||||
|
||||
if (!SupportsTapGestureRecognizer)
|
||||
stackLayout.Children.Remove (_gestureRecognizerEventViewContainer.ContainerLayout);
|
||||
{
|
||||
stackLayout.Children.Remove(gestureRecognizerEventViewContainer.ContainerLayout);
|
||||
}
|
||||
|
||||
foreach (var element in viewContainers)
|
||||
InitializeElement (element.View);
|
||||
foreach (var element in _viewContainers)
|
||||
{
|
||||
InitializeElement(element.View);
|
||||
}
|
||||
}
|
||||
|
||||
void PickerSelectedIndexChanged (object sender, EventArgs eventArgs)
|
||||
void GoClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (!_viewContainers.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var target = _targetEntry.Text;
|
||||
_targetEntry.Text = "";
|
||||
var index = -1;
|
||||
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int n = 0; n < _viewContainers.Count; n++)
|
||||
{
|
||||
if (_viewContainers[n].View.AutomationId == target)
|
||||
{
|
||||
index = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetContainer = _viewContainers[index];
|
||||
|
||||
_layout.Children.RemoveAt(3);
|
||||
_layout.Children.Add(targetContainer.ContainerLayout);
|
||||
|
||||
_picker.SelectedIndexChanged -= PickerSelectedIndexChanged;
|
||||
_picker.SelectedIndex = index;
|
||||
_picker.SelectedIndexChanged += PickerSelectedIndexChanged;
|
||||
}
|
||||
|
||||
void PickerSelectedIndexChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_currentIndex = _picker.SelectedIndex;
|
||||
_moveNextStack.Children.RemoveAt (2);
|
||||
_moveNextStack.Children.Add (_views[_currentIndex]);
|
||||
_layout.Children.RemoveAt(3);
|
||||
_layout.Children.Add(_viewContainers[_currentIndex].ContainerLayout);
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool SupportsTapGestureRecognizer
|
||||
{
|
||||
get { return true; }
|
||||
|
@ -196,9 +229,10 @@ namespace Xamarin.Forms.Controls
|
|||
get { return true; }
|
||||
}
|
||||
|
||||
protected void Add (ViewContainer<T> view) {
|
||||
_views.Add (view.ContainerLayout);
|
||||
_picker.Items.Add(view.TitleLabel.Text);
|
||||
protected void Add(ViewContainer<T> viewContainer)
|
||||
{
|
||||
_viewContainers.Add(viewContainer);
|
||||
_picker.Items.Add(viewContainer.TitleLabel.Text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -74,24 +74,10 @@ namespace Xamarin.Forms.Core.UITests
|
|||
};
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
#if __MACOS__
|
||||
var result = App.Query(o => o.Raw(ViewQuery));
|
||||
#else
|
||||
var result = App.Query (o => o.Raw(ContainerQuery));
|
||||
#endif
|
||||
|
||||
if (result.Any())
|
||||
break;
|
||||
App.Tap(o => o.Raw("* marked:'MoveNextButton'"));
|
||||
}
|
||||
|
||||
//Assert.True (App.ScrollForElement (
|
||||
// ContainerQuery, new Drag (scrollBounds, Drag.Direction.BottomToTop, Drag.DragLength.Medium)
|
||||
//), "Failed to find element in: " + callerMemberName);
|
||||
|
||||
App.Screenshot("Go to element");
|
||||
App.WaitForElement("TargetViewContainer");
|
||||
App.Tap("TargetViewContainer");
|
||||
App.EnterText(callerMemberName.Replace("_", "") + "VisualElement");
|
||||
App.Tap("GoButton");
|
||||
}
|
||||
|
||||
public void TapView()
|
||||
|
@ -161,6 +147,8 @@ namespace Xamarin.Forms.Core.UITests
|
|||
}
|
||||
#endif
|
||||
|
||||
App.WaitForElement(q => q.Raw(query));
|
||||
|
||||
bool found = MaybeGetProperty<string>(App, query, propertyPath, out prop) ||
|
||||
MaybeGetProperty<float>(App, query, propertyPath, out prop) ||
|
||||
MaybeGetProperty<bool>(App, query, propertyPath, out prop) ||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using NUnit.Framework;
|
||||
using Xamarin.Forms.Controls.Issues;
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.UITest.Queries;
|
||||
|
||||
namespace Xamarin.Forms.Core.UITests
|
||||
{
|
||||
|
@ -25,14 +26,18 @@ namespace Xamarin.Forms.Core.UITests
|
|||
{
|
||||
var remote = new StateViewContainerRemote(App, Test.VisualElement.Focus, PlatformViewType);
|
||||
remote.GoTo();
|
||||
bool isFocused = System.Convert.ToBoolean( App.Query("FocusStateLabel")[0].ReadText());
|
||||
Assert.IsFalse(isFocused);
|
||||
|
||||
Assert.IsFalse(IsFocused());
|
||||
remote.TapView();
|
||||
isFocused = System.Convert.ToBoolean(App.Query("FocusStateLabel")[0].ReadText());
|
||||
Assert.IsTrue(isFocused);
|
||||
App.Tap("FocusStateLabel");
|
||||
isFocused = System.Convert.ToBoolean(App.Query("FocusStateLabel")[0].ReadText());
|
||||
Assert.IsFalse(isFocused);
|
||||
Assert.IsTrue(IsFocused());
|
||||
App.Tap("Go"); // Won't do anything, we just need to take focus away from the Entry
|
||||
Assert.IsFalse(IsFocused());
|
||||
}
|
||||
|
||||
bool IsFocused()
|
||||
{
|
||||
var focusedText = App.Query(q => q.Marked("FocusStateLabel").All())[0].ReadText();
|
||||
return System.Convert.ToBoolean(focusedText);
|
||||
}
|
||||
|
||||
[UiTestExempt(ExemptReason.CannotTest, "Invalid interaction")]
|
||||
|
|
Загрузка…
Ссылка в новой задаче