Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// PostElementDoubleClickRequest.swift
// Copyright (c) 2025 GetAutomaApp
// All source code and related assets are the property of GetAutomaApp.
// All rights reserved.

import AnyCodable
import AsyncHTTPClient
import Foundation
import NIO
import NIOHTTP1

internal struct PostElementDoubleClickRequest: RequestType {
typealias Response = PostElementClickResponse

var baseURL: URL

var sessionId: String

var elementId: String

var path: String {
"session/\(sessionId)/actions"
}

var method: HTTPMethod = .POST

var headers: HTTPHeaders = [:]

var body: HTTPClient.Body? {
let origin = WebDriverElementOrigin(element: elementId)

let pointerActions = [
PointerAction(type: "pointerMove", origin: origin, x: 0, y: 0),
PointerAction(type: "pointerDown", button: 0),
PointerAction(type: "pointerUp", button: 0),
PointerAction(type: "pause", duration: 50),
PointerAction(type: "pointerDown", button: 0),
PointerAction(type: "pointerUp", button: 0)
]

let pointerSource = PointerSource(
type: "pointer",
id: "mouse",
parameters: .init(pointerType: "mouse"),
actions: pointerActions
)

let payload = ActionsPayload(actions: [pointerSource])

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try? encoder.encode(payload)

guard let data else {
return nil
}

return .data(data)
}
}

struct WebDriverElementOrigin: Encodable {
let element: String

enum CodingKeys: String, CodingKey {
case element = "element-6066-11e4-a52e-4f735466cecf"
}
}

struct PointerAction: Encodable {
let type: String
let origin: WebDriverElementOrigin?
let x: Int?

Check failure on line 73 in Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Variable name 'x' should be between 3 and 40 characters long (identifier_name)
let y: Int?

Check failure on line 74 in Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Variable name 'y' should be between 3 and 40 characters long (identifier_name)
let button: Int?
let duration: Int?

init(
type: String,
origin: WebDriverElementOrigin? = nil,
x: Int? = nil,

Check failure on line 81 in Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Variable name 'x' should be between 3 and 40 characters long (identifier_name)
y: Int? = nil,

Check failure on line 82 in Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Variable name 'y' should be between 3 and 40 characters long (identifier_name)
button: Int? = nil,
duration: Int? = nil
) {
self.type = type
self.origin = origin
self.x = x
self.y = y
self.button = button
self.duration = duration
}
}

struct PointerSource: Encodable {
let type: String
let id: String
let parameters: Parameters
let actions: [PointerAction]

struct Parameters: Encodable {
let pointerType: String
}
}

struct ActionsPayload: Encodable {
let actions: [PointerSource]
}
12 changes: 9 additions & 3 deletions Sources/SwiftWebDriver/Element/Element.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
// Copyright (c) 2025 GetAutomaApp
// All source code and related assets are the property of GetAutomaApp.
// All rights reserved.
//
// This package is freely distributable under the MIT license.
// This Package is a modified fork of https://github.com/ashi-psn/SwiftWebDriver.

import Foundation
import NIO
Expand All @@ -19,6 +16,7 @@ public protocol ElementCommandProtocol: FindElementProtocol {
func text() async throws -> String
func name() async throws -> String
func click() async throws -> String?
func doubleClick() async throws -> String?
func clear() async throws -> String?
func attribute(name: String) async throws -> String
func send(value: String) async throws -> String?
Expand Down Expand Up @@ -79,6 +77,14 @@ public struct Element: ElementCommandProtocol, Sendable {
return response.value
}

@discardableResult
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func doubleClick() async throws -> String? {
let request = PostElementDoubleClickRequest(baseURL: baseURL, sessionId: sessionId, elementId: elementId)
let response = try await APIClient.shared.request(request)
return response.value
}

@discardableResult
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public func clear() async throws -> String? {
Expand Down
6 changes: 6 additions & 0 deletions TestAssets/elementHandleTestPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
element.innerHTML = "clicked!"
}

function doubleClick() {
let element = document.getElementById("doubleclick")
element.innerHTML += "i"
}

function startTimer() {
window.setTimeout(function () {
let element = document.getElementById("willAppendChild")
Expand All @@ -27,6 +32,7 @@

<body>
<button id="button" onclick="onClick()"></button>
<button id="doubleclick" onclick="doubleClick()"></button>
<input type="text" id="attribute" value="expect attribute">
<div id="setproperty"></div>
<input type="text" id="clearInputValue" value="clearInputValue">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@
// Copyright (c) 2025 GetAutomaApp
// All source code and related assets are the property of GetAutomaApp.
// All rights reserved.
//
// This package is freely distributable under the MIT license.
// This Package is a modified fork of https://github.com/ashi-psn/SwiftWebDriver.

@testable import SwiftWebDriver
import Testing

@Suite("Chrome Driver Element Handles", .serialized)
internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
@Test("Click Button")
public func clickButton() async throws {
func clickButton() async throws {
page = "elementHandleTestPage.html"

try await driver.navigateTo(urlString: testPageURL.absoluteString)
Expand All @@ -22,8 +19,19 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
#expect(test == "clicked!")
}

@Test("Double Click Button")
func doubleClickButton() async throws {
page = "elementHandleTestPage.html"

try await driver.navigateTo(urlString: testPageURL.absoluteString)
let button = try await driver.findElement(.css(.id("doubleclick")))
try await button.doubleClick()
let test = try await button.text()
#expect(test == "ii")
}

@Test("Get Element Attributes")
public func getAttribute() async throws {
func getAttribute() async throws {
page = "elementHandleTestPage.html"
try await driver.navigateTo(urlString: testPageURL.absoluteString)

Expand All @@ -34,7 +42,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
}

@Test("Clear Element")
public func clearElement() async throws {
func clearElement() async throws {
page = "elementHandleTestPage.html"
try await driver.navigateTo(urlString: testPageURL.absoluteString)

Expand All @@ -48,7 +56,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
}

@Test("Send Key")
public func sendKey() async throws {
func sendKey() async throws {
page = "elementHandleTestPage.html"
try await driver.navigateTo(urlString: testPageURL.absoluteString)
let element = try await driver.findElement(.css(.id("sendValue")))
Expand All @@ -58,7 +66,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
}

@Test("Get Screenshot")
public func getScreenshot() async throws {
func getScreenshot() async throws {
page = "elementHandleTestPage.html"
try await driver.navigateTo(urlString: testPageURL.absoluteString)
let element = try await driver.findElement(.css(.id("sendValue")))
Expand All @@ -68,7 +76,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
}

@Test("Fail any operation if element becomes stale")
public func throwStaleError() async throws {
func throwStaleError() async throws {
let sleepTotal = 3
page = "elementHandleTestPage.html"
try await driver.navigateTo(urlString: testPageURL.absoluteString)
Expand Down
Loading