Skip to content

Commit

Permalink
Fixes #3341 - Adding basic python playwright browser test
Browse files Browse the repository at this point in the history
Fixes #3341 - Adding basic python playwright browser test
  • Loading branch information
alexcottner authored Feb 5, 2024
1 parent 039d3e3 commit e025672
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 102 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ functional: install-dev need-kinto-running
$(VENV)/bin/py.test tests/functional.py

browser-test: need-kinto-running
$(VENV)/bin/playwright install firefox
$(VENV)/bin/py.test tests/browser.py

clean:
Expand Down
2 changes: 1 addition & 1 deletion constraints.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ bravado_core
pytest
pytest-cache
pytest-cov
selenium
playwright
webtest
# dev
build
Expand Down
47 changes: 11 additions & 36 deletions constraints.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
#
# This file is autogenerated by pip-compile with Python 3.9
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --strip-extras
# pip-compile --output-file=constraints.txt --strip-extras constraints.in
#
arrow==1.3.0
# via isoduration
attrs==23.2.0
# via
# jsonschema
# outcome
# referencing
# trio
bcrypt==4.1.2
# via -r constraints.in
beautifulsoup4==4.12.3
Expand All @@ -23,7 +21,6 @@ build==1.0.3
certifi==2023.11.17
# via
# requests
# selenium
# sentry-sdk
charset-normalizer==3.3.2
# via requests
Expand All @@ -46,27 +43,21 @@ coverage==7.4.0
dockerflow==2024.1.0
# via -r constraints.in
exceptiongroup==1.2.0
# via
# pytest
# trio
# trio-websocket
# via pytest
execnet==2.0.2
# via pytest-cache
fqdn==1.5.1
# via jsonschema
greenlet==3.0.3
# via sqlalchemy
h11==0.14.0
# via wsproto
# via
# playwright
# sqlalchemy
hupper==1.12
# via pyramid
idna==3.6
# via
# jsonschema
# requests
# trio
importlib-metadata==7.0.1
# via build
iniconfig==2.0.0
# via pytest
iso8601==2.1.0
Expand Down Expand Up @@ -96,8 +87,6 @@ msgpack==1.0.7
# via bravado-core
newrelic==9.6.0
# via -r constraints.in
outcome==1.3.0.post0
# via trio
packaging==23.2
# via
# build
Expand All @@ -111,10 +100,14 @@ plaster==1.1.2
# pyramid
plaster-pastedeploy==1.0.1
# via pyramid
playwright==1.41.1
# via -r constraints.in
pluggy==1.3.0
# via pytest
psycopg2==2.9.9
# via -r constraints.in
pyee==11.0.1
# via playwright
pyproject-hooks==1.0.0
# via build
pyramid==2.0.2
Expand All @@ -130,8 +123,6 @@ pyramid-multiauth==1.0.1
# via -r constraints.in
pyramid-tm==2.5
# via -r constraints.in
pysocks==1.7.1
# via urllib3
pytest==7.4.4
# via
# -r constraints.in
Expand Down Expand Up @@ -176,8 +167,6 @@ rpds-py==0.17.1
# referencing
ruff==0.1.15
# via -r constraints.in
selenium==4.12.0
# via -r constraints.in
sentry-sdk==1.39.2
# via -r constraints.in
simplejson==3.19.2
Expand All @@ -188,10 +177,6 @@ six==1.16.0
# cornice-swagger
# python-dateutil
# rfc3339-validator
sniffio==1.3.0
# via trio
sortedcontainers==2.4.0
# via trio
soupsieve==2.5
# via beautifulsoup4
sqlalchemy==2.0.25
Expand Down Expand Up @@ -220,24 +205,18 @@ translationstring==1.4
# via
# colander
# pyramid
trio==0.24.0
# via
# selenium
# trio-websocket
trio-websocket==0.11.1
# via selenium
types-python-dateutil==2.8.19.20240106
# via arrow
typing-extensions==4.9.0
# via
# pyee
# sqlalchemy
# swagger-spec-validator
uri-template==1.3.0
# via jsonschema
urllib3==2.1.0
# via
# requests
# selenium
# sentry-sdk
venusian==3.1.0
# via
Expand All @@ -257,10 +236,6 @@ webtest==3.0.0
# via -r constraints.in
werkzeug==3.0.1
# via -r constraints.in
wsproto==1.2.0
# via trio-websocket
zipp==3.17.0
# via importlib-metadata
zope-deprecation==5.0
# via pyramid
zope-interface==6.1
Expand Down
11 changes: 1 addition & 10 deletions docs/community.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,7 @@ In another terminal, run the end-to-end tests with:

Browser Tests
-------------

Make sure the `geckodriver <https://github.com/mozilla/geckodriver/releases>`_ binary is available in your path.

.. note::

If your installation of *Firefox* is custom, specify the path of its binary using an alias:

::

alias geckodriver="geckodriver --binary /path/to/firefox"
We use `playwright <https://playwright.dev/>`_ for browser testing. The tests included in this repo are very simple and verify the admin UI can at least authenticate with the current kinto back-end. Comprehensive unit tests are maintained in the kinto-admin repo.


In a terminal, run an instance with the provided ``browser.ini`` configuration:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ test = [
"pytest",
"pytest-cache",
"pytest-cov",
"selenium",
"playwright",
"webtest",
]
dev = [
Expand Down
78 changes: 24 additions & 54 deletions tests/browser.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,38 @@
import time
import re
import unittest
from urllib.parse import urljoin

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from playwright.sync_api import expect, sync_playwright


SERVER_URL = "http://localhost:8888/v1"
DEFAULT_AUTH = ("user", "p4ssw0rd")
baseUrl = "http://localhost:8888/v1/"
auth = {"user": "user", "password": "p4ssw0rd"}

browser = sync_playwright().start().firefox.launch()
context = browser.new_context(base_url=baseUrl)
page = browser.new_page()


class BrowserTest(unittest.TestCase):
def setUp(self):
options = webdriver.FirefoxOptions()
options.headless = True
self.driver = webdriver.Firefox(options=options)
self.driver.implicitly_wait(10) # seconds

@classmethod
def setUpClass(cls):
# Make sure our user exists.
requests.post(
urljoin(SERVER_URL, "/accounts"),
json={"data": {"id": DEFAULT_AUTH[0], "password": DEFAULT_AUTH[1]}},
)

# Create a bucket and a collection for our user.
bucket_url = urljoin(SERVER_URL, "/buckets/workspace")
collection_url = f"{bucket_url}/collections/articles"
session = requests.Session()
session.auth = DEFAULT_AUTH
resp = session.put(bucket_url)
resp.raise_for_status()
resp = session.put(collection_url)
resp.raise_for_status()
request = context.request

def tearDown(self):
self.driver.close()
request.post("accounts", data={"data": {"id": auth["user"], "password": auth["password"]}})

def test_admin_ui_renders_properly(self):
base_url = urljoin(SERVER_URL, "/v1/admin/")
self.driver.get(base_url)
def test_login_and_view_home_page(self):
page.goto(f"{baseUrl}admin/")

# Load auth page.
header = self.driver.find_element(By.CSS_SELECTOR, ".content div > h1")
self.assertIn("Administration", header.text)
self.assertTrue(header.is_displayed())
expect(page).to_have_title(re.compile("Kinto Administration"))

# Select Kinto Accounts.
radio = self.driver.find_element(By.XPATH, "//label[contains(.,'Kinto Account Auth')]")
radio.click()
page.get_by_label("Kinto Account Auth").click()
txtUsername = page.get_by_label(re.compile("Username"))
txtPassword = page.get_by_label(re.compile("Password"))

# Fill username and password.
user_field = self.driver.find_element(By.ID, "root_credentials_username")
user_field.send_keys(DEFAULT_AUTH[0])
user_pass = self.driver.find_element(By.ID, "root_credentials_password")
user_pass.send_keys(DEFAULT_AUTH[1])
# Login
submit = self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
submit.click()
txtUsername.fill(auth["user"])
txtPassword.fill(auth["password"])
page.get_by_text(re.compile("Sign in using Kinto Account Auth")).click()

# Navigate to simple review page (uses React Hooks and broke a few times)
review_url = base_url + "#/buckets/workspace/collections/articles/simple-review"
self.driver.get(review_url)
time.sleep(1)
self.assertTrue(self.driver.find_element(By.CSS_SELECTOR, ".alert-warning").is_displayed())
expect(page.get_by_text("Kinto Administration")).to_be_visible()
expect(page.get_by_text("project_name")).to_be_visible()
expect(page.get_by_text("project_version")).to_be_visible()
expect(page.get_by_text("http_api_version")).to_be_visible()
expect(page.get_by_text("project_docs")).to_be_visible()

0 comments on commit e025672

Please sign in to comment.