tests: start fixing selenium tests

This commit is contained in:
Jens Langhammer 2021-02-21 23:30:31 +01:00
parent 2dd8119abe
commit 217595bb01
3 changed files with 56 additions and 16 deletions

View File

@ -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,

View File

@ -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"))

View File

@ -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")