Skip to content

Commit

Permalink
Cleanup WebDriverRequest struct (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlabelle authored Aug 28, 2023
1 parent c3d472e commit 5417268
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 57 deletions.
6 changes: 0 additions & 6 deletions Sources/Element+Request.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "click"] }
var method: HTTPMethod { .post }
var body: Body { .init() }
}

/// text - the element text
Expand All @@ -49,7 +48,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "text"] }
var method: HTTPMethod { .get }
var body: Body { .init() }
}

/// findElement(byName:)
Expand Down Expand Up @@ -126,7 +124,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "attribute", name] }
var method: HTTPMethod { .get }
var body: Body = .init()
}

/// location - return x, y location of the element relative to the screen top left corner
Expand All @@ -148,7 +145,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "location"] }
var method: HTTPMethod { .get }
var body: Body = .init()

struct ResponseValue: Codable {
let x: Int
Expand Down Expand Up @@ -176,7 +172,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "size"] }
var method: HTTPMethod { .get }
var body: Body { .init() }

struct ResponseValue: Codable {
let width: Int
Expand All @@ -202,7 +197,6 @@ extension Element {

var pathComponents: [String] { ["session", element.session.id, "element", element.id, "displayed"] }
var method: HTTPMethod { .get }
var body: Body = .init()

// Override the whole Response struct instead of just ResponseValue
// because the value property is a boolean instead of a struct
Expand Down
58 changes: 18 additions & 40 deletions Sources/HTTPWebDriver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,57 +13,35 @@ public struct HTTPWebDriver: WebDriver {
// Send a WebDriverRequest to the web driver local service
// TODO: consider making this function async/awaitable
@discardableResult
public func send<Request>(_ request: Request) throws -> Request.Response where Request: WebDriverRequest {
// Create urlRequest with proper Url and method
let url = Self.buildURL(base: rootURL, pathComponents: request.pathComponents, query: request.query)
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = request.method.rawValue
// TODO: Setting timeoutInterval causes a crash when sending the request on the CI machines.
// https://linear.app/the-browser-company/issue/WIN-627/setting-timeoutinterval-on-urlrequest-makes-request-crash
// urlRequest.timeoutInterval = Self.defaultTimeout

// Add the body if the WebDriverRequest type defines one
if Request.Body.self != CodableNone.self {
urlRequest.addValue("content-encoding", forHTTPHeaderField: "json")
urlRequest.addValue("application/json;charset=UTF-8", forHTTPHeaderField: "content-type")
urlRequest.httpBody = try JSONEncoder().encode(request.body)
}
public func send<Request: WebDriverRequest>(_ request: Request) throws -> Request.Response {
let urlRequest = try buildURLRequest(request)

// Send the request and decode result or error
let (status, responseData) = try urlRequest.send()
guard status == 200 else {
let error = try JSONDecoder().decode(WebDriverError.self, from: responseData)
throw error
throw try JSONDecoder().decode(WebDriverError.self, from: responseData)
}
let res = try JSONDecoder().decode(Request.Response.self, from: responseData)
return res
return try JSONDecoder().decode(Request.Response.self, from: responseData)
}

// Utility function to build a URL from its parts; inspired by GPT4.
private static func buildURL(base: URL, pathComponents: [String], query: [String: String] = [:]) -> URL {
var url = base

// Append the path components
for pathComponent in pathComponents {
url.appendPathComponent(pathComponent)
private func buildURLRequest<Request: WebDriverRequest>(_ request: Request) throws -> URLRequest {
var url = rootURL
for (index, pathComponent) in request.pathComponents.enumerated() {
let last = index == request.pathComponents.count - 1
url.appendPathComponent(pathComponent, isDirectory: !last)
}

if !query.isEmpty {
// Get the URL components
var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false)!

// Convert dictionary to query items
let queryItems = query.map { key, value in
URLQueryItem(name: key, value: value)
}

// Append query items to URL components
urlComponents.queryItems = queryItems
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = request.method.rawValue
// TODO(#40): Setting timeoutInterval causes a crash when sending the request on the CI machines.
// urlRequest.timeoutInterval = Self.defaultTimeout

// Get the final URL
url = urlComponents.url!
// Add the body if the WebDriverRequest type defines one
if Request.Body.self != CodableNone.self {
urlRequest.addValue("application/json;charset=UTF-8", forHTTPHeaderField: "content-type")
urlRequest.httpBody = try JSONEncoder().encode(request.body)
}

return url
return urlRequest
}
}
3 changes: 0 additions & 3 deletions Sources/Session+Requests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ extension Session {

var pathComponents: [String] { ["session", session.id, "title"] }
var method: HTTPMethod { .get }
var body: Body { .init() }
}

/// screenshot()
Expand Down Expand Up @@ -50,7 +49,6 @@ extension Session {

var pathComponents: [String] { ["session", session.id, "screenshot"] }
var method: HTTPMethod { .get }
var body: Body { .init() }
}

/// findElement(byName:)
Expand Down Expand Up @@ -173,7 +171,6 @@ extension Session {

var pathComponents: [String] { ["session", session.id, "element", "active"] }
var method: HTTPMethod { .post }
var body: Body = .init()

struct ResponseValue: Codable {
var element: String
Expand Down
1 change: 0 additions & 1 deletion Sources/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,5 @@ public class Session {
let sessionId: String
var pathComponents: [String] { ["session", sessionId] }
var method: HTTPMethod { .delete }
var body: Body { .init() }
}
}
1 change: 0 additions & 1 deletion Sources/WebDriver+Requests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct WebDriverStatusRequest: WebDriverRequest {

var pathComponents: [String] { ["status"] }
var method: HTTPMethod { .get }
var body: Body { .init() }
}

public struct WebDriverStatus: Codable {
Expand Down
8 changes: 2 additions & 6 deletions Sources/WebDriverRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@ public protocol WebDriverRequest {
associatedtype Response: Codable = WebDriverResponse<ResponseValue>

var pathComponents: [String] { get }
var query: [String: String] { get }
var method: HTTPMethod { get }
var body: Body { get }
}

// Provide a default for the query part of the request URL
// Saves protocol implementers from having to define if they do not use
// TODO: is there a way to provide a default for body?
extension WebDriverRequest {
public var query: [String: String] { [:] }
extension WebDriverRequest where Body == CodableNone {
var body: Body { .init() }
}

public enum HTTPMethod: String {
Expand Down

0 comments on commit 5417268

Please sign in to comment.