From 8626746c6cd33baa1e6e1734b57f971a68c329af Mon Sep 17 00:00:00 2001 From: Brian Harvey Date: Tue, 5 Mar 2024 09:21:35 -0500 Subject: [PATCH] feat: Current window position (#130) --- Docs/SupportedAPIs.md | 12 ++-- Sources/WebDriver/Requests.swift | 59 ++++++++++++++++--- Sources/WebDriver/Session.swift | 13 +--- Sources/WebDriver/Window.swift | 46 +++++++++++++++ .../UnitTests/APIToRequestMappingTests.swift | 26 ++++++-- 5 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 Sources/WebDriver/Window.swift diff --git a/Docs/SupportedAPIs.md b/Docs/SupportedAPIs.md index 20947af..4de4e51 100644 --- a/Docs/SupportedAPIs.md +++ b/Docs/SupportedAPIs.md @@ -64,10 +64,10 @@ Contributions to expand support to unimplemented functionality are always welcom | POST | `/session/:sessionId/window/maximize` | Supported | Not implemented | | POST | `/session/:sessionId/window/size` | Supported | Not implemented | | GET | `/session/:sessionId/window/size` | Supported | Not implemented | -| POST | `/session/:sessionId/window/:windowHandle/size` | Supported | `Session.resize()` | -| GET | `/session/:sessionId/window/:windowHandle/size` | Supported | `Session.size()` | -| POST | `/session/:sessionId/window/:windowHandle/position` | Supported | Not implemented | -| GET | `/session/:sessionId/window/:windowHandle/position` | Supported | Not implemented | -| POST | `/session/:sessionId/window/:windowHandle/maximize` | Supported | Not implemented | +| POST | `/session/:sessionId/window/:windowHandle/size` | Supported | `Window.setSize()` | +| GET | `/session/:sessionId/window/:windowHandle/size` | Supported | `Window.size` | +| POST | `/session/:sessionId/window/:windowHandle/position` | Supported | `Window.setPosition()`| +| GET | `/session/:sessionId/window/:windowHandle/position` | Supported | `Window.position`| +| POST | `/session/:sessionId/window/:windowHandle/maximize` | Supported | `Window.maximize()`| | GET | `/session/:sessionId/window_handle` | Supported | `Session.windowHandle`| -| GET | `/session/:sessionId/window_handles` | Supported | `Session.windowHandles`| \ No newline at end of file +| GET | `/session/:sessionId/window_handles` | Supported | `Session.windowHandles`| diff --git a/Sources/WebDriver/Requests.swift b/Sources/WebDriver/Requests.swift index 5413e5b..2f9f776 100644 --- a/Sources/WebDriver/Requests.swift +++ b/Sources/WebDriver/Requests.swift @@ -509,20 +509,20 @@ public enum Requests { } // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidwindowwindowhandlesize - public enum SessionWindowSize { + public enum WindowSize { public struct Post: Request { public var session: String public var windowHandle: String - public var width: Int - public var height: Int + public var width: Double + public var height: Double public var pathComponents: [String] { ["session", session, "window", windowHandle, "size"] } public var method: HTTPMethod { .post } public var body: Body { .init(width: width, height: height) } public struct Body: Codable { - public var width: Int - public var height: Int + public var width: Double + public var height: Double } } @@ -535,8 +535,8 @@ public enum Requests { public typealias Response = ResponseWithValue public struct ResponseValue: Codable { - public var width: Int - public var height: Int + public var width: Double + public var height: Double } } } @@ -558,8 +558,8 @@ public enum Requests { public typealias Response = WebDriverStatus } - - // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidorientation + + // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidorientation public enum SessionOrientation { public struct Post: Request { public var session: String @@ -584,6 +584,47 @@ public enum Requests { } } + // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidwindowwindowhandleposition + public enum WindowPosition { + public struct Post: Request { + public var session: String + public var windowHandle: String + public var x: Double + public var y: Double + + public var pathComponents: [String] { ["session", session, "window", windowHandle, "position"] } + public var method: HTTPMethod { .post } + public var body: Body { .init(x: x, y: y) } + + public struct Body: Codable { + public var x: Double + public var y: Double + } + } + + public struct Get: Request { + public var session: String + public var windowHandle: String + + public var pathComponents: [String] { ["session", session, "window", windowHandle, "position"] } + public var method: HTTPMethod { .get } + + public typealias Response = ResponseWithValue + public struct ResponseValue: Codable { + public var x: Double + public var y: Double + } + } + } + + public struct WindowMaximize: Request { + public var session: String + public var windowHandle: String + + public var pathComponents: [String] { ["session", session, "window", windowHandle, "maximize"] } + public var method: HTTPMethod { .post } + } + // https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidwindow_handle public struct SessionWindowHandle: Request { public var session: String diff --git a/Sources/WebDriver/Session.swift b/Sources/WebDriver/Session.swift index 6d6fcbe..6bea0d5 100644 --- a/Sources/WebDriver/Session.swift +++ b/Sources/WebDriver/Session.swift @@ -315,18 +315,7 @@ public class Session { try webDriver.send(Requests.SessionWindow.Delete(session: id, name: name)) } - public func size(window handle: String) throws -> (width: Int, height: Int) { - let response = try webDriver.send(Requests.SessionWindowSize.Get(session: id, windowHandle: handle)) - return (width: response.value.width, height: response.value.height) - } - - /// Change the size of the specified window - /// - Parameter name: URL parameter is "current", the currently active window will be resized. - /// - Parameter width: The new window width. - /// - Parameter height: The new window height - public func resize(window handle: String, width: Int, height: Int) throws { - try webDriver.send(Requests.SessionWindowSize.Post(session: id, windowHandle: handle, width: width, height: height)) - } + public func window(handle: String) throws -> Window { .init(session: self, handle: handle) } /// - Prarmeter: Orientation the window will flip to {LANDSCAPE|PORTRAIT} public func setOrientation(_ value: ScreenOrientation) throws { diff --git a/Sources/WebDriver/Window.swift b/Sources/WebDriver/Window.swift new file mode 100644 index 0000000..f598c35 --- /dev/null +++ b/Sources/WebDriver/Window.swift @@ -0,0 +1,46 @@ +/// Exposes window-specific webdriver operations +public struct Window { + var webDriver: WebDriver { session.webDriver } + public let session: Session + public let handle: String + + public init(session: Session, handle: String) { + self.session = session + self.handle = handle + } + + public var position: (x: Double, y: Double) { + get throws { + let responseValue = try webDriver.send(Requests.WindowPosition.Get( + session: session.id, windowHandle: handle)).value + return (responseValue.x, responseValue.y) + } + } + + public var size: (width: Double, height: Double) { + get throws { + let responseValue = try webDriver.send(Requests.WindowSize.Get( + session: session.id, windowHandle: handle)).value + return (responseValue.width, responseValue.height) + } + } + + /// - Parameters: + /// - width: The new window width + /// - height: The new window height + public func setSize(width: Double, height: Double) throws { + try webDriver.send(Requests.WindowSize.Post(session: session.id, windowHandle: handle, width: width, height: height)) + } + + /// - Parameters: + /// - x: Position in the top left corner of the x coordinate + /// - y: Position in the top left corner of the y coordinate + public func setPosition(x: Double, y: Double) throws { + try webDriver.send(Requests.WindowPosition.Post(session: session.id, windowHandle: handle, x: x, y: y)) + } + + /// Maximize specific window if :windowHandle is "current" the current window will be maximized + public func maximize() throws { + try webDriver.send(Requests.WindowMaximize(session: session.id, windowHandle: handle)) + } +} diff --git a/Tests/UnitTests/APIToRequestMappingTests.swift b/Tests/UnitTests/APIToRequestMappingTests.swift index 6d75cf4..bf3e3bf 100644 --- a/Tests/UnitTests/APIToRequestMappingTests.swift +++ b/Tests/UnitTests/APIToRequestMappingTests.swift @@ -190,6 +190,18 @@ class APIToRequestMappingTests: XCTestCase { XCTAssert(try element.enabled == true) } + func testWindowPosition() throws { + let mockWebDriver: MockWebDriver = MockWebDriver() + let session = Session(webDriver: mockWebDriver, existingId: "mySession") + mockWebDriver.expect(path: "session/mySession/window/myWindow/position", method: .post) + try session.window(handle: "myWindow").setPosition(x: 9, y: 16) + + mockWebDriver.expect(path: "session/mySession/window/myWindow/position", method: .get, type: Requests.WindowPosition.Get.self) { + ResponseWithValue(.init(x: 9, y: 16)) + } + XCTAssert(try session.window(handle: "myWindow").position == (x: 9, y: 16)) + } + func testSessionScript() throws { let mockWebDriver = MockWebDriver() let session = Session(webDriver: mockWebDriver, existingId: "mySession") @@ -226,12 +238,19 @@ class APIToRequestMappingTests: XCTestCase { let mockWebDriver: MockWebDriver = MockWebDriver() let session = Session(webDriver: mockWebDriver, existingId: "mySession") mockWebDriver.expect(path: "session/mySession/window/myWindow/size", method: .post) - try session.resize(window: "myWindow", width: 500, height: 500) + try session.window(handle: "myWindow").setSize(width: 500, height: 500) - mockWebDriver.expect(path: "session/mySession/window/myWindow/size", method: .get, type: Requests.SessionWindowSize.Get.self) { + mockWebDriver.expect(path: "session/mySession/window/myWindow/size", method: .get, type: Requests.WindowSize.Get.self) { ResponseWithValue(.init(width: 500, height: 500)) } - XCTAssert(try session.size(window: "myWindow") == (width: 500, height: 500)) + XCTAssert(try session.window(handle: "myWindow").size == (width: 500, height: 500)) + } + + func testMaximizeWindow() throws { + let mockWebDriver: MockWebDriver = MockWebDriver() + let session: Session = Session(webDriver: mockWebDriver, existingId: "mySession") + mockWebDriver.expect(path: "session/mySession/window/myWindow/maximize", method: .post) + try session.window(handle: "myWindow").maximize() } func testWindowHandle() throws { @@ -257,7 +276,6 @@ class APIToRequestMappingTests: XCTestCase { 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("currentSource") }