Skip to content

Commit

Permalink
Add retry to Element.click().
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffdav committed Jul 31, 2023
1 parent d988bc2 commit a5bf234
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
17 changes: 15 additions & 2 deletions Sources/Element+Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,22 @@ import Foundation
extension Element {
/// click() - simulate clicking this Element
/// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidelementidclick
public func click() {
public func click(retryTimeout: TimeInterval? = nil) {
let clickRequest = ClickRequest(element: self)
try! webDriver.send(clickRequest)
retryUntil(retryTimeout ?? session.defaultRetryTimeout, work: {
do {
try webDriver.send(clickRequest)
return true
} catch let error as WebDriverError {
if error.status == .elementNotInteractable {
return false
} else {
fatalError("Unhandled error: \(String(describing: error.status))")
}
} catch {
fatalError("Unexpected error: \(error)")
}
})
}

struct ClickRequest: WebDriverRequest {
Expand Down
26 changes: 19 additions & 7 deletions Sources/Retry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,33 @@ internal func retryUntil<T>(_ timeout: TimeInterval, work: () throws -> T?) reth
var timeUsed: TimeInterval = 0.0
var nextTimeout: TimeInterval = 0.001 // Start at 1ms and double until we exhaust time.

var result: T?
repeat {
result = try work()
if let result {
return result
}
if let result = try work() { return result }

if timeUsed < timeout {
Thread.sleep(forTimeInterval: nextTimeout)
timeUsed += nextTimeout
nextTimeout = min(nextTimeout * 2.0, timeout - timeUsed)
} else {
break
return nil
}
} while true
}

// Retry the given work using exponential backoff until we use allocated time or work returns true.
internal func retryUntil(_ timeout: TimeInterval, work: () throws -> Bool) rethrows {
var timeUsed: TimeInterval = 0.0
var nextTimeout: TimeInterval = 0.001 // Start at 1ms and double until we exhaust time.

repeat {
if try work() { return }

return result
if timeUsed < timeout {
Thread.sleep(forTimeInterval: nextTimeout)
timeUsed += nextTimeout
nextTimeout = min(nextTimeout * 2.0, timeout - timeUsed)
} else {
return
}
} while true
}

0 comments on commit a5bf234

Please sign in to comment.