1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-24 08:46:24 -07:00

Add selenium tests

This commit is contained in:
Eggbertx 2022-09-27 10:42:11 -07:00
parent ae179a3762
commit 05da962dfe
5 changed files with 405 additions and 1 deletions

3
.gitignore vendored
View file

@ -16,4 +16,5 @@ __debug_bin
node_modules
/frontend/coverage
/frontend/tests/coverage
.parcel-cache
.parcel-cache
__pycache__

176
devtools/selenium-testing/main.py Executable file
View file

@ -0,0 +1,176 @@
#!/usr/bin/env python3
# Don't forget to set NewThreadDelay and ReplyDelay to 0 in
# the config (with gochan running) before running, otherwise some posts may be rejected
# by the server
import argparse
from lib2to3.pgen2 import driver
from os import path
import os
from pickletools import optimize
import re
import sys
import unittest
from urllib.parse import urljoin
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.edge.options import Options as EdgeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from util.localstorage import LocalStorage
from util.qr import openQR,closeQR,qrIsVisible
testingSite = "http://192.168.56.3"
testingName = "Selenium"
testingEmail = "selenium@gochan.org#noko"
testingMessage = "Hello, from Selenium!\n(driver is %s)"
testingSubject = "Selenium post creation"
testingUploadPath = "../../html/banned.png"
testingPassword = "12345"
testingBoard = "test"
threadRE = re.compile('.*/(\S+)/(\d+)(\+50)?.html')
parser = argparse.ArgumentParser(description="Browser testing via Selenium")
browser = ""
headless = False
keepOpen = False
def gotoPage(driver: WebDriver, page: str):
driver.get(urljoin(testingSite, page))
def loginToStaff(driver: WebDriver, username = "admin", pw = "password"):
gotoPage(driver, "manage")
driver.find_element(by=By.NAME, value="username").send_keys(username)
driver.find_element(by=By.NAME, value="password").send_keys(pw)
driver.find_element(by=By.CSS_SELECTOR, value="input[value=Login]").click()
def sendPost(postForm:WebElement, name="", email="", subject="", message="", file=""):
postForm.find_element(by=By.NAME, value="postname").send_keys(name)
postForm.find_element(by=By.NAME, value="postemail").send_keys(email)
postForm.find_element(by=By.NAME, value="postsubject").send_keys(subject)
postForm.find_element(by=By.NAME, value="postmsg").send_keys(message)
if file != "":
postForm.find_element(by=By.NAME, value="imagefile").send_keys(file)
postForm.find_element(by=By.CSS_SELECTOR, value="input[type=submit]").click()
class TestRunner(unittest.TestCase):
def setUp(self):
if browser == "firefox":
options = FirefoxOptions()
if headless:
options.headless = True
self.driver = webdriver.Firefox(options=options)
elif browser == "chrome" or browser == "chromium":
options = ChromeOptions()
if headless:
options.headless = True
if keepOpen:
options.add_experimental_option("detach", True)
self.driver = webdriver.Chrome(options=options)
else:
self.fail("Unrecognized --browser option '%s'" % browser)
return super().setUp()
def test_qr(self):
gotoPage(self.driver, testingBoard)
self.assertIn("/test/ - Testing board", self.driver.title)
elem = self.driver.find_element(by=By.ID, value="board-subtitle")
self.assertIn("Board for testing stuff", elem.text)
openQR(self.driver)
self.assertTrue(qrIsVisible(self.driver), "Confirm that the QR box was properly opened")
closeQR(self.driver)
self.assertFalse(qrIsVisible(self.driver), "Confirm that the QR box was properly closed")
def test_localStorage(self):
gotoPage(self.driver, testingBoard)
localStorage = LocalStorage(self.driver)
localStorage["foo"] = "bar"
self.assertEqual(localStorage.get("foo"), "bar", "making sure that LocalStorage.get works")
self.assertGreater(localStorage.__len__(), 0)
def test_staffLogin(self):
loginToStaff(self.driver)
self.assertEqual(
self.driver.find_element(by=By.CSS_SELECTOR, value="header h1").text,
"Dashboard",
"Testing staff login"
)
def test_makeThread(self):
gotoPage(self.driver, testingBoard)
WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "form#postform input[type=submit]")))
valProp = self.driver.find_element(by=By.CSS_SELECTOR, value="form#postform input[type=submit]").get_property("value")
self.assertEqual(valProp, "Post")
form = self.driver.find_element(by=By.CSS_SELECTOR, value="form#postform")
sendPost(form,
testingName,
testingEmail,
testingSubject,
testingMessage % self.driver.name,
path.abspath(testingUploadPath))
WebDriverWait(self.driver, 10).until(
EC.url_matches(threadRE))
threadID = threadRE.findall(self.driver.current_url)[0][1]
self.driver.find_element(by=By.CSS_SELECTOR, value=("input#check%s"%threadID)).click()
delPasswordInput = self.driver.find_element(by=By.CSS_SELECTOR, value="input#delete-password")
val = delPasswordInput.get_attribute("value")
if val == "" or val is None:
val = testingPassword
delPasswordInput.send_keys(testingPassword)
cur_url = self.driver.current_url
self.driver.find_element(by=By.CSS_SELECTOR, value="input[name=delete_btn]").click()
self.driver.switch_to.alert.accept()
WebDriverWait(self.driver, 10).until(
EC.url_changes(cur_url))
self.assertNotIn("Error :c", self.driver.title, "No errors when we try to delete the post we just made")
def tearDown(self):
if not keepOpen:
self.driver.close()
return super().tearDown()
def startBrowserTests(testBrowser:str, testHeadless=False, testKeepOpen=False, site=testingSite, board=testingBoard):
global browser
global testingSite
global testingBoard
global headless
global keepOpen
browser = testBrowser
headless = testHeadless
keepOpen = testKeepOpen
if headless:
keepOpen = False
testingSite = site
testingBoard = board
print("Using browser %s (headless: %s) on site %s" % (browser, headless, testingSite))
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestRunner)
unittest.TextTestRunner(verbosity=3, descriptions=True).run(suite)
if __name__ == "__main__":
testable_browsers = ("firefox","chrome","chromium")
parser.add_argument("--browser", choices=testable_browsers, required=True)
parser.add_argument("--site", default=testingSite, help=("Sets the site to be used for testing, defaults to %s" % testingSite))
parser.add_argument("--board", default=testingBoard, help="Sets the board to be used for testing")
parser.add_argument("--headless", action="store_true", help="If set, the driver will run without opening windows (overrides --keepopen if it is set)")
parser.add_argument("--keepopen", action="store_true", help="If set, the browser windows will stay open after the tests are complete")
args = parser.parse_args()
try:
startBrowserTests(args.browser, args.headless, args.keepopen, args.site, args.board)
except KeyboardInterrupt:
print("Tests interrupted, exiting")

View file

@ -0,0 +1,129 @@
from os import path
import re
import unittest
from urllib.parse import urljoin
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.edge.options import Options as EdgeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from util.localstorage import LocalStorage
from util.qr import openQR,closeQR,qrIsVisible
testingSite = "http://192.168.56.3"
testingName = "Selenium"
testingEmail = "selenium@gochan.org#noko"
testingMessage = "Hello, from Selenium!\n(driver is %s)"
testingSubject = "Selenium post creation"
testingUploadPath = "../../html/banned.png"
testingPassword = "12345"
testingBoard = "test"
browser = ""
threadRE = re.compile('.*/(\S+)/(\d+)(\+50)?.html')
def gotoPage(driver: WebDriver, page: str):
driver.get(urljoin(testingSite, page))
def loginToStaff(driver: WebDriver, username = "admin", pw = "password"):
gotoPage(driver, "manage")
driver.find_element(by=By.NAME, value="username").send_keys(username)
driver.find_element(by=By.NAME, value="password").send_keys(pw)
driver.find_element(by=By.CSS_SELECTOR, value="input[value=Login]").click()
def sendPost(postForm:WebElement, name="", email="", subject="", message="", file=""):
postForm.find_element(by=By.NAME, value="postname").send_keys(name)
postForm.find_element(by=By.NAME, value="postemail").send_keys(email)
postForm.find_element(by=By.NAME, value="postsubject").send_keys(subject)
postForm.find_element(by=By.NAME, value="postmsg").send_keys(message)
if file != "":
postForm.find_element(by=By.NAME, value="imagefile").send_keys(file)
postForm.find_element(by=By.CSS_SELECTOR, value="input[type=submit]").click()
class TestRunner(unittest.TestCase):
def setUp(self):
if browser == "firefox":
options = FirefoxOptions()
options.headless = True
self.driver = webdriver.Firefox(options=options)
elif browser == "chrome" or browser == "chromium":
options = ChromeOptions()
options.headless = True
self.driver = webdriver.Chrome(options=options)
else:
self.fail("Unrecognized --browser option '%s'" % browser)
print("Using browser %s on site %s" % (browser, testingSite))
return super().setUp()
def test_qr(self):
gotoPage(self.driver, testingBoard)
self.assertIn("/test/ - Testing board", self.driver.title)
elem = self.driver.find_element(by=By.ID, value="board-subtitle")
self.assertIn("Board for testing stuff", elem.text)
openQR(self.driver)
self.assertTrue(qrIsVisible(self.driver), "Confirm that the QR box was properly opened")
closeQR(self.driver)
self.assertFalse(qrIsVisible(self.driver), "Confirm that the QR box was properly closed")
def test_localStorage(self):
gotoPage(self.driver, testingBoard)
localStorage = LocalStorage(self.driver)
localStorage["foo"] = "bar"
self.assertEqual(localStorage.get("foo"), "bar", "making sure that LocalStorage.get works")
self.assertGreater(localStorage.__len__(), 0)
def test_staffLogin(self):
loginToStaff(self.driver)
self.assertEqual(
self.driver.find_element(by=By.CSS_SELECTOR, value="header h1").text,
"Dashboard",
"Testing staff login"
)
def test_makeThread(self):
gotoPage(self.driver, testingBoard)
WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "form#postform input[type=submit]")))
valProp = self.driver.find_element(by=By.CSS_SELECTOR, value="form#postform input[type=submit]").get_property("value")
self.assertEqual(valProp, "Post")
form = self.driver.find_element(by=By.CSS_SELECTOR, value="form#postform")
sendPost(form,
testingName,
testingEmail,
testingSubject,
testingMessage % self.driver.name,
path.abspath(testingUploadPath))
WebDriverWait(self.driver, 10).until(
EC.url_matches(threadRE))
threadID = threadRE.findall(self.driver.current_url)[0][1]
self.driver.find_element(by=By.CSS_SELECTOR, value=("input#check%s"%threadID)).click()
delPasswordInput = self.driver.find_element(by=By.CSS_SELECTOR, value="input#delete-password")
val = delPasswordInput.get_attribute("value")
if val == "" or val is None:
val = testingPassword
delPasswordInput.send_keys(testingPassword)
cur_url = self.driver.current_url
self.driver.find_element(by=By.CSS_SELECTOR, value="input[name=delete_btn]").click()
self.driver.switch_to.alert.accept()
WebDriverWait(self.driver, 10).until(
EC.url_changes(cur_url))
self.assertNotIn("Error :c", self.driver.title, "No errors when we try to delete the post we just made")
def tearDown(self):
self.driver.close()
return super().tearDown()

View file

@ -0,0 +1,54 @@
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.firefox.webdriver import WebDriver
class LocalStorage():
# from https://stackoverflow.com/a/46361900
def __init__(self, driver: WebDriver):
self.driver = driver
def __len__(self):
return self.driver.execute_script("return window.localStorage.length;")
def items(self):
return self.driver.execute_script( \
"var ls = window.localStorage, items = {}; " \
"for (var i = 0, k; i < ls.length; ++i) " \
" items[k = ls.key(i)] = ls.getItem(k); " \
"return items;")
def keys(self):
return self.driver.execute_script("return Object.keys(window.localStorage);")
def get(self, key):
return self.driver.execute_script("return window.localStorage.getItem(arguments[0]);", key)
def set(self, key, value):
self.driver.execute_script("window.localStorage.setItem(arguments[0], arguments[1]);", key, value)
def has(self, key):
return key in self.keys()
def remove(self, key):
self.driver.execute_script("window.localStorage.removeItem(arguments[0]);", key)
def clear(self):
self.driver.execute_script("window.localStorage.clear();")
def __getitem__(self, key) :
value = self.get(key)
if value is None :
raise KeyError(key)
return value
def __setitem__(self, key, value):
self.set(key, value)
def __contains__(self, key):
return key in self.keys()
def __iter__(self):
return self.items().__iter__()
def __repr__(self):
return self.items().__str__()

View file

@ -0,0 +1,44 @@
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.common.by import By
def qrIsVisible(driver: WebDriver):
try:
return driver.find_element(by=By.CSS_SELECTOR, value="div#qr-box").is_displayed()
except:
return False
def enableQR(driver: WebDriver):
topbar = driver.find_element(by=By.ID, value="topbar")
topbar.click()
topbar.find_element(by=By.CSS_SELECTOR, value="a#settings").click()
useqr = driver.find_element(by=By.CSS_SELECTOR, value="input#useqr")
if not useqr.is_selected():
useqr.click()
driver.find_element(by=By.CSS_SELECTOR, value="a.lightbox-x").click()
def disableQR(driver: WebDriver):
topbar = driver.find_element(by=By.ID, value="topbar")
topbar.click()
topbar.find_element(by=By.CSS_SELECTOR, value="a#settings").click()
useqr = driver.find_element(by=By.CSS_SELECTOR, value="input#useqr")
if useqr.is_selected():
useqr.click()
driver.find_element(by=By.CSS_SELECTOR, value="a#lightbox-x").click()
def openQR(driver: WebDriver):
enableQR(driver)
if qrIsVisible(driver):
return
body = driver.find_element(by=By.CSS_SELECTOR, value="body")
body.click()
body.send_keys("q")
def closeQR(driver: WebDriver):
if not qrIsVisible(driver):
return
closeLink = driver.find_element(by=By.LINK_TEXT, value="X")
driver.execute_script("arguments[0].click();", closeLink)