-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add
test_shows_validation_errors
E2E test
Ref: #119
- Loading branch information
Showing
3 changed files
with
91 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import pytest | ||
from selenium import webdriver | ||
from selenium.webdriver.common.by import By | ||
from selenium.webdriver.support import expected_conditions as ec | ||
from selenium.webdriver.support.ui import WebDriverWait | ||
|
||
from questionpy import Package, QuestionTypeWrapper | ||
from questionpy.form import FormModel, checkbox, group, repeat, section | ||
from questionpy_common.api.qtype import QuestionTypeInterface | ||
|
||
from .conftest import _NoopQuestion, use_package | ||
|
||
|
||
def package_init(package: Package) -> QuestionTypeInterface: | ||
class Group(FormModel): | ||
checkbox: bool = checkbox("Checkbox", required=True) | ||
|
||
class Repetition(FormModel): | ||
group: Group = group("Group", Group) | ||
|
||
class PackageForm(FormModel): | ||
checkbox: bool = checkbox("Checkbox", required=True) | ||
repetition: list[Repetition] = repeat(Repetition) | ||
group: Group = group("Group", Group) | ||
section: Group = section("Section", Group) | ||
|
||
class PackageQuestion(_NoopQuestion): | ||
options: PackageForm | ||
|
||
return QuestionTypeWrapper(PackageQuestion, package) | ||
|
||
|
||
def assert_hidden(driver: webdriver.Chrome, selector: str) -> None: | ||
assert not driver.find_element(By.CSS_SELECTOR, f"{selector} .errors").is_displayed() | ||
|
||
|
||
def await_and_assert_msg(driver: webdriver.Chrome, selector: str) -> None: | ||
msg_selector = f"{selector} .errors" | ||
el_error = WebDriverWait(driver, 5).until(ec.visibility_of_element_located((By.CSS_SELECTOR, msg_selector))) | ||
assert el_error.text == "Field required" | ||
|
||
|
||
@pytest.mark.usefixtures("_start_runner_thread") | ||
@use_package(package_init) | ||
def test_shows_validation_errors(driver: webdriver.Chrome, url: str) -> None: | ||
driver.get(url) | ||
|
||
# Assert error messages are hidden. | ||
assert_hidden(driver, "#general_checkbox") | ||
assert_hidden(driver, "#general_repetition #general_repetition_1_group") | ||
assert_hidden(driver, "#general_group #general_group_checkbox") | ||
assert_hidden(driver, "#section #section_checkbox") | ||
|
||
# Submit form. | ||
driver.find_element(By.ID, "submit-options-button").click() | ||
|
||
# Assert error messages are shown. | ||
await_and_assert_msg(driver, "#general_checkbox") | ||
await_and_assert_msg(driver, "#general_repetition #general_repetition_1_group") | ||
await_and_assert_msg(driver, "#general_group #general_group_checkbox") | ||
await_and_assert_msg(driver, "#section #section_checkbox") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,19 @@ | ||
# This file is part of the QuestionPy SDK. (https://questionpy.org) | ||
# The QuestionPy SDK is free software released under terms of the MIT license. See LICENSE.md. | ||
# (c) Technische Universität Berlin, innoCampus <[email protected]> | ||
from collections.abc import Callable | ||
from typing import Any, TypeVar, cast | ||
|
||
import pytest | ||
from selenium import webdriver | ||
from selenium.webdriver.common.by import By | ||
from selenium.webdriver.support import expected_conditions | ||
from selenium.webdriver.support.wait import WebDriverWait | ||
|
||
from questionpy import Attempt, NeedsManualScoringError, Package, Question, QuestionTypeWrapper | ||
from questionpy import Package, QuestionTypeWrapper | ||
from questionpy.form import FormModel, checkbox, repeat | ||
from questionpy_common.api.qtype import QuestionTypeInterface | ||
from questionpy_common.environment import PackageInitFunction | ||
from questionpy_common.manifest import Manifest | ||
from questionpy_server.worker.runtime.package_location import FunctionPackageLocation | ||
|
||
|
||
class _NoopAttempt(Attempt): | ||
def _compute_score(self) -> float: | ||
raise NeedsManualScoringError | ||
|
||
formulation = "" | ||
|
||
|
||
class _NoopQuestion(Question): | ||
attempt_class = _NoopAttempt | ||
from .conftest import _NoopQuestion, use_package | ||
|
||
|
||
def package_1_init(package: Package) -> QuestionTypeInterface: | ||
|
@@ -62,17 +49,6 @@ class Package3Question(_NoopQuestion): | |
return QuestionTypeWrapper(Package3Question, package) | ||
|
||
|
||
_C = TypeVar("_C", bound=Callable) | ||
|
||
|
||
def use_package(init_fun: PackageInitFunction, manifest: Manifest | None = None) -> Callable[[_C], _C]: | ||
def decorator(wrapped: _C) -> _C: | ||
cast(Any, wrapped).qpy_package_location = FunctionPackageLocation.from_function(init_fun, manifest) | ||
return wrapped | ||
|
||
return decorator | ||
|
||
|
||
@pytest.mark.usefixtures("_start_runner_thread") | ||
class TestTemplates: | ||
@use_package(package_1_init) | ||
|