diff --git a/README.md b/README.md deleted file mode 100644 index ba163c0..0000000 --- a/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# webdriver - -A simple implementation of the pretty recent [W3C WebDriver spec](https://www.w3.org/TR/webdriver/). -Currently Firefox is just about the only browser that supports it. - -I have coded this library during a livestream, do check that out to see how the library is used: -https://www.youtube.com/watch?v=583BwZ7uSro&index=1&list=PLm-fq5xBdPkrMuVkPWuho7XzszB6kJ2My diff --git a/src/webdriver.nim b/src/webdriver.nim index b164ca2..ea4477c 100644 --- a/src/webdriver.nim +++ b/src/webdriver.nim @@ -1,6 +1,4 @@ -# For reference, this is brilliant: https://github.com/jlipps/simple-wd-spec - -import httpclient, uri, json, tables, options, strutils, unicode +import httpclient, uri, json, tables type WebDriver* = ref object @@ -45,13 +43,12 @@ proc createSession*(self: WebDriver): Session = # Check the readiness of the Web Driver. let resp = self.client.getContent($(self.url / "status")) let obj = parseJson(resp) - let ready = obj{"value", "ready"} - if ready.isNil(): + if obj{"value", "ready"}.isNil(): let msg = "Readiness message does not follow spec" raise newException(ProtocolException, msg) - if not ready.getBool(): + if not obj{"value", "ready"}.getBool(): raise newException(WebDriverException, "WebDriver is not ready") # Create our session. @@ -59,17 +56,10 @@ proc createSession*(self: WebDriver): Session = let sessionResp = self.client.postContent($(self.url / "session"), $sessionReq) let sessionObj = parseJson(sessionResp) - let sessionId = sessionObj{"value", "sessionId"} - if sessionId.isNil(): + if sessionObj{"value", "sessionId"}.isNil(): raise newException(ProtocolException, "No sessionId in response to request") - return Session(id: sessionId.getStr(), driver: self) - -proc close*(self: Session) = - let reqUrl = $(self.driver.url / "session" / self.id) - let resp = self.driver.client.request(reqUrl, HttpDelete) - - let respObj = checkResponse(resp.body) + return Session(id: sessionObj["value"]["sessionId"].getStr(), driver: self) proc navigate*(self: Session, url: string) = ## Instructs the session to navigate to the specified URL. @@ -91,20 +81,15 @@ proc getPageSource*(self: Session): string = return respObj{"value"}.getStr() proc findElement*(self: Session, selector: string, - strategy = CssSelector): Option[Element] = + strategy = CssSelector): Element = let reqUrl = $(self.driver.url / "session" / self.id / "element") let reqObj = %*{"using": toKeyword(strategy), "value": selector} - let resp = self.driver.client.post(reqUrl, $reqObj) - if resp.status == Http404: - return none(Element) + let resp = self.driver.client.postContent(reqUrl, $reqObj) - if resp.status != Http200: - raise newException(WebDriverException, resp.status) - - let respObj = checkResponse(resp.body) + let respObj = checkResponse(resp) for key, value in respObj["value"].getFields().pairs(): - return some(Element(id: value.getStr(), session: self)) + return Element(id: value.getStr(), session: self) proc getText*(self: Element): string = let reqUrl = $(self.session.driver.url / "session" / self.session.id / @@ -114,77 +99,6 @@ proc getText*(self: Element): string = return respObj["value"].getStr() -proc click*(self: Element) = - let reqUrl = $(self.session.driver.url / "session" / self.session.id / - "element" / self.id / "click") - let obj = %*{} - let resp = self.session.driver.client.post(reqUrl, $obj) - if resp.status != Http200: - raise newException(WebDriverException, resp.status) - - discard checkResponse(resp.body) - -# Note: There currently is an open bug in geckodriver that causes DOM events not to fire when sending keys. -# https://github.com/mozilla/geckodriver/issues/348 -proc sendKeys*(self: Element, text: string) = - let reqUrl = $(self.session.driver.url / "session" / self.session.id / - "element" / self.id / "value") - let obj = %*{"text": text} - let resp = self.session.driver.client.post(reqUrl, $obj) - if resp.status != Http200: - raise newException(WebDriverException, resp.status) - - discard checkResponse(resp.body) - -type - # https://w3c.github.io/webdriver/#keyboard-actions - Key* = enum - Unidentified = 0, - Cancel, - Help, - Backspace, - Tab, - Clear, - Return, - Enter, - Shift, - Control, - Alt, - Pause, - Escape - -proc toUnicode(key: Key): Rune = - Rune(0xE000 + ord(key)) - -proc press*(self: Session, keys: varargs[Key]) = - let reqUrl = $(self.driver.url / "session" / self.id / "actions") - let obj = %*{"actions": [ - { - "type": "key", - "id": "keyboard", - "actions": [] - } - ]} - for key in keys: - obj["actions"][0]["actions"].elems.add( - %*{ - "type": "keyDown", - "value": $toUnicode(key) - } - ) - obj["actions"][0]["actions"].elems.add( - %*{ - "type": "keyUp", - "value": $toUnicode(key) - } - ) - - let resp = self.driver.client.post(reqUrl, $obj) - if resp.status != Http200: - raise newException(WebDriverException, resp.status) - - discard checkResponse(resp.body) - when isMainModule: let webDriver = newWebDriver() let session = webDriver.createSession() @@ -192,6 +106,4 @@ when isMainModule: "Entertainment-System/dp/B073BVHY3F" session.navigate(amazonUrl) - echo session.findElement("#priceblock_ourprice").get().getText() - - session.close() + echo session.findElement("#priceblock_ourprice").getText() \ No newline at end of file diff --git a/webdriver.nimble b/webdriver.nimble index 80c27b8..66a8e12 100644 --- a/webdriver.nimble +++ b/webdriver.nimble @@ -1,6 +1,6 @@ # Package -version = "0.2.0" +version = "0.1.0" author = "Dominik Picheta" description = "Implementation of the WebDriver w3c spec." license = "MIT"