GuiTestContext.Navigation.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. namespace TerminalGuiFluentTesting;
  3. public partial class GuiTestContext
  4. {
  5. /// <summary>
  6. /// Sets the input focus to the given <see cref="View"/>.
  7. /// Throws <see cref="ArgumentException"/> if focus did not change due to system
  8. /// constraints e.g. <paramref name="toFocus"/>
  9. /// <see cref="View.CanFocus"/> is <see langword="false"/>
  10. /// </summary>
  11. /// <param name="toFocus"></param>
  12. /// <returns></returns>
  13. /// <exception cref="ArgumentException"></exception>
  14. public GuiTestContext Focus (View toFocus)
  15. {
  16. toFocus.FocusDeepest (NavigationDirection.Forward, TabBehavior.TabStop);
  17. if (!toFocus.HasFocus)
  18. {
  19. throw new ArgumentException ("Failed to set focus, FocusDeepest did not result in HasFocus becoming true. Ensure view is added and focusable");
  20. }
  21. return WaitIteration ();
  22. }
  23. /// <summary>
  24. /// Tabs through the UI until a View matching the <paramref name="evaluator"/>
  25. /// is found (of Type T) or all views are looped through (back to the beginning)
  26. /// in which case triggers hard stop and Exception
  27. /// </summary>
  28. /// <param name="evaluator">
  29. /// Delegate that returns true if the passed View is the one
  30. /// you are trying to focus. Leave <see langword="null"/> to focus the first view of type
  31. /// <typeparamref name="T"/>
  32. /// </param>
  33. /// <returns></returns>
  34. /// <exception cref="ArgumentException"></exception>
  35. public GuiTestContext Focus<T> (Func<T, bool>? evaluator = null) where T : View
  36. {
  37. evaluator ??= _ => true;
  38. Toplevel? t = App?.Current;
  39. HashSet<View> seen = new ();
  40. if (t == null)
  41. {
  42. Fail ("Application.Current was null when trying to set focus");
  43. return this;
  44. }
  45. do
  46. {
  47. View? next = t.MostFocused;
  48. // Is view found?
  49. if (next is T v && evaluator (v))
  50. {
  51. return this;
  52. }
  53. // No, try tab to the next (or first)
  54. EnqueueKeyEvent (Terminal.Gui.App.Application.NextTabKey);
  55. WaitIteration ();
  56. next = t.MostFocused;
  57. if (next is null)
  58. {
  59. Fail (
  60. "Failed to tab to a view which matched the Type and evaluator constraints of the test because MostFocused became or was always null"
  61. + DescribeSeenViews (seen));
  62. return this;
  63. }
  64. // Track the views we have seen
  65. // We have looped around to the start again if it was already there
  66. if (!seen.Add (next))
  67. {
  68. Fail (
  69. "Failed to tab to a view which matched the Type and evaluator constraints of the test before looping back to the original View"
  70. + DescribeSeenViews (seen));
  71. return this;
  72. }
  73. }
  74. while (true);
  75. }
  76. private string DescribeSeenViews (HashSet<View> seen) { return Environment.NewLine + string.Join (Environment.NewLine, seen); }
  77. }