Skip to content

Commit 80173a2

Browse files
Element.doubleClick() Implemented (#57)
* feat(Element,PostElementDoubleClickRequest): implemented double click method, created request to double click on element * test(ChromeDriverElementHandleIntegrationTests): implemented integration test for double click method Tests passed as expected
1 parent 06a049b commit 80173a2

File tree

4 files changed

+140
-12
lines changed

4 files changed

+140
-12
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// PostElementDoubleClickRequest.swift
2+
// Copyright (c) 2025 GetAutomaApp
3+
// All source code and related assets are the property of GetAutomaApp.
4+
// All rights reserved.
5+
6+
import AnyCodable
7+
import AsyncHTTPClient
8+
import Foundation
9+
import NIO
10+
import NIOHTTP1
11+
12+
internal struct PostElementDoubleClickRequest: RequestType {
13+
typealias Response = PostElementClickResponse
14+
15+
var baseURL: URL
16+
17+
var sessionId: String
18+
19+
var elementId: String
20+
21+
var path: String {
22+
"session/\(sessionId)/actions"
23+
}
24+
25+
var method: HTTPMethod = .POST
26+
27+
var headers: HTTPHeaders = [:]
28+
29+
var body: HTTPClient.Body? {
30+
let origin = WebDriverElementOrigin(element: elementId)
31+
32+
let pointerActions = [
33+
PointerAction(type: "pointerMove", origin: origin, x: 0, y: 0),
34+
PointerAction(type: "pointerDown", button: 0),
35+
PointerAction(type: "pointerUp", button: 0),
36+
PointerAction(type: "pause", duration: 50),
37+
PointerAction(type: "pointerDown", button: 0),
38+
PointerAction(type: "pointerUp", button: 0)
39+
]
40+
41+
let pointerSource = PointerSource(
42+
type: "pointer",
43+
id: "mouse",
44+
parameters: .init(pointerType: "mouse"),
45+
actions: pointerActions
46+
)
47+
48+
let payload = ActionsPayload(actions: [pointerSource])
49+
50+
let encoder = JSONEncoder()
51+
encoder.outputFormatting = .prettyPrinted
52+
let data = try? encoder.encode(payload)
53+
54+
guard let data else {
55+
return nil
56+
}
57+
58+
return .data(data)
59+
}
60+
}
61+
62+
struct WebDriverElementOrigin: Encodable {
63+
let element: String
64+
65+
enum CodingKeys: String, CodingKey {
66+
case element = "element-6066-11e4-a52e-4f735466cecf"
67+
}
68+
}
69+
70+
struct PointerAction: Encodable {
71+
let type: String
72+
let origin: WebDriverElementOrigin?
73+
let x: Int?
74+
let y: Int?
75+
let button: Int?
76+
let duration: Int?
77+
78+
init(
79+
type: String,
80+
origin: WebDriverElementOrigin? = nil,
81+
x: Int? = nil,
82+
y: Int? = nil,
83+
button: Int? = nil,
84+
duration: Int? = nil
85+
) {
86+
self.type = type
87+
self.origin = origin
88+
self.x = x
89+
self.y = y
90+
self.button = button
91+
self.duration = duration
92+
}
93+
}
94+
95+
struct PointerSource: Encodable {
96+
let type: String
97+
let id: String
98+
let parameters: Parameters
99+
let actions: [PointerAction]
100+
101+
struct Parameters: Encodable {
102+
let pointerType: String
103+
}
104+
}
105+
106+
struct ActionsPayload: Encodable {
107+
let actions: [PointerSource]
108+
}

Sources/SwiftWebDriver/Element/Element.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// Copyright (c) 2025 GetAutomaApp
33
// All source code and related assets are the property of GetAutomaApp.
44
// All rights reserved.
5-
//
6-
// This package is freely distributable under the MIT license.
7-
// This Package is a modified fork of https://github.com/ashi-psn/SwiftWebDriver.
85

96
import Foundation
107
import NIO
@@ -19,6 +16,7 @@ public protocol ElementCommandProtocol: FindElementProtocol {
1916
func text() async throws -> String
2017
func name() async throws -> String
2118
func click() async throws -> String?
19+
func doubleClick() async throws -> String?
2220
func clear() async throws -> String?
2321
func attribute(name: String) async throws -> String
2422
func send(value: String) async throws -> String?
@@ -79,6 +77,14 @@ public struct Element: ElementCommandProtocol, Sendable {
7977
return response.value
8078
}
8179

80+
@discardableResult
81+
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
82+
public func doubleClick() async throws -> String? {
83+
let request = PostElementDoubleClickRequest(baseURL: baseURL, sessionId: sessionId, elementId: elementId)
84+
let response = try await APIClient.shared.request(request)
85+
return response.value
86+
}
87+
8288
@discardableResult
8389
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
8490
public func clear() async throws -> String? {

TestAssets/elementHandleTestPage.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
element.innerHTML = "clicked!"
99
}
1010

11+
function doubleClick() {
12+
let element = document.getElementById("doubleclick")
13+
element.innerHTML += "i"
14+
}
15+
1116
function startTimer() {
1217
window.setTimeout(function () {
1318
let element = document.getElementById("willAppendChild")
@@ -27,6 +32,7 @@
2732

2833
<body>
2934
<button id="button" onclick="onClick()"></button>
35+
<button id="doubleclick" onclick="doubleClick()"></button>
3036
<input type="text" id="attribute" value="expect attribute">
3137
<div id="setproperty"></div>
3238
<input type="text" id="clearInputValue" value="clearInputValue">

Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverElementHandleIntegrationTests.swift

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@
22
// Copyright (c) 2025 GetAutomaApp
33
// All source code and related assets are the property of GetAutomaApp.
44
// All rights reserved.
5-
//
6-
// This package is freely distributable under the MIT license.
7-
// This Package is a modified fork of https://github.com/ashi-psn/SwiftWebDriver.
85

96
@testable import SwiftWebDriver
107
import Testing
118

129
@Suite("Chrome Driver Element Handles", .serialized)
1310
internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
1411
@Test("Click Button")
15-
public func clickButton() async throws {
12+
func clickButton() async throws {
1613
page = "elementHandleTestPage.html"
1714

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

22+
@Test("Double Click Button")
23+
func doubleClickButton() async throws {
24+
page = "elementHandleTestPage.html"
25+
26+
try await driver.navigateTo(urlString: testPageURL.absoluteString)
27+
let button = try await driver.findElement(.css(.id("doubleclick")))
28+
try await button.doubleClick()
29+
let test = try await button.text()
30+
#expect(test == "ii")
31+
}
32+
2533
@Test("Get Element Attributes")
26-
public func getAttribute() async throws {
34+
func getAttribute() async throws {
2735
page = "elementHandleTestPage.html"
2836
try await driver.navigateTo(urlString: testPageURL.absoluteString)
2937

@@ -34,7 +42,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
3442
}
3543

3644
@Test("Clear Element")
37-
public func clearElement() async throws {
45+
func clearElement() async throws {
3846
page = "elementHandleTestPage.html"
3947
try await driver.navigateTo(urlString: testPageURL.absoluteString)
4048

@@ -48,7 +56,7 @@ internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest {
4856
}
4957

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

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

7078
@Test("Fail any operation if element becomes stale")
71-
public func throwStaleError() async throws {
79+
func throwStaleError() async throws {
7280
let sleepTotal = 3
7381
page = "elementHandleTestPage.html"
7482
try await driver.navigateTo(urlString: testPageURL.absoluteString)

0 commit comments

Comments
 (0)