Merge pull request #263 from jyapayne/change-to-halonium

Replace webdriver with halonium
This commit is contained in:
Joey 2020-09-01 07:14:00 -06:00 • committed by GitHub
commit b2932e9348
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 87 deletions

View file

@ -21,7 +21,7 @@ requires "sass#649e0701fa5c"
requires "karax#5f21dcd" requires "karax#5f21dcd"
requires "webdriver#429933a" requires "halonium#f54c83f"
# Tasks # Tasks

View file

@ -1,6 +1,6 @@
import options, osproc, streams, threadpool, os, strformat, httpclient import options, osproc, streams, threadpool, os, strformat, httpclient
import webdriver import halonium
proc runProcess(cmd: string) = proc runProcess(cmd: string) =
let p = startProcess( let p = startProcess(
@ -46,22 +46,13 @@ template withBackend(body: untyped): untyped =
import browsertests/[scenario1, threads, issue181, categories] import browsertests/[scenario1, threads, issue181, categories]
proc main() = proc main() =
# Kill any already running instances
discard execCmd("killall geckodriver")
spawn runProcess("geckodriver -p 4444 --log config")
defer:
discard execCmd("killall geckodriver")
# Create a fresh DB for the tester. # Create a fresh DB for the tester.
doAssert(execCmd("nimble testdb") == QuitSuccess) doAssert(execCmd("nimble testdb") == QuitSuccess)
doAssert(execCmd("nimble -y frontend") == QuitSuccess) doAssert(execCmd("nimble -y frontend") == QuitSuccess)
echo("Waiting for geckodriver to startup...")
sleep(5000)
try: try:
let driver = newWebDriver() let session = createSession(Firefox)
let session = driver.createSession()
withBackend: withBackend:
scenario1.test(session, baseUrl) scenario1.test(session, baseUrl)

View file

@ -1,5 +1,5 @@
import unittest, common import unittest, common
import webdriver import halonium
import karaxutils import karaxutils
@ -47,12 +47,12 @@ proc categoriesUserTests(session: Session, baseUrl: string) =
with session: with session:
click "#new-thread-btn" click "#new-thread-btn"
checkIsNone "#add-category" checkIsNone "#add-category .plus-btn"
test "no category add available category page": test "no category add available category page":
with session: with session:
click "#categories-btn" click "#categories-btn"
checkIsNone "#add-category" checkIsNone "#add-category .plus-btn"
test "can create category thread": test "can create category thread":
with session: with session:
@ -139,17 +139,17 @@ proc categoriesUserTests(session: Session, baseUrl: string) =
checkText "#threads-list .thread-title a", "Post 3" checkText "#threads-list .thread-title a", "Post 3"
for element in session.waitForElements("#threads-list .category-name"): for element in session.waitForElements("#threads-list .category-name"):
# Have to user "innerText" because elements are hidden on this page # Have to user "innerText" because elements are hidden on this page
assert element.getProperty("innerText") == "Unsorted" assert element.text == "Unsorted"
selectCategory "announcements" selectCategory "announcements"
checkText "#threads-list .thread-title a", "Post 2" checkText "#threads-list .thread-title a", "Post 2"
for element in session.waitForElements("#threads-list .category-name"): for element in session.waitForElements("#threads-list .category-name"):
assert element.getProperty("innerText") == "Announcements" assert element.text == "Announcements"
selectCategory "fun" selectCategory "fun"
checkText "#threads-list .thread-title a", "Post 1" checkText "#threads-list .thread-title a", "Post 1"
for element in session.waitForElements("#threads-list .category-name"): for element in session.waitForElements("#threads-list .category-name"):
assert element.getProperty("innerText") == "Fun" assert element.text == "Fun"
session.logout() session.logout()
@ -168,7 +168,7 @@ proc categoriesAdminTests(session: Session, baseUrl: string) =
with session: with session:
click "#new-thread-btn" click "#new-thread-btn"
ensureExists "#add-category" ensureExists "#add-category .plus-btn"
click "#add-category .plus-btn" click "#add-category .plus-btn"
@ -195,10 +195,10 @@ proc categoriesAdminTests(session: Session, baseUrl: string) =
test "category adding disabled on admin logout": test "category adding disabled on admin logout":
with session: with session:
navigate(baseUrl & "c/0") navigate(baseUrl & "c/0")
ensureExists "#add-category" ensureExists "#add-category .plus-btn"
logout() logout()
checkIsNone "#add-category" checkIsNone "#add-category .plus-btn"
navigate baseUrl navigate baseUrl
login "admin", "admin" login "admin", "admin"

View file

@ -1,9 +1,9 @@
import os, options, unittest, strutils import os, options, unittest, strutils
import webdriver import halonium
import macros import macros
const actionDelayMs {.intdefine.} = 0 export waitForElement
## Inserts a delay in milliseconds between automated actions. Useful for debugging tests export waitForElements
macro with*(obj: typed, code: untyped): untyped = macro with*(obj: typed, code: untyped): untyped =
## Execute a set of statements with an object ## Execute a set of statements with an object
@ -24,14 +24,6 @@ macro with*(obj: typed, code: untyped): untyped =
result = getAst(checkCompiles(result, code)) result = getAst(checkCompiles(result, code))
proc elementIsSome(element: Option[Element]): bool =
return element.isSome
proc elementIsNone(element: Option[Element]): bool =
return element.isNone
proc waitForElement*(session: Session, selector: string, strategy=CssSelector, timeout=20000, pollTime=50, waitCondition=elementIsSome): Option[Element]
proc click*(session: Session, element: string, strategy=CssSelector) = proc click*(session: Session, element: string, strategy=CssSelector) =
let el = session.waitForElement(element, strategy) let el = session.waitForElement(element, strategy)
el.get().click() el.get().click()
@ -44,78 +36,33 @@ proc clear*(session: Session, element: string) =
let el = session.waitForElement(element) let el = session.waitForElement(element)
el.get().clear() el.get().clear()
proc sendKeys*(session: Session, element: string, keys: varargs[Key]) = proc sendKeys*(session: Session, element: string, keys: varargs[string, convertKeyRuneString]) =
let el = session.waitForElement(element) let el = session.waitForElement(element)
# focus el.get().sendKeys(keys)
el.get().click()
for key in keys:
session.press(key)
proc ensureExists*(session: Session, element: string, strategy=CssSelector) = proc ensureExists*(session: Session, element: string, strategy=CssSelector) =
discard session.waitForElement(element, strategy) discard session.waitForElement(element, strategy)
template check*(session: Session, element: string, function: untyped) = template check*(session: Session, element: string, function: untyped) =
let el = session.waitForElement(element) let el = session.waitForElement(element)
check function(el) doAssert function(el)
template check*(session: Session, element: string, template check*(session: Session, element: string,
strategy: LocationStrategy, function: untyped) = strategy: LocationStrategy, function: untyped) =
let el = session.waitForElement(element, strategy) let el = session.waitForElement(element, strategy)
check function(el) doAssert function(el)
proc setColor*(session: Session, element, color: string, strategy=CssSelector) = proc setColor*(session: Session, element, color: string, strategy=CssSelector) =
let el = session.waitForElement(element, strategy) let el = session.waitForElement(element, strategy)
discard session.execute("arguments[0].setAttribute('value', '" & color & "')", el.get()) discard session.executeScript("arguments[0].setAttribute('value', '" & color & "')", el.get())
proc checkIsNone*(session: Session, element: string, strategy=CssSelector) = proc checkIsNone*(session: Session, element: string, strategy=CssSelector) =
discard session.waitForElement(element, strategy, waitCondition=elementIsNone) discard session.waitForElement(element, strategy, waitCondition=elementIsNone)
proc checkText*(session: Session, element, expectedValue: string) = proc checkText*(session: Session, element, expectedValue: string) =
let el = session.waitForElement(element) let el = session.waitForElement(element)
check el.get().getText() == expectedValue doAssert el.get().text.strip() == expectedValue
proc waitForElement*(
session: Session, selector: string, strategy=CssSelector,
timeout=20000, pollTime=50,
waitCondition=elementIsSome
): Option[Element] =
var waitTime = 0
when actionDelayMs > 0:
sleep(actionDelayMs)
while true:
try:
let loading = session.findElement(selector, strategy)
if waitCondition(loading):
return loading
finally:
discard
sleep(pollTime)
waitTime += pollTime
if waitTime > timeout:
doAssert false, "Wait for load time exceeded"
proc waitForElements*(
session: Session, selector: string, strategy=CssSelector,
timeout=20000, pollTime=50
): seq[Element] =
var waitTime = 0
when actionDelayMs > 0:
sleep(actionDelayMs)
while true:
let loading = session.findElements(selector, strategy)
if loading.len > 0:
return loading
sleep(pollTime)
waitTime += pollTime
if waitTime > timeout:
doAssert false, "Wait for load time exceeded"
proc setUserRank*(session: Session, baseUrl, user, rank: string) = proc setUserRank*(session: Session, baseUrl, user, rank: string) =
with session: with session:

View file

@ -1,6 +1,6 @@
import unittest, common import unittest, common
import webdriver import halonium
proc test*(session: Session, baseUrl: string) = proc test*(session: Session, baseUrl: string) =
session.navigate(baseUrl) session.navigate(baseUrl)

View file

@ -1,6 +1,6 @@
import unittest, common import unittest, common
import webdriver import halonium
proc test*(session: Session, baseUrl: string) = proc test*(session: Session, baseUrl: string) =
session.navigate(baseUrl) session.navigate(baseUrl)

View file

@ -1,6 +1,6 @@
import unittest, common import unittest, common
import webdriver import halonium
let let
userTitleStr = "This is a user thread!" userTitleStr = "This is a user thread!"