UnitTestApplication.cs 3.9 KB

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