tests: start fixing selenium tests
This commit is contained in:
parent
2dd8119abe
commit
217595bb01
|
@ -6,11 +6,7 @@ from django.shortcuts import get_object_or_404
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
from webauthn import (
|
from webauthn import WebAuthnAssertionOptions, WebAuthnAssertionResponse, WebAuthnUser
|
||||||
WebAuthnAssertionOptions,
|
|
||||||
WebAuthnAssertionResponse,
|
|
||||||
WebAuthnUser,
|
|
||||||
)
|
|
||||||
from webauthn.webauthn import (
|
from webauthn.webauthn import (
|
||||||
AuthenticationRejectedException,
|
AuthenticationRejectedException,
|
||||||
RegistrationRejectedException,
|
RegistrationRejectedException,
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.test import override_settings
|
||||||
from docker.types import Healthcheck
|
from docker.types import Healthcheck
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.support import expected_conditions as ec
|
from selenium.webdriver.support import expected_conditions as ec
|
||||||
|
from selenium.webdriver.support.wait import WebDriverWait
|
||||||
|
|
||||||
from authentik.core.models import User
|
from authentik.core.models import User
|
||||||
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||||
|
@ -36,6 +37,7 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||||
}
|
}
|
||||||
|
|
||||||
@retry()
|
@retry()
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
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
|
||||||
|
@ -87,17 +89,44 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||||
FlowStageBinding.objects.create(target=flow, stage=user_login, order=3)
|
FlowStageBinding.objects.create(target=flow, stage=user_login, order=3)
|
||||||
|
|
||||||
self.driver.get(self.live_server_url)
|
self.driver.get(self.live_server_url)
|
||||||
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#enroll")))
|
|
||||||
self.driver.find_element(By.CSS_SELECTOR, "#enroll").click()
|
|
||||||
|
|
||||||
self.wait.until(ec.presence_of_element_located((By.ID, "id_username")))
|
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||||
self.driver.find_element(By.ID, "id_username").send_keys("foo")
|
identification_stage = self.get_shadow_root(
|
||||||
self.driver.find_element(By.ID, "id_password").send_keys(USER().username)
|
"ak-stage-identification", flow_executor
|
||||||
self.driver.find_element(By.ID, "id_password_repeat").send_keys(USER().username)
|
)
|
||||||
self.driver.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
|
wait = WebDriverWait(identification_stage, self.wait_timeout)
|
||||||
self.driver.find_element(By.ID, "id_name").send_keys("some name")
|
|
||||||
self.driver.find_element(By.ID, "id_email").send_keys("foo@bar.baz")
|
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#enroll")))
|
||||||
self.driver.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
|
identification_stage.find_element(By.CSS_SELECTOR, "#enroll").click()
|
||||||
|
|
||||||
|
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||||
|
prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor)
|
||||||
|
wait = WebDriverWait(prompt_stage, self.wait_timeout)
|
||||||
|
|
||||||
|
wait.until(
|
||||||
|
ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=username]"))
|
||||||
|
)
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=username]").send_keys(
|
||||||
|
"foo"
|
||||||
|
)
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys(
|
||||||
|
USER().username
|
||||||
|
)
|
||||||
|
prompt_stage.find_element(
|
||||||
|
By.CSS_SELECTOR, "input[name=password_repeat]"
|
||||||
|
).send_keys(USER().username)
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
|
||||||
|
|
||||||
|
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||||
|
prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor)
|
||||||
|
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=name]").send_keys(
|
||||||
|
"some name"
|
||||||
|
)
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=email]").send_keys(
|
||||||
|
"foo@bar.baz"
|
||||||
|
)
|
||||||
|
prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
|
||||||
|
|
||||||
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
|
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
|
||||||
self.driver.get(self.shell_url("authentik_core:user-settings"))
|
self.driver.get(self.shell_url("authentik_core:user-settings"))
|
||||||
|
|
|
@ -25,6 +25,7 @@ from selenium.common.exceptions import (
|
||||||
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.remote.webdriver import WebDriver
|
from selenium.webdriver.remote.webdriver import WebDriver
|
||||||
|
from selenium.webdriver.remote.webelement import WebElement
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
@ -43,14 +44,16 @@ class SeleniumTestCase(StaticLiveServerTestCase):
|
||||||
"""StaticLiveServerTestCase which automatically creates a Webdriver instance"""
|
"""StaticLiveServerTestCase which automatically creates a Webdriver instance"""
|
||||||
|
|
||||||
container: Optional[Container] = None
|
container: Optional[Container] = None
|
||||||
|
wait_timeout: int
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
self.wait_timeout = 60
|
||||||
makedirs("selenium_screenshots/", exist_ok=True)
|
makedirs("selenium_screenshots/", exist_ok=True)
|
||||||
self.driver = self._get_driver()
|
self.driver = self._get_driver()
|
||||||
self.driver.maximize_window()
|
self.driver.maximize_window()
|
||||||
self.driver.implicitly_wait(30)
|
self.driver.implicitly_wait(30)
|
||||||
self.wait = WebDriverWait(self.driver, 60)
|
self.wait = WebDriverWait(self.driver, self.wait_timeout)
|
||||||
self.apply_default_data()
|
self.apply_default_data()
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
if specs := self.get_container_specs():
|
if specs := self.get_container_specs():
|
||||||
|
@ -112,6 +115,18 @@ class SeleniumTestCase(StaticLiveServerTestCase):
|
||||||
"""same as self.url() but show URL in shell"""
|
"""same as self.url() but show URL in shell"""
|
||||||
return f"{self.live_server_url}/#{reverse(view, kwargs=kwargs)}"
|
return f"{self.live_server_url}/#{reverse(view, kwargs=kwargs)}"
|
||||||
|
|
||||||
|
def get_shadow_root(
|
||||||
|
self, selector: str, container: Optional[WebElement] = None
|
||||||
|
) -> WebElement:
|
||||||
|
"""Get shadow root element's inner shadowRoot"""
|
||||||
|
if not container:
|
||||||
|
container = self.driver
|
||||||
|
shadow_root = container.find_element(By.CSS_SELECTOR, selector)
|
||||||
|
element = self.driver.execute_script(
|
||||||
|
"return arguments[0].shadowRoot", shadow_root
|
||||||
|
)
|
||||||
|
return element
|
||||||
|
|
||||||
def assert_user(self, expected_user: User):
|
def assert_user(self, expected_user: User):
|
||||||
"""Check users/me API and assert it matches expected_user"""
|
"""Check users/me API and assert it matches expected_user"""
|
||||||
self.driver.get(self.url("authentik_api:user-me") + "?format=json")
|
self.driver.get(self.url("authentik_api:user-me") + "?format=json")
|
||||||
|
|
Reference in a new issue