diff --git a/.dotfiles b/.dotfiles index ec9bc76..b9e67aa 160000 --- a/.dotfiles +++ b/.dotfiles @@ -1 +1 @@ -Subproject commit ec9bc762fe9f4a14eee111d5ae65f02dab540b0b +Subproject commit b9e67aa29dd6f69a719295f30935bbee00544847 diff --git a/.github/workflows/run-all-tests.yml b/.github/workflows/run-all-tests.yml index 1822eaf..d02f051 100644 --- a/.github/workflows/run-all-tests.yml +++ b/.github/workflows/run-all-tests.yml @@ -3,11 +3,17 @@ name: Run All Tests on: pull_request: paths: - - '**.swift' + - "**.swift" jobs: all-tests: runs-on: ubuntu-latest + + env: + PATH: "/usr/local/bin:/usr/bin:/bin" + SELENIUM_MAX_SESSIONS: "2" + SWIFT_TEST_WORKERS: "2" + steps: - uses: actions/checkout@v4 @@ -19,15 +25,14 @@ jobs: id: cache-build uses: actions/cache@v3 with: - key: tests-build-cache-${{ hashFiles('Package.resolved') }}-${{ github.ref_name }} - path: ./.build + key: tests-build-cache-${{ hashFiles('Package.resolved') }}-${{ github.ref_name }} + path: ./.build - name: Run All Tests uses: GetAutomaApp/opensource-actions/swifttesting@main with: compose: "true" - required_healthy_services_docker_compose: '["selenium", "httpd"]' - compose_services_to_startup: '["selenium", "httpd"]' + required_healthy_services_docker_compose: '["selenium_chrome", "selenium_firefox", "httpd"]' + compose_services_to_startup: '["selenium_chrome", "selenium_firefox", "httpd"]' + tests-as-compose-service-name: "test" - env: - PATH: "/usr/local/bin:/usr/bin:/bin" diff --git a/Example/Sources/SeleniumSwiftExample/main.swift b/Example/Sources/SeleniumSwiftExample/main.swift index 2b82d73..c31b0ec 100644 --- a/Example/Sources/SeleniumSwiftExample/main.swift +++ b/Example/Sources/SeleniumSwiftExample/main.swift @@ -1,5 +1,5 @@ -// Main.swift -// Copyright (c) 2025 GetAutomaApp +// main.swift +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. @@ -10,12 +10,12 @@ internal enum Main { public static func main() async throws { let chromeOption = ChromeOptions( args: [ - Args(.headless), + ChromeArgs(.headless), ] ) let chromeDriver = try ChromeDriver( - driverURLString: "http://localhost:4444", + driverURLString: "http://selenium_chrome:4444", browserObject: chromeOption ) diff --git a/Example/Tests/SeleniumSwiftExampleTests/SeleniumSwiftExampleTests.swift b/Example/Tests/SeleniumSwiftExampleTests/SeleniumSwiftExampleTests.swift index 97835cb..4e678e2 100644 --- a/Example/Tests/SeleniumSwiftExampleTests/SeleniumSwiftExampleTests.swift +++ b/Example/Tests/SeleniumSwiftExampleTests/SeleniumSwiftExampleTests.swift @@ -1,14 +1,13 @@ // SeleniumSwiftExampleTests.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 class Foundation.Bundle import XCTest +internal enum SeleniumSwiftExample {} + public final class SeleniumSwiftExampleTests: XCTestCase { public func testExample() throws { // This is an example of a functional test case. diff --git a/Package.swift b/Package.swift index 69b6124..ae3fccd 100644 --- a/Package.swift +++ b/Package.swift @@ -2,7 +2,6 @@ import PackageDescription -/// A public let package = Package( name: "swift-webdriver", platforms: [ diff --git a/README.md b/README.md index 1951ec5..be067ec 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ docker-compose run test // Run Tests in Docker # Testing on Host Machine ```bash -docker compose up selenium httpd -d +docker compose up selenium_chrome httpd -d ``` 2. Run tests via test runner / `swift test` @@ -47,7 +47,7 @@ docker compose up selenium httpd -d ```Swift let chromeOption = ChromeOptions( args: [ - Args(.headless), + ChromeArgs(.headless), ] ) diff --git a/Sources/SwiftWebDriver/API/APIClient.swift b/Sources/SwiftWebDriver/API/APIClient.swift index 3095cea..7439f79 100644 --- a/Sources/SwiftWebDriver/API/APIClient.swift +++ b/Sources/SwiftWebDriver/API/APIClient.swift @@ -1,5 +1,5 @@ // APIClient.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. @@ -47,7 +47,7 @@ internal struct APIClient { /// - `APIError.responseStatsFailed` if the status code indicates failure. /// - `APIError.responseBodyIsNil` if no response body is returned. /// - Any `DecodingError` if the response cannot be decoded. - public func request(_ request: R) -> EventLoopFuture where R: RequestType { + public func request(_ request: R) -> EventLoopFuture { httpClient.execute(request: request).flatMapResult { response -> Result in guard response.status == .ok else { if @@ -89,7 +89,7 @@ internal struct APIClient { /// - `APIError.responseBodyIsNil` if no response body is returned. /// - Any `DecodingError` if the response cannot be decoded. @discardableResult - public func request(_ request: R) async throws -> R.Response where R: RequestType { + public func request(_ request: R) async throws -> R.Response { try await self.request(request).get() } } diff --git a/Sources/SwiftWebDriver/API/Request/ActionsPayload.swift b/Sources/SwiftWebDriver/API/Request/ActionsPayload.swift index 4a44171..47336cf 100644 --- a/Sources/SwiftWebDriver/API/Request/ActionsPayload.swift +++ b/Sources/SwiftWebDriver/API/Request/ActionsPayload.swift @@ -1,5 +1,5 @@ // ActionsPayload.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/DevTools/AnyEncodable.swift b/Sources/SwiftWebDriver/API/Request/DevTools/AnyEncodable.swift index 076ec3e..06db586 100644 --- a/Sources/SwiftWebDriver/API/Request/DevTools/AnyEncodable.swift +++ b/Sources/SwiftWebDriver/API/Request/DevTools/AnyEncodable.swift @@ -1,5 +1,5 @@ // AnyEncodable.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/DevTools/DevToolTypes.swift b/Sources/SwiftWebDriver/API/Request/DevTools/DevToolTypes.swift index 9a85032..d0600ed 100644 --- a/Sources/SwiftWebDriver/API/Request/DevTools/DevToolTypes.swift +++ b/Sources/SwiftWebDriver/API/Request/DevTools/DevToolTypes.swift @@ -1,5 +1,5 @@ // DevToolTypes.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/DevTools/PostExecuteRequest.swift b/Sources/SwiftWebDriver/API/Request/DevTools/PostExecuteRequest.swift index 5ea476c..2d1a5d7 100644 --- a/Sources/SwiftWebDriver/API/Request/DevTools/PostExecuteRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/DevTools/PostExecuteRequest.swift @@ -1,5 +1,5 @@ // PostExecuteRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/Elements/ElementsTypes.swift b/Sources/SwiftWebDriver/API/Request/Elements/ElementsTypes.swift index 99db4fa..f388d1b 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/ElementsTypes.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/ElementsTypes.swift @@ -14,45 +14,32 @@ public enum ElementsTypes { /// such as `Enter`, `Return`, and `Tab`. They can be sent along with regular /// text input to simulate keyboard events in browser automation. public enum SendValueActionKeyTypes: String { - /// The **Enter** key (Unicode: `\u{E007}`). - /// - /// Typically used to submit forms or trigger button actions in web pages. - case ENTER1 = "\u{E007}" - - /// The **Return** key (Unicode: `\u{E006}`). - /// - /// Often treated similarly to `Enter`, but provided as a separate code - /// for systems that distinguish between them. - case RETURN1 = "\u{E006}" - - /// The **Tab** key (Unicode: `\u{E004}`). - /// - /// Used to move focus between interactive elements (e.g., form fields) in a web page. - case TAB = "\u{E004}" - - case NULL = "\u{E000}" - case CANCEL = "\u{E001}" - case HELP = "\u{E002}" + case ALT = "\u{E00A}" case BACKSPACE = "\u{E003}" + case CANCEL = "\u{E001}" case CLEAR = "\u{E005}" - case SHIFT = "\u{E008}" case CONTROL = "\u{E009}" - case ALT = "\u{E00A}" - case PAUSE = "\u{E00B}" - case ESCAPE = "\u{E00C}" - case SPACE = "\u{E00D}" - case PAGE_UP = "\u{E00E}" - case PAGE_DOWN = "\u{E00F}" + case DELETE = "\u{E017}" + case DOWNARROW = "\u{E015}" case END = "\u{E010}" + case ENTER1 = "\u{E007}" + case ESCAPE = "\u{E00C}" + case FKEY1 = "\u{E031}" + case FKEY2 = "\u{E032}" + case HELP = "\u{E002}" case HOME = "\u{E011}" - case LEFT_ARROW = "\u{E012}" - case UP_ARROW = "\u{E013}" - case RIGHT_ARROW = "\u{E014}" - case DOWN_ARROW = "\u{E015}" case INSERT = "\u{E016}" - case DELETE = "\u{E017}" - case F1 = "\u{E031}" - case F2 = "\u{E032}" + case LEFTARROW = "\u{E012}" + case NULL = "\u{E000}" + case PAGEDOWN = "\u{E00F}" + case PAGEUP = "\u{E00E}" + case PAUSE = "\u{E00B}" + case RETURN1 = "\u{E006}" + case RIGHTARROW = "\u{E014}" + case SHIFT = "\u{E008}" + case SPACE = "\u{E00D}" + case TAB = "\u{E004}" + case UPARROW = "\u{E013}" /// The raw Unicode representation of the key. /// diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementAttributeRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementAttributeRequest.swift index 994ce6f..f1006e6 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementAttributeRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementAttributeRequest.swift @@ -1,10 +1,7 @@ // GetElementAttributeRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementNamePropertyRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementNamePropertyRequest.swift index 9d21ca2..368e2a4 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementNamePropertyRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementNamePropertyRequest.swift @@ -1,10 +1,7 @@ // GetElementNamePropertyRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementNameRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementNameRequest.swift index 3c424e8..49b147d 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementNameRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementNameRequest.swift @@ -1,10 +1,7 @@ // GetElementNameRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementPropertyNameRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementPropertyNameRequest.swift index c525806..4034b34 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementPropertyNameRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementPropertyNameRequest.swift @@ -1,10 +1,7 @@ // GetElementPropertyNameRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementRectRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementRectRequest.swift index 9a4073b..615c93e 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementRectRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementRectRequest.swift @@ -1,5 +1,5 @@ // GetElementRectRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. @@ -25,7 +25,9 @@ internal struct GetElementRectRequest: RequestType { public var elementId: String /// Endpoint path for retrieving the element rectangle. - public var path: String { "session/\(sessionId)/element/\(elementId)/rect" } + public var path: String { + "session/\(sessionId)/element/\(elementId)/rect" + } /// HTTP method used for this request (`GET`). public var method: HTTPMethod = .GET @@ -34,5 +36,7 @@ internal struct GetElementRectRequest: RequestType { public var headers: HTTPHeaders = [:] /// HTTP request body (none required for this request). - public var body: HTTPClient.Body? { nil } + public var body: HTTPClient.Body? { + nil + } } diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementScreenShotRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementScreenShotRequest.swift index 07aa560..569774b 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementScreenShotRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementScreenShotRequest.swift @@ -1,10 +1,7 @@ // GetElementScreenShotRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementSelectedRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementSelectedRequest.swift index 406896f..1c80b4e 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementSelectedRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementSelectedRequest.swift @@ -1,10 +1,7 @@ // GetElementSelectedRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetElementTextRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetElementTextRequest.swift index a9783da..5fd32af 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetElementTextRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetElementTextRequest.swift @@ -1,10 +1,7 @@ // GetElementTextRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetScreenShotRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetScreenShotRequest.swift index 63eed89..d99687e 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetScreenShotRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetScreenShotRequest.swift @@ -1,10 +1,7 @@ // GetScreenShotRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/GetSessionActiveElementRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/GetSessionActiveElementRequest.swift index 971a0d1..4495c17 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/GetSessionActiveElementRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/GetSessionActiveElementRequest.swift @@ -1,14 +1,10 @@ // GetSessionActiveElementRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient +import Foundation import NIO import NIOHTTP1 diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementByIdRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementByIdRequest.swift index acf9974..347065c 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementByIdRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementByIdRequest.swift @@ -1,10 +1,7 @@ // PostElementByIdRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementClearRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementClearRequest.swift index 5510447..93db575 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementClearRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementClearRequest.swift @@ -1,10 +1,7 @@ // PostElementClearRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementClickRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementClickRequest.swift index 926d6b8..353bb70 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementClickRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementClickRequest.swift @@ -1,10 +1,7 @@ // PostElementClickRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift index c789f18..cbce474 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementDoubleClickRequest.swift @@ -1,5 +1,5 @@ // PostElementDoubleClickRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementDragAndDropRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementDragAndDropRequest.swift index cb2ec9c..a5137dd 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementDragAndDropRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementDragAndDropRequest.swift @@ -1,5 +1,5 @@ // PostElementDragAndDropRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementRequest.swift index 60f0043..e8b0b88 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementRequest.swift @@ -1,10 +1,7 @@ // PostElementRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementSendValueRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementSendValueRequest.swift index 5027dbe..9cae6d4 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementSendValueRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementSendValueRequest.swift @@ -1,10 +1,7 @@ // PostElementSendValueRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementsByIdRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementsByIdRequest.swift index 9214dd5..7419683 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementsByIdRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementsByIdRequest.swift @@ -1,10 +1,7 @@ // PostElementsByIdRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Elements/PostElementsRequest.swift b/Sources/SwiftWebDriver/API/Request/Elements/PostElementsRequest.swift index 2871b47..2f7f7d4 100644 --- a/Sources/SwiftWebDriver/API/Request/Elements/PostElementsRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Elements/PostElementsRequest.swift @@ -1,10 +1,7 @@ // PostElementsRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationRequest.swift index 72daf36..7a41d5e 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationRequest.swift @@ -1,10 +1,7 @@ // GetNavigationRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationTitleRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationTitleRequest.swift index c5ea272..a54da29 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationTitleRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/GetNavigationTitleRequest.swift @@ -1,10 +1,7 @@ // GetNavigationTitleRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationBackRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationBackRequest.swift index 50077fb..36bd62d 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationBackRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationBackRequest.swift @@ -1,10 +1,9 @@ // PostNavigationBackRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient // PostNavigatioinBackRequest.swift // Copyright (c) 2025 GetAutomaApp @@ -14,8 +13,6 @@ // 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 AsyncHTTPClient import NIO import NIOHTTP1 diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationForwardRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationForwardRequest.swift index 6be662e..38465b6 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationForwardRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationForwardRequest.swift @@ -1,10 +1,7 @@ // PostNavigationForwardRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRefreshRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRefreshRequest.swift index 5bf64f5..0694fe7 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRefreshRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRefreshRequest.swift @@ -1,10 +1,7 @@ // PostNavigationRefreshRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRequest.swift b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRequest.swift index 3850519..c62b9b7 100644 --- a/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Navigation/PostNavigationRequest.swift @@ -1,10 +1,7 @@ // PostNavigationRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/RequestType.swift b/Sources/SwiftWebDriver/API/Request/RequestType.swift index 126eaa1..59ece79 100644 --- a/Sources/SwiftWebDriver/API/Request/RequestType.swift +++ b/Sources/SwiftWebDriver/API/Request/RequestType.swift @@ -39,7 +39,7 @@ internal extension RequestType { internal extension HTTPClient { func execute(request: some RequestType, deadline: NIODeadline? = nil) -> EventLoopFuture { do { - let request = try HTTPClient.Request( + let request = try Self.Request( url: request.url, method: request.method, headers: request.headers, diff --git a/Sources/SwiftWebDriver/API/Request/Sessions/DeleteSessionRequest.swift b/Sources/SwiftWebDriver/API/Request/Sessions/DeleteSessionRequest.swift index ac2e498..a8051b6 100644 --- a/Sources/SwiftWebDriver/API/Request/Sessions/DeleteSessionRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Sessions/DeleteSessionRequest.swift @@ -1,10 +1,7 @@ // DeleteSessionRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Request/Sessions/NewSessionRequest.swift b/Sources/SwiftWebDriver/API/Request/Sessions/NewSessionRequest.swift index d0f6341..26cc68e 100644 --- a/Sources/SwiftWebDriver/API/Request/Sessions/NewSessionRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Sessions/NewSessionRequest.swift @@ -22,7 +22,7 @@ internal struct NewSessionRequest: RequestType { public var body: HTTPClient.Body? { let requestBody = RequestBody( capabilities: RequestBodyCapabilities( - alwaysMatch: RequestBodyCapabilities.AlwaysMatch( + alwaysMatch: AlwaysMatch( browserOptions: browserOptions ) ) @@ -41,43 +41,44 @@ internal struct NewSessionRequest: RequestType { internal extension NewSessionRequest { struct RequestBody: Codable { - let capabilities: RequestBodyCapabilities + internal let capabilities: RequestBodyCapabilities } struct Capabilities: Codable { - let alwaysMatch: AlwaysMatch + internal let alwaysMatch: AlwaysMatch } - struct AlwaysMatch: Decodable, Encodable { - let browserName: String - let browserOptions: Options + struct AlwaysMatch: Encodable, Decodable { + internal let browserOptions: Options - enum StaticCodingKeys: String, CodingKey { + internal enum StaticCodingKeys: String, CodingKey { case browserName } - struct DynamicCodingKey: CodingKey { - var stringValue: String - var intValue: Int? { - nil - } + internal struct DynamicCodingKey: CodingKey { + internal let stringValue: String + + internal let intValue: Int? = nil - init(stringValue: String) { + internal init(stringValue: String) { self.stringValue = stringValue } - init?(intValue _: Int) { + internal init?(intValue _: Int) { nil } } - func encode(to encoder: Encoder) throws { + internal func encode(to encoder: Encoder) throws { var staticContainer = encoder.container(keyedBy: StaticCodingKeys.self) - try staticContainer.encode(browserName, forKey: .browserName) + + try staticContainer.encode(Options.browserName, forKey: .browserName) var dynamicContainer = encoder.container(keyedBy: DynamicCodingKey.self) + try dynamicContainer.encode( browserOptions, + forKey: DynamicCodingKey(stringValue: Options.codingKey) ) } @@ -96,43 +97,7 @@ internal extension NewSessionRequest { internal extension NewSessionRequest { struct RequestBodyCapabilities: Encodable, Decodable { - let alwaysMatch: AlwaysMatch - - struct AlwaysMatch: Encodable, Decodable { - let browserOptions: Options - - enum StaticCodingKeys: String, CodingKey { - case browserName - } - - struct DynamicCodingKey: CodingKey { - let stringValue: String - - let intValue: Int? = nil - - init(stringValue: String) { - self.stringValue = stringValue - } - - init?(intValue _: Int) { - nil - } - } - - func encode(to encoder: Encoder) throws { - var staticContainer = encoder.container(keyedBy: StaticCodingKeys.self) - - try staticContainer.encode(Options.browserName, forKey: .browserName) - - var dynamicContainer = encoder.container(keyedBy: DynamicCodingKey.self) - - try dynamicContainer.encode( - browserOptions, - - forKey: DynamicCodingKey(stringValue: Options.codingKey) - ) - } - } + internal let alwaysMatch: AlwaysMatch } } @@ -155,11 +120,11 @@ internal protocol BrowserOptions: Codable, Decodable { } extension ChromeOptions: BrowserOptions { - static let browserName = "chrome" - static let codingKey = "goog:chromeOptions" + internal static let browserName = "chrome" + internal static let codingKey = "goog:chromeOptions" } extension FirefoxOptions: BrowserOptions { - static let browserName = "firefox" - static let codingKey = "moz:firefoxOptions" + internal static let browserName = "firefox" + internal static let codingKey = "moz:firefoxOptions" } diff --git a/Sources/SwiftWebDriver/API/Request/Sessions/StatusRequest.swift b/Sources/SwiftWebDriver/API/Request/Sessions/StatusRequest.swift index 8832a16..eb1dd83 100644 --- a/Sources/SwiftWebDriver/API/Request/Sessions/StatusRequest.swift +++ b/Sources/SwiftWebDriver/API/Request/Sessions/StatusRequest.swift @@ -1,10 +1,7 @@ // StatusRequest.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AsyncHTTPClient import Foundation diff --git a/Sources/SwiftWebDriver/API/Response/DevTools/PostExecuteResponse.swift b/Sources/SwiftWebDriver/API/Response/DevTools/PostExecuteResponse.swift index 1602320..49c3398 100644 --- a/Sources/SwiftWebDriver/API/Response/DevTools/PostExecuteResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/DevTools/PostExecuteResponse.swift @@ -1,10 +1,7 @@ // PostExecuteResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 AnyCodable import Foundation diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementAttributeResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementAttributeResponse.swift index 3dfbc0f..7f4b9bf 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementAttributeResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementAttributeResponse.swift @@ -1,10 +1,7 @@ // GetElementAttributeResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementNamePropertyResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementNamePropertyResponse.swift index 0a94099..9cd6c33 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementNamePropertyResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementNamePropertyResponse.swift @@ -1,10 +1,7 @@ // GetElementNamePropertyResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementNameResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementNameResponse.swift index df8a3b1..99f0bca 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementNameResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementNameResponse.swift @@ -1,10 +1,7 @@ // GetElementNameResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementPropertyNameResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementPropertyNameResponse.swift index d8154c9..f2fb31c 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementPropertyNameResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementPropertyNameResponse.swift @@ -1,10 +1,7 @@ // GetElementPropertyNameResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementRectResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementRectResponse.swift index 13e34e2..6c5ab88 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementRectResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementRectResponse.swift @@ -1,5 +1,5 @@ // GetElementRectResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementScreenShotResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementScreenShotResponse.swift index ee9ba62..3609259 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementScreenShotResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementScreenShotResponse.swift @@ -1,10 +1,7 @@ // GetElementScreenShotResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementSelectedResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementSelectedResponse.swift index 1f16431..5fdda4f 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementSelectedResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementSelectedResponse.swift @@ -1,10 +1,7 @@ // GetElementSelectedResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetElementTextResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetElementTextResponse.swift index d62ffdd..db84f59 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetElementTextResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetElementTextResponse.swift @@ -1,10 +1,7 @@ // GetElementTextResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetScreenShotResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetScreenShotResponse.swift index 006baf1..003b9f0 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetScreenShotResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetScreenShotResponse.swift @@ -1,10 +1,7 @@ // GetScreenShotResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/GetSessionActiveElementResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/GetSessionActiveElementResponse.swift index ad20682..dc621d3 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/GetSessionActiveElementResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/GetSessionActiveElementResponse.swift @@ -1,10 +1,7 @@ // GetSessionActiveElementResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementByIdResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementByIdResponse.swift index e02290f..3246d4e 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementByIdResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementByIdResponse.swift @@ -1,10 +1,7 @@ // PostElementByIdResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementClearResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementClearResponse.swift index 5b13ba6..c01456e 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementClearResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementClearResponse.swift @@ -1,10 +1,7 @@ // PostElementClearResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementClickResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementClickResponse.swift index 222ae24..3b6978f 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementClickResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementClickResponse.swift @@ -1,10 +1,7 @@ // PostElementClickResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementResponse.swift index 8846e98..d9f0582 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementResponse.swift @@ -1,10 +1,7 @@ // PostElementResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementSendValueResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementSendValueResponse.swift index 982bdaa..21d4cb8 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementSendValueResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementSendValueResponse.swift @@ -1,10 +1,7 @@ // PostElementSendValueResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementsByIdResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementsByIdResponse.swift index c48128d..c357dac 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementsByIdResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementsByIdResponse.swift @@ -1,10 +1,7 @@ // PostElementsByIdResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Elements/PostElementsResponse.swift b/Sources/SwiftWebDriver/API/Response/Elements/PostElementsResponse.swift index fb78d51..0246d97 100644 --- a/Sources/SwiftWebDriver/API/Response/Elements/PostElementsResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Elements/PostElementsResponse.swift @@ -1,10 +1,7 @@ // PostElementsResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationResponse.swift index 0539d95..805b89e 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationResponse.swift @@ -1,10 +1,7 @@ // GetNavigationResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationTitleResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationTitleResponse.swift index e086d9e..b6b2357 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationTitleResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/GetNavigationTitleResponse.swift @@ -1,10 +1,7 @@ // GetNavigationTitleResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationBackResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationBackResponse.swift index d6a1b88..81a5b76 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationBackResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationBackResponse.swift @@ -1,10 +1,7 @@ // PostNavigationBackResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationForwardResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationForwardResponse.swift index 2620bb8..0387cc8 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationForwardResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationForwardResponse.swift @@ -1,10 +1,7 @@ -// PostNavigatoinForwardResponse.swift -// Copyright (c) 2025 GetAutomaApp +// PostNavigationForwardResponse.swift +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationRefreshResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationRefreshResponse.swift index 72f9252..df2f85a 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationRefreshResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationRefreshResponse.swift @@ -1,10 +1,7 @@ // PostNavigationRefreshResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationResponse.swift b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationResponse.swift index 5136e99..2512fed 100644 --- a/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Navigation/PostNavigationResponse.swift @@ -1,10 +1,7 @@ -// NavigationResponse.swift -// Copyright (c) 2025 GetAutomaApp +// PostNavigationResponse.swift +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/ResponseType.swift b/Sources/SwiftWebDriver/API/Response/ResponseType.swift index 89f3df4..e3a6de5 100644 --- a/Sources/SwiftWebDriver/API/Response/ResponseType.swift +++ b/Sources/SwiftWebDriver/API/Response/ResponseType.swift @@ -1,9 +1,6 @@ // ResponseType.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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. public protocol ResponseType: Sendable, Codable {} diff --git a/Sources/SwiftWebDriver/API/Response/Sessions/DeleteSessionResponse.swift b/Sources/SwiftWebDriver/API/Response/Sessions/DeleteSessionResponse.swift index 1be12ea..c138584 100644 --- a/Sources/SwiftWebDriver/API/Response/Sessions/DeleteSessionResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Sessions/DeleteSessionResponse.swift @@ -1,10 +1,7 @@ // DeleteSessionResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Sessions/NewSessionResponse.swift b/Sources/SwiftWebDriver/API/Response/Sessions/NewSessionResponse.swift index 67c1f74..e5018d1 100644 --- a/Sources/SwiftWebDriver/API/Response/Sessions/NewSessionResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Sessions/NewSessionResponse.swift @@ -1,10 +1,7 @@ // NewSessionResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/API/Response/Sessions/StatusResponse.swift b/Sources/SwiftWebDriver/API/Response/Sessions/StatusResponse.swift index c71350b..f8f5772 100644 --- a/Sources/SwiftWebDriver/API/Response/Sessions/StatusResponse.swift +++ b/Sources/SwiftWebDriver/API/Response/Sessions/StatusResponse.swift @@ -1,10 +1,7 @@ // StatusResponse.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/Element/ElementRect.swift b/Sources/SwiftWebDriver/Element/ElementRect.swift index 417caf3..76c8ba5 100644 --- a/Sources/SwiftWebDriver/Element/ElementRect.swift +++ b/Sources/SwiftWebDriver/Element/ElementRect.swift @@ -1,5 +1,5 @@ // ElementRect.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/Element/Elements.swift b/Sources/SwiftWebDriver/Element/Elements.swift index 117d521..cde929e 100644 --- a/Sources/SwiftWebDriver/Element/Elements.swift +++ b/Sources/SwiftWebDriver/Element/Elements.swift @@ -1,5 +1,5 @@ // Elements.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. @@ -111,7 +111,7 @@ public extension Elements { /// - Throws: An error if the WebDriver request fails. @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) func findElements(_ locatorType: LocatorType) async throws -> Elements { - var elements = [Elements]() + var elements = [Self]() try await withThrowingTaskGroup(of: Elements.self) { group in for element in self { group.addTask { diff --git a/Sources/SwiftWebDriver/Element/Selector/CSSSelector.swift b/Sources/SwiftWebDriver/Element/Selector/CSSSelector.swift index 91c9954..89347b0 100644 --- a/Sources/SwiftWebDriver/Element/Selector/CSSSelector.swift +++ b/Sources/SwiftWebDriver/Element/Selector/CSSSelector.swift @@ -1,10 +1,7 @@ // CSSSelector.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/Element/Selector/LocatorSelector.swift b/Sources/SwiftWebDriver/Element/Selector/LocatorSelector.swift index d96d021..2643b1c 100644 --- a/Sources/SwiftWebDriver/Element/Selector/LocatorSelector.swift +++ b/Sources/SwiftWebDriver/Element/Selector/LocatorSelector.swift @@ -1,10 +1,7 @@ // LocatorSelector.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/Element/Selector/LocatorType.swift b/Sources/SwiftWebDriver/Element/Selector/LocatorType.swift index f64a4ea..49069e0 100644 --- a/Sources/SwiftWebDriver/Element/Selector/LocatorType.swift +++ b/Sources/SwiftWebDriver/Element/Selector/LocatorType.swift @@ -1,10 +1,7 @@ // LocatorType.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/Error/SeleniumError.swift b/Sources/SwiftWebDriver/Error/SeleniumError.swift index 58f0343..5cc99a0 100644 --- a/Sources/SwiftWebDriver/Error/SeleniumError.swift +++ b/Sources/SwiftWebDriver/Error/SeleniumError.swift @@ -1,5 +1,5 @@ // SeleniumError.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/Error/WebDriverError.swift b/Sources/SwiftWebDriver/Error/WebDriverError.swift index 1676c3e..fa0c10b 100644 --- a/Sources/SwiftWebDriver/Error/WebDriverError.swift +++ b/Sources/SwiftWebDriver/Error/WebDriverError.swift @@ -1,10 +1,7 @@ // WebDriverError.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 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 diff --git a/Sources/SwiftWebDriver/WebDriver.swift b/Sources/SwiftWebDriver/WebDriver.swift index 087b275..cc50129 100644 --- a/Sources/SwiftWebDriver/WebDriver.swift +++ b/Sources/SwiftWebDriver/WebDriver.swift @@ -1,5 +1,5 @@ // WebDriver.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. diff --git a/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeDriver.swift b/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeDriver.swift index 34dff4a..f934029 100644 --- a/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeDriver.swift +++ b/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeDriver.swift @@ -24,7 +24,7 @@ public class ChromeDriver: Driver { } public convenience init( - driverURLString urlString: String = "http://localhost:4444", + driverURLString urlString: String = "http://selenium_chrome:4444", browserObject: ChromeOptions ) throws { guard let url = URL(string: urlString) else { diff --git a/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeOptions.swift b/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeOptions.swift index acd9f19..3db7c95 100644 --- a/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeOptions.swift +++ b/Sources/SwiftWebDriver/WebDrivers/Chrome/ChromeOptions.swift @@ -1,5 +1,5 @@ // ChromeOptions.swift -// Copyright (c) 2025 GetAutomaApp +// Copyright (c) 2026 GetAutomaApp // All source code and related assets are the property of GetAutomaApp. // All rights reserved. @@ -7,22 +7,22 @@ import Foundation import NIOCore /// Typealias for a single ChromeOptions argument -public typealias Args = String +public typealias ChromeArgs = String /// ChromeOptions data structure, used to configure Chrome Driver instantiation public struct ChromeOptions: Codable { /// Chrome arguments - public let args: [Args]? + public let args: [ChromeArgs]? /// Initialize ChromeOptions /// - Parameter args: an array of arguments - public init(args: [Args]?) { + public init(args: [ChromeArgs]?) { self.args = args } } /// Restrict arguments to an enum of allowed arguments -public extension Args { +public extension ChromeArgs { /// Initialize chrome option argument init(_ args: Arguments) { self.init(describing: args) diff --git a/Sources/SwiftWebDriver/WebDrivers/Driver.swift b/Sources/SwiftWebDriver/WebDrivers/Driver.swift index d3672a9..8c82a62 100644 --- a/Sources/SwiftWebDriver/WebDrivers/Driver.swift +++ b/Sources/SwiftWebDriver/WebDrivers/Driver.swift @@ -54,17 +54,19 @@ public protocol Driver: FindElementProtocol { func setProperty(element: Element, propertyName: String, newValue: String) async throws func dragAndDrop(from source: Element, to target: Element) async throws + + init(driverURL url: URL, browserObject: BrowserOption) } extension Driver { - static func stopDriverExternal(url: URL, sessionId: String) async throws { + internal static func stopDriverExternal(url: URL, sessionId: String) async throws { let request = DeleteSessionRequest(baseURL: url, sessionId: sessionId) _ = try await APIClient.shared.request(request).map(\.value).get() } - static func startDriverExternal( + internal static func startDriverExternal( url: URL, - browserObject: ChromeOptions, + browserObject: some BrowserOptions, client: APIClient ) async throws -> String { let request = NewSessionRequest(baseURL: url, browserOptions: browserObject) diff --git a/Sources/SwiftWebDriver/WebDrivers/ElementDragAndDropper.swift b/Sources/SwiftWebDriver/WebDrivers/ElementDragAndDropper.swift index 07140cf..cfd53a1 100644 --- a/Sources/SwiftWebDriver/WebDrivers/ElementDragAndDropper.swift +++ b/Sources/SwiftWebDriver/WebDrivers/ElementDragAndDropper.swift @@ -93,7 +93,7 @@ internal struct ElementDragAndDropper { AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": source.elementId]), AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": target.elementId]) ] - try await driver.execute(script, args: arguments, type: .sync) + _ = try await driver.execute(script, args: arguments, type: .sync) } /// Determines whether the source element is HTML5-draggable. diff --git a/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxDriver.swift b/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxDriver.swift index dd253ff..b8e9de7 100644 --- a/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxDriver.swift +++ b/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxDriver.swift @@ -3,349 +3,359 @@ // All source code and related assets are the property of GetAutomaApp. // All rights reserved. -// -// import AsyncHTTPClient -// import Foundation -// import NIO -// import NIOHTTP1 -// - -// public class ChromeDriver: Driver { -// public typealias BrowserOption = ChromeOptions -// -// public var browserObject: ChromeOptions -// -// public var url: URL -// -// private let client = APIClient.shared -// -// public var sessionId: String? -// -// public required init(driverURL url: URL, browserObject: ChromeOptions) { -// self.url = url -// self.browserObject = browserObject -// } -// -// public convenience init( -// driverURLString urlString: String = "http://localhost:4444", -// browserObject: ChromeOptions -// ) throws { -// guard let url = URL(string: urlString) else { -// throw HTTPClientError.invalidURL -// } -// self.init(driverURL: url, browserObject: browserObject) -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func start() async throws -> String { -// // swiftlint:disable:next prefer_self_in_static_references -// let id = try await ChromeDriver.startDriverExternal(url: url, browserObject: browserObject, client: client) -// sessionId = id -// return id -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func stop() async throws -> String? { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = DeleteSessionRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).map(\.value).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func status() async throws -> StatusResponse { -// let request = StatusRequest(baseURL: url) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func getNavigation() async throws -> GetNavigationResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = GetNavigationRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postNavigation(requestURL: String) async throws -> PostNavigationResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostNavigationRequest(baseURL: url, sessionId: sessionId, requestURL: requestURL) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postNavigationBack() async throws -> PostNavigationBackResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostNavigationBackRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postNavigationForward() async throws -> PostNavigationForwardResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostNavigationForwardRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postNavigationRefresh() async throws -> PostNavigationRefreshResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostNavigationRefreshRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func getNavigationTitle() async throws -> GetNavigationTitleResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = GetNavigationTitleRequest(baseURL: url, sessionId: sessionId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postElement(locatorSelector: LocatorSelector) async throws -> PostElementResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorSelector) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postElements(locatorSelector: LocatorSelector) async throws -> PostElementsResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementsRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorSelector) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postElementByElementId( -// locatorSelector: LocatorSelector, -// elementId: String -// ) async throws -> PostElementByIdResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementByIdRequest( -// baseURL: url, -// sessionId: sessionId, -// elementId: elementId, -// cssSelector: locatorSelector -// ) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func postElementsByElementId( -// locatorSelector: LocatorSelector, -// elementId: String -// ) async throws -> PostElementsByIdResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementsByIdRequest( -// baseURL: url, -// sessionId: sessionId, -// elementId: elementId, -// cssSelector: locatorSelector -// ) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func getElementText(elementId: String) async throws -> GetElementTextResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = GetElementTextRequest(baseURL: url, sessionId: sessionId, elementId: elementId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func getElementName(elementId: String) async throws -> GetElementNameResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = GetElementNameRequest(baseURL: url, sessionId: sessionId, elementId: elementId) -// return try await client.request(request).get() -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func findElement(_ locatorType: LocatorType) async throws -> Element { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) -// let response = try await client.request(request) -// return Element(baseURL: url, sessionId: sessionId, elementId: response.elementId) -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func findElements(_ locatorType: LocatorType) async throws -> Elements { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementsRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) -// let response = try await client.request(request) -// return response.value.map { elementId in -// Element(baseURL: url, sessionId: sessionId, elementId: elementId) -// } -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// public func getScreenShot() async throws -> String { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = GetScreenShotRequest(baseURL: url, sessionId: sessionId) -// let response = try await client.request(request) -// return response.value -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// @discardableResult -// public func waitUntil( -// _ locatorType: LocatorType, -// retryCount: Int = 3, -// durationSeconds: Int = 1 -// ) async throws -> Bool { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) -// -// do { -// try await client.request(request) -// return true -// } catch { -// guard -// retryCount > 0, -// error.isSeleniumError(ofType: .noSuchElement) -// else { -// return false -// } -// -// let retryCount = retryCount - 1 -// -// sleep(UInt32(durationSeconds)) -// -// return try await waitUntil(locatorType, retryCount: retryCount, durationSeconds: durationSeconds) -// } -// } -// -// private func executeJavascriptSync(_ script: String, args: [AnyEncodable]) async throws -> PostExecuteResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// -// let request = PostExecuteRequest( -// baseURL: url, -// sessionId: sessionId, -// type: .sync, -// javascriptSnippet: .init(script: script, args: args) -// ) -// -// return try await client.request(request) -// } -// -// private func executeJavascriptAsync(_ script: String, args: [AnyEncodable]) async throws -> PostExecuteResponse { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// -// let request = PostExecuteRequest( -// baseURL: url, -// sessionId: sessionId, -// type: .async, -// javascriptSnippet: .init(script: script, args: args) -// ) -// -// return try await client.request(request) -// } -// -// @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -// @discardableResult -// public func execute( -// _ script: String, -// args: [AnyEncodable], -// type: DevToolTypes.JavascriptExecutionTypes -// ) async throws -> PostExecuteResponse { -// try await type == .sync ? -// executeJavascriptSync(script, args: args) : -// executeJavascriptAsync( -// script, -// args: args -// ) -// } -// -// public func getActiveElement() async throws -> Element { -// guard let sessionId else { -// throw WebDriverError.sessionIdIsNil -// } -// -// let request = GetSessionActiveElementRequest(baseURL: url, sessionId: sessionId) -// -// let response = try await client.request(request) -// return Element(baseURL: url, sessionId: sessionId, elementId: response.elementId) -// } -// -// public func setAttribute(element: Element, attributeName: String, newValue: String) async throws { -// let script = "arguments[0].setAttribute(arguments[1], arguments[2]);" -// -// let args: [AnyEncodable] = [ -// AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), -// AnyEncodable(attributeName), -// AnyEncodable(newValue) -// ] -// try await execute(script, args: args, type: .sync) -// } -// -// public func getProperty(element: Element, propertyName: String) async throws -> PostExecuteResponse { -// let script = "return arguments[0][arguments[1]];" -// -// let args: [AnyEncodable] = [ -// AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), -// AnyEncodable(propertyName) -// ] -// return try await execute(script, args: args, type: .sync) -// } -// -// public func setProperty(element: Element, propertyName: String, newValue: String) async throws { -// let script = "arguments[0][arguments[1]] = arguments[2];" -// let args: [AnyEncodable] = [ -// AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), -// AnyEncodable(propertyName), -// AnyEncodable(newValue) -// ] -// -// try await execute(script, args: args, type: .sync) -// } -// -// public func dragAndDrop(from source: Element, to target: Element) async throws { -// try await ElementDragAndDropper(driver: self, from: source, to: target).dragAndDrop() -// } -// -// deinit { -// let url = url -// let sessionId = sessionId -// Task { -// guard let sessionId else { return } -// // swiftlint:disable:next prefer_self_in_static_references -// try await ChromeDriver.stopDriverExternal(url: url, sessionId: sessionId) -// } -// } -// -// } +import AsyncHTTPClient +import Foundation +import NIO +import NIOHTTP1 + +public class FirefoxDriver: Driver { + public typealias BrowserOption = FirefoxOptions + + public var browserObject: FirefoxOptions + + public var url: URL + + private let client = APIClient.shared + + public var sessionId: String? + + public required init(driverURL url: URL, browserObject: FirefoxOptions) { + self.url = url + self.browserObject = browserObject + } + + public convenience init( + driverURLString urlString: String = "http://selenium_firefox:4444", + browserObject: FirefoxOptions + ) throws { + guard let url = URL(string: urlString) else { + throw HTTPClientError.invalidURL + } + self.init(driverURL: url, browserObject: browserObject) + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func start() async throws -> String { + let id = try await Self.startDriverExternal( + url: url, + browserObject: browserObject, + client: client + ) + sessionId = id + return id + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func stop() async throws -> String? { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = DeleteSessionRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).map(\.value).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func status() async throws -> StatusResponse { + let request = StatusRequest(baseURL: url) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func getNavigation() async throws -> GetNavigationResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = GetNavigationRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postNavigation(requestURL: String) async throws -> PostNavigationResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostNavigationRequest(baseURL: url, sessionId: sessionId, requestURL: requestURL) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postNavigationBack() async throws -> PostNavigationBackResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostNavigationBackRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postNavigationForward() async throws -> PostNavigationForwardResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostNavigationForwardRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postNavigationRefresh() async throws -> PostNavigationRefreshResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostNavigationRefreshRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func getNavigationTitle() async throws -> GetNavigationTitleResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = GetNavigationTitleRequest(baseURL: url, sessionId: sessionId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postElement(locatorSelector: LocatorSelector) async throws -> PostElementResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorSelector) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postElements(locatorSelector: LocatorSelector) async throws -> PostElementsResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementsRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorSelector) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postElementByElementId( + locatorSelector: LocatorSelector, + elementId: String + ) async throws -> PostElementByIdResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementByIdRequest( + baseURL: url, + sessionId: sessionId, + elementId: elementId, + cssSelector: locatorSelector + ) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func postElementsByElementId( + locatorSelector: LocatorSelector, + elementId: String + ) async throws -> PostElementsByIdResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementsByIdRequest( + baseURL: url, + sessionId: sessionId, + elementId: elementId, + cssSelector: locatorSelector + ) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func getElementText(elementId: String) async throws -> GetElementTextResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = GetElementTextRequest(baseURL: url, sessionId: sessionId, elementId: elementId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func getElementName(elementId: String) async throws -> GetElementNameResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = GetElementNameRequest(baseURL: url, sessionId: sessionId, elementId: elementId) + return try await client.request(request).get() + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func findElement(_ locatorType: LocatorType) async throws -> Element { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) + let response = try await client.request(request) + return Element(baseURL: url, sessionId: sessionId, elementId: response.elementId) + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func findElements(_ locatorType: LocatorType) async throws -> Elements { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementsRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) + let response = try await client.request(request) + return response.value.map { elementId in + Element(baseURL: url, sessionId: sessionId, elementId: elementId) + } + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func getScreenShot() async throws -> String { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = GetScreenShotRequest(baseURL: url, sessionId: sessionId) + let response = try await client.request(request) + return response.value + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + @discardableResult + public func waitUntil( + _ locatorType: LocatorType, + retryCount: Int = 3, + durationSeconds: Int = 1 + ) async throws -> Bool { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + let request = PostElementRequest(baseURL: url, sessionId: sessionId, cssSelector: locatorType.create()) + + do { + try await client.request(request) + return true + } catch { + guard retryCount > 0, error.isSeleniumError(ofType: .noSuchElement) else { + return false + } + + sleep(UInt32(durationSeconds)) + + return try await waitUntil( + locatorType, + retryCount: retryCount - 1, + durationSeconds: durationSeconds + ) + } + } + + private func executeJavascriptSync(_ script: String, args: [AnyEncodable]) async throws -> PostExecuteResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + + let request = PostExecuteRequest( + baseURL: url, + sessionId: sessionId, + type: .sync, + javascriptSnippet: .init(script: script, args: args) + ) + + return try await client.request(request) + } + + private func executeJavascriptAsync(_ script: String, args: [AnyEncodable]) async throws -> PostExecuteResponse { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + + let request = PostExecuteRequest( + baseURL: url, + sessionId: sessionId, + type: .async, + javascriptSnippet: .init(script: script, args: args) + ) + + return try await client.request(request) + } + + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + @discardableResult + public func execute( + _ script: String, + args: [AnyEncodable], + type: DevToolTypes.JavascriptExecutionTypes + ) async throws -> PostExecuteResponse { + try await type == .sync + ? executeJavascriptSync(script, args: args) + : executeJavascriptAsync(script, args: args) + } + + public func getActiveElement() async throws -> Element { + guard let sessionId else { + throw WebDriverError.sessionIdIsNil + } + + let request = GetSessionActiveElementRequest(baseURL: url, sessionId: sessionId) + let response = try await client.request(request) + + return Element(baseURL: url, sessionId: sessionId, elementId: response.elementId) + } + + public func setAttribute(element: Element, attributeName: String, newValue: String) async throws { + let script = "arguments[0].setAttribute(arguments[1], arguments[2]);" + let args: [AnyEncodable] = [ + AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), + AnyEncodable(attributeName), + AnyEncodable(newValue) + ] + + try await execute(script, args: args, type: .sync) + } + + public func getProperty(element: Element, propertyName: String) async throws -> PostExecuteResponse { + let script = "return arguments[0][arguments[1]];" + let args: [AnyEncodable] = [ + AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), + AnyEncodable(propertyName) + ] + + return try await execute(script, args: args, type: .sync) + } + + public func setProperty(element: Element, propertyName: String, newValue: String) async throws { + let script = "arguments[0][arguments[1]] = arguments[2];" + let args: [AnyEncodable] = [ + AnyEncodable(["element-6066-11e4-a52e-4f735466cecf": element.elementId]), + AnyEncodable(propertyName), + AnyEncodable(newValue) + ] + + try await execute(script, args: args, type: .sync) + } + + public func dragAndDrop(from source: Element, to target: Element) async throws { + try await ElementDragAndDropper(driver: self, from: source, to: target).dragAndDrop() + } + + private static func stopDriverExternal(url: URL, sessionId: String) async throws { + let request = DeleteSessionRequest(baseURL: url, sessionId: sessionId) + _ = try await APIClient.shared.request(request).map(\.value).get() + } + + private static func startDriverExternal( + url: URL, + browserObject: FirefoxOptions, + client: APIClient + ) async throws -> String { + let request = NewSessionRequest(baseURL: url, browserOptions: browserObject) + return try await client.request(request).map(\.value.sessionId).get() + } + + deinit { + let url = url + let sessionId = sessionId + Task { + guard let sessionId else { return } + // swiftlint:disable:next prefer_self_in_static_references + try await FirefoxDriver.stopDriverExternal(url: url, sessionId: sessionId) + } + } +} diff --git a/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxOptions.swift b/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxOptions.swift index 22d0a12..4b2a0aa 100644 --- a/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxOptions.swift +++ b/Sources/SwiftWebDriver/WebDrivers/Firefox/FirefoxOptions.swift @@ -10,64 +10,75 @@ // // import Foundation // import NIOCore -// public struct FirefoxOptions: Codable { public let binary: String? - public let args: [String]? + public let args: [FirefoxArgs]? public let profile: String? public let prefs: [String: FirefoxPreferenceValue]? public let log: FirefoxLog? public let env: [String: String]? + + public init( + binary: String? = nil, + args: [FirefoxArgs]? = nil, + profile: String? = nil, + prefs: [String: FirefoxPreferenceValue]? = nil, + log: FirefoxLog? = nil, + env: [String: String]? = nil + ) { + self.binary = binary + self.args = args + self.profile = profile + self.prefs = prefs + self.log = log + self.env = env + } } -public enum FirefoxArgument: CustomStringConvertible, Codable { - case headless - case profile(path: String) - case privateMode - case privateWindow - case newWindow(url: String) - case newTab(url: String) - case kiosk(url: String) - case devTools - case safeMode +public struct FirefoxArgs: RawRepresentable, Codable, CustomStringConvertible { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } + + public init(_ argument: Argument) { + rawValue = argument.description + } public var description: String { - switch self { - case .headless: - "-headless" - case let .profile(path): - "-profile \(path)" - case .privateMode: - "-private" - case .privateWindow: - "-private-window" - case let .newWindow(url): - "-new-window \(url)" - case let .newTab(url): - "-new-tab \(url)" - case let .kiosk(url): - "--kiosk \(url)" - case .devTools: - "-devtools" - case .safeMode: - "-safe-mode" - } + rawValue } -} -public typealias FirefoxArg = String + public enum Argument: CustomStringConvertible, Codable { + case headless + case privateMode + case privateWindow + case devTools + case safeMode -public extension FirefoxArg { - init(_ argument: FirefoxArgument) { - self.init(describing: argument) + public var description: String { + switch self { + case .headless: + "-headless" + case .privateMode: + "-private" + case .privateWindow: + "-private-window" + case .devTools: + "-devtools" + case .safeMode: + "-safe-mode" + } + } } } public enum FirefoxPreferenceValue: Codable { - case string(String) case bool(Bool) case int(Int) + case string(String) } public struct FirefoxLog: Codable { diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/ChromeDriverIntegrationTestsBase.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/ChromeDriverIntegrationTestsBase.swift deleted file mode 100644 index f6346c1..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/ChromeDriverIntegrationTestsBase.swift +++ /dev/null @@ -1,51 +0,0 @@ -// ChromeDriverIntegrationTestsBase.swift -// 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 -@testable import SwiftWebDriver - -internal protocol ChromeDriverIntegrationTestsBase { - var driver: WebDriver { get set } - var testPageURL: URL { get } - var baseUrl: String { get } - var page: String { get set } -} - -internal class ChromeDriverTest: ChromeDriverIntegrationTestsBase { - public let baseUrl: String = "http://localhost" - public var testPageURL: URL { - // swiftlint:disable:next force_unwrapping - .init(string: "\(baseUrl)/\(page)")! - } - - public var page: String = "index.html" - public var driver: WebDriver - - public init() async throws { - // swiftlint:disable:next force_unwrapping - let driverURL = URL(string: "http://localhost:4444")! - let chromeOptions = ChromeOptions(args: [ - Args(.disableDevShmUsage), - Args(.noSandbox), - ]) - - // Initialize the WebDriver on the main actor - driver = WebDriver( - driver: ChromeDriver( - driverURL: driverURL, - browserObject: chromeOptions - ) - ) - - try await driver.start() - } - - deinit { - // Add deinit here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/DevTools/ChromeDriverJavascriptIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/DevTools/ChromeDriverJavascriptIntegrationTests.swift deleted file mode 100644 index a803826..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/DevTools/ChromeDriverJavascriptIntegrationTests.swift +++ /dev/null @@ -1,76 +0,0 @@ -// ChromeDriverJavascriptIntegrationTests.swift -// 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 -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Javascript Sync", .serialized) -internal class ChromeDriverJavascriptIntegrationTests: ChromeDriverTest { - @Test("Test sync Javascript Execution", arguments: [ - ("return `${1 + 2}`", "3"), - ("return `${5 - 3}`", "2"), - ("return `${3 * 4}`", "12"), - ("return `${10 / 2}`", "5"), - ("return `Hello, ` + 'World!'", "Hello, World!"), - ("localStorage.setItem('user', 'John'); return localStorage.getItem('user')", "John"), - ("localStorage.setItem('token', 'abc123'); return localStorage.getItem('token')", "abc123"), - ("sessionStorage.setItem('session', 'active'); return sessionStorage.getItem('session')", "active"), - ("let arr = [1, 2, 3]; arr.push(4); return arr.join(',')", "1,2,3,4"), - ("let obj = { name: 'Alice', age: 25 }; obj.age = 26; return `${obj.age}`", "26"), - ("document.body.innerHTML = '

Hello, World!

'; return document.body.innerText", "Hello, World!"), - ]) - public func executeJavascript(input: (String, String)) async throws { - try await driver.navigateTo(url: testPageURL) - let output = try await driver.execute(input.0, args: []) - #expect(output.value?.stringValue == input.1) - - try await driver.stop() - } - - @Test("Test async Javascript Execution", arguments: [ - ( - """ - var callback = arguments[arguments.length - 1]; - setTimeout(function() { callback('Hello from async JavaScript'); }, 2000); - """, - "Hello from async JavaScript" - ), - ]) - public func executeAsyncJavascript(input: (String, String)) async throws { - try await driver.navigateTo(url: testPageURL) - let output = try await driver.execute( - input.0, - args: [], - type: .async - ) - #expect(output.value?.stringValue == input.1) - - try await driver.stop() - } - - @Test("Throws `javascript error` if JS fails") - public func throwSeleniumError() async throws { - do { - try await driver.navigateTo(url: testPageURL) - try await driver.execute("throw new Error('Test Error')", args: []) - try #require(Bool(false)) - } catch { - guard error.isSeleniumError(ofType: .javascriptError) else { - try #require(Bool(false)) - return - } - } - - try await driver.stop() - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverDragAndDropIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverDragAndDropIntegrationTests.swift deleted file mode 100644 index c457eb2..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverDragAndDropIntegrationTests.swift +++ /dev/null @@ -1,42 +0,0 @@ -// ChromeDriverDragAndDropIntegrationTests.swift -// Copyright (c) 2025 GetAutomaApp -// All source code and related assets are the property of GetAutomaApp. -// All rights reserved. - -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Drag and Drop Integration Tests", .serialized) -internal class ChromeDriverDragAndDropIntegrationTests: ChromeDriverTest { - /// Drag and drop draggable element to another element, testing the `dragAndDrop` method. - /// This test tests the JavaScript script executed in the DOM to drag the draggable element to the other element. - @Test("Drag Element To Another (JavaScript)") - public func dragAndDropDraggableElementToAnother() async throws { - page = "dragTarget.html" - try await dragAndDrop() - } - - /// Drag and drop draggable element to another element, testing the `dragAndDrop` method. - /// This test tests the Actions API request to drag the draggable element to the other element. - @Test("Drag Element To Another (WebDriver Actions API)") - public func dragAndDropElementToAnother() async throws { - page = "dragBox.html" - try await dragAndDrop() - } - - private func dragAndDrop() async throws { - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let sourceElement = try await driver.findElement(.css(.id("source"))) - let targetElement = try await driver.findElement(.css(.id("target"))) - - try await driver.dragAndDrop(from: sourceElement, to: targetElement) - - let targetElementText = try await driver.getProperty(element: targetElement, propertyName: "innerText").value? - .stringValue - - #expect(targetElementText == "DROPPED!") - } - - deinit {} -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverElementHandleIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverElementHandleIntegrationTests.swift deleted file mode 100644 index 6ac3977..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverElementHandleIntegrationTests.swift +++ /dev/null @@ -1,145 +0,0 @@ -// ChromeDriverElementHandleIntegrationTests.swift -// Copyright (c) 2026 GetAutomaApp -// All source code and related assets are the property of GetAutomaApp. -// All rights reserved. - -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Element Handles", .serialized) -internal class ChromeDriverElementHandleIntegrationTests: ChromeDriverTest { - @Test("Click Button") - public func clickButton() async throws { - page = "elementHandleTestPage.html" - - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let button = try await driver.findElement(.css(.id("button"))) - try await button.click() - let test = try await button.text() - #expect(test == "clicked!") - } - - @Test("Double Click Button") - public 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("Drag Element To Another") - public func dragElementToAnother() async throws { - page = "dragBox.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let source = try await driver.findElement(.css(.id("source"))) - let target = try await driver.findElement(.css(.id("target"))) - - try await source.dragAndDrop(to: target) - - let targetText = try await driver.getProperty(element: target, propertyName: "innerText").value?.stringValue - #expect(targetText == "DROPPED!", "Target text should be 'DROPPED!' after pointer drag") - } - - @Test("Get Element Attributes") - public func getAttribute() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let inputElement = try await driver - .findElement(.css(.id("attribute"))) - let attribute = try await inputElement.attribute(name: "value") - #expect(attribute == "expect attribute") - } - - @Test("Get Element Rect") - public func getRect() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let element = try await driver - .findElement(.css(.id("rect"))) - - let rect = try await element.rect() - - #expect(rect.height == 100) - #expect(rect.xPosition > 5) - #expect(rect.yPosition > 5) - #expect(rect.width == 100) - } - - @Test("Clear Element") - public func clearElement() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let inputElement = try await driver - .findElement(.css(.id("clearInputValue"))) - - try await inputElement.clear() - - let text = try await inputElement.text() - #expect(text == "") - } - - @Test("Send Key") - public func sendKey() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let element = try await driver.findElement(.css(.id("sendValue"))) - try await element.send(value: "newValue") - let text = try await driver.execute("return document.querySelector('#sendValue').value").value?.stringValue - #expect(text == "newValue") - } - - @Test("Send Chord") - public func sendChord() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let element = try await driver.findElement(.css(.id("sendValue"))) - try await element.send(value: "newValue") - let text = try await driver.execute("return document.querySelector('#sendValue').value").value?.stringValue - #expect(text == "newValue") - - // Remove text from element - try await element.sendKeys(keys: .CONTROL, characters: "a") - try await element.sendKeys(keys: .BACKSPACE) - let newText = try await driver.execute("return document.querySelector('#sendValue').value").value?.stringValue - #expect(newText == "") - } - - @Test("Get Screenshot") - public func getScreenshot() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let element = try await driver.findElement(.css(.id("sendValue"))) - let elementScreenshot = try await element.screenshot() - let data = elementScreenshot.data(using: .utf8) - #expect(data != nil) - } - - @Test("Fail any operation if element becomes stale") - public func throwStaleError() async throws { - let sleepTotal = 3 - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let element = try await driver.findElement(.css(.id("willDelete"))) - try await element.click() - - try await Task.sleep(for: .seconds(sleepTotal)) - - do { - try await element.click() - #expect(Bool(false)) - } catch { - #expect(Bool(true)) - } - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementIntegrationTests.swift deleted file mode 100644 index 2e2f5c9..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementIntegrationTests.swift +++ /dev/null @@ -1,75 +0,0 @@ -// ChromeDriverFindElementIntegrationTests.swift -// 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 Find Element Tests", .serialized) -internal class ChromeDriverFindElementIntegrationTests: ChromeDriverTest { - @Test("Get Element By CSS Selector") - public func getElementCSSElement() async throws { - page = "index.html" - try await driver.navigateTo(url: testPageURL) - - let classText = try await driver.findElement(.css(.class("classElement"))).text() - #expect(classText == "classElement") - - let idElement = try await driver.findElement(.css(.id("idElement"))).text() - #expect(idElement == "idElement") - - let nameElement = try await driver.findElement(.css(.name("nameElement"))).text() - #expect(nameElement == "nameElement") - } - - @Test("Get Element By XPath") - public func getElementByXPath() async throws { - page = "index.html" - try await driver.navigateTo(url: testPageURL) - - let inParentSingleElement = try await driver.findElement(.xpath("//*[@id=\"inParentSingleElement\"]")).text() - #expect(inParentSingleElement == "inParentSingleElement") - } - - @Test("Get Element By Link Text") - public func getElementByLinkText() async throws { - page = "index.html" - try await driver.navigateTo(url: testPageURL) - - let text = try await driver - .findElement(.linkText("go to next page")) - .text() - #expect(text == "go to next page") - } - - @Test("Get Element By Partial Link") - public func getElementByPartialLink() async throws { - page = "index.html" - try await driver.navigateTo(url: testPageURL) - - let text = try await driver - .findElement(.partialLinkText("go")) - .text() - - #expect(text == "go to next page") - } - - @Test("Get Element By TagName") - public func getElementByTagName() async throws { - page = "index.html" - try await driver.navigateTo(url: testPageURL) - - let text = try await driver - .findElement(.tagName("h1")) - .text() - #expect(text == "this is h1") - } - - deinit { - // no-op - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementsIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementsIntegrationTests.swift deleted file mode 100644 index 37d5703..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverFindElementsIntegrationTests.swift +++ /dev/null @@ -1,113 +0,0 @@ -// ChromeDriverFindElementsIntegrationTests.swift -// 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 Find Elements Tests", .serialized) -internal class ChromeDriverFindElementsIntegrationTests: ChromeDriverTest { - @Test("Get Elements CSS Elements") - public func getElementsCSSElements() async throws { - page = "findElementsTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let expectedElements1Count = 1 - let expectedElements2Count = 2 - - let elements = try await driver.findElements(.css(.class("classElement1"))) - #expect(elements.count == expectedElements1Count) - - let elements2 = try await driver.findElements(.css(.class("classElement2"))) - #expect(elements2.count == expectedElements2Count) - - let idElement1 = try await driver.findElements(.css(.id("idElement1"))) - #expect(idElement1.count == expectedElements1Count) - - let idElement2 = try await driver.findElements(.css(.id("idElement2"))) - #expect(idElement2.count == expectedElements2Count) - - let nameElement1 = try await driver.findElements(.css(.name("nameElement1"))) - #expect(nameElement1.count == expectedElements1Count) - - let nameElement2 = try await driver.findElements(.css(.name("nameElement2"))) - #expect(nameElement2.count == expectedElements2Count) - } - - @Test("Get Elements By XPath") - public func getElementsByXPath() async throws { - page = "findElementsTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let xpathFirstLayerElementsCount = 9 - let xpathElements = try await driver - .findElements(.xpath("/html/body/div")) - - #expect(xpathElements.count == xpathFirstLayerElementsCount) - } - - @Test("Get Elements By Link Text") - public func getElementsByLinkText() async throws { - page = "findElementsTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let linkElements1Count = 1 - let linkElements2Count = 2 - - let linkElement1 = try await driver - .findElements(.linkText("1linkElement")) - - #expect(linkElement1.count == linkElements1Count) - - let linkElement2 = try await driver - .findElements(.linkText("2linkElements")) - - #expect(linkElement2.count == linkElements2Count) - } - - @Test("Get Elements By Partial Link Text") - public func getElementsByPartialLink() async throws { - let partialLinkElements1Count = 1 - let partialLinkElements2Count = 2 - - page = "findElementsTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let linkElement1 = try await driver - .findElements(.partialLinkText("1")) - - #expect(linkElement1.count == partialLinkElements1Count) - - let linkElement2 = try await driver - .findElements(.partialLinkText("2")) - - #expect(linkElement2.count == partialLinkElements2Count) - } - - @Test("Get Elements By Tag Name") - public func getElementByTagName() async throws { - let tagElements1Count = 1 - let tagElements2Count = 2 - - page = "findElementsTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let tagElement1 = try await driver - .findElements(.tagName("p")) - - #expect(tagElement1.count == tagElements1Count) - - let tagElement2 = try await driver - .findElements(.tagName("b")) - - #expect(tagElement2.count == tagElements2Count) - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverPropertyIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverPropertyIntegrationTests.swift deleted file mode 100644 index 2c594ba..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverPropertyIntegrationTests.swift +++ /dev/null @@ -1,53 +0,0 @@ -// ChromeDriverPropertyIntegrationTests.swift -// Copyright (c) 2025 GetAutomaApp -// All source code and related assets are the property of GetAutomaApp. -// All rights reserved. - -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Property Integration Tests", .serialized) -internal class ChromeDriverPropertyIntegrationTests: ChromeDriverTest { - /// Test `getProperty()` method, a method to get a specific property value from an element. - @Test("Get Property") - public func getProperty() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let updatedElementValue = "NewElementValue" - try await driver.execute(""" - let element = document.getElementById('attribute') - element.value = '\(updatedElementValue)' - """) - let element = try await driver.findElement(.css(.id("attribute"))) - guard - let elementValue = try await driver.getProperty(element: element, propertyName: "value").value?.stringValue - else { - #expect(Bool(false), "Could not convert element value to string value") - return - } - - #expect(elementValue == updatedElementValue) - } - - /// Test `setProperty()` method, a method to set a specific property value from an element. - @Test("Set Property") - public func setProperty() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - let element = try await driver.findElement(.css(.id("setproperty"))) - let newPropertyValue = "element new inner text" - - try await driver.setProperty(element: element, propertyName: "innerText", newValue: newPropertyValue) - guard - let elementInnerTextValue = try await driver.getProperty(element: element, propertyName: "innerText").value? - .stringValue - else { - #expect(Bool(false), "Could not convert element innerText value to string value") - return - } - - #expect(newPropertyValue == elementInnerTextValue) - } - - deinit {} -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSetAttributeIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSetAttributeIntegrationTests.swift deleted file mode 100644 index ba63848..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSetAttributeIntegrationTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -// ChromeDriverSetAttributeIntegrationTests.swift -// Copyright (c) 2025 GetAutomaApp -// All source code and related assets are the property of GetAutomaApp. -// All rights reserved. - -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Set Attribute", .serialized) -internal class ChromeDriverSetAttributeIntegrationTests: ChromeDriverTest { - @Test("Set Attribute") - public func setAttribute() async throws { - page = "elementHandleTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let element = try await driver.findElement(.css(.id("attribute"))) - let newIdentifier = "newidentifier" - try await driver.setAttribute(element: element, attributeName: "id", newValue: newIdentifier) - - let elementId = try await element.attribute(name: "id") - #expect(elementId == newIdentifier) - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSpecialKeysIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSpecialKeysIntegrationTests.swift deleted file mode 100644 index 17ae241..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Element/ChromeDriverSpecialKeysIntegrationTests.swift +++ /dev/null @@ -1,26 +0,0 @@ -// ChromeDriverSpecialKeysIntegrationTests.swift -// Copyright (c) 2026 GetAutomaApp -// All source code and related assets are the property of GetAutomaApp. -// All rights reserved. - -@testable import SwiftWebDriver -import Testing - -@Suite("Chrome Driver Special Keys", .serialized) -internal class ChromeDriverSpecialKeysIntegrationTests: ChromeDriverTest { - @Test("Tab Should Cycle Input Elements Focus") - public func tabCycleInputElementFocus() async throws { - page = "testSpecialKeys.html" - - try await driver.navigateTo(url: testPageURL) - let inputElement = try await driver.findElement(.css(.id("input1"))) - try await inputElement.send(value: .TAB) - try await Task.sleep(for: .seconds(1)) - let activeElement = try await driver.getActiveElement() - #expect(try await activeElement.attribute(name: "id") == "input2") - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Navigation/ChromeDriverNavigationIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Navigation/ChromeDriverNavigationIntegrationTests.swift deleted file mode 100644 index 8484b13..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Navigation/ChromeDriverNavigationIntegrationTests.swift +++ /dev/null @@ -1,43 +0,0 @@ -// ChromeDriverNavigationIntegrationTests.swift -// 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 Navigation Tests", .serialized) -internal class ChromeDriverNavigationIntegrationTests: ChromeDriverTest { - @Test("Get Navigation Title") - public func getNavigationTitle() async throws { - page = "awaitTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - let title = try await driver.navigationTitle() - #expect(title.value != nil) - #expect(title.value == "expect title") - } - - @Test("Wait Until Element Exists") - public func waitUntilElements() async throws { - page = "awaitTestPage.html" - try await driver.navigateTo(urlString: testPageURL.absoluteString) - - try await driver - .findElement(.css(.id("startButton"))) - .click() - - let retries = 5, sleepDuration = 1 - let result = try await driver - .waitUntil(.css(.id("asyncAddElement")), retryCount: retries, durationSeconds: sleepDuration) - - #expect(result) - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Start/ChromeDriverStartTests.swift b/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Start/ChromeDriverStartTests.swift deleted file mode 100644 index fd60021..0000000 --- a/Tests/SwiftWebDriverIntegrationTests/ChromeDriver/Start/ChromeDriverStartTests.swift +++ /dev/null @@ -1,25 +0,0 @@ -// ChromeDriverStartTests.swift -// 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 Start Tests", .serialized) -internal class ChromeDriverStartTests: ChromeDriverTest { - @Test("Start & Stop") - public func startAndStop() async throws { - let status = try await driver.status() - #expect(status.value.message != "") - let sessionId = try await driver.start() - #expect(sessionId != "") - } - - deinit { - // Add deinit logic here - } -} diff --git a/Tests/SwiftWebDriverIntegrationTests/DevTools/DriverJavascriptIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/DevTools/DriverJavascriptIntegrationTests.swift new file mode 100644 index 0000000..8b58899 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/DevTools/DriverJavascriptIntegrationTests.swift @@ -0,0 +1,131 @@ +// DriverJavascriptIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +import Foundation +@testable import SwiftWebDriver +import Testing + +internal enum JavascriptIntegrationTestCases { + internal static let syncExecution: [(script: String, expected: String)] = [ + ("return `${1 + 2}`", "3"), + ("return `${5 - 3}`", "2"), + ("return `${3 * 4}`", "12"), + ("return `${10 / 2}`", "5"), + ("return `Hello, ` + 'World!'", "Hello, World!"), + ("localStorage.setItem('user', 'John'); return localStorage.getItem('user')", "John"), + ("localStorage.setItem('token', 'abc123'); return localStorage.getItem('token')", "abc123"), + ("sessionStorage.setItem('session', 'active'); return sessionStorage.getItem('session')", "active"), + ("let arr = [1, 2, 3]; arr.push(4); return arr.join(',')", "1,2,3,4"), + ("let obj = { name: 'Alice', age: 25 }; obj.age = 26; return `${obj.age}`", "26"), + ("document.body.innerHTML = '

Hello, World!

'; return document.body.innerText", "Hello, World!") + ] + + internal static let asyncExecution: [(script: String, expected: String)] = [ + ( + """ + var callback = arguments[arguments.length - 1]; + setTimeout(function() { callback('Hello from async JavaScript'); }, 2000); + """, + "Hello from async JavaScript" + ) + ] +} + +internal enum DriverJavascriptIntegration {} + +internal class DriverJavascriptIntegrationTest: + DriverIntegrationTest +{ + internal func runExecuteJavascriptTest(input: (script: String, expected: String)) async throws { + try await driver.navigateTo(url: testPageURL) + + let output = try await driver.execute(input.script, args: []) + + #expect(output.value?.stringValue == input.expected) + } + + internal func runExecuteAsyncJavascriptTest(input: (script: String, expected: String)) async throws { + try await driver.navigateTo(url: testPageURL) + + let output = try await driver.execute( + input.script, + args: [], + type: .async + ) + + #expect(output.value?.stringValue == input.expected) + } + + internal func runThrowSeleniumErrorTest() async throws { + do { + try await driver.navigateTo(url: testPageURL) + try await driver.execute("throw new Error('Test Error')", args: []) + try #require(Bool(false)) + } catch { + guard error.isSeleniumError(ofType: .javascriptError) else { + try #require(Bool(false)) + return + } + } + } + + deinit {} +} + +@Suite("Chrome Driver Javascript Integration Tests", .serialized) +internal final class ChromeDriverJavascriptIntegrationTests: + DriverJavascriptIntegrationTest +{ + @Test( + "Test sync Javascript Execution", + arguments: JavascriptIntegrationTestCases.syncExecution + ) + internal func executeJavascript(input: (script: String, expected: String)) async throws { + try await runExecuteJavascriptTest(input: input) + } + + @Test( + "Test async Javascript Execution", + arguments: JavascriptIntegrationTestCases.asyncExecution + ) + internal func executeAsyncJavascript(input: (script: String, expected: String)) async throws { + try await runExecuteAsyncJavascriptTest(input: input) + } + + @Test("Throws `javascript error` if JS fails") + internal func throwSeleniumError() async throws { + try await runThrowSeleniumErrorTest() + } + + deinit {} +} + +@Suite("Firefox Driver Javascript Integration Tests", .serialized) +internal final class FirefoxDriverJavascriptIntegrationTests: + DriverJavascriptIntegrationTest +{ + @Test( + "Test sync Javascript Execution", + arguments: JavascriptIntegrationTestCases.syncExecution + ) + internal func executeJavascript(input: (script: String, expected: String)) async throws { + try await runExecuteJavascriptTest(input: input) + } + + @Test( + "Test async Javascript Execution", + arguments: JavascriptIntegrationTestCases.asyncExecution + ) + internal func executeAsyncJavascript(input: (script: String, expected: String)) async throws { + try await runExecuteAsyncJavascriptTest(input: input) + } + + @Test("Throws `javascript error` if JS fails") + internal func throwSeleniumError() async throws { + try await runThrowSeleniumErrorTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/DriverIntegrationTest.swift b/Tests/SwiftWebDriverIntegrationTests/DriverIntegrationTest.swift new file mode 100644 index 0000000..531cf6d --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/DriverIntegrationTest.swift @@ -0,0 +1,71 @@ +// DriverIntegrationTest.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +import Foundation +@testable import SwiftWebDriver + +internal protocol DriverTestConfiguration { + associatedtype ConcreteDriver: Driver + + static var suiteName: String { get } + static var seleniumURL: URL { get } + static var browserObject: ConcreteDriver.BrowserOption { get } +} + +internal enum ChromeTestConfiguration: DriverTestConfiguration { + internal static let suiteName = "Chrome" + + internal static let seleniumURL = URL(string: "http://selenium_chrome:4444")! + + nonisolated(unsafe) internal static let browserObject = ChromeOptions(args: [ + ChromeArgs(.disableDevShmUsage), + ChromeArgs(.noSandbox) + ]) + + internal typealias ConcreteDriver = ChromeDriver +} + +internal enum FirefoxTestConfiguration: DriverTestConfiguration { + internal static let suiteName = "Firefox" + + internal static let seleniumURL = URL(string: "http://selenium_firefox:4444")! + + nonisolated(unsafe) internal static let browserObject = FirefoxOptions( + args: [ + FirefoxArgs(FirefoxArgs.Argument.headless) + ], + log: FirefoxLog(level: .info) + ) + + internal typealias ConcreteDriver = FirefoxDriver +} + +internal class DriverIntegrationTest { + internal let baseUrl = "http://httpd" + + internal var testPageURL: URL { + guard let url = URL(string: "\(baseUrl)/\(page)") else { + fatalError("Invalid test page URL for page: \(page)") + } + return url + } + + internal var page = "index.html" + + internal var driver: WebDriver + + internal required init() async throws { + driver = WebDriver( + driver: Configuration.ConcreteDriver( + driverURL: Configuration.seleniumURL, + browserObject: Configuration.browserObject + ) + ) + + try await driver.start() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverDragAndDropIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverDragAndDropIntegrationTests.swift new file mode 100644 index 0000000..1941a7d --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverDragAndDropIntegrationTests.swift @@ -0,0 +1,67 @@ +// DriverDragAndDropIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverDragAndDropIntegration {} + +internal class DriverDragAndDropIntegrationTest: + DriverIntegrationTest +{ + internal func runDragAndDropTest(page: String) async throws { + self.page = page + + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let sourceElement = try await driver.findElement(.css(.id("source"))) + let targetElement = try await driver.findElement(.css(.id("target"))) + + try await driver.dragAndDrop(from: sourceElement, to: targetElement) + + let targetElementText = try await driver + .getProperty(element: targetElement, propertyName: "innerText") + .value? + .stringValue + + #expect(targetElementText == "DROPPED!") + } + + deinit {} +} + +@Suite("Chrome Driver Drag and Drop Integration Tests", .serialized) +internal final class ChromeDriverDragAndDropIntegrationTests: + DriverDragAndDropIntegrationTest +{ + @Test("Drag Element To Another (JavaScript)") + internal func dragAndDropDraggableElementToAnother() async throws { + try await runDragAndDropTest(page: "dragTarget.html") + } + + @Test("Drag Element To Another (WebDriver Actions API)") + internal func dragAndDropElementToAnother() async throws { + try await runDragAndDropTest(page: "dragBox.html") + } + + deinit {} +} + +@Suite("Firefox Driver Drag and Drop Integration Tests", .serialized) +internal final class FirefoxDriverDragAndDropIntegrationTests: + DriverDragAndDropIntegrationTest +{ + @Test("Drag Element To Another (JavaScript)") + internal func dragAndDropDraggableElementToAnother() async throws { + try await runDragAndDropTest(page: "dragTarget.html") + } + + @Test("Drag Element To Another (WebDriver Actions API)") + internal func dragAndDropElementToAnother() async throws { + try await runDragAndDropTest(page: "dragBox.html") + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverElementHandleIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverElementHandleIntegrationTests.swift new file mode 100644 index 0000000..ce5a5bd --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverElementHandleIntegrationTests.swift @@ -0,0 +1,267 @@ +// DriverElementHandleIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverElementHandleIntegration {} + +internal class DriverElementHandleIntegrationTest: + DriverIntegrationTest +{ + internal func runClickButtonTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let button = try await driver.findElement(.css(.id("button"))) + try await button.click() + + #expect(try await button.text() == "clicked!") + } + + internal func runDoubleClickButtonTest() 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() + + #expect(try await button.text() == "ii") + } + + internal func runDragElementToAnotherTest() async throws { + page = "dragBox.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let source = try await driver.findElement(.css(.id("source"))) + let target = try await driver.findElement(.css(.id("target"))) + + try await source.dragAndDrop(to: target) + + let targetText = try await driver + .getProperty(element: target, propertyName: "innerText") + .value? + .stringValue + + #expect(targetText == "DROPPED!", "Target text should be 'DROPPED!' after pointer drag") + } + + internal func runGetAttributeTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let inputElement = try await driver.findElement(.css(.id("attribute"))) + let attribute = try await inputElement.attribute(name: "value") + + #expect(attribute == "expect attribute") + } + + internal func runGetRectTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("rect"))) + let rect = try await element.rect() + + #expect(rect.height == 100) + #expect(rect.xPosition > 5) + #expect(rect.yPosition > 5) + #expect(rect.width == 100) + } + + internal func runClearElementTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let inputElement = try await driver.findElement(.css(.id("clearInputValue"))) + try await inputElement.clear() + + #expect(try await inputElement.text() == "") + } + + internal func runSendKeyTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("sendValue"))) + try await element.send(value: "newValue") + + let text = try await driver + .execute("return document.querySelector('#sendValue').value") + .value? + .stringValue + + #expect(text == "newValue") + } + + internal func runSendChordTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("sendValue"))) + try await element.send(value: "newValue") + + let text = try await driver + .execute("return document.querySelector('#sendValue').value") + .value? + .stringValue + + #expect(text == "newValue") + + try await element.sendKeys(keys: .CONTROL, characters: "a") + try await element.sendKeys(keys: .BACKSPACE) + + let newText = try await driver + .execute("return document.querySelector('#sendValue').value") + .value? + .stringValue + + #expect(newText == "") + } + + internal func runGetScreenshotTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("sendValue"))) + let elementScreenshot = try await element.screenshot() + let data = elementScreenshot.data(using: .utf8) + + #expect(data != nil) + } + + internal func runThrowStaleErrorTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("willDelete"))) + try await element.click() + + try await Task.sleep(for: .seconds(3)) + + do { + try await element.click() + #expect(Bool(false)) + } catch { + #expect(Bool(true)) + } + } + + deinit {} +} + +@Suite("Chrome Driver Element Handles", .serialized) +internal final class ChromeDriverElementHandleIntegrationTests: + DriverElementHandleIntegrationTest +{ + @Test("Click Button") + internal func clickButton() async throws { + try await runClickButtonTest() + } + + @Test("Double Click Button") + internal func doubleClickButton() async throws { + try await runDoubleClickButtonTest() + } + + @Test("Drag Element To Another") + internal func dragElementToAnother() async throws { + try await runDragElementToAnotherTest() + } + + @Test("Get Element Attributes") + internal func getAttribute() async throws { + try await runGetAttributeTest() + } + + @Test("Get Element Rect") + internal func getRect() async throws { + try await runGetRectTest() + } + + @Test("Clear Element") + internal func clearElement() async throws { + try await runClearElementTest() + } + + @Test("Send Key") + internal func sendKey() async throws { + try await runSendKeyTest() + } + + @Test("Send Chord") + internal func sendChord() async throws { + try await runSendChordTest() + } + + @Test("Get Screenshot") + internal func getScreenshot() async throws { + try await runGetScreenshotTest() + } + + @Test("Fail any operation if element becomes stale") + internal func throwStaleError() async throws { + try await runThrowStaleErrorTest() + } + + deinit {} +} + +@Suite("Firefox Driver Element Handles", .serialized) +internal final class FirefoxDriverElementHandleIntegrationTests: + DriverElementHandleIntegrationTest +{ + @Test("Click Button") + internal func clickButton() async throws { + try await runClickButtonTest() + } + + @Test("Double Click Button") + internal func doubleClickButton() async throws { + try await runDoubleClickButtonTest() + } + + @Test("Drag Element To Another") + internal func dragElementToAnother() async throws { + try await runDragElementToAnotherTest() + } + + @Test("Get Element Attributes") + internal func getAttribute() async throws { + try await runGetAttributeTest() + } + + @Test("Get Element Rect") + internal func getRect() async throws { + try await runGetRectTest() + } + + @Test("Clear Element") + internal func clearElement() async throws { + try await runClearElementTest() + } + + @Test("Send Key") + internal func sendKey() async throws { + try await runSendKeyTest() + } + + @Test("Send Chord") + internal func sendChord() async throws { + try await runSendChordTest() + } + + @Test("Get Screenshot") + internal func getScreenshot() async throws { + try await runGetScreenshotTest() + } + + @Test("Fail any operation if element becomes stale") + internal func throwStaleError() async throws { + try await runThrowStaleErrorTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementIntegrationTests.swift new file mode 100644 index 0000000..cf58883 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementIntegrationTests.swift @@ -0,0 +1,146 @@ +// DriverFindElementIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverFindElementIntegration {} + +internal class DriverFindElementIntegrationTest: + DriverIntegrationTest +{ + internal func runGetElementCSSElementTest() async throws { + page = "index.html" + try await driver.navigateTo(url: testPageURL) + + let classText = try await driver + .findElement(.css(.class("classElement"))) + .text() + + #expect(classText == "classElement") + + let idElement = try await driver + .findElement(.css(.id("idElement"))) + .text() + + #expect(idElement == "idElement") + + let nameElement = try await driver + .findElement(.css(.name("nameElement"))) + .text() + + #expect(nameElement == "nameElement") + } + + internal func runGetElementByXPathTest() async throws { + page = "index.html" + try await driver.navigateTo(url: testPageURL) + + let inParentSingleElement = try await driver + .findElement(.xpath("//*[@id=\"inParentSingleElement\"]")) + .text() + + #expect(inParentSingleElement == "inParentSingleElement") + } + + internal func runGetElementByLinkTextTest() async throws { + page = "index.html" + try await driver.navigateTo(url: testPageURL) + + let text = try await driver + .findElement(.linkText("go to next page")) + .text() + + #expect(text == "go to next page") + } + + internal func runGetElementByPartialLinkTest() async throws { + page = "index.html" + try await driver.navigateTo(url: testPageURL) + + let text = try await driver + .findElement(.partialLinkText("go")) + .text() + + #expect(text == "go to next page") + } + + internal func runGetElementByTagNameTest() async throws { + page = "index.html" + try await driver.navigateTo(url: testPageURL) + + let text = try await driver + .findElement(.tagName("h1")) + .text() + + #expect(text == "this is h1") + } + + deinit {} +} + +@Suite("Chrome Driver Find Element Tests", .serialized) +internal final class ChromeDriverFindElementIntegrationTests: + DriverFindElementIntegrationTest +{ + @Test("Get Element By CSS Selector") + internal func getElementCSSElement() async throws { + try await runGetElementCSSElementTest() + } + + @Test("Get Element By XPath") + internal func getElementByXPath() async throws { + try await runGetElementByXPathTest() + } + + @Test("Get Element By Link Text") + internal func getElementByLinkText() async throws { + try await runGetElementByLinkTextTest() + } + + @Test("Get Element By Partial Link") + internal func getElementByPartialLink() async throws { + try await runGetElementByPartialLinkTest() + } + + @Test("Get Element By TagName") + internal func getElementByTagName() async throws { + try await runGetElementByTagNameTest() + } + + deinit {} +} + +@Suite("Firefox Driver Find Element Tests", .serialized) +internal final class FirefoxDriverFindElementIntegrationTests: + DriverFindElementIntegrationTest +{ + @Test("Get Element By CSS Selector") + internal func getElementCSSElement() async throws { + try await runGetElementCSSElementTest() + } + + @Test("Get Element By XPath") + internal func getElementByXPath() async throws { + try await runGetElementByXPathTest() + } + + @Test("Get Element By Link Text") + internal func getElementByLinkText() async throws { + try await runGetElementByLinkTextTest() + } + + @Test("Get Element By Partial Link") + internal func getElementByPartialLink() async throws { + try await runGetElementByPartialLinkTest() + } + + @Test("Get Element By TagName") + internal func getElementByTagName() async throws { + try await runGetElementByTagNameTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementsIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementsIntegrationTests.swift new file mode 100644 index 0000000..a461437 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverFindElementsIntegrationTests.swift @@ -0,0 +1,178 @@ +// DriverFindElementsIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverFindElementsIntegration {} + +internal class DriverFindElementsIntegrationTest: + DriverIntegrationTest +{ + internal func runGetElementsCSSElementsTest() async throws { + page = "findElementsTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let expectedElements1Count = 1 + let expectedElements2Count = 2 + + let elements = try await driver.findElements(.css(.class("classElement1"))) + #expect(elements.count == expectedElements1Count) + + let elements2 = try await driver.findElements(.css(.class("classElement2"))) + #expect(elements2.count == expectedElements2Count) + + let idElement1 = try await driver.findElements(.css(.id("idElement1"))) + #expect(idElement1.count == expectedElements1Count) + + let idElement2 = try await driver.findElements(.css(.id("idElement2"))) + #expect(idElement2.count == expectedElements2Count) + + let nameElement1 = try await driver.findElements(.css(.name("nameElement1"))) + #expect(nameElement1.count == expectedElements1Count) + + let nameElement2 = try await driver.findElements(.css(.name("nameElement2"))) + #expect(nameElement2.count == expectedElements2Count) + } + + internal func runGetElementsByXPathTest() async throws { + page = "findElementsTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let xpathFirstLayerElementsCount = 9 + + let xpathElements = try await driver.findElements( + .xpath("/html/body/div") + ) + + #expect(xpathElements.count == xpathFirstLayerElementsCount) + } + + internal func runGetElementsByLinkTextTest() async throws { + page = "findElementsTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let linkElements1Count = 1 + let linkElements2Count = 2 + + let linkElement1 = try await driver.findElements( + .linkText("1linkElement") + ) + + #expect(linkElement1.count == linkElements1Count) + + let linkElement2 = try await driver.findElements( + .linkText("2linkElements") + ) + + #expect(linkElement2.count == linkElements2Count) + } + + internal func runGetElementsByPartialLinkTest() async throws { + page = "findElementsTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let partialLinkElements1Count = 1 + let partialLinkElements2Count = 2 + + let linkElement1 = try await driver.findElements( + .partialLinkText("1") + ) + + #expect(linkElement1.count == partialLinkElements1Count) + + let linkElement2 = try await driver.findElements( + .partialLinkText("2") + ) + + #expect(linkElement2.count == partialLinkElements2Count) + } + + internal func runGetElementsByTagNameTest() async throws { + page = "findElementsTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let tagElements1Count = 1 + let tagElements2Count = 2 + + let tagElement1 = try await driver.findElements( + .tagName("p") + ) + + #expect(tagElement1.count == tagElements1Count) + + let tagElement2 = try await driver.findElements( + .tagName("b") + ) + + #expect(tagElement2.count == tagElements2Count) + } + + deinit {} +} + +@Suite("Chrome Driver Find Elements Tests", .serialized) +internal final class ChromeDriverFindElementsIntegrationTests: + DriverFindElementsIntegrationTest +{ + @Test("Get Elements CSS Elements") + internal func getElementsCSSElements() async throws { + try await runGetElementsCSSElementsTest() + } + + @Test("Get Elements By XPath") + internal func getElementsByXPath() async throws { + try await runGetElementsByXPathTest() + } + + @Test("Get Elements By Link Text") + internal func getElementsByLinkText() async throws { + try await runGetElementsByLinkTextTest() + } + + @Test("Get Elements By Partial Link Text") + internal func getElementsByPartialLink() async throws { + try await runGetElementsByPartialLinkTest() + } + + @Test("Get Elements By Tag Name") + internal func getElementByTagName() async throws { + try await runGetElementsByTagNameTest() + } + + deinit {} +} + +@Suite("Firefox Driver Find Elements Tests", .serialized) +internal final class FirefoxDriverFindElementsIntegrationTests: + DriverFindElementsIntegrationTest +{ + @Test("Get Elements CSS Elements") + internal func getElementsCSSElements() async throws { + try await runGetElementsCSSElementsTest() + } + + @Test("Get Elements By XPath") + internal func getElementsByXPath() async throws { + try await runGetElementsByXPathTest() + } + + @Test("Get Elements By Link Text") + internal func getElementsByLinkText() async throws { + try await runGetElementsByLinkTextTest() + } + + @Test("Get Elements By Partial Link Text") + internal func getElementsByPartialLink() async throws { + try await runGetElementsByPartialLinkTest() + } + + @Test("Get Elements By Tag Name") + internal func getElementByTagName() async throws { + try await runGetElementsByTagNameTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverPropertyIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverPropertyIntegrationTests.swift new file mode 100644 index 0000000..59a32f8 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverPropertyIntegrationTests.swift @@ -0,0 +1,103 @@ +// DriverPropertyIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverPropertyIntegration {} + +internal class DriverPropertyIntegrationTest: + DriverIntegrationTest +{ + /// Test `getProperty()` method, a method to get a specific property value from an element. + internal func runGetPropertyTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let updatedElementValue = "NewElementValue" + + try await driver.execute(""" + let element = document.getElementById('attribute') + element.value = '\(updatedElementValue)' + """) + + let element = try await driver.findElement(.css(.id("attribute"))) + + guard + let elementValue = try await driver + .getProperty(element: element, propertyName: "value") + .value? + .stringValue + else { + #expect(Bool(false), "Could not convert element value to string value") + return + } + + #expect(elementValue == updatedElementValue) + } + + /// Test `setProperty()` method, a method to set a specific property value from an element. + internal func runSetPropertyTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("setproperty"))) + let newPropertyValue = "element new inner text" + + try await driver.setProperty( + element: element, + propertyName: "innerText", + newValue: newPropertyValue + ) + + guard + let elementInnerTextValue = try await driver + .getProperty(element: element, propertyName: "innerText") + .value? + .stringValue + else { + #expect(Bool(false), "Could not convert element innerText value to string value") + return + } + + #expect(newPropertyValue == elementInnerTextValue) + } + + deinit {} +} + +@Suite("Chrome Driver Property Integration Tests", .serialized) +internal final class ChromeDriverPropertyIntegrationTests: + DriverPropertyIntegrationTest +{ + @Test("Get Property") + internal func getProperty() async throws { + try await runGetPropertyTest() + } + + @Test("Set Property") + internal func setProperty() async throws { + try await runSetPropertyTest() + } + + deinit {} +} + +@Suite("Firefox Driver Property Integration Tests", .serialized) +internal final class FirefoxDriverPropertyIntegrationTests: + DriverPropertyIntegrationTest +{ + @Test("Get Property") + internal func getProperty() async throws { + try await runGetPropertyTest() + } + + @Test("Set Property") + internal func setProperty() async throws { + try await runSetPropertyTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverSetAttributeIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverSetAttributeIntegrationTests.swift new file mode 100644 index 0000000..e99a66c --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverSetAttributeIntegrationTests.swift @@ -0,0 +1,57 @@ +// DriverSetAttributeIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverSetAttributeIntegration {} + +internal class DriverSetAttributeIntegrationTest: + DriverIntegrationTest +{ + internal func runSetAttributeTest() async throws { + page = "elementHandleTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let element = try await driver.findElement(.css(.id("attribute"))) + let newIdentifier = "newidentifier" + + try await driver.setAttribute( + element: element, + attributeName: "id", + newValue: newIdentifier + ) + + let elementId = try await element.attribute(name: "id") + + #expect(elementId == newIdentifier) + } + + deinit {} +} + +@Suite("Chrome Driver Set Attribute", .serialized) +internal final class ChromeDriverSetAttributeIntegrationTests: + DriverSetAttributeIntegrationTest +{ + @Test("Set Attribute") + internal func setAttribute() async throws { + try await runSetAttributeTest() + } + + deinit {} +} + +@Suite("Firefox Driver Set Attribute", .serialized) +internal final class FirefoxDriverSetAttributeIntegrationTests: + DriverSetAttributeIntegrationTest +{ + @Test("Set Attribute") + internal func setAttribute() async throws { + try await runSetAttributeTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Element/DriverSpecialKeysIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Element/DriverSpecialKeysIntegrationTests.swift new file mode 100644 index 0000000..67ff3b6 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Element/DriverSpecialKeysIntegrationTests.swift @@ -0,0 +1,55 @@ +// DriverSpecialKeysIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverSpecialKeysIntegration {} + +internal class DriverSpecialKeysIntegrationTest: + DriverIntegrationTest +{ + internal func runTabCycleInputElementFocusTest() async throws { + page = "testSpecialKeys.html" + + try await driver.navigateTo(url: testPageURL) + + let inputElement = try await driver.findElement(.css(.id("input1"))) + try await inputElement.send(value: .TAB) + + try await Task.sleep(for: .seconds(1)) + + let activeElement = try await driver.getActiveElement() + let activeElementId = try await activeElement.attribute(name: "id") + + #expect(activeElementId == "input2") + } + + deinit {} +} + +@Suite("Chrome Driver Special Keys", .serialized) +internal final class ChromeDriverSpecialKeysIntegrationTests: + DriverSpecialKeysIntegrationTest +{ + @Test("Tab Should Cycle Input Elements Focus") + internal func tabCycleInputElementFocus() async throws { + try await runTabCycleInputElementFocusTest() + } + + deinit {} +} + +@Suite("Firefox Driver Special Keys", .serialized) +internal final class FirefoxDriverSpecialKeysIntegrationTests: + DriverSpecialKeysIntegrationTest +{ + @Test("Tab Should Cycle Input Elements Focus") + internal func tabCycleInputElementFocus() async throws { + try await runTabCycleInputElementFocusTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Navigation/DriverNavigationIntegrationTests.swift b/Tests/SwiftWebDriverIntegrationTests/Navigation/DriverNavigationIntegrationTests.swift new file mode 100644 index 0000000..28a58ef --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Navigation/DriverNavigationIntegrationTests.swift @@ -0,0 +1,79 @@ +// DriverNavigationIntegrationTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverNavigationIntegration {} + +internal class DriverNavigationIntegrationTest: + DriverIntegrationTest +{ + internal func runGetNavigationTitleTest() async throws { + page = "awaitTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + let title = try await driver.navigationTitle() + + #expect(title.value != nil) + #expect(title.value == "expect title") + } + + internal func runWaitUntilElementsTest() async throws { + page = "awaitTestPage.html" + try await driver.navigateTo(urlString: testPageURL.absoluteString) + + try await driver + .findElement(.css(.id("startButton"))) + .click() + + let retries = 5 + let sleepDuration = 1 + + let result = try await driver.waitUntil( + .css(.id("asyncAddElement")), + retryCount: retries, + durationSeconds: sleepDuration + ) + + #expect(result) + } + + deinit {} +} + +@Suite("Chrome Driver Navigation Tests", .serialized) +internal final class ChromeDriverNavigationIntegrationTests: + DriverNavigationIntegrationTest +{ + @Test("Get Navigation Title") + internal func getNavigationTitle() async throws { + try await runGetNavigationTitleTest() + } + + @Test("Wait Until Element Exists") + internal func waitUntilElements() async throws { + try await runWaitUntilElementsTest() + } + + deinit {} +} + +@Suite("Firefox Driver Navigation Tests", .serialized) +internal final class FirefoxDriverNavigationIntegrationTests: + DriverNavigationIntegrationTest +{ + @Test("Get Navigation Title") + internal func getNavigationTitle() async throws { + try await runGetNavigationTitleTest() + } + + @Test("Wait Until Element Exists") + internal func waitUntilElements() async throws { + try await runWaitUntilElementsTest() + } + + deinit {} +} diff --git a/Tests/SwiftWebDriverIntegrationTests/Start/DriverStartTests.swift b/Tests/SwiftWebDriverIntegrationTests/Start/DriverStartTests.swift new file mode 100644 index 0000000..ed524c9 --- /dev/null +++ b/Tests/SwiftWebDriverIntegrationTests/Start/DriverStartTests.swift @@ -0,0 +1,47 @@ +// DriverStartTests.swift +// Copyright (c) 2026 GetAutomaApp +// All source code and related assets are the property of GetAutomaApp. +// All rights reserved. + +@testable import SwiftWebDriver +import Testing + +internal enum DriverStart {} + +internal class DriverStartTest: + DriverIntegrationTest +{ + internal func runStartAndStopTest() async throws { + let status = try await driver.status() + #expect(status.value.message != "") + + let sessionId = try await driver.start() + #expect(sessionId != "") + } + + deinit {} +} + +@Suite("Chrome Driver Start Tests", .serialized) +internal final class ChromeDriverStartTests: + DriverStartTest +{ + @Test("Start & Stop") + internal func startAndStop() async throws { + try await runStartAndStopTest() + } + + deinit {} +} + +@Suite("Firefox Driver Start Tests", .serialized) +internal final class FirefoxDriverStartTests: + DriverStartTest +{ + @Test("Start & Stop") + internal func startAndStop() async throws { + try await runStartAndStopTest() + } + + deinit {} +} diff --git a/docker-compose.yml b/docker-compose.yml index d013105..98c1a2d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,47 +1,62 @@ services: httpd: - network_mode: host - build: - context: . - dockerfile: ./infra/HTTPDDockerfile - volumes: - - ./TestAssets:/usr/local/apache2/htdocs/ - ports: - - "80:80" - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost"] - interval: 30s - timeout: 10s - retries: 3 + build: + context: . + dockerfile: ./infra/HTTPDDockerfile + volumes: + - ./TestAssets:/usr/local/apache2/htdocs/ + ports: + - "80:80" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost"] + interval: 30s + timeout: 10s + retries: 3 - selenium: + selenium_chrome: image: selenium/standalone-chrome:4.2.1-20220531 - network_mode: host ports: - 4444:4444 - 7900:7900 environment: - - SE_NODE_MAX_SESSIONS=4 + SE_NODE_MAX_SESSIONS: "${SELENIUM_MAX_SESSIONS:-4}" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:4444/status"] interval: 30s timeout: 10s retries: 3 - swift_web_driver: - &SwiftWebDriver + selenium_firefox: + image: selenium/standalone-firefox:152.0-20260606 + ports: + - 4445:4444 + - 7901:7900 + environment: + SE_NODE_MAX_SESSIONS: "${SELENIUM_MAX_SESSIONS:-4}" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:4444/status"] + interval: 30s + timeout: 10s + retries: 3 + + swift_web_driver: &SwiftWebDriver build: context: . dockerfile: ./infra/Dockerfile volumes: - .:/SwiftWebDriver working_dir: /SwiftWebDriver - network_mode: host environment: - SELENIUM_URL: http://localhost:4444 + CHROME_SELENIUM_URL: http://selenium_chrome:4444 + FIREFOX_SELENIUM_URL: http://selenium_firefox:4444 + TEST_SERVER_URL: http://httpd + SANITIZER_ARG: "${SANITIZER_ARG:-}" + SWIFT_TEST_WORKERS: "${SWIFT_TEST_WORKERS:-4}" tty: true depends_on: - selenium: + selenium_chrome: + condition: service_healthy + selenium_firefox: condition: service_healthy httpd: condition: service_healthy @@ -52,7 +67,13 @@ services: test: <<: *SwiftWebDriver - command: /bin/bash -xcl "swift test -Xswiftc -warnings-as-errors $${SANITIZER_ARG-}" + command: > + /bin/bash -xcl + "swift test + --parallel + --num-workers $${SWIFT_TEST_WORKERS:-4} + -Xswiftc -warnings-as-errors + $${SANITIZER_ARG:-}" shell: <<: *SwiftWebDriver diff --git a/package.json b/package.json index 8f94bc3..ce80464 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "install:swiftformat": "brew install swiftformat", "install:swiftlint": "brew install swiftlint", "compose:up": "npm run compose -- up -d", - "compose:up:integration-services": "npm run compose:up -- --wait selenium httpd", + "compose:up:integration-services": "npm run compose:up -- --wait selenium_chrome httpd", "compose:build": "npm run compose -- build", "compose:build:no-cache": "npm run compose -- build --no-cache", "compose:build-and-up": "npx npm-run-all --sequential compose:build compose:up",