UnitTestApplication.cs 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using System;
  2. using Avalonia.Input;
  3. using Avalonia.Layout;
  4. using Avalonia.Platform;
  5. using Avalonia.Styling;
  6. using Avalonia.Controls;
  7. using Avalonia.Rendering;
  8. using Avalonia.Threading;
  9. using System.Reactive.Disposables;
  10. using System.Reactive.Concurrency;
  11. using System.Threading;
  12. using Avalonia.Input.Platform;
  13. using Avalonia.Animation;
  14. using Avalonia.Media;
  15. namespace Avalonia.UnitTests
  16. {
  17. public class UnitTestApplication : Application
  18. {
  19. private readonly TestServices _services;
  20. public UnitTestApplication() : this(null)
  21. {
  22. }
  23. public UnitTestApplication(TestServices services)
  24. {
  25. _services = services ?? new TestServices();
  26. AvaloniaLocator.CurrentMutable.BindToSelf<Application>(this);
  27. RegisterServices();
  28. }
  29. static UnitTestApplication()
  30. {
  31. AssetLoader.RegisterResUriParsers();
  32. }
  33. public static new UnitTestApplication Current => (UnitTestApplication)Application.Current;
  34. public TestServices Services => _services;
  35. public static IDisposable Start(TestServices services = null)
  36. {
  37. var scope = AvaloniaLocator.EnterScope();
  38. var oldContext = SynchronizationContext.Current;
  39. _ = new UnitTestApplication(services);
  40. Dispatcher.ResetForUnitTests();
  41. return Disposable.Create(() =>
  42. {
  43. if (Dispatcher.UIThread.CheckAccess())
  44. {
  45. Dispatcher.UIThread.RunJobs();
  46. }
  47. scope.Dispose();
  48. Dispatcher.ResetForUnitTests();
  49. SynchronizationContext.SetSynchronizationContext(oldContext);
  50. });
  51. }
  52. public override void RegisterServices()
  53. {
  54. AvaloniaLocator.CurrentMutable
  55. .Bind<IAssetLoader>().ToConstant(Services.AssetLoader)
  56. .Bind<IFocusManager>().ToConstant(Services.FocusManager)
  57. .Bind<IGlobalClock>().ToConstant(Services.GlobalClock)
  58. .BindToSelf<IGlobalStyles>(this)
  59. .Bind<IInputManager>().ToConstant(Services.InputManager)
  60. .Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke())
  61. .Bind<IMouseDevice>().ToConstant(Services.MouseDevice?.Invoke())
  62. .Bind<IKeyboardNavigationHandler>().ToFunc(Services.KeyboardNavigation ?? (() => null))
  63. .Bind<IRuntimePlatform>().ToConstant(Services.Platform)
  64. .Bind<IPlatformRenderInterface>().ToConstant(Services.RenderInterface)
  65. .Bind<IFontManagerImpl>().ToConstant(Services.FontManagerImpl)
  66. .Bind<ITextShaperImpl>().ToConstant(Services.TextShaperImpl)
  67. .Bind<IDispatcherImpl>().ToConstant(Services.DispatcherImpl)
  68. .Bind<ICursorFactory>().ToConstant(Services.StandardCursorFactory)
  69. .Bind<IWindowingPlatform>().ToConstant(Services.WindowingPlatform)
  70. .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
  71. .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>();
  72. // This is a hack to make tests work, we need to refactor the way font manager is registered
  73. // See https://github.com/AvaloniaUI/Avalonia/issues/10081
  74. AvaloniaLocator.CurrentMutable.Bind<FontManager>().ToConstant((FontManager)null!);
  75. var theme = Services.Theme?.Invoke();
  76. if (theme is Style styles)
  77. {
  78. Styles.AddRange(styles.Children);
  79. }
  80. else if (theme is not null)
  81. {
  82. Styles.Add(theme);
  83. }
  84. }
  85. }
  86. }