e2e: add custom testcase class to simplify code
This commit is contained in:
parent
7b7305607c
commit
68efcc7bf2
|
@ -6,7 +6,7 @@ from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
from selenium.webdriver.support import expected_conditions as ec
|
from selenium.webdriver.support import expected_conditions as ec
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
from e2e.utils import apply_default_data
|
from e2e.utils import SeleniumTestCase
|
||||||
from passbook.flows.models import Flow, FlowDesignation, FlowStageBinding
|
from passbook.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||||
from passbook.policies.expression.models import ExpressionPolicy
|
from passbook.policies.expression.models import ExpressionPolicy
|
||||||
from passbook.policies.models import PolicyBinding
|
from passbook.policies.models import PolicyBinding
|
||||||
|
@ -16,22 +16,9 @@ from passbook.stages.user_login.models import UserLoginStage
|
||||||
from passbook.stages.user_write.models import UserWriteStage
|
from passbook.stages.user_write.models import UserWriteStage
|
||||||
|
|
||||||
|
|
||||||
class TestEnroll2Step(StaticLiveServerTestCase):
|
class TestEnroll2Step(SeleniumTestCase):
|
||||||
"""Test 2-step enroll flow"""
|
"""Test 2-step enroll flow"""
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.driver = webdriver.Remote(
|
|
||||||
command_executor="http://localhost:4444/wd/hub",
|
|
||||||
desired_capabilities=DesiredCapabilities.CHROME,
|
|
||||||
)
|
|
||||||
self.wait = WebDriverWait(self.driver, 10)
|
|
||||||
self.driver.implicitly_wait(5)
|
|
||||||
apply_default_data()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super().tearDown()
|
|
||||||
self.driver.quit()
|
|
||||||
|
|
||||||
def test_enroll_2_step(self):
|
def test_enroll_2_step(self):
|
||||||
"""Test 2-step enroll flow"""
|
"""Test 2-step enroll flow"""
|
||||||
# First stage fields
|
# First stage fields
|
||||||
|
|
|
@ -1,28 +1,15 @@
|
||||||
"""test default login flow"""
|
"""test default login flow"""
|
||||||
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
|
|
||||||
from e2e.utils import apply_default_data
|
from e2e.utils import SeleniumTestCase
|
||||||
|
|
||||||
|
|
||||||
class TestLogin(StaticLiveServerTestCase):
|
class TestLogin(SeleniumTestCase):
|
||||||
"""test default login flow"""
|
"""test default login flow"""
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.driver = webdriver.Remote(
|
|
||||||
command_executor="http://localhost:4444/wd/hub",
|
|
||||||
desired_capabilities=DesiredCapabilities.CHROME,
|
|
||||||
)
|
|
||||||
self.driver.implicitly_wait(5)
|
|
||||||
apply_default_data()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
super().tearDown()
|
|
||||||
self.driver.quit()
|
|
||||||
|
|
||||||
def test_login(self):
|
def test_login(self):
|
||||||
"""test default login flow"""
|
"""test default login flow"""
|
||||||
self.driver.get(f"{self.live_server_url}/flows/default-authentication-flow/")
|
self.driver.get(f"{self.live_server_url}/flows/default-authentication-flow/")
|
||||||
|
|
|
@ -12,22 +12,17 @@ from selenium.webdriver.common.keys import Keys
|
||||||
from docker import DockerClient, from_env
|
from docker import DockerClient, from_env
|
||||||
from docker.models.containers import Container
|
from docker.models.containers import Container
|
||||||
from docker.types import Healthcheck
|
from docker.types import Healthcheck
|
||||||
from e2e.utils import apply_default_data, ensure_rsa_key
|
from e2e.utils import SeleniumTestCase, ensure_rsa_key
|
||||||
from passbook.core.models import Application
|
from passbook.core.models import Application
|
||||||
from passbook.flows.models import Flow
|
from passbook.flows.models import Flow
|
||||||
from passbook.providers.oidc.models import OpenIDProvider
|
from passbook.providers.oidc.models import OpenIDProvider
|
||||||
|
|
||||||
|
|
||||||
class TestProviderOIDC(StaticLiveServerTestCase):
|
class TestProviderOIDC(SeleniumTestCase):
|
||||||
"""test OpenID Provider flow"""
|
"""test OpenID Provider flow"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.driver = webdriver.Remote(
|
super().setUp()
|
||||||
command_executor="http://localhost:4444/wd/hub",
|
|
||||||
desired_capabilities=DesiredCapabilities.CHROME,
|
|
||||||
)
|
|
||||||
self.driver.implicitly_wait(5)
|
|
||||||
apply_default_data()
|
|
||||||
self.client_id = generate_client_id()
|
self.client_id = generate_client_id()
|
||||||
self.client_secret = generate_client_secret()
|
self.client_secret = generate_client_secret()
|
||||||
self.container = self.setup_client()
|
self.container = self.setup_client()
|
||||||
|
|
80
e2e/utils.py
80
e2e/utils.py
|
@ -1,41 +1,17 @@
|
||||||
"""passbook e2e testing utilities"""
|
"""passbook e2e testing utilities"""
|
||||||
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from importlib.util import module_from_spec, spec_from_file_location
|
from importlib.util import module_from_spec, spec_from_file_location
|
||||||
from inspect import getmembers, isfunction
|
from inspect import getmembers, isfunction
|
||||||
|
|
||||||
from Cryptodome.PublicKey import RSA
|
from Cryptodome.PublicKey import RSA
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||||
from django.db import connection, transaction
|
from django.db import connection, transaction
|
||||||
from django.db.utils import IntegrityError
|
from django.db.utils import IntegrityError
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
def apply_default_data():
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
"""apply objects created by migrations after tables have been truncated"""
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
# Find all migration files
|
|
||||||
# load all functions
|
|
||||||
migration_files = glob("**/migrations/*.py", recursive=True)
|
|
||||||
matches = []
|
|
||||||
for migration in migration_files:
|
|
||||||
with open(migration, "r+") as migration_file:
|
|
||||||
# Check if they have a `RunPython`
|
|
||||||
if "RunPython" in migration_file.read():
|
|
||||||
matches.append(migration)
|
|
||||||
|
|
||||||
with connection.schema_editor() as schema_editor:
|
|
||||||
for match in matches:
|
|
||||||
# Load module from file path
|
|
||||||
spec = spec_from_file_location("", match)
|
|
||||||
migration_module = module_from_spec(spec)
|
|
||||||
# pyright: reportGeneralTypeIssues=false
|
|
||||||
spec.loader.exec_module(migration_module)
|
|
||||||
# Call all functions from module
|
|
||||||
for _, func in getmembers(migration_module, isfunction):
|
|
||||||
with transaction.atomic():
|
|
||||||
try:
|
|
||||||
func(apps, schema_editor)
|
|
||||||
except IntegrityError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_rsa_key():
|
def ensure_rsa_key():
|
||||||
|
@ -46,3 +22,49 @@ def ensure_rsa_key():
|
||||||
key = RSA.generate(2048)
|
key = RSA.generate(2048)
|
||||||
rsakey = RSAKey(key=key.exportKey("PEM").decode("utf8"))
|
rsakey = RSAKey(key=key.exportKey("PEM").decode("utf8"))
|
||||||
rsakey.save()
|
rsakey.save()
|
||||||
|
|
||||||
|
|
||||||
|
class SeleniumTestCase(StaticLiveServerTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.driver = self._get_driver()
|
||||||
|
self.driver.implicitly_wait(5)
|
||||||
|
self.wait = WebDriverWait(self.driver, 10)
|
||||||
|
self.apply_default_data()
|
||||||
|
|
||||||
|
def _get_driver(self) -> WebDriver:
|
||||||
|
return webdriver.Remote(
|
||||||
|
command_executor="http://localhost:4444/wd/hub",
|
||||||
|
desired_capabilities=DesiredCapabilities.CHROME,
|
||||||
|
)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super().tearDown()
|
||||||
|
self.driver.quit()
|
||||||
|
|
||||||
|
def apply_default_data(self):
|
||||||
|
"""apply objects created by migrations after tables have been truncated"""
|
||||||
|
# Find all migration files
|
||||||
|
# load all functions
|
||||||
|
migration_files = glob("**/migrations/*.py", recursive=True)
|
||||||
|
matches = []
|
||||||
|
for migration in migration_files:
|
||||||
|
with open(migration, "r+") as migration_file:
|
||||||
|
# Check if they have a `RunPython`
|
||||||
|
if "RunPython" in migration_file.read():
|
||||||
|
matches.append(migration)
|
||||||
|
|
||||||
|
with connection.schema_editor() as schema_editor:
|
||||||
|
for match in matches:
|
||||||
|
# Load module from file path
|
||||||
|
spec = spec_from_file_location("", match)
|
||||||
|
migration_module = module_from_spec(spec)
|
||||||
|
# pyright: reportGeneralTypeIssues=false
|
||||||
|
spec.loader.exec_module(migration_module)
|
||||||
|
# Call all functions from module
|
||||||
|
for _, func in getmembers(migration_module, isfunction):
|
||||||
|
with transaction.atomic():
|
||||||
|
try:
|
||||||
|
func(apps, schema_editor)
|
||||||
|
except IntegrityError:
|
||||||
|
pass
|
||||||
|
|
|
@ -215,7 +215,9 @@ class FlowExecutorShellView(TemplateView):
|
||||||
kwargs["exec_url"] = reverse("passbook_flows:flow-executor", kwargs=self.kwargs)
|
kwargs["exec_url"] = reverse("passbook_flows:flow-executor", kwargs=self.kwargs)
|
||||||
kwargs["msg_url"] = reverse("passbook_api:messages-list")
|
kwargs["msg_url"] = reverse("passbook_api:messages-list")
|
||||||
if NEXT_ARG_NAME in self.request.GET:
|
if NEXT_ARG_NAME in self.request.GET:
|
||||||
self.request.session[SESSION_KEY_NEXT] = self.request.GET[NEXT_ARG_NAME]
|
next_arg = self.request.GET[NEXT_ARG_NAME]
|
||||||
|
LOGGER.debug("f(exec/shell): Saved next param", next=next_arg)
|
||||||
|
self.request.session[SESSION_KEY_NEXT] = next_arg
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue