Skip to content

Commit 9aa6af7

Browse files
authored
[feature:tests] Added SeleniumTestMixin
1 parent f950d57 commit 9aa6af7

File tree

6 files changed

+84
-64
lines changed

6 files changed

+84
-64
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151

5252
- name: Install openwisp-utils
5353
run: |
54-
pip install -e .[qa,rest]
54+
pip install -e .[qa,rest,selenium]
5555
pip install ${{ matrix.django-version }}
5656
5757
- name: QA checks

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,12 @@ Example usage:
14431443
# the assertion above will fail but this line will be executed
14441444
print('This will be printed anyway.')
14451445
1446+
``openwisp_utils.test_selenium_mixins.SeleniumTestMixin``
1447+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1448+
1449+
This mixin provides basic setup for Selenium tests with method to
1450+
open URL and login and logout a user.
1451+
14461452
Quality Assurance Checks
14471453
------------------------
14481454

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from django.conf import settings
2+
from selenium import webdriver
3+
from selenium.webdriver.common.by import By
4+
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
5+
from selenium.webdriver.support import expected_conditions as EC
6+
from selenium.webdriver.support.ui import WebDriverWait
7+
8+
9+
class SeleniumTestMixin:
10+
"""
11+
A base test case for Selenium, providing helped methods for generating
12+
clients and logging in profiles.
13+
"""
14+
15+
admin_username = 'admin'
16+
admin_password = 'password'
17+
18+
@classmethod
19+
def setUpClass(cls):
20+
super().setUpClass()
21+
chrome_options = webdriver.ChromeOptions()
22+
if getattr(settings, 'SELENIUM_HEADLESS', True):
23+
chrome_options.add_argument('--headless')
24+
chrome_options.add_argument('--window-size=1366,768')
25+
chrome_options.add_argument('--ignore-certificate-errors')
26+
chrome_options.add_argument('--remote-debugging-port=9222')
27+
capabilities = DesiredCapabilities.CHROME
28+
capabilities['goog:loggingPrefs'] = {'browser': 'ALL'}
29+
cls.web_driver = webdriver.Chrome(
30+
options=chrome_options,
31+
desired_capabilities=capabilities,
32+
)
33+
34+
@classmethod
35+
def tearDownClass(cls):
36+
cls.web_driver.quit()
37+
super().tearDownClass()
38+
39+
def open(self, url, driver=None):
40+
"""
41+
Opens a URL
42+
Argument:
43+
url: URL to open
44+
driver: selenium driver (default: cls.base_driver)
45+
"""
46+
if not driver:
47+
driver = self.web_driver
48+
driver.get(f'{self.live_server_url}{url}')
49+
WebDriverWait(self.web_driver, 2).until(
50+
EC.visibility_of_element_located((By.CSS_SELECTOR, '#main-content'))
51+
)
52+
53+
def login(self, username=None, password=None, driver=None):
54+
"""
55+
Log in to the admin dashboard
56+
Argument:
57+
driver: selenium driver (default: cls.web_driver)
58+
username: username to be used for login (default: cls.admin.username)
59+
password: password to be used for login (default: cls.admin.password)
60+
"""
61+
if not driver:
62+
driver = self.web_driver
63+
if not username:
64+
username = self.admin_username
65+
if not password:
66+
password = self.admin_password
67+
driver.get(f'{self.live_server_url}/admin/login/')
68+
if 'admin/login' in driver.current_url:
69+
driver.find_element(by=By.NAME, value='username').send_keys(username)
70+
driver.find_element(by=By.NAME, value='password').send_keys(password)
71+
driver.find_element(by=By.XPATH, value='//input[@type="submit"]').click()

requirements-test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# For testing Dependency loaders
22
openwisp_controller @ https://github.com/openwisp/openwisp-controller/tarball/master
3-
selenium~=4.9.1
3+

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
'drf-yasg~=1.21.0',
6666
],
6767
'celery': ['celery~=5.2.3'],
68+
'selenium': ['selenium~=4.9.1'],
6869
},
6970
classifiers=[
7071
'Development Status :: 3 - Alpha',

tests/test_project/tests/utils.py

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
import os
33
import uuid
44

5-
from django.conf import settings
65
from django.contrib.auth import get_user_model
76
from django.contrib.auth.models import AnonymousUser
8-
from selenium import webdriver
7+
from openwisp_utils.test_selenium_mixins import (
8+
SeleniumTestMixin as BaseSeleniumTestMixin,
9+
)
910
from selenium.common.exceptions import NoSuchElementException
1011
from selenium.webdriver.common.by import By
11-
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
1212
from selenium.webdriver.support import expected_conditions as EC
1313
from selenium.webdriver.support.wait import WebDriverWait
1414

@@ -26,44 +26,7 @@ class TestConfigMixin(object):
2626
config = json.load(json_file)
2727

2828

29-
class SeleniumTestMixin(TestConfigMixin):
30-
@classmethod
31-
def setUpClass(cls):
32-
super().setUpClass()
33-
chrome_options = webdriver.ChromeOptions()
34-
if getattr(settings, 'SELENIUM_HEADLESS', True):
35-
chrome_options.add_argument('--headless')
36-
chrome_options.add_argument('--window-size=1366,768')
37-
chrome_options.add_argument('--ignore-certificate-errors')
38-
chrome_options.add_argument('--remote-debugging-port=9222')
39-
capabilities = DesiredCapabilities.CHROME
40-
capabilities['goog:loggingPrefs'] = {'browser': 'ALL'}
41-
cls.web_driver = webdriver.Chrome(
42-
options=chrome_options,
43-
desired_capabilities=capabilities,
44-
)
45-
46-
@classmethod
47-
def tearDownClass(cls):
48-
cls.web_driver.quit()
49-
super().tearDownClass()
50-
51-
def open(self, url, driver=None):
52-
"""
53-
Opens a URL
54-
Argument:
55-
url: URL to open
56-
driver: selenium driver (default: cls.base_driver)
57-
"""
58-
if not driver:
59-
driver = self.web_driver
60-
driver.get(f'{self.live_server_url}{url}')
61-
WebDriverWait(self.web_driver, 2).until(
62-
EC.visibility_of_element_located(
63-
(By.CSS_SELECTOR, self.config['main_content_css_selector'])
64-
)
65-
)
66-
29+
class SeleniumTestMixin(BaseSeleniumTestMixin, TestConfigMixin):
6730
def _create_user(self, **kwargs):
6831
opts = dict(
6932
username=self.config['tester_username'],
@@ -88,27 +51,6 @@ def _create_admin(self, **kwargs):
8851
opts.update(kwargs)
8952
return self._create_user(**opts)
9053

91-
def login(self, username=None, password=None, driver=None):
92-
"""
93-
Log in to the admin dashboard
94-
Argument:
95-
driver: selenium driver (default: cls.web_driver)
96-
username: username to be used for login (default: cls.admin.username)
97-
password: password to be used for login (default: cls.admin.password)
98-
"""
99-
if not driver:
100-
driver = self.web_driver
101-
if not username:
102-
username = self.config['admin_username']
103-
if not password:
104-
password = self.config['admin_password']
105-
url = self.live_server_url + self.config['login_url']
106-
driver.get(url)
107-
if 'admin/login' in driver.current_url:
108-
driver.find_element(By.NAME, 'username').send_keys(username)
109-
driver.find_element(By.NAME, 'password').send_keys(password)
110-
driver.find_element(By.XPATH, '//input[@type="submit"]').click()
111-
11254
def logout(self):
11355
account_button = self._get_account_button()
11456
account_button.click()

0 commit comments

Comments
 (0)