Skip to content

Commit

Permalink
Merge branch 'main' into squid/geolocation
Browse files Browse the repository at this point in the history
  • Loading branch information
Squidonomics authored Feb 23, 2024
2 parents 3cbcb11 + 0e62310 commit cc306c2
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 14 deletions.
6 changes: 4 additions & 2 deletions Docs/SupportedAPIs.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Contributions to expand support to unimplemented functionality are always welcom
| GET | `/session/:sessionId/element/:id/size` | Supported | `Element.size` |
| GET | `/session/:sessionId/element/:id/text` | Supported | `Element.text` |
| POST | `/session/:sessionId/element/:id/value` | Supported | `Element.sendKeys()`|
| POST | `/session/:sessionId/execute` | Not Supported| `Session.execute()` |
| POST | `/session/:sessionId/execute_async` | Not Supported| `Session.execute()` |
| POST | `/session/:sessionId/forward` | Supported | `Session.forward()` |
| POST | `/session/:sessionId/keys` | Supported | `Session.sendKeys()`|
| POST | `/session/:sessionId/location` | Supported | `Session.setLocation`|
Expand All @@ -45,7 +47,7 @@ Contributions to expand support to unimplemented functionality are always welcom
| GET | `/session/:sessionId/orientation` | Supported | Not implemented |
| POST | `/session/:sessionId/refresh` | Not supported| `Session.refresh()` |
| GET | `/session/:sessionId/screenshot` | Supported | `Session.screenshot()`|
| GET | `/session/:sessionId/source` | Supported | Not implemented |
| GET | `/session/:sessionId/source` | Supported | `Session.source` |
| POST | `/session/:sessionId/timeouts` | Supported | `Session.setTimeout()`|
| GET | `/session/:sessionId/title` | Supported | `Session.title` |
| POST | `/session/:sessionId/touch/click` | Supported | `Element.touchClick()`|
Expand All @@ -69,4 +71,4 @@ Contributions to expand support to unimplemented functionality are always welcom
| GET | `/session/:sessionId/window/:windowHandle/position` | Supported | Not implemented |
| POST | `/session/:sessionId/window/:windowHandle/maximize` | Supported | Not implemented |
| GET | `/session/:sessionId/window_handle` | Supported | Not implemented |
| GET | `/session/:sessionId/window_handles` | Supported | Not implemented |
| GET | `/session/:sessionId/window_handles` | Supported | Not implemented |
33 changes: 21 additions & 12 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,37 @@ import PackageDescription
let package = Package(
name: "swift-webdriver",
products: [
.library(name: "WebDriver", targets: ["WebDriver", "WinAppDriver"]),
.library(name: "WebDriver", targets: ["WebDriver"]),
],
targets: [
.target(
name: "WebDriver",
path: "Sources/WebDriver"),
.target(
name: "WinAppDriver",
dependencies: ["WebDriver"],
path: "Sources/WinAppDriver"),
.target(
name: "TestsCommon",
path: "Tests/Common"),
.testTarget(
name: "WinAppDriverTests",
dependencies: ["TestsCommon", "WebDriver", "WinAppDriver"],
// Ignore "LNK4217: locally defined symbol imported" spew due to SPM library support limitations
linkerSettings: [ .unsafeFlags(["-Xlinker", "-ignore:4217"]) ]),
.testTarget(
name: "UnitTests",
dependencies: ["TestsCommon", "WebDriver", "WinAppDriver"],
dependencies: ["TestsCommon", "WebDriver"],
// Ignore "LNK4217: locally defined symbol imported" spew due to SPM library support limitations
linkerSettings: [ .unsafeFlags(["-Xlinker", "-ignore:4217"]) ]),
linkerSettings: [ .unsafeFlags(["-Xlinker", "-ignore:4217"], .when(platforms: [.windows])) ]),
]
)

#if os(Windows)
package.products += [
.library(name: "WinAppDriver", targets: ["WinAppDriver"])
]
package.targets += [
.target(
name: "WinAppDriver",
dependencies: ["WebDriver"],
path: "Sources/WinAppDriver"),
.testTarget(
name: "WinAppDriverTests",
dependencies: ["TestsCommon", "WebDriver", "WinAppDriver"],
// Ignore "LNK4217: locally defined symbol imported" spew due to SPM library support limitations
linkerSettings: [ .unsafeFlags(["-Xlinker", "-ignore:4217"]) ]),
]
#endif

2 changes: 2 additions & 0 deletions Sources/WebDriver/HTTPWebDriver.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

public struct HTTPWebDriver: WebDriver {
let rootURL: URL
Expand Down
32 changes: 32 additions & 0 deletions Sources/WebDriver/Requests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,23 @@ public enum Requests {
}
}

// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidexecute
// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidexecute_async
public struct SessionScript: Request {
public var session: String
public var script: String
public var args: [String]
public var async: Bool

public var pathComponents: [String] { ["session", session, async ? "execute_async" : "execute"] }
public var method: HTTPMethod { .post }
public var body: Body { .init(script: script, args: args) }
public struct Body: Codable {
public var script: String
public var args: [String]
}
}

// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidwindow
public enum SessionWindow {
public struct Post: Request {
Expand Down Expand Up @@ -557,6 +574,21 @@ public enum Requests {
public var altitude: Int
}
}

// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidsource
public struct SessionSource: Request {
public var session: String

public var pathComponents: [String] { ["session", session, "source"] }
public var method: HTTPMethod {.get}

public typealias Response = ResponseWithValue<ResponseValue>

public struct ResponseValue: Codable {
public var source: String
}


}

// https://www.selenium.dev/documentation/legacy/json_wire_protocol/#status
Expand Down
9 changes: 9 additions & 0 deletions Sources/WebDriver/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public class Session {
Requests.SessionTimeouts(session: id, type: type, ms: duration * 1000))
}

public func execute(script: String, args: [String] = [], async: Bool = false) throws {
try webDriver.send(Requests.SessionScript(session: id, script: script, args: args, async: async))
}

public func back() throws {
try webDriver.send(Requests.SessionBack(session: id))
}
Expand Down Expand Up @@ -328,6 +332,11 @@ public class Session {
public func getLocation() throws -> (latitude: Int, longitude: Int, altitude: Int) {
let response = try webDriver.send(Requests.SessionGeoLocation.Get(session: id))
return (latitude: response.value.latitude, longitude: response.value.longitude, altitude: response.value.altitude)

/// - Returns: The current page source.
public func source() throws -> String {
let response = try webDriver.send(Requests.SessionSource(session: id))
return response.value.source
}

/// Deletes the current session.
Expand Down
2 changes: 2 additions & 0 deletions Sources/WebDriver/URLRequestExtensions.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

extension URLSession {
func dataTask(
Expand Down
2 changes: 2 additions & 0 deletions Sources/WinAppDriver/ErrorResponse+WinAppDriver.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WebDriver

extension ErrorResponse.Status {
// WinAppDriver returns when passing an incorrect window handle to attach to.
static let winAppDriver_invalidArgument = Self(rawValue: 100)
Expand Down
24 changes: 24 additions & 0 deletions Tests/UnitTests/APIToRequestMappingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,20 @@ class APIToRequestMappingTests: XCTestCase {
XCTAssert(try element.enabled == true)
}

func testSessionScript() throws {
let mockWebDriver = MockWebDriver()
let session = Session(webDriver: mockWebDriver, existingId: "mySession")
mockWebDriver.expect(path: "session/mySession/execute", method: .post)
XCTAssertNotNil(try session.execute(script: "return document.body", args: ["script"], async: false))
}

func testSessionScriptAsync() throws {
let mockWebDriver = MockWebDriver()
let session = Session(webDriver: mockWebDriver, existingId: "mySession")
mockWebDriver.expect(path: "session/mySession/execute_async", method: .post)
XCTAssertNotNil(try session.execute(script: "return document.body", args: ["script"], async: true))
}

func testSessionTouchScroll() throws {
let mockWebDriver: MockWebDriver = MockWebDriver()
let session = Session(webDriver: mockWebDriver, existingId: "mySession")
Expand Down Expand Up @@ -211,5 +225,15 @@ class APIToRequestMappingTests: XCTestCase {
ResponseWithValue(.init(latitude: 5, longitude: 20, altitude: 2003))
}
XCTAssert(try session.getLocation() == (latitude: 5, longitude: 20, altitude: 2003))

func testSessionSource() throws {
let mockWebDriver: MockWebDriver = MockWebDriver()
let session = Session(webDriver: mockWebDriver, existingId: "mySession")

mockWebDriver.expect(path: "session/mySession/source", method: .get, type: Requests.SessionSource.self) {
ResponseWithValue(.init(source: "currentSource"))
}
XCTAssert(try session.source() == "currentSource")

}
}
File renamed without changes.

0 comments on commit cc306c2

Please sign in to comment.