diff --git a/hw4/__init__.py b/hw4/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/hw4/selenium/__init__.py b/hw4/selenium/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/hw4/selenium/tests/__init__.py b/hw4/selenium/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/hw4/selenium/tests/conftest.py b/hw4/selenium/tests/conftest.py
new file mode 100644
index 0000000..22424de
--- /dev/null
+++ b/hw4/selenium/tests/conftest.py
@@ -0,0 +1,28 @@
+import pytest
+from selenium.webdriver.chrome.options import Options
+from selenium import webdriver
+from selenium.webdriver.support.wait import WebDriverWait
+
+
+@pytest.fixture
+def chrome_options():
+ options = Options()
+ options.add_argument("--window-size=1900x1000")
+ return options
+
+
+@pytest.fixture
+def driver(chrome_options):
+ driver = webdriver.Chrome(options=chrome_options)
+ driver.implicitly_wait(10)
+ driver.get('http://195.133.27.184/')
+ yield driver
+ driver.quit()
+
+
+@pytest.fixture
+def wait(driver):
+ wait = WebDriverWait(driver, timeout=10)
+ return wait
+
+
diff --git a/hw4/selenium/tests/test.py b/hw4/selenium/tests/test.py
new file mode 100644
index 0000000..32410c0
--- /dev/null
+++ b/hw4/selenium/tests/test.py
@@ -0,0 +1,162 @@
+import pytest
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+
+
+def test_register_positive(driver, wait):
+ # main page
+ driver.get('http://195.133.27.184/')
+ assert driver.title == "Объявления"
+
+ toggler_nav_locator = "//*[text()='Регистрация']"
+ driver.find_element(By.XPATH, toggler_nav_locator).click()
+
+ # registration form
+ page_title_locator = "//h1[text() = 'Регистрация']"
+ page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator)))
+ assert page_title.text == "Регистрация"
+
+ # input username
+ login_locator = "//*[@placeholder = 'Введите имя пользователя']"
+ driver.find_element(By.XPATH, login_locator).send_keys("Jerry") # John exists
+
+ # input password
+ password_locator = "//*[@placeholder = 'Введите пароль']"
+ driver.find_element(By.XPATH, password_locator).send_keys("Iamateacher") # password is too spread
+
+ # confirm password
+ confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']"
+ driver.find_element(By.XPATH, confirm_password_locator).send_keys("Iamateacher")
+
+ # click check-box is_tutor
+ check_box_locator = "//*[@name = 'is_tutor']"
+ check_box = driver.find_element(By.XPATH, check_box_locator)
+ if not check_box.is_selected():
+ check_box.click()
+
+ # submit form
+ submit_btn_locator = "//*[@type = 'submit']"
+ driver.find_element(By.XPATH, submit_btn_locator).click()
+
+ # new page opens
+ logout_btn_locator = "//*[text() = 'Выйти']"
+ logout_btn = wait.until(EC.element_to_be_clickable((By.XPATH, logout_btn_locator)))
+ assert logout_btn.is_displayed()
+
+
+# NEGATIVE scenarios
+
+# FOR TEACHER
+
+def test_register_teacher_check_box(driver, wait):
+
+ toggler_nav_locator = "//*[text()='Регистрация']"
+ driver.find_element(By.XPATH, toggler_nav_locator).click()
+
+ # registration form
+ page_title_locator = "//h1[text() = 'Регистрация']"
+ page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator)))
+ assert page_title.text == "Регистрация"
+
+ # input username
+ login_locator = "//*[@placeholder = 'Введите имя пользователя']"
+ driver.find_element(By.XPATH, login_locator).send_keys("Jerry") # John exists
+
+ # input password
+ password_locator = "//*[@placeholder = 'Введите пароль']"
+ driver.find_element(By.XPATH, password_locator).send_keys("Iamateacher") # password is too spread
+
+ # confirm password
+ confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']"
+ driver.find_element(By.XPATH, confirm_password_locator).send_keys("Iamateacher")
+
+ # click check-box is_tutor
+ check_box_locator = "//*[@name = 'is_tutor']"
+ check_box = driver.find_element(By.XPATH, check_box_locator)
+ if not check_box.is_selected():
+ check_box.click()
+
+ # submit form
+ submit_btn_locator = "//*[@type = 'submit']"
+ driver.find_element(By.XPATH, submit_btn_locator).click()
+
+ # new page opens
+ logout_btn_locator = "//*[text() = 'Выйти']"
+ logout_btn = wait.until(EC.element_to_be_clickable((By.XPATH, logout_btn_locator)))
+ assert logout_btn.is_displayed()
+
+
+### FOR STUDENT
+@pytest.mark.parametrize("username, password, confirm_password, expected", [
+ ("", "", "", "Обязательное поле."),
+ ("Jerry", "", "", "Пользователь с таким именем уже существует."),
+ ("", "qwertyuiop", "qwertyuiop", "Обязательное поле."),
+ # ("123456", "qwertyuiop", "qwertyuiop", " ? ") # ? should be an error. In fact, it passes
+])
+def test_register_student_username_negative(driver, wait, username, password, confirm_password, expected):
+ # main page
+ toggler_nav_locator = "//*[text()='Регистрация']"
+ driver.find_element(By.XPATH, toggler_nav_locator).click()
+
+ # registration form
+ page_title_locator = "//h1[text() = 'Регистрация']"
+ page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator)))
+ assert page_title.text == "Регистрация"
+
+ # input username
+ login_locator = "//*[@placeholder = 'Введите имя пользователя']"
+ driver.find_element(By.XPATH, login_locator).send_keys(username)
+
+ # input password
+ password_locator = "//*[@placeholder = 'Введите пароль']"
+ driver.find_element(By.XPATH, password_locator).send_keys(password)
+
+ # confirm password
+ confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']"
+ driver.find_element(By.XPATH, confirm_password_locator).send_keys(confirm_password)
+
+ # submit form
+ submit_btn_locator = "//*[@type = 'submit']"
+ driver.find_element(By.XPATH, submit_btn_locator).click()
+
+ error_message_locator = f"//*[text() = '{expected}']"
+ error_message = wait.until(EC.visibility_of_element_located((By.XPATH, error_message_locator)))
+ assert error_message.text == expected
+
+
+@pytest.mark.parametrize("username, password, confirm_password, expected", [
+ ("Nina", "qwertyuiop", "qwertyuiop", "Введённый пароль слишком широко распространён."),
+ ("Nina", "12345678", "12345678", "Введённый пароль слишком широко распространён."),
+ ("Nina", "poiuytre", "poiuytr", "Введенные пароли не совпадают."),
+ ("Nina", "poiuytre", "poiuytree", "Введенные пароли не совпадают."),
+ ("Nina", "qwertyu", "qwertyu", "Введённый пароль слишком короткий. Он должен содержать как минимум 8 символов.")
+])
+def test_register_student_password_negative(driver, wait, username, password, confirm_password, expected):
+ # main page
+ toggler_nav_locator = "//*[text()='Регистрация']"
+ driver.find_element(By.XPATH, toggler_nav_locator).click()
+
+ # registration form
+ page_title_locator = "//h1[text() = 'Регистрация']"
+ page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator)))
+ assert page_title.text == "Регистрация"
+
+ # input username
+ login_locator = "//*[@placeholder = 'Введите имя пользователя']"
+ driver.find_element(By.XPATH, login_locator).send_keys(username)
+
+ # input password
+ password_locator = "//*[@placeholder = 'Введите пароль']"
+ driver.find_element(By.XPATH, password_locator).send_keys(password)
+
+ # confirm password
+ confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']"
+ driver.find_element(By.XPATH, confirm_password_locator).send_keys(confirm_password)
+
+ # submit form
+ submit_btn_locator = "//*[@type = 'submit']"
+ driver.find_element(By.XPATH, submit_btn_locator).click()
+
+ error_message_locator = f"//*[text() = '{expected}']"
+ error_message = wait.until(EC.visibility_of_element_located((By.XPATH, error_message_locator)))
+ assert error_message.text == expected
diff --git a/lesson1/api_tests/services/case/data.py b/lesson1/api_tests/services/case/data.py
index d9e7670..33feca1 100644
--- a/lesson1/api_tests/services/case/data.py
+++ b/lesson1/api_tests/services/case/data.py
@@ -6,3 +6,39 @@
"steps": ["шаг 1", "шаг 2", "шаг 3"],
"expected_result": "Задание выполнено",
}
+
+
+schema_response_empty_data = {
+"detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "name"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "description"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "steps"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "expected_result"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "priority"],
+ "msg": "Field required",
+ "input": {},
+ },
+ ]
+}
\ No newline at end of file
diff --git a/lesson1/api_tests/services/case/pom.py b/lesson1/api_tests/services/case/pom.py
index 0d6ff88..16bb5eb 100644
--- a/lesson1/api_tests/services/case/pom.py
+++ b/lesson1/api_tests/services/case/pom.py
@@ -1,6 +1,65 @@
-from utils.api_client import client
+from lesson1.api_tests.utils.api_client import client
+from lesson1.api_tests.services.case.data import create_case_dict
def create_case(json={}):
response = client.make_request(handle="/testcases", method="POST", json=json)
return response
+
+
+def get_read_root():
+ response = client.make_request(
+ handle="/",
+ method="GET"
+ )
+ return response
+
+
+def read_cases():
+ response = client.make_request(
+ handle="/testcases",
+ method="GET",
+ )
+ return response
+
+
+def read_case():
+ response = create_case(json=create_case_dict)
+ case_id = response.get_value_with_key("id")
+ response = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="GET",
+ )
+ return response
+
+
+def get_case_id():
+ response = create_case(json=create_case_dict)
+ case_id = response.get_value_with_key("id")
+ return case_id
+
+
+def update_case():
+ case_id = get_case_id()
+ response = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": 5,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ return response
+
+
+def delete_case():
+ case_id = create_case(json=create_case_dict).get_value_with_key("id")
+ response = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="DELETE",
+ )
+ return response
diff --git a/lesson1/api_tests/tests/test_case.py b/lesson1/api_tests/tests/test_case.py
index 2e5b45a..488b7e8 100644
--- a/lesson1/api_tests/tests/test_case.py
+++ b/lesson1/api_tests/tests/test_case.py
@@ -1,6 +1,6 @@
-from services.case.pom import create_case
-from services.case.data import create_case_dict
-from services.case.models import Case
+from lesson1.api_tests.services.case.pom import create_case
+from lesson1.api_tests.services.case.data import create_case_dict
+from lesson1.api_tests.services.case.models import Case
def test_create_case():
diff --git a/lesson1/api_tests/tests/test_cases_les1.py b/lesson1/api_tests/tests/test_cases_les1.py
new file mode 100644
index 0000000..3af2ded
--- /dev/null
+++ b/lesson1/api_tests/tests/test_cases_les1.py
@@ -0,0 +1,339 @@
+from lesson1.api_tests.services.case.data import create_case_dict
+from lesson1.api_tests.utils.api_client import client
+
+
+### Get Read Root - GET
+def test_get_read_root():
+ response = client.make_request(handle="/", method="GET")
+ response.status_code_should_be_eq(200)
+ response.json_should_be_eq({"Hello": "World"})
+
+
+### Get all TCs - GET
+def test_get_testcases():
+ response = client.make_request(
+ handle="/testcases",
+ method="GET",
+ )
+ response.status_code_should_be_eq(200)
+ # not clear how to verify the list ?
+
+
+### Create Test Case - POST
+def test1_create_case():
+ response = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 3,
+ "name": "Имя",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+ response.status_code_should_be_eq(200)
+ response.json_should_contains({"id": 3})
+
+
+# OR
+def test1_create_case1():
+ response = client.make_request(
+ handle="/testcases", method="POST", json=create_case_dict
+ )
+ response.status_code_should_be_eq(200)
+ response.value_with_key("id").should_be_eq(0)
+
+
+def test2_create_case_empty_data():
+ """
+ negative - body is empty
+ """
+ response = client.make_request(handle="/testcases", method="POST", json={})
+ response.status_code_should_be_eq(422)
+ response.json_should_be_eq(
+ {
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "name"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "description"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "steps"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "expected_result"],
+ "msg": "Field required",
+ "input": {},
+ },
+ {
+ "type": "missing",
+ "loc": ["body", "priority"],
+ "msg": "Field required",
+ "input": {},
+ },
+ ]
+ }
+ )
+
+
+def test3_create_case_missed_priority_data():
+ """
+ negative - key "priority" is missing in the body
+ """
+ response = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 0,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ },
+ )
+ response.status_code_should_be_eq(422)
+ response.json_should_contains(
+ {
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "priority"],
+ "msg": "Field required",
+ "input": {
+ "id": 0,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ },
+ }
+ ]
+ }
+ )
+
+### Get TC ID - GET
+def test1_get_case_id():
+ response1 = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+
+ case_id = response1.get_value_with_key("id")
+ response2 = client.make_request(handle=f"/testcases/{case_id}", method="GET")
+ response2.status_code_should_be_eq(200)
+ response2.json_should_be_eq(
+ {
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ }
+ )
+
+
+def test2_get_case_not_existing_id():
+ """
+ negative - id is not exist
+ """
+ response2 = client.make_request(handle=f"/testcases/455", method="GET")
+ response2.status_code_should_be_eq(404)
+ response2.json_should_be_eq({"detail": "Test case not found."})
+
+
+# not clear how to get Validation Error 422 ?
+
+
+### To update TC data - PUT
+def test1_update_case():
+ response1 = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+
+ case_id = response1.get_value_with_key("id")
+ response2 = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": 5,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ response2.status_code_should_be_eq(200)
+ response2.json_should_be_eq(
+ {
+ "id": 5,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ }
+ )
+
+
+def test2_update_case_empty_id():
+ """
+ negative = update to "id": ""
+ """
+ response1 = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+
+ case_id = response1.get_value_with_key("id")
+ response2 = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": "",
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ response2.status_code_should_be_eq(422)
+ response2.json_should_be_eq(
+ {
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": ["body", "id"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "",
+ }
+ ]
+ }
+ )
+
+
+def test3_update_case_missed_description():
+ """
+ negative - description is missing in update body
+ """
+ response1 = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+
+ case_id = response1.get_value_with_key("id")
+ response2 = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": 2,
+ "name": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ response2.status_code_should_be_eq(422)
+ response2.json_should_be_eq(
+ {
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "description"],
+ "msg": "Field required",
+ "input": {
+ "id": 2,
+ "name": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ }
+ ]
+ }
+ )
+
+
+### Delete TC
+def test1_delete_case():
+ response1 = client.make_request(
+ handle="/testcases",
+ method="POST",
+ json={
+ "id": 4,
+ "name": "Tom",
+ "description": "Описание",
+ "steps": ["Шаг 1", "Шаг 2", "Шаг 3"],
+ "expected_result": "Ожидаемый результат",
+ "priority": "низкий",
+ },
+ )
+ response1.status_code_should_be_eq(200)
+ case_id = response1.get_value_with_key("id")
+ response2 = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="DELETE",
+ )
+ response2.status_code_should_be_eq(200)
+ response2.json_should_be_eq({"detail": "Test case deleted."})
+
+
+def test2_delete_not_existing_case():
+ """
+ negative - delete not existing case
+ """
+ response2 = client.make_request(
+ handle=f"/testcases/455",
+ method="DELETE",
+ )
+ response2.status_code_should_be_eq(404)
+ response2.json_should_be_eq({"detail": "Test case not found."})
diff --git a/lesson1/api_tests/tests/test_cases_les1_optimization.py b/lesson1/api_tests/tests/test_cases_les1_optimization.py
new file mode 100644
index 0000000..6b40584
--- /dev/null
+++ b/lesson1/api_tests/tests/test_cases_les1_optimization.py
@@ -0,0 +1,189 @@
+from lesson1.api_tests.services.case.pom import create_case, get_read_root, read_cases, get_case_id, update_case, \
+ delete_case
+from lesson1.api_tests.services.case.data import create_case_dict, schema_response_empty_data
+from lesson1.api_tests.services.case.models import Case
+from lesson1.api_tests.utils.api_client import client
+
+
+### Get Read Root - GET
+def test_get_read_root():
+ response = get_read_root()
+ response.status_code_should_be_eq(200)
+ response.json_should_be_eq({"Hello": "World"})
+
+
+### Get all TCs - GET
+def test_get_testcases():
+ response = read_cases()
+ response.status_code_should_be_eq(200)
+
+
+### Create Test Case - POST
+def test_create_case():
+ response = create_case(Case(**create_case_dict).model_dump())
+ response.status_code_should_be_eq(200)
+ response.json_should_be_eq(create_case_dict)
+ response.schema_should_be_eq(Case(**create_case_dict).model_json_schema())
+
+
+def test2_create_case_empty_data():
+ """
+ negative - body is empty
+ """
+ response = create_case()
+ response.status_code_should_be_eq(422)
+ response.json_should_be_eq(schema_response_empty_data)
+
+
+def test3_create_case_missed_priority_data():
+ """
+ negative - key "priority" is missing in the body
+ """
+ response = create_case(json={
+ "id": 0,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string"
+ }, )
+
+ response.status_code_should_be_eq(422)
+ response.json_should_contains(
+ {
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "priority"],
+ "msg": "Field required",
+ "input": {
+ "id": 0,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ },
+ }
+ ]
+ }
+ )
+
+
+### Get TC ID - GET
+def test1_get_case_id():
+ response = read_cases()
+ response.status_code_should_be_eq(200)
+ # response.schema_should_be_eq(Case(**create_case_dict).model_json_schema())
+
+
+def test2_get_case_not_existing_id():
+ """
+ negative - id is not exist
+ """
+ response2 = client.make_request(handle=f"/testcases/455", method="GET")
+ response2.status_code_should_be_eq(404)
+ response2.json_should_be_eq({"detail": "Test case not found."})
+
+
+### To update TC data - PUT
+def test1_update_case():
+ response = update_case()
+ response.status_code_should_be_eq(200)
+ response.json_should_be_eq(
+ {
+ "id": 5,
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ }
+ )
+
+
+def test2_update_case_empty_id():
+ """
+ negative = update to "id": ""
+ """
+ case_id = get_case_id()
+
+ response = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": "",
+ "name": "string",
+ "description": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ response.status_code_should_be_eq(422)
+ response.json_should_be_eq(
+ {
+ "detail": [
+ {
+ "type": "int_parsing",
+ "loc": ["body", "id"],
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
+ "input": "",
+ }
+ ]
+ }
+ )
+
+
+def test3_update_case_missed_description():
+ """
+ negative - description is missing in body update
+ """
+ case_id = get_case_id()
+ response = client.make_request(
+ handle=f"/testcases/{case_id}",
+ method="PUT",
+ json={
+ "id": 2,
+ "name": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ )
+ response.status_code_should_be_eq(422)
+ response.json_should_be_eq(
+ {
+ "detail": [
+ {
+ "type": "missing",
+ "loc": ["body", "description"],
+ "msg": "Field required",
+ "input": {
+ "id": 2,
+ "name": "string",
+ "steps": ["string"],
+ "expected_result": "string",
+ "priority": "низкий",
+ },
+ }
+ ]
+ }
+ )
+
+
+### Delete TC
+def test1_delete_case():
+ response = delete_case()
+ response.status_code_should_be_eq(200)
+ response.json_should_be_eq({"detail": "Test case deleted."})
+
+
+def test2_delete_not_existing_case():
+ """
+ negative - delete not existing case
+ """
+ response2 = client.make_request(
+ handle=f"/testcases/455",
+ method="DELETE",
+ )
+ response2.status_code_should_be_eq(404)
+ response2.json_should_be_eq({"detail": "Test case not found."})
diff --git a/lesson1/api_tests/utils/api_client.py b/lesson1/api_tests/utils/api_client.py
index 1565074..d3a75ce 100644
--- a/lesson1/api_tests/utils/api_client.py
+++ b/lesson1/api_tests/utils/api_client.py
@@ -3,11 +3,11 @@
import allure
import requests
from allure_commons.types import AttachmentType
-from services.config import settings
+from lesson1.api_tests.services.config import settings
from curlify2 import Curlify # Curlify2 работает и с httpx и с requests.
from loguru import logger
from requests import Response
-from utils.api_response import APIResponse
+from lesson1.api_tests.utils.api_response import APIResponse
# Inspired by https://github.com/qa-guru/knowledge-base/wiki/17.-REST-API.-%D0%A7%D0%B0%D1%81%D1%82%D1%8C-II.-%D0%9F%D1%80%D0%BE%D0%B4%D0%BE%D0%BB%D0%B6%D0%B0%D0%B5%D0%BC-%D0%B8%D0%B7%D1%83%D1%87%D0%B0%D1%82%D1%8C
diff --git a/lesson1/api_tests/utils/api_response.py b/lesson1/api_tests/utils/api_response.py
index 7e14a90..cfdcbc4 100644
--- a/lesson1/api_tests/utils/api_response.py
+++ b/lesson1/api_tests/utils/api_response.py
@@ -10,13 +10,13 @@ def __init__(self, response: Response):
def status_code_should_be_eq(self, expected_status):
assert (
- self.response.status_code == expected_status
+ self.response.status_code == expected_status
), f"Ожидали {expected_status}, но получили {self.response.status_code}"
return self
def len_of_json_should_be_eq(self, expected_len):
assert (
- len(self.response.json()) == expected_len
+ len(self.response.json()) == expected_len
), f"Ожидали {expected_len}, но получили {len(self.response.json())}"
return self
@@ -116,6 +116,6 @@ def get_value_with_key(self, key_name):
def should_be_eq(self, expected_value):
assert (
- self._current_value == expected_value
+ self._current_value == expected_value
), f"Ожидали {expected_value}, но получили {self._current_value}"
return self
diff --git a/lesson2/requirements.txt b/lesson2/requirements.txt
index 537ba9d..d5fdcb6 100644
--- a/lesson2/requirements.txt
+++ b/lesson2/requirements.txt
@@ -1,4 +1,24 @@
+attrs==24.2.0
+certifi==2024.8.30
+Faker==32.1.0
+h11==0.14.0
+idna==3.10
+iniconfig==2.0.0
+loguru==0.7.2
+outcome==1.3.0.post0
+packaging==24.2
+pluggy==1.5.0
+PySocks==1.7.1
pytest==8.3.3
+python-dateutil==2.9.0.post0
ruff==0.7.1
selenium==4.25.0
-loguru==0.7.2
\ No newline at end of file
+six==1.16.0
+sniffio==1.3.1
+sortedcontainers==2.4.0
+trio==0.27.0
+trio-websocket==0.11.1
+typing_extensions==4.12.2
+urllib3==2.2.3
+websocket-client==1.8.0
+wsproto==1.2.0
diff --git a/lesson2/simple_example.py b/lesson2/simple_example.py
index ba92fed..22dd944 100644
--- a/lesson2/simple_example.py
+++ b/lesson2/simple_example.py
@@ -1,9 +1,17 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
+import time
browser = webdriver.Chrome()
browser.get("http://195.133.27.184/")
+
+time.sleep(4)
+
+
element = browser.find_element(By.XPATH, "//a[@href='/2/']")
+element.is_displayed()
+# element.click()
+# assert browser.current_url == "http://195.133.27.184/2/", "Wrong URL"
element.click()
assert browser.current_url == "http://195.133.27.184/3/", "Wrong URL"
\ No newline at end of file
diff --git a/lesson3/__init__.py b/lesson3/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lesson3/example1/tests/test_example.py b/lesson3/example1/tests/test_example.py
index e1a0475..f30be9b 100644
--- a/lesson3/example1/tests/test_example.py
+++ b/lesson3/example1/tests/test_example.py
@@ -1,7 +1,9 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
+
def test_visible_after_with_explicit_waits_with_selenium(driver, wait):
driver.get('https://demoqa.com/dynamic-properties')
- visible_after_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']")))
+ visible_after_button = wait.until(
+ EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']")))
assert visible_after_button.text == 'Visible After 5 Seconds'
diff --git a/lesson3/example2/tests/test_example.py b/lesson3/example2/tests/test_example.py
index a87eb5b..f79ea8f 100644
--- a/lesson3/example2/tests/test_example.py
+++ b/lesson3/example2/tests/test_example.py
@@ -4,4 +4,4 @@
def test_visible_after_with_explicit_waits_with_selene():
browser.open('https://demoqa.com/dynamic-properties')
browser.element('//button[text()="Visible After 5 Seconds"]'). \
- should(have.exact_text('Visible After 5 Secon'))
\ No newline at end of file
+ should(have.exact_text('Visible After 5 Seconds'))
diff --git a/lesson3/example3/tests/test_example.py b/lesson3/example3/tests/test_example.py
index dce255b..eb79288 100644
--- a/lesson3/example3/tests/test_example.py
+++ b/lesson3/example3/tests/test_example.py
@@ -1,5 +1,16 @@
-from playwright.sync_api import Page, expect
+from playwright.sync_api import Page, expect, sync_playwright
+
def test_visible_after_with_explicit_waits_with_playwright(page: Page):
page.goto('https://demoqa.com/dynamic-properties')
- expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds')
\ No newline at end of file
+ expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds')
+
+
+def test_my_visible_after_with_explicit_waits_with_playwright():
+ with sync_playwright() as p:
+ browser = p.chromium.launch(headless=False)
+ page = browser.new_page()
+ page.goto('https://demoqa.com/dynamic-properties')
+ expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds',
+ timeout=15000)
+ browser.close()
diff --git a/lesson3/requirements.txt b/lesson3/requirements.txt
index 5a0b33c..87845cc 100644
--- a/lesson3/requirements.txt
+++ b/lesson3/requirements.txt
@@ -3,11 +3,13 @@ allure-python-commons==2.13.5
attrs==24.2.0
certifi==2024.8.30
charset-normalizer==3.4.0
+Faker==32.1.0
future==1.0.0
greenlet==3.1.1
h11==0.14.0
idna==3.10
iniconfig==2.0.0
+loguru==0.7.2
outcome==1.3.0.post0
packaging==24.1
playwright==1.48.0
@@ -17,10 +19,13 @@ PySocks==1.7.1
pytest==8.3.3
pytest-base-url==2.1.0
pytest-playwright==0.5.2
+python-dateutil==2.9.0.post0
python-slugify==8.0.4
requests==2.32.3
+ruff==0.7.1
selene==2.0.0rc9
selenium==4.26.1
+six==1.16.0
sniffio==1.3.1
sortedcontainers==2.4.0
text-unidecode==1.3
diff --git a/lesson3/waits/__init__.py b/lesson3/waits/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lesson3/waits/hw3/__init__.py b/lesson3/waits/hw3/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lesson3/waits/hw3/selenium/__init__.py b/lesson3/waits/hw3/selenium/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lesson3/waits/hw3/selenium/test_wait_expl.py b/lesson3/waits/hw3/selenium/test_wait_expl.py
new file mode 100644
index 0000000..84ff61a
--- /dev/null
+++ b/lesson3/waits/hw3/selenium/test_wait_expl.py
@@ -0,0 +1,72 @@
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium import webdriver
+from selenium.webdriver.chrome.options import Options
+import pytest
+
+
+@pytest.fixture
+def chrome_options():
+ options = Options()
+ options.add_argument("--incognito")
+ options.add_argument("--window-size=1920,1080")
+ return options
+
+
+@pytest.fixture
+def driver(chrome_options):
+ driver = webdriver.Chrome(options=chrome_options)
+ yield driver
+ driver.quit()
+
+
+@pytest.fixture
+def wait(driver):
+ wait = WebDriverWait(driver, timeout=10)
+ return wait
+
+
+def test_registration(driver, wait):
+ # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/
+ # Проверить заголовок: Убедиться, что текст в теге
+ driver.get("https://victoretc.github.io/selenium_waits/")
+ title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']")
+ assert title.text == 'Практика с ожиданиями в Selenium'
+
+ # Дождаться появления кнопки "Начать тестирование"
+ # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование".
+ begin_test_btn = wait.until(EC.visibility_of_element_located((By.XPATH, "//button[@id='startTest']")))
+ assert begin_test_btn.is_displayed()
+ assert begin_test_btn.text == 'Начать тестирование'
+
+ # Кликнуть по кнопке "Начать тестирование".
+ begin_test_btn.click()
+ login = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[@for='login']")))
+
+ assert login.is_displayed()
+
+ # Ввести "login" в поле для логина.
+ login_field = driver.find_element(By.XPATH, "//*[@id='login']")
+ login_field.send_keys("email")
+
+ # Ввести "password" в поле для пароля.
+ password_field = driver.find_element(By.XPATH, "//*[@id='password']")
+ password_field.send_keys("password")
+
+ # Установить флажок в чекбокс "Согласен со всеми правилами".
+ check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']")
+ check_box_agree.click()
+
+ # Нажать кнопку "Зарегистрироваться".
+ registration_btn = driver.find_element(By.XPATH, "//*[@id='register']")
+ registration_btn.click()
+
+ # Удостовериться, что появился индикатор загрузки.
+ loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']")
+ assert loader_indicator.is_displayed()
+
+ # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы".
+ success_registration = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[@id='successMessage']")))
+ assert success_registration.is_displayed()
+ assert success_registration.text == 'Вы успешно зарегистрированы!'
diff --git a/lesson3/waits/hw3/selenium/test_wait_impl.py b/lesson3/waits/hw3/selenium/test_wait_impl.py
new file mode 100644
index 0000000..fe346cd
--- /dev/null
+++ b/lesson3/waits/hw3/selenium/test_wait_impl.py
@@ -0,0 +1,116 @@
+import time
+
+from selenium.webdriver.common.by import By
+from selenium import webdriver
+from selenium.webdriver.chrome.options import Options
+import pytest
+
+
+@pytest.fixture
+def chrome_options():
+ options = Options()
+ options.add_argument("--incognito")
+ options.add_argument("--window-size=1920,1080")
+ return options
+
+
+@pytest.fixture
+def driver(chrome_options):
+ driver = webdriver.Chrome(options=chrome_options)
+ driver.implicitly_wait(10)
+ yield driver
+ driver.quit()
+
+
+def test_registration(driver):
+ # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/
+ # Проверить заголовок: Убедиться, что текст в теге
+ driver.get("https://victoretc.github.io/selenium_waits/")
+ title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']")
+ assert title.text == 'Практика с ожиданиями в Selenium'
+
+ # Дождаться появления кнопки "Начать тестирование"
+ # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование".
+ # Кликнуть по кнопке "Начать тестирование".
+ start_test_btn = driver.find_element(By.XPATH, "//button[@id='startTest']")
+ start_test_btn.click()
+
+ login = driver.find_element(By.XPATH, "//*[@for='login']")
+ assert login.is_displayed()
+
+ # Ввести "login" в поле для логина.
+ login_field = driver.find_element(By.XPATH, "//*[@id='login']")
+ login_field.send_keys("email")
+
+ # Ввести "password" в поле для пароля.
+ password_field = driver.find_element(By.XPATH, "//*[@id='password']")
+ password_field.send_keys("password")
+
+ # Установить флажок в чекбокс "Согласен со всеми правилами".
+ check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']")
+ check_box_agree.click()
+
+ # Нажать кнопку "Зарегистрироваться".
+ registration_btn = driver.find_element(By.XPATH, "//*[@id='register']")
+ registration_btn.click()
+
+ # Удостовериться, что появился индикатор загрузки.
+ loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']")
+ assert loader_indicator.is_displayed()
+
+ time.sleep(5)
+
+ # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы".
+ success_registration = driver.find_element(By.XPATH, "//*[@id='successMessage']")
+ assert success_registration.is_displayed()
+ assert success_registration.text == 'Вы успешно зарегистрированы!'
+
+
+def test_registration1(driver):
+ try:
+ # 1. Переходим на сайт
+ driver.get('https://victoretc.github.io/selenium_waits/')
+
+ # 2. Проверяем заголовок страницы
+ assert "Практика Selenium" in driver.title, "Заголовок страницы не совпадает"
+
+ # 3. Ждем появления кнопки "Начать тестирование"
+ # Убедимся, что кнопка присутствует на странице
+ start_testing_button = driver.find_element(By.XPATH, "//button[text()='Начать тестирование']")
+
+ # 4. Кликаем по кнопке "Начать тестирование"
+ start_testing_button.click()
+
+ # 5. Вводим логин в поле для логина
+ login_field = driver.find_element(By.XPATH, "//*[@id='login']")
+ login_field.send_keys('login')
+
+ # 6. Вводим пароль в поле для пароля
+ password_field = driver.find_element(By.XPATH, "//*[@id='password']")
+ password_field.send_keys('password')
+
+ # 7. Устанавливаем флажок "Согласен со всеми правилами"
+ agree_checkbox = driver.find_element(By.XPATH, "//*[@id='agree']")
+ if not agree_checkbox.is_selected():
+ agree_checkbox.click()
+
+ # 8. Нажимаем кнопку "Зарегистрироваться"
+ register_button = driver.find_element(By.XPATH, "//*[@id='register']")
+ register_button.click()
+
+ # 9. Проверяем наличие индикатора загрузки
+ loading_indicator = driver.find_element(By.XPATH, "//*[@id='loader']") # Пример ID для индикатора
+ assert loading_indicator.is_displayed(), "Индикатор загрузки не отображается"
+
+ # 10. Ждем завершения загрузки и появления сообщения о успешной регистрации
+ time.sleep(5) # Ожидаем, что индикатор загрузки исчезнет
+
+ # 11. Проверяем сообщение о успешной регистрации
+ success_message = driver.find_element(By.XPATH, "//*[@id='successMessage']")
+ assert success_message.is_displayed(), "Сообщение об успешной регистрации не появилось"
+
+ print("Тест прошел успешно!")
+
+ finally:
+ # Закрываем браузер
+ driver.quit()
diff --git a/lesson3/waits/hw3/selenium/test_wait_time_sleep.py b/lesson3/waits/hw3/selenium/test_wait_time_sleep.py
new file mode 100644
index 0000000..2682515
--- /dev/null
+++ b/lesson3/waits/hw3/selenium/test_wait_time_sleep.py
@@ -0,0 +1,53 @@
+import time
+from selenium.webdriver.common.by import By
+
+
+def test_registration(driver):
+ # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/
+ # Проверить заголовок: Убедиться, что текст в теге
+ driver.get("https://victoretc.github.io/selenium_waits/")
+ title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']")
+ assert title.text == 'Практика с ожиданиями в Selenium'
+ time.sleep(5)
+
+ # Дождаться появления кнопки "Начать тестирование"
+ # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование".
+ begin_test_btn = driver.find_element(By.XPATH, "//button[@id='startTest']")
+ assert begin_test_btn.is_displayed()
+ assert begin_test_btn.text == 'Начать тестирование'
+
+ # Кликнуть по кнопке "Начать тестирование".
+ begin_test_btn.click()
+ time.sleep(5)
+ login = driver.find_element(By.XPATH, "//*[@for='login']")
+ assert login.is_displayed()
+
+ # Ввести "login" в поле для логина.
+ login_field = driver.find_element(By.XPATH, "//*[@id='login']")
+ login_field.send_keys("email")
+ time.sleep(3)
+
+ # Ввести "password" в поле для пароля.
+ password_field = driver.find_element(By.XPATH, "//*[@id='password']")
+ password_field.send_keys("password")
+ time.sleep(3)
+
+ # Установить флажок в чекбокс "Согласен со всеми правилами".
+ check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']")
+ check_box_agree.click()
+ time.sleep(3)
+
+ # Нажать кнопку "Зарегистрироваться".
+ registration_btn = driver.find_element(By.XPATH, "//*[@id='register']")
+ registration_btn.click()
+ time.sleep(2)
+
+ # Удостовериться, что появился индикатор загрузки.
+ loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']")
+ assert loader_indicator.is_displayed()
+ time.sleep(5)
+
+ # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы".
+ success_registration = driver.find_element(By.XPATH, "//*[@id='successMessage']")
+ assert success_registration.is_displayed()
+ assert success_registration.text == 'Вы успешно зарегистрированы!'
diff --git a/lesson3/waits/hw3/selenium/test_waits_practice.py b/lesson3/waits/hw3/selenium/test_waits_practice.py
new file mode 100644
index 0000000..e08df42
--- /dev/null
+++ b/lesson3/waits/hw3/selenium/test_waits_practice.py
@@ -0,0 +1,147 @@
+import time
+import requests
+
+import pytest
+from selenium.webdriver.chrome.options import Options
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.wait import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+
+@pytest.fixture
+def chrome_options():
+ options = Options()
+ options.add_argument("--window-size=1900x1000")
+ return options
+
+
+@pytest.fixture
+def driver(chrome_options):
+ driver = webdriver.Chrome(options=chrome_options)
+ driver.implicitly_wait(10)
+ yield driver
+ driver.quit()
+
+
+@pytest.fixture
+def wait(driver):
+ wait = WebDriverWait(driver, timeout=10)
+ return wait
+
+
+def test1(driver, wait):
+ driver.get("https://www.selenium.dev/selenium/web/dynamic.html")
+ add_box_locator = "//*[@value = 'Add a box!']"
+ box_locator = "//div[contains(@id, 'box')]"
+
+ add_box = wait.until(EC.visibility_of_element_located((By.XPATH, add_box_locator)))
+ assert add_box.is_displayed()
+ assert add_box.get_attribute("value") == 'Add a box!'
+
+ lst = []
+ add_box.click()
+ box = wait.until(EC.visibility_of_element_located((By.XPATH, box_locator)))
+ lst.append(box)
+ count = 1
+
+ add_box.click()
+ lst.append(box)
+ count += 1
+ assert len(lst) == count
+
+
+def test2(driver, wait):
+ driver.get("https://demoqa.com/dynamic-properties")
+ will_enable_5sec_locator = "//*[@id = 'enableAfter']"
+
+ will_enable_5sec_btn = wait.until(EC.visibility_of_element_located((By.XPATH, will_enable_5sec_locator)))
+ assert will_enable_5sec_btn.is_displayed()
+
+
+def test3(driver, wait):
+ driver.get("https://the-internet.herokuapp.com/dynamic_loading")
+ assert driver.title == "The Internet"
+
+ hidden_element_locator = "//*[contains(text(), 'Element on page that is hidden')]"
+ start_btn_locator = "//*[contains(text(), 'Start')]"
+ loading_indicator_locator = "//*[@id = 'loading']"
+ hello_world_locator = "//*[contains(text(), 'Hello World!')]"
+
+ hidden_element = wait.until(EC.element_to_be_clickable((By.XPATH, hidden_element_locator)))
+ hidden_element.click()
+
+ start_btn = wait.until(EC.element_to_be_clickable((By.XPATH, start_btn_locator)))
+ assert start_btn.is_enabled()
+ start_btn.click()
+
+ loading_indicator = wait.until(EC.visibility_of_element_located((By.XPATH, loading_indicator_locator)))
+ assert loading_indicator.is_displayed()
+
+ hello_world = wait.until(EC.visibility_of_element_located((By.XPATH, hello_world_locator)))
+ assert hello_world.is_displayed()
+
+
+# 1. (Необходимо создать и удалить элемент)
+def test4(driver, wait):
+ driver.get("https://the-internet.herokuapp.com/add_remove_elements/")
+ add_element_btn_locator = "//*[@onclick= 'addElement()']"
+ delete_btn_locator = "//*[@onclick= 'deleteElement()']"
+ add_element = wait.until(EC.element_to_be_clickable((By.XPATH, add_element_btn_locator)))
+ add_element.click()
+ delete_btn = wait.until(EC.element_to_be_clickable((By.XPATH, delete_btn_locator)))
+ delete_btn.click()
+ assert wait.until(EC.invisibility_of_element_located((By.XPATH, delete_btn_locator)))
+
+
+# 2. (Необходимо пройти базовую авторизацию)
+# (NOT CLEAR)
+def test5(driver, wait):
+ username = "admin"
+ password = "admin"
+
+ url = f"http://{username}:{password}@the-internet.herokuapp.com/basic_auth"
+ title_locator = "//*[text()='Basic Auth']"
+
+ driver.get(url)
+ time.sleep(2)
+ title = wait.until(EC.visibility_of_element_located((By.XPATH, title_locator)))
+ assert title.text == "Basic Auth"
+
+
+# 3. (Необходимо найти сломанные изображения)
+# (NOT CLEAR)
+def test6(driver, wait):
+ driver.get("https://the-internet.herokuapp.com/broken_images")
+
+ image_locator = "//div/img"
+ images = wait.until(EC.visibility_of_all_elements_located((By.XPATH, image_locator)))
+
+ broken_images = []
+
+ for i in images:
+ src = i.get_attribute("src")
+
+ response = requests.get(src)
+ if response.status_code != 200 or response.status_code == 404:
+ broken_images.append(src)
+
+ assert len(broken_images) == 2
+
+
+# 4. (Практика с чек боксами)
+def test7(driver, wait):
+ driver.get("https://the-internet.herokuapp.com/checkboxes")
+
+ check_boxs_locator = "//*[@type = 'checkbox']"
+ check_boxs = wait.until(EC.visibility_of_all_elements_located((By.XPATH, check_boxs_locator)))
+
+ for check_box in check_boxs:
+ if not check_box.is_selected():
+ check_box.click()
+ assert check_box.is_selected()
+
+ for check_box in check_boxs:
+ check_box.click()
+ assert not check_box.is_selected()
+ time.sleep(2)
diff --git a/lesson3/waits/test_expl.py b/lesson3/waits/test_expl.py
index 2ca066a..a24801e 100644
--- a/lesson3/waits/test_expl.py
+++ b/lesson3/waits/test_expl.py
@@ -1,3 +1,4 @@
+# Явные ожидания
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
@@ -5,28 +6,28 @@
from selenium.webdriver.support import expected_conditions as EC
import pytest
+
@pytest.fixture
def chrome_options():
options = Options()
options.add_argument('--start-maximized')
return options
+
@pytest.fixture
def driver(chrome_options):
driver = webdriver.Chrome(options=chrome_options)
return driver
+
@pytest.fixture
def wait(driver):
wait = WebDriverWait(driver, timeout=10)
return wait
+
def test_visible_after_with_explicit_waits(driver, wait):
driver.get('https://demoqa.com/dynamic-properties')
- visible_after_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']")))
+ visible_after_button = wait.until(
+ EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']")))
assert visible_after_button.text == 'Visible After 5 Seconds'
-
-
-
-
-
diff --git a/lesson3/waits/test_impl.py b/lesson3/waits/test_impl.py
index 2db0c4a..a62c723 100644
--- a/lesson3/waits/test_impl.py
+++ b/lesson3/waits/test_impl.py
@@ -1,14 +1,17 @@
+# неявные ожидания
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import pytest
+
@pytest.fixture
def chrome_options():
options = Options()
options.add_argument('--start-maximized')
return options
+
@pytest.fixture
def driver(chrome_options):
driver = webdriver.Chrome(options=chrome_options)
@@ -16,12 +19,20 @@ def driver(chrome_options):
yield driver
driver.quit()
+
def test_visible_after_with_implicit_wait(driver):
driver.get('https://demoqa.com/dynamic-properties')
vissible_after_button = driver.find_element(By.XPATH, "//button[text()='Visible After 5 Seconds']")
assert vissible_after_button.is_displayed()
+def test_will_enable_5sec_implicit_wait(driver):
+ driver.get('https://demoqa.com/dynamic-properties')
+ will_enable_5_sec = driver.find_element(By.XPATH, "//*[@id='enableAfter']")
+ assert will_enable_5_sec.is_displayed()
-
+def test_color_change_btn_implicit_wait(driver):
+ driver.get('https://demoqa.com/dynamic-properties')
+ color_change_btn = driver.find_element(By.XPATH, "//button[@id='colorChange']")
+ assert color_change_btn.is_displayed()
diff --git a/lesson4/__init__.py b/lesson4/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lesson4/components/header.py b/lesson4/components/header.py
index 65d84e2..53a8df8 100644
--- a/lesson4/components/header.py
+++ b/lesson4/components/header.py
@@ -1,17 +1,23 @@
from selene import by, be, have, browser
-from core.settings import settings
+from lesson4.core.settings import settings
+import allure
+
+@allure.step("Открываем Хэдер на главной странице")
def visit():
browser.open('/')
+@allure.step("Проверяем открытие Хэдера")
def should_be_opened():
browser.should(have.url(settings.base_url))
+@allure.step("Открываем фщрму регистрации")
def open_registration_component():
browser.element(by.text('Регистрация')).click()
+@allure.step("Проверяем видимость кнопки создания объявления")
def create_post_button_should_be_visible():
- browser.element(by.text('Создать объявление')).should(be.visible)
\ No newline at end of file
+ browser.element(by.text('Создать объявление')).should(be.visible)
diff --git a/lesson4/components/register.py b/lesson4/components/register.py
index b79ace1..ee426bf 100644
--- a/lesson4/components/register.py
+++ b/lesson4/components/register.py
@@ -1,40 +1,39 @@
from selene import be, have, browser
+import allure
+@allure.step("Открываем форму регистрации")
def visit():
browser.open('/signup/')
+@allure.step("Проверяем открытие формы регистрации")
def should_be_opened():
browser.should(have.url('/signup/'))
+@allure.step("Вводим логин")
def type_login(login):
browser.element('#id_username').type(login)
+@allure.step("Вводим пароль")
def type_password(password):
browser.element('#id_password1').type(password)
+@allure.step("Вводим подтверждение пароля")
def type_confirm_password(password):
browser.element('#id_password2').type(password)
+@allure.step("Выбираем роль учителя")
def choose_tutor_role():
checkbox = browser.element('#id_is_tutor')
checkbox.click()
checkbox.should(be.selected)
+@allure.step("Нажимаем кнопку регистрации")
def click_register_button():
browser.element('button[type="submit"]').click()
-
-
-
-
-
-
-
-
-
diff --git a/lesson4/core/settings.py b/lesson4/core/settings.py
index 15280a3..d076dcc 100644
--- a/lesson4/core/settings.py
+++ b/lesson4/core/settings.py
@@ -1,4 +1,8 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
+import os
+from dotenv import load_dotenv
+
+load_dotenv()
class Settings(BaseSettings):
@@ -12,3 +16,4 @@ class Settings(BaseSettings):
settings = Settings()
+# settings = Settings(base_url="http://195.133.27.184/", register_password="Pknewbkj1212234112****")
diff --git a/lesson4/pytest.ini b/lesson4/pytest.ini
index a06f653..dadbce1 100644
--- a/lesson4/pytest.ini
+++ b/lesson4/pytest.ini
@@ -1,3 +1,8 @@
[pytest]
-addopts = -s -vv --alluredir=allure-results --clean-alluredir
\ No newline at end of file
+addopts = -s -vv --alluredir=allure-results --clean-alluredir
+
+
+# посмотреть репорт allure serve
+
+# почистить алюр rm -r allure-result
\ No newline at end of file
diff --git a/lesson4/requirements.txt b/lesson4/requirements.txt
index 5c407df..2bcb0e1 100644
--- a/lesson4/requirements.txt
+++ b/lesson4/requirements.txt
@@ -1,23 +1,39 @@
allure-pytest==2.13.5
allure-python-commons==2.13.5
+annotated-types==0.7.0
attrs==24.2.0
certifi==2024.8.30
+charset-normalizer==3.4.0
Faker==30.8.2
future==1.0.0
+greenlet==3.1.1
h11==0.14.0
idna==3.10
iniconfig==2.0.0
+loguru==0.7.2
outcome==1.3.0.post0
packaging==24.2
+playwright==1.48.0
pluggy==1.5.0
+pydantic==2.9.2
+pydantic-settings==2.6.1
+pydantic_core==2.23.4
+pyee==12.0.0
PySocks==1.7.1
pytest==8.3.3
+pytest-base-url==2.1.0
+pytest-playwright==0.5.2
python-dateutil==2.9.0.post0
+python-dotenv==1.0.1
+python-slugify==8.0.4
+requests==2.32.3
+ruff==0.7.1
selene==2.0.0rc9
selenium==4.26.1
six==1.16.0
sniffio==1.3.1
sortedcontainers==2.4.0
+text-unidecode==1.3
trio==0.27.0
trio-websocket==0.11.1
typing_extensions==4.12.2
diff --git a/lesson4/tests/conftest.py b/lesson4/tests/conftest.py
index cb42485..098d201 100644
--- a/lesson4/tests/conftest.py
+++ b/lesson4/tests/conftest.py
@@ -2,11 +2,11 @@
from selene import browser, support
from selenium import webdriver
import allure_commons
-import allure
+import allure
+
@pytest.fixture(autouse=True)
def browser_management():
-
options = webdriver.ChromeOptions()
# options.add_argument('--headless')
browser.config.driver_options = options
@@ -18,7 +18,7 @@ def browser_management():
browser.config._wait_decorator = support._logging.wait_with(
context=allure_commons._allure.StepContext
)
-
+
yield
allure.attach(
diff --git a/lesson4/tests/test_register.py b/lesson4/tests/test_register.py
index 0fe644b..7c974f4 100644
--- a/lesson4/tests/test_register.py
+++ b/lesson4/tests/test_register.py
@@ -1,8 +1,12 @@
+from lesson4.components import header, register
+from lesson4.core.settings import settings
+import allure
from faker import Faker
+
fake = Faker()
-from components import header, register
-from core.settings import settings
+
+@allure.title("Регистрация")
def test_register():
# main page
header.visit()