Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2be578271 | ||
|
|
c51d51fd72 |
||
|
|
61aea333ae |
||
|
|
038b5c8c70 |
||
|
|
bc9dd909a6 | ||
|
|
ef844cd998 |
2 changed files with 88 additions and 6 deletions
7
README.md
Normal file
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# 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
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
import httpclient, uri, json, tables, options
|
||||
# For reference, this is brilliant: https://github.com/jlipps/simple-wd-spec
|
||||
|
||||
import httpclient, uri, json, tables, options, strutils, unicode
|
||||
|
||||
type
|
||||
WebDriver* = ref object
|
||||
|
|
@ -43,12 +45,13 @@ 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 obj{"value", "ready"}.isNil():
|
||||
if ready.isNil():
|
||||
let msg = "Readiness message does not follow spec"
|
||||
raise newException(ProtocolException, msg)
|
||||
|
||||
if not obj{"value", "ready"}.getBool():
|
||||
if not ready.getBool():
|
||||
raise newException(WebDriverException, "WebDriver is not ready")
|
||||
|
||||
# Create our session.
|
||||
|
|
@ -56,10 +59,11 @@ proc createSession*(self: WebDriver): Session =
|
|||
let sessionResp = self.client.postContent($(self.url / "session"),
|
||||
$sessionReq)
|
||||
let sessionObj = parseJson(sessionResp)
|
||||
if sessionObj{"value", "sessionId"}.isNil():
|
||||
let sessionId = sessionObj{"value", "sessionId"}
|
||||
if sessionId.isNil():
|
||||
raise newException(ProtocolException, "No sessionId in response to request")
|
||||
|
||||
return Session(id: sessionObj["value"]["sessionId"].getStr(), driver: self)
|
||||
return Session(id: sessionId.getStr(), driver: self)
|
||||
|
||||
proc close*(self: Session) =
|
||||
let reqUrl = $(self.driver.url / "session" / self.id)
|
||||
|
|
@ -110,6 +114,77 @@ 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()
|
||||
|
|
@ -119,4 +194,4 @@ when isMainModule:
|
|||
|
||||
echo session.findElement("#priceblock_ourprice").get().getText()
|
||||
|
||||
session.close()
|
||||
session.close()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue