Class: Appom::SmartWait::ConditionalWait

Inherits:
Wait
  • Object
show all
Defined in:
lib/appom/smart_wait.rb

Overview

Enhanced Wait class with smart conditions

Constant Summary

Constants inherited from Wait

Wait::DEFAULT_INTERVAL, Wait::DEFAULT_TIMEOUT

Instance Attribute Summary collapse

Attributes inherited from Wait

#interval, #timeout

Instance Method Summary collapse

Methods inherited from Wait

#until

Methods included from Logging

level, level=, #log_debug, #log_element_action, #log_error, #log_info, #log_wait_end, #log_wait_start, #log_warn, #logger

Constructor Details

#initialize(timeout: Appom.max_wait_time, interval: DEFAULT_INTERVAL, condition: nil, description: nil) ⇒ ConditionalWait

Returns a new instance of ConditionalWait.



154
155
156
157
158
159
# File 'lib/appom/smart_wait.rb', line 154

def initialize(timeout: Appom.max_wait_time, interval: DEFAULT_INTERVAL, condition: nil,
               description: nil)
  super(timeout: timeout, interval: interval)
  @condition = condition
  @condition_description = description || 'custom condition'
end

Instance Attribute Details

#conditionObject (readonly)

Returns the value of attribute condition.



152
153
154
# File 'lib/appom/smart_wait.rb', line 152

def condition
  @condition
end

#condition_descriptionObject (readonly)

Returns the value of attribute condition_description.



152
153
154
# File 'lib/appom/smart_wait.rb', line 152

def condition_description
  @condition_description
end

Instance Method Details

#for_any_condition(*conditions_with_elements) ⇒ Object

Wait for any of multiple conditions to be met



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/appom/smart_wait.rb', line 217

def for_any_condition(*conditions_with_elements)
  raise ArgumentError, 'No conditions provided' unless conditions_with_elements.any?

  log_wait_start("any of #{conditions_with_elements.size} conditions", @timeout)
  start_time = Time.now

  until_with_condition do
    conditions_with_elements.each_with_index do |(find_args, condition), index|
      element = _find_element(*find_args)
      if condition.call(element)
        duration = Time.now - start_time
        log_wait_end("condition #{index + 1}", duration.round(3), success: true)
        return { index: index, element: element, find_args: find_args }
      end
    rescue StandardError
      # Continue to next condition
    end
    false
  end
rescue Appom::WaitError
  duration = Time.now - start_time
  log_wait_end('any condition', duration.round(3), success: false)
  descriptions = conditions_with_elements.map.with_index do |(find_args, _), i|
    "#{i + 1}: #{find_args.join(', ')}"
  end
  raise Appom::ElementNotFoundError.new("any of: #{descriptions.join('; ')}", @timeout)
end

#for_element(*find_args, &condition_block) ⇒ Object

Wait for element with specific condition



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/appom/smart_wait.rb', line 162

def for_element(*find_args, &condition_block)
  condition = condition_block || @condition
  raise Appom::ArgumentError, 'No condition provided' unless condition

  log_wait_start(@condition_description, @timeout)
  start_time = Time.now

  until_with_condition do
    element = _find_element(*find_args)
    if condition.call(element)
      duration = Time.now - start_time
      log_wait_end(@condition_description, duration.round(3), success: true)
      return element
    end
    false
  rescue StandardError
    # Continue waiting for condition even if element not found initially
    false
  end
rescue Appom::WaitError
  duration = Time.now - start_time
  log_wait_end(@condition_description, duration.round(3), success: false)
  raise Appom::ElementNotFoundError.new(
    "#{find_args.join(', ')} with condition: #{@condition_description}", @timeout,
  )
end

#for_elements(*find_args, &condition_block) ⇒ Object

Wait for elements collection with condition



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/appom/smart_wait.rb', line 190

def for_elements(*find_args, &condition_block)
  condition = condition_block || @condition
  raise Appom::ArgumentError, 'No condition provided' unless condition

  log_wait_start("#{@condition_description} (collection)", @timeout)
  start_time = Time.now

  until_with_condition do
    elements = _find_elements(*find_args)
    if condition.call(elements)
      duration = Time.now - start_time
      log_wait_end("#{@condition_description} (collection)", duration.round(3), success: true)
      return elements
    end
    false
  rescue StandardError
    false
  end
rescue Appom::WaitError
  duration = Time.now - start_time
  log_wait_end("#{@condition_description} (collection)", duration.round(3), success: false)
  raise Appom::ElementNotFoundError.new(
    "#{find_args.join(', ')} collection with condition: #{@condition_description}", @timeout,
  )
end

#wait_for_stable_condition(condition, stable_duration: 1.0, timeout: @timeout, interval: @interval) ⇒ Object

Wait for condition to remain stable for specified duration



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/appom/smart_wait.rb', line 277

def wait_for_stable_condition(condition, stable_duration: 1.0, timeout: @timeout,
                              interval: @interval)
  start_time = Time.now
  stable_start = nil

  loop do
    begin
      if condition.call
        stable_start ||= Time.now
        return true if Time.now - stable_start >= stable_duration
      else
        stable_start = nil
      end
    rescue StandardError
      stable_start = nil
    end

    if Time.now - start_time > timeout
      raise Appom::TimeoutError,
            "Condition did not remain stable for #{stable_duration}s within #{timeout}s"
    end

    sleep interval
  end
end

#wait_until(condition, timeout: @timeout, interval: @interval, backoff_factor: nil, max_interval: nil) ⇒ Object

Wait until condition becomes true



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/appom/smart_wait.rb', line 246

def wait_until(condition, timeout: @timeout, interval: @interval, backoff_factor: nil,
               max_interval: nil)
  start_time = Time.now
  last_error = nil
  current_interval = interval

  loop do
    result = evaluate_condition_safely(condition, last_error)
    return true if result[:success]

    last_error = result[:error]

    check_timeout_reached(start_time, timeout, last_error)

    sleep current_interval
    current_interval = apply_backoff(current_interval, backoff_factor, max_interval)
  end
end

#wait_while(condition, timeout: @timeout, interval: @interval) ⇒ Object

Wait while condition remains true (until it becomes false)



266
267
268
269
270
271
272
273
274
# File 'lib/appom/smart_wait.rb', line 266

def wait_while(condition, timeout: @timeout, interval: @interval) # rubocop:disable Naming/PredicateMethod
  start_time = Time.now
  while condition.call
    raise Appom::TimeoutError, "Condition remained true for #{timeout}s" if Time.now - start_time > timeout

    sleep interval
  end
  true
end