Browse Source

Merge branch 'master' into fixes/10374-carousel-bringintoview-exception

pull/10470/head
Steven Kirk 3 years ago
committed by GitHub
parent
commit
ef3ffa68b0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      Avalonia.sln
  2. 1
      samples/IntegrationTestApp/MainWindow.axaml
  3. 12
      samples/IntegrationTestApp/MainWindow.axaml.cs
  4. 22
      samples/IntegrationTestApp/Program.cs
  5. 5
      src/Avalonia.Base/Input/AccessKeyHandler.cs
  6. 34
      src/Avalonia.Controls/MenuItem.cs
  7. 4
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  8. 2
      src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
  9. 25
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
  10. 25
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  11. 2
      tests/Avalonia.IntegrationTests.Appium/AutomationTests.cs
  12. 2
      tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs
  13. 2
      tests/Avalonia.IntegrationTests.Appium/CheckBoxTests.cs
  14. 14
      tests/Avalonia.IntegrationTests.Appium/CollectionDefinitions.cs
  15. 17
      tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs
  16. 38
      tests/Avalonia.IntegrationTests.Appium/DefaultAppFixture.cs
  17. 9
      tests/Avalonia.IntegrationTests.Appium/DefaultCollection.cs
  18. 2
      tests/Avalonia.IntegrationTests.Appium/GestureTests.cs
  19. 2
      tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs
  20. 16
      tests/Avalonia.IntegrationTests.Appium/MenuTests.cs
  21. 2
      tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs
  22. 19
      tests/Avalonia.IntegrationTests.Appium/OverlayPopupsAppFixture.cs
  23. 10
      tests/Avalonia.IntegrationTests.Appium/RadioButtonTests.cs
  24. 2
      tests/Avalonia.IntegrationTests.Appium/SliderTests.cs
  25. 2
      tests/Avalonia.IntegrationTests.Appium/WindowTests.cs
  26. 2
      tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs

11
Avalonia.sln

@ -555,9 +555,14 @@ Global
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.Build.0 = Release|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Release|Any CPU.Build.0 = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Debug|Any CPU.Build.0 = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Release|Any CPU.Build.0 = Release|Any CPU
{EE0F0DD4-A70D-472B-BD5D-B7D32D0E9386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE0F0DD4-A70D-472B-BD5D-B7D32D0E9386}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE0F0DD4-A70D-472B-BD5D-B7D32D0E9386}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -566,10 +571,6 @@ Global
{F4E36AA8-814E-4704-BC07-291F70F45193}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4E36AA8-814E-4704-BC07-291F70F45193}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4E36AA8-814E-4704-BC07-291F70F45193}.Release|Any CPU.Build.0 = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Debug|Any CPU.Build.0 = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C692FE73-43DB-49CE-87FC-F03ED61F25C9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -635,8 +636,8 @@ Global
{90B08091-9BBD-4362-B712-E9F2CC62B218} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{75C47156-C5D8-44BC-A5A7-E8657C2248D6} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C810060E-3809-4B74-A125-F11533AF9C1B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{F4E36AA8-814E-4704-BC07-291F70F45193} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{C692FE73-43DB-49CE-87FC-F03ED61F25C9} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{F4E36AA8-814E-4704-BC07-291F70F45193} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

1
samples/IntegrationTestApp/MainWindow.axaml

@ -25,6 +25,7 @@
<StackPanel DockPanel.Dock="Bottom" Margin="4" Orientation="Horizontal">
<TextBlock Margin="0,0,4,0">WindowState:</TextBlock>
<TextBlock Name="MainWindowState" Text="{Binding WindowState}"/>
<TextBlock Name="AppOverlayPopups" Margin="8 0"/>
</StackPanel>
<TabControl TabStripPlacement="Left" Name="MainTabs">

12
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -1,19 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
using Avalonia.Automation;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.VisualTree;
using Microsoft.CodeAnalysis;
using Avalonia.Controls.Primitives;
using Avalonia.Threading;
using Avalonia.Controls.Primitives.PopupPositioning;
namespace IntegrationTestApp
{
@ -25,6 +23,10 @@ namespace IntegrationTestApp
InitializeViewMenu();
InitializeGesturesTab();
this.AttachDevTools();
var overlayPopups = this.Get<TextBlock>("AppOverlayPopups");
overlayPopups.Text = Program.OverlayPopups ? "Overlay Popups" : "Native Popups";
AddHandler(Button.ClickEvent, OnButtonClick);
ListBoxItems = Enumerable.Range(0, 100).Select(x => "Item " + x).ToList();
DataContext = this;

22
samples/IntegrationTestApp/Program.cs

@ -1,17 +1,31 @@
using System;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace IntegrationTestApp
{
class Program
{
public static bool OverlayPopups { get; private set; }
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
public static void Main(string[] args)
{
OverlayPopups = args.Contains("--overlayPopups");
BuildAvaloniaApp()
.With(new Win32PlatformOptions
{
OverlayPopups = OverlayPopups,
})
.With(new AvaloniaNativePlatformOptions
{
OverlayPopups = OverlayPopups,
})
.StartWithClassicDesktopLifetime(args);
}
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()

5
src/Avalonia.Base/Input/AccessKeyHandler.cs

@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
using Avalonia.LogicalTree;
namespace Avalonia.Input
{
@ -190,7 +189,7 @@ namespace Avalonia.Input
// If the menu is open, only match controls in the menu's visual tree.
if (menuIsOpen)
{
matches = matches.Where(x => x is not null && ((Visual)MainMenu!).IsVisualAncestorOf((Visual)x));
matches = matches.Where(x => x is not null && ((Visual)MainMenu!).IsLogicalAncestorOf((Visual)x));
}
var match = matches.FirstOrDefault();

34
src/Avalonia.Controls/MenuItem.cs

@ -13,6 +13,7 @@ using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Layout;
namespace Avalonia.Controls
{
@ -85,16 +86,16 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="PointerEnteredItem"/> event.
/// </summary>
public static readonly RoutedEvent<PointerEventArgs> PointerEnteredItemEvent =
RoutedEvent.Register<MenuItem, PointerEventArgs>(
public static readonly RoutedEvent<RoutedEventArgs> PointerEnteredItemEvent =
RoutedEvent.Register<MenuItem, RoutedEventArgs>(
nameof(PointerEnteredItem),
RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="PointerExitedItem"/> event.
/// </summary>
public static readonly RoutedEvent<PointerEventArgs> PointerExitedItemEvent =
RoutedEvent.Register<MenuItem, PointerEventArgs>(
public static readonly RoutedEvent<RoutedEventArgs> PointerExitedItemEvent =
RoutedEvent.Register<MenuItem, RoutedEventArgs>(
nameof(PointerExitedItem),
RoutingStrategies.Bubble);
@ -184,7 +185,7 @@ namespace Avalonia.Controls
/// <remarks>
/// A bubbling version of the <see cref="InputElement.PointerEntered"/> event for menu items.
/// </remarks>
public event EventHandler<PointerEventArgs>? PointerEnteredItem
public event EventHandler<RoutedEventArgs>? PointerEnteredItem
{
add { AddHandler(PointerEnteredItemEvent, value); }
remove { RemoveHandler(PointerEnteredItemEvent, value); }
@ -196,7 +197,7 @@ namespace Avalonia.Controls
/// <remarks>
/// A bubbling version of the <see cref="InputElement.PointerExited"/> event for menu items.
/// </remarks>
public event EventHandler<PointerEventArgs>? PointerExitedItem
public event EventHandler<RoutedEventArgs>? PointerExitedItem
{
add { AddHandler(PointerExitedItemEvent, value); }
remove { RemoveHandler(PointerExitedItemEvent, value); }
@ -437,20 +438,14 @@ namespace Avalonia.Controls
protected override void OnPointerEntered(PointerEventArgs e)
{
base.OnPointerEntered(e);
var point = e.GetCurrentPoint(null);
RaiseEvent(new PointerEventArgs(PointerEnteredItemEvent, this, e.Pointer, (Visual?)VisualRoot, point.Position,
e.Timestamp, point.Properties, e.KeyModifiers));
RaiseEvent(new RoutedEventArgs(PointerEnteredItemEvent));
}
/// <inheritdoc/>
protected override void OnPointerExited(PointerEventArgs e)
{
base.OnPointerExited(e);
var point = e.GetCurrentPoint(null);
RaiseEvent(new PointerEventArgs(PointerExitedItemEvent, this, e.Pointer, (Visual?)VisualRoot, point.Position,
e.Timestamp, point.Properties, e.KeyModifiers));
RaiseEvent(new RoutedEventArgs(PointerExitedItemEvent));
}
/// <summary>
@ -686,6 +681,12 @@ namespace Avalonia.Controls
/// <param name="e">The event args.</param>
private void PopupOpened(object? sender, EventArgs e)
{
// If we're using overlay popups, there's a chance we need to do a layout pass before
// the child items are added to the visual tree. If we don't do this here, then
// selection breaks.
if (Presenter?.IsAttachedToVisualTree == false)
UpdateLayout();
var selected = SelectedIndex;
if (selected != -1)
@ -705,6 +706,11 @@ namespace Avalonia.Controls
SelectedItem = null;
}
private void UpdateLayout()
{
(VisualRoot as ILayoutRoot)?.LayoutManager.ExecuteLayoutPass();
}
void ICommandSource.CanExecuteChanged(object sender, EventArgs e) => this.CanExecuteChanged(sender, e);
void IClickableControl.RaiseClick()

4
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -301,7 +301,7 @@ namespace Avalonia.Controls.Platform
e.Handled = true;
}
protected internal virtual void PointerEntered(object? sender, PointerEventArgs e)
protected internal virtual void PointerEntered(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as Control);
@ -368,7 +368,7 @@ namespace Avalonia.Controls.Platform
}
}
protected internal virtual void PointerExited(object? sender, PointerEventArgs e)
protected internal virtual void PointerExited(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as Control);

2
src/Avalonia.Controls/Primitives/OverlayPopupHost.cs

@ -51,7 +51,7 @@ namespace Avalonia.Controls.Primitives
}
/// <inheritdoc />
protected internal override Interactive? InteractiveParent => (Interactive?)VisualParent;
protected internal override Interactive? InteractiveParent => Parent as Interactive;
/// <inheritdoc />
public void Dispose() => Hide();

25
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@ -11,9 +11,6 @@ namespace Avalonia.Controls.UnitTests.Platform
{
public class DefaultMenuInteractionHandlerTests
{
static PointerEventArgs CreateArgs(RoutedEvent ev, object source)
=> new PointerEventArgs(ev, source, new FakePointer(), (Visual)source, default, 0, PointerPointProperties.None, default);
static PointerPressedEventArgs CreatePressed(object source) => new PointerPressedEventArgs(source,
new FakePointer(), (Visual)source, default,0, new PointerPointProperties (RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
default);
@ -171,7 +168,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var menu = new Mock<IMenu>();
var item = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, isSubMenuOpen: true, parent: menu.Object);
var nextItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu.Object);
var e = CreateArgs(MenuItem.PointerEnteredItemEvent, nextItem.Object);
var e = new RoutedEventArgs(MenuItem.PointerEnteredItemEvent, nextItem.Object);
menu.SetupGet(x => x.SelectedItem).Returns(item.Object);
@ -191,7 +188,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var target = new DefaultMenuInteractionHandler(false);
var menu = new Mock<IMenu>();
var item = CreateMockMenuItem(isTopLevel: true, parent: menu.Object);
var e = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
menu.SetupGet(x => x.SelectedItem).Returns(item.Object);
target.PointerExited(item, e);
@ -206,7 +203,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var target = new DefaultMenuInteractionHandler(false);
var menu = new Mock<IMenu>();
var item = CreateMockMenuItem(isTopLevel: true, parent: menu.Object);
var e = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
menu.SetupGet(x => x.IsOpen).Returns(true);
menu.SetupGet(x => x.SelectedItem).Returns(item.Object);
@ -365,7 +362,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var menu = Mock.Of<IMenu>();
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerEnteredItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerEnteredItemEvent, item.Object);
target.PointerEntered(item.Object, e);
@ -381,7 +378,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var menu = Mock.Of<IMenu>();
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(hasSubMenu: true, parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerEnteredItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerEnteredItemEvent, item.Object);
target.PointerEntered(item.Object, e);
item.Verify(x => x.Open(), Times.Never);
@ -401,7 +398,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(parent: parentItem.Object);
var sibling = CreateMockMenuItem(hasSubMenu: true, isSubMenuOpen: true, parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerEnteredItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerEnteredItemEvent, item.Object);
parentItem.SetupGet(x => x.SubItems).Returns(new[] { item.Object, sibling.Object });
@ -421,7 +418,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var menu = Mock.Of<IMenu>();
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
parentItem.SetupGet(x => x.SelectedItem).Returns(item.Object);
target.PointerExited(item, e);
@ -438,7 +435,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(parent: parentItem.Object);
var sibling = CreateMockMenuItem(parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
parentItem.SetupGet(x => x.SelectedItem).Returns(sibling.Object);
target.PointerExited(item, e);
@ -454,7 +451,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var menu = Mock.Of<IMenu>();
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(hasSubMenu: true, parent: parentItem.Object);
var e = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var e = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
item.Setup(x => x.IsPointerOverSubMenu).Returns(true);
target.PointerExited(item, e);
@ -488,8 +485,8 @@ namespace Avalonia.Controls.UnitTests.Platform
var parentItem = CreateMockMenuItem(isTopLevel: true, hasSubMenu: true, parent: menu);
var item = CreateMockMenuItem(hasSubMenu: true, parent: parentItem.Object);
var childItem = CreateMockMenuItem(parent: item.Object);
var enter = CreateArgs(MenuItem.PointerEnteredItemEvent, item.Object);
var leave = CreateArgs(MenuItem.PointerExitedItemEvent, item.Object);
var enter = new RoutedEventArgs(MenuItem.PointerEnteredItemEvent, item.Object);
var leave = new RoutedEventArgs(MenuItem.PointerExitedItemEvent, item.Object);
// Pointer enters item; item is selected.
target.PointerEntered(item, enter);

25
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -18,6 +18,7 @@ using Avalonia.Input;
using Avalonia.Rendering;
using System.Threading.Tasks;
using Avalonia.Threading;
using Avalonia.Interactivity;
namespace Avalonia.Controls.UnitTests.Primitives
{
@ -1048,6 +1049,30 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
[Fact]
public void Events_Should_Be_Routed_To_Popup_Parent()
{
using (CreateServices())
{
var popupContent = new Border();
var popup = new Popup { Child = popupContent };
var popupParent = new Border { Child = popup };
var root = PreparedWindow(popupParent);
var raised = 0;
root.LayoutManager.ExecuteInitialLayoutPass();
popup.Open();
root.LayoutManager.ExecuteLayoutPass();
var ev = new RoutedEventArgs(Button.ClickEvent);
popupParent.AddHandler(Button.ClickEvent, (s, e) => ++raised);
popupContent.RaiseEvent(ev);
Assert.Equal(1, raised);
}
}
private IDisposable CreateServices()
{
return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform:

2
tests/Avalonia.IntegrationTests.Appium/AutomationTests.cs

@ -8,7 +8,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public AutomationTests(TestAppFixture fixture)
public AutomationTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs

@ -9,7 +9,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public ButtonTests(TestAppFixture fixture)
public ButtonTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/CheckBoxTests.cs

@ -8,7 +8,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public CheckBoxTests(TestAppFixture fixture)
public CheckBoxTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

14
tests/Avalonia.IntegrationTests.Appium/CollectionDefinitions.cs

@ -0,0 +1,14 @@
using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[CollectionDefinition("Default")]
public class DefaultCollection : ICollectionFixture<DefaultAppFixture>
{
}
[CollectionDefinition("OverlayPopups")]
public class OverlayPopupsCollection : ICollectionFixture<OverlayPopupsAppFixture>
{
}
}

17
tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs

@ -4,12 +4,11 @@ using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[Collection("Default")]
public class ComboBoxTests
public abstract class ComboBoxTests
{
private readonly AppiumDriver<AppiumWebElement> _session;
public ComboBoxTests(TestAppFixture fixture)
public ComboBoxTests(DefaultAppFixture fixture)
{
_session = fixture.Session;
@ -153,5 +152,17 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal(string.Empty, comboBox.GetComboBoxValue());
}
[Collection("Default")]
public class Default : ComboBoxTests
{
public Default(DefaultAppFixture fixture) : base(fixture) { }
}
[Collection("OverlayPopups")]
public class OverlayPopups : ComboBoxTests
{
public OverlayPopups(OverlayPopupsAppFixture fixture) : base(fixture) { }
}
}
}

38
tests/Avalonia.IntegrationTests.Appium/TestAppFixture.cs → tests/Avalonia.IntegrationTests.Appium/DefaultAppFixture.cs

@ -9,25 +9,21 @@ using OpenQA.Selenium.Appium.Windows;
namespace Avalonia.IntegrationTests.Appium
{
public class TestAppFixture : IDisposable
public class DefaultAppFixture : IDisposable
{
private const string TestAppPath = @"..\..\..\..\..\samples\IntegrationTestApp\bin\Debug\net7.0\IntegrationTestApp.exe";
private const string TestAppBundleId = "net.avaloniaui.avalonia.integrationtestapp";
public TestAppFixture()
public DefaultAppFixture()
{
var opts = new AppiumOptions();
var path = Path.GetFullPath(TestAppPath);
var options = new AppiumOptions();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
opts.AddAdditionalCapability(MobileCapabilityType.App, path);
opts.AddAdditionalCapability(MobileCapabilityType.PlatformName, MobilePlatform.Windows);
opts.AddAdditionalCapability(MobileCapabilityType.DeviceName, "WindowsPC");
ConfigureWin32Options(options);
Session = new WindowsDriver<AppiumWebElement>(
new Uri("http://127.0.0.1:4723"),
opts);
options);
// https://github.com/microsoft/WinAppDriver/issues/1025
SetForegroundWindow(new IntPtr(int.Parse(
@ -36,14 +32,10 @@ namespace Avalonia.IntegrationTests.Appium
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
opts.AddAdditionalCapability("appium:bundleId", TestAppBundleId);
opts.AddAdditionalCapability(MobileCapabilityType.PlatformName, MobilePlatform.MacOS);
opts.AddAdditionalCapability(MobileCapabilityType.AutomationName, "mac2");
opts.AddAdditionalCapability("appium:showServerLogs", true);
ConfigureMacOptions(options);
Session = new MacDriver<AppiumWebElement>(
new Uri("http://127.0.0.1:4723/wd/hub"),
opts);
options);
}
else
{
@ -51,6 +43,22 @@ namespace Avalonia.IntegrationTests.Appium
}
}
protected virtual void ConfigureWin32Options(AppiumOptions options)
{
var path = Path.GetFullPath(TestAppPath);
options.AddAdditionalCapability(MobileCapabilityType.App, path);
options.AddAdditionalCapability(MobileCapabilityType.PlatformName, MobilePlatform.Windows);
options.AddAdditionalCapability(MobileCapabilityType.DeviceName, "WindowsPC");
}
protected virtual void ConfigureMacOptions(AppiumOptions options)
{
options.AddAdditionalCapability("appium:bundleId", TestAppBundleId);
options.AddAdditionalCapability(MobileCapabilityType.PlatformName, MobilePlatform.MacOS);
options.AddAdditionalCapability(MobileCapabilityType.AutomationName, "mac2");
options.AddAdditionalCapability("appium:showServerLogs", true);
}
public AppiumDriver<AppiumWebElement> Session { get; }
public void Dispose()

9
tests/Avalonia.IntegrationTests.Appium/DefaultCollection.cs

@ -1,9 +0,0 @@
using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[CollectionDefinition("Default")]
public class DefaultCollection : ICollectionFixture<TestAppFixture>
{
}
}

2
tests/Avalonia.IntegrationTests.Appium/GestureTests.cs

@ -11,7 +11,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public GestureTests(TestAppFixture fixture)
public GestureTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs

@ -11,7 +11,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public ListBoxTests(TestAppFixture fixture)
public ListBoxTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

16
tests/Avalonia.IntegrationTests.Appium/MenuTests.cs

@ -7,11 +7,11 @@ using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[Collection("Default")]
public class MenuTests
public abstract class MenuTests
{
private readonly AppiumDriver<AppiumWebElement> _session;
public MenuTests(TestAppFixture fixture)
public MenuTests(DefaultAppFixture fixture)
{
_session = fixture.Session;
@ -181,5 +181,17 @@ namespace Avalonia.IntegrationTests.Appium
var tab = tabs.FindElementByName("Menu");
tab.MovePointerOver();
}
[Collection("Default")]
public class Default : MenuTests
{
public Default(DefaultAppFixture fixture) : base(fixture) { }
}
[Collection("OverlayPopups")]
public class OverlayPopups : MenuTests
{
public OverlayPopups(OverlayPopupsAppFixture fixture) : base(fixture) { }
}
}
}

2
tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs

@ -8,7 +8,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public NativeMenuTests(TestAppFixture fixture)
public NativeMenuTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

19
tests/Avalonia.IntegrationTests.Appium/OverlayPopupsAppFixture.cs

@ -0,0 +1,19 @@
using OpenQA.Selenium.Appium;
namespace Avalonia.IntegrationTests.Appium
{
public class OverlayPopupsAppFixture : DefaultAppFixture
{
protected override void ConfigureWin32Options(AppiumOptions options)
{
base.ConfigureWin32Options(options);
options.AddAdditionalCapability("appArguments", "--overlayPopups");
}
protected override void ConfigureMacOptions(AppiumOptions options)
{
base.ConfigureMacOptions(options);
options.AddAdditionalCapability("appium:arguments", new[] { "--overlayPopups" });
}
}
}

10
tests/Avalonia.IntegrationTests.Appium/RadioButtonTests.cs

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium;
using Xunit;
namespace Avalonia.IntegrationTests.Appium
@ -14,7 +8,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public RadioButtonTests(TestAppFixture fixture)
public RadioButtonTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/SliderTests.cs

@ -10,7 +10,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public SliderTests(TestAppFixture fixture)
public SliderTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

@ -19,7 +19,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public WindowTests(TestAppFixture fixture)
public WindowTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

2
tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs

@ -16,7 +16,7 @@ namespace Avalonia.IntegrationTests.Appium
{
private readonly AppiumDriver<AppiumWebElement> _session;
public WindowTests_MacOS(TestAppFixture fixture)
public WindowTests_MacOS(DefaultAppFixture fixture)
{
var retry = 0;

Loading…
Cancel
Save