custom_extensions.rb 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. class Capybara::Node::Element
  3. # This is an extension to each node to check if the element
  4. # is moving or in a fixed position. This is especially helpful
  5. # for animated elements that cause flanky tests.
  6. # NOTE: In CI env a special sleep is performed between checks
  7. # because animations can be slow.
  8. #
  9. # @param [Integer] checks the number of performed movement checks
  10. #
  11. # @example
  12. # find('.clues-close').in_fixed_position.click
  13. # => waits till clues moved to final position and performs click afterwards
  14. #
  15. # @raise [RuntimeError] raised in case the element is
  16. # still moving after max number of checks was passed
  17. #
  18. # @return [Capybara::Node::Element] the element/node
  19. def in_fixed_position(checks: 100, wait: 0.2)
  20. previous = native.location
  21. (checks + 1).times do
  22. sleep wait
  23. current = native.location
  24. return self if previous == current
  25. previous = current
  26. end
  27. raise "Element still moving after #{checks} checks"
  28. end
  29. end
  30. module ZammadCapybarActionDelegator
  31. def select(...)
  32. super.tap do
  33. await_empty_ajax_queue
  34. end
  35. end
  36. def click(...)
  37. super.tap do
  38. await_empty_ajax_queue
  39. end
  40. end
  41. def click_on(...)
  42. super.tap do
  43. await_empty_ajax_queue
  44. end
  45. end
  46. def click_link_or_button(...)
  47. super.tap do
  48. await_empty_ajax_queue
  49. end
  50. end
  51. def click_button(...)
  52. super.tap do
  53. await_empty_ajax_queue
  54. end
  55. end
  56. def select_option(...)
  57. super.tap do
  58. await_empty_ajax_queue
  59. end
  60. end
  61. def send_keys(...)
  62. super.tap do
  63. await_empty_ajax_queue
  64. end
  65. end
  66. def hot_keys
  67. mac_platform? ? %i[control alt] : %i[control shift]
  68. end
  69. def magic_key
  70. mac_platform? ? :command : :control
  71. end
  72. def mac_platform?
  73. Gem::Platform.local.os.eql? 'darwin'
  74. end
  75. end
  76. module ZammadCapybarSelectorDelegator
  77. def find_field(...)
  78. ZammadCapybaraElementDelegator.new(element: super, context: self)
  79. end
  80. def find_button(...)
  81. ZammadCapybaraElementDelegator.new(element: super, context: self)
  82. end
  83. def find_by_id(...)
  84. ZammadCapybaraElementDelegator.new(element: super, context: self)
  85. end
  86. def find_link(...)
  87. ZammadCapybaraElementDelegator.new(element: super, context: self)
  88. end
  89. def find(...)
  90. ZammadCapybaraElementDelegator.new(element: super, context: self)
  91. end
  92. def first(...)
  93. ZammadCapybaraElementDelegator.new(element: super, context: self)
  94. end
  95. def all(...)
  96. super.map { |element| ZammadCapybaraElementDelegator.new(element: element, context: self) }
  97. end
  98. end
  99. class ZammadCapybaraSessionDelegator < SimpleDelegator
  100. extend Forwardable
  101. def_delegator :@context, :await_empty_ajax_queue
  102. include ZammadCapybarSelectorDelegator
  103. def initialize(context:, element:)
  104. @context = context
  105. super(element)
  106. end
  107. end
  108. class ZammadCapybaraElementDelegator < ZammadCapybaraSessionDelegator
  109. include ZammadCapybarActionDelegator
  110. end
  111. module CapybaraCustomExtensions
  112. include ZammadCapybarActionDelegator
  113. include ZammadCapybarSelectorDelegator
  114. def page(...)
  115. ZammadCapybaraSessionDelegator.new(element: super, context: self)
  116. end
  117. end
  118. RSpec.configure do |config|
  119. config.include CapybaraCustomExtensions, type: :system
  120. end