init here

This commit is contained in:
2025-11-26 21:32:41 +03:00
commit 33c97acade
91 changed files with 9155 additions and 0 deletions

View File

View File

@@ -0,0 +1,25 @@
TEST_NAME = "users:create teacher"
def run(context) -> None:
payload = {
context.K_FIRST_NAME: context.teacher_first,
context.K_LAST_NAME: context.teacher_last,
context.K_MIDDLE_NAME: context.teacher_middle,
context.K_EDUCATION: context.teacher_education,
context.K_PASSWORD: context.teacher_password,
context.K_CONFIRM_PASSWORD: context.teacher_password,
}
status, body, _ = context.send_request("POST", "/api/users", body=payload)
context.expect(status == 201, f"expected 201, got {status}, body={body!r}")
user_id = context.query_single_value(
"SELECT id FROM users WHERE username = ?",
(context.teacher_username,),
)
context.teacher_user_id = user_id
teacher_id = context.query_single_value(
"SELECT id FROM teachers WHERE user_id = ?",
(user_id,),
)
context.expect(teacher_id > 0, "teacher id must be positive")
context.teacher_id = teacher_id

View File

@@ -0,0 +1,18 @@
TEST_NAME = "users:create mismatch"
def run(context) -> None:
payload = {
context.K_FIRST_NAME: "Bob",
context.K_LAST_NAME: "Doe",
context.K_MIDDLE_NAME: "Ray",
context.K_EDUCATION: "History",
context.K_PASSWORD: "OnePass",
context.K_CONFIRM_PASSWORD: "OtherPass",
}
status, body, _ = context.send_request("POST", "/api/users", body=payload)
context.expect(status == 400, f"expected 400, got {status}")
context.expect(
context.MESSAGE_PASSWORD_MISMATCH in body,
"expected mismatch message",
)

View File

@@ -0,0 +1,18 @@
TEST_NAME = "users:login success"
def run(context) -> None:
payload = {
context.K_USERNAME: context.teacher_username,
context.K_PASSWORD: context.teacher_password,
}
status, body, _ = context.send_request(
"POST",
"/api/users/login",
body=payload,
)
context.expect(status == 200, f"expected 200, got {status}")
context.expect(
body == context.MESSAGE_LOGIN_OK,
f"unexpected login body: {body!r}",
)

View File

@@ -0,0 +1,14 @@
TEST_NAME = "users:login failure"
def run(context) -> None:
payload = {
context.K_USERNAME: context.teacher_username,
context.K_PASSWORD: "WrongPass",
}
status, _, _ = context.send_request(
"POST",
"/api/users/login",
body=payload,
)
context.expect(status == 401, f"expected 401, got {status}")

View File

@@ -0,0 +1,16 @@
TEST_NAME = "users:change password"
def run(context) -> None:
payload = {context.K_NEW_PASSWORD: context.teacher_password_new}
status, body, _ = context.send_request(
"PUT",
"/api/users/password",
body=payload,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 204, f"expected 204, got {status}, body={body!r}")
context.teacher_password = context.teacher_password_new

View File

@@ -0,0 +1,18 @@
TEST_NAME = "users:login with new password"
def run(context) -> None:
payload = {
context.K_USERNAME: context.teacher_username,
context.K_PASSWORD: context.teacher_password,
}
status, body, _ = context.send_request(
"POST",
"/api/users/login",
body=payload,
)
context.expect(status == 200, f"expected 200, got {status}")
context.expect(
body == context.MESSAGE_LOGIN_OK,
f"unexpected login body: {body!r}",
)

View File

@@ -0,0 +1,9 @@
TEST_NAME = "teachers:auth required"
def run(context) -> None:
status, _, _ = context.send_request("GET", "/api/classes")
context.expect(status == 401, f"expected 401, got {status}")
payload = {context.K_CLASS_NUMBER: 5, context.K_CLASS_LETTER: "A"}
status, _, _ = context.send_request("POST", "/api/classes", body=payload)
context.expect(status == 401, f"expected 401, got {status}")

View File

@@ -0,0 +1,31 @@
import json
TEST_NAME = "teachers:create class"
def run(context) -> None:
payload = {context.K_CLASS_NUMBER: 5, context.K_CLASS_LETTER: "A"}
status, body, _ = context.send_request(
"POST",
"/api/classes",
body=payload,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}, body={body!r}")
data = json.loads(body)
context.class_id = int(data[context.K_IDENTIFIER])
context.expect(
data[context.K_CLASS_NUMBER] == payload[context.K_CLASS_NUMBER],
"class number mismatch",
)
context.expect(
data[context.K_CLASS_LETTER] == payload[context.K_CLASS_LETTER],
"class letter mismatch",
)
context.expect(
int(data[context.K_CREATOR]) > 0,
"creator id must be positive",
)

View File

@@ -0,0 +1,24 @@
import json
TEST_NAME = "teachers:list classes"
def run(context) -> None:
status, body, _ = context.send_request(
"GET",
"/api/classes",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200, got {status}")
data = json.loads(body)
entries = data.get(context.K_CLASSES, [])
context.expect(
any(
int(item[context.K_IDENTIFIER]) == context.class_id
for item in entries
),
"class not listed",
)

View File

@@ -0,0 +1,19 @@
import json
TEST_NAME = "teachers:create extra class"
def run(context) -> None:
payload = {context.K_CLASS_NUMBER: 6, context.K_CLASS_LETTER: "B"}
status, body, _ = context.send_request(
"POST",
"/api/classes",
body=payload,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}")
data = json.loads(body)
context.class_two_id = int(data[context.K_IDENTIFIER])

View File

@@ -0,0 +1,27 @@
TEST_NAME = "teachers:delete extra class"
def run(context) -> None:
path = f"/api/classes/{context.class_two_id}"
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 204, f"expected 204, got {status}")
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 404,
f"expected 404 on repeated delete, got {status}",
)
context.class_two_id = None

View File

@@ -0,0 +1,33 @@
TEST_NAME = "students:create student"
def run(context) -> None:
status, _, _ = context.send_request("POST", "/api/students", body={})
context.expect(status == 401, f"expected 401, got {status}")
payload = {
context.K_FIRST_NAME: "Charlie",
context.K_LAST_NAME: "Stone",
context.K_MIDDLE_NAME: "Lee",
context.K_PASSWORD: "Student42",
context.K_CONFIRM_PASSWORD: "Student42",
context.K_SNILS: "00011122233",
context.K_PASSPORT: "AB1234567",
}
status, body, _ = context.send_request(
"POST",
"/api/students",
body=payload,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}, body={body!r}")
context.student_one_id = context.query_single_value(
"SELECT id FROM students WHERE snils = ?",
(payload[context.K_SNILS],),
)
context.student_one_username = (
f"{payload[context.K_FIRST_NAME]}.{payload[context.K_LAST_NAME]}"
)
context.student_one_password = payload[context.K_PASSWORD]

View File

@@ -0,0 +1,31 @@
TEST_NAME = "students:create second student"
def run(context) -> None:
payload = {
context.K_FIRST_NAME: "Daisy",
context.K_LAST_NAME: "King",
context.K_MIDDLE_NAME: "May",
context.K_PASSWORD: "Student84",
context.K_CONFIRM_PASSWORD: "Student84",
context.K_SNILS: "99988877766",
context.K_PASSPORT: "CD7654321",
}
status, body, _ = context.send_request(
"POST",
"/api/students",
body=payload,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}, body={body!r}")
context.student_two_id = context.query_single_value(
"SELECT id FROM students WHERE snils = ?",
(payload[context.K_SNILS],),
)
context.student_two_username = (
f"{payload[context.K_FIRST_NAME]}.{payload[context.K_LAST_NAME]}"
)
context.student_two_password = payload[context.K_PASSWORD]

View File

@@ -0,0 +1,32 @@
TEST_NAME = "teachers:add student to class"
def run(context) -> None:
path = f"/api/classes/{context.class_id}/students/{context.student_two_id}"
status, _, _ = context.send_request("POST", path)
context.expect(status == 401, f"expected 401, got {status}")
status, _, _ = context.send_request(
"POST",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}")
invalid_path = (
f"/api/classes/{context.class_id + 999}/students/"
f"{context.student_two_id}"
)
status, _, _ = context.send_request(
"POST",
invalid_path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 403,
f"expected 403 for foreign class, got {status}",
)

View File

@@ -0,0 +1,31 @@
import json
TEST_NAME = "students:list"
def run(context) -> None:
status, _, _ = context.send_request("GET", "/api/students")
context.expect(status == 401, f"expected 401, got {status}")
status, body, _ = context.send_request(
"GET",
"/api/students",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200, got {status}")
data = json.loads(body)
students = data.get("ученики", [])
ids = {int(item[context.K_IDENTIFIER]) for item in students}
context.expect(
context.student_one_id in ids,
"first student missing from list",
)
context.expect(
context.student_two_id in ids,
"second student missing from list",
)

View File

@@ -0,0 +1,48 @@
import json
TEST_NAME = "students:get one"
def run(context) -> None:
path = f"/api/students/{context.student_one_id}"
status, _, _ = context.send_request("GET", path)
context.expect(status == 401, f"expected 401, got {status}")
status, body, _ = context.send_request(
"GET",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200, got {status}")
data = json.loads(body)
context.expect(
int(data[context.K_IDENTIFIER]) == context.student_one_id,
"unexpected student id",
)
context.expect(
data.get(context.K_FIRST_NAME),
"missing student first name",
)
context.expect(
data.get(context.K_LAST_NAME),
"missing student last name",
)
context.expect(
data.get(context.K_USERNAME),
"missing student username",
)
missing_path = f"/api/students/{context.student_two_id + 999}"
status, _, _ = context.send_request(
"GET",
missing_path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 404, f"expected 404, got {status}")

View File

@@ -0,0 +1,39 @@
TEST_NAME = "students:delete"
def run(context) -> None:
path = f"/api/students/{context.student_one_id}"
status, _, _ = context.send_request("DELETE", path)
context.expect(status == 401, f"expected 401, got {status}")
status, _, _ = context.send_request(
"DELETE",
f"/api/students/{context.student_one_id + 999}",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 404, f"expected 404, got {status}")
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 204, f"expected 204, got {status}")
status, _, _ = context.send_request(
"GET",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 404, f"expected 404 after delete, got {status}")
context.student_one_id = None

View File

@@ -0,0 +1,86 @@
import json
TEST_NAME = "lessons:create"
def run(context) -> None:
path = f"/api/classes/{context.class_id}/lessons"
payload_primary = {
"дата": "2025-09-01",
"название": "Алгебра",
"домашнее задание": "Упражнения 1-3",
}
status, _, _ = context.send_request("POST", path, body=payload_primary)
context.expect(status == 401, f"expected 401, got {status}")
status, _, _ = context.send_request(
"POST",
f"/api/classes/{context.class_id + 999}/lessons",
body=payload_primary,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 403,
f"expected 403 for foreign class, got {status}",
)
status, body, _ = context.send_request(
"POST",
path,
body=payload_primary,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 201, f"expected 201, got {status}, body={body!r}")
data = json.loads(body)
context.lesson_first_id = int(data[context.K_IDENTIFIER])
context.lesson_first_date = payload_primary["дата"]
context.lesson_first_title = payload_primary["название"]
context.expect(
int(data["идентификатор класса"]) == context.class_id,
"lesson class mismatch",
)
context.expect(
data["название"] == payload_primary["название"],
"lesson title mismatch",
)
context.expect(
data["дата"] == payload_primary["дата"],
"lesson date mismatch",
)
payload_secondary = {
"дата урока": "2025-09-02",
"тема": "Геометрия",
"домашка": "Читать параграф 4",
}
status, body, _ = context.send_request(
"POST",
path,
body=payload_secondary,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 201,
f"expected 201 for second lesson, got {status}",
)
data = json.loads(body)
context.lesson_second_id = int(data[context.K_IDENTIFIER])
context.lesson_second_date = payload_secondary["дата урока"]
context.lesson_second_title = payload_secondary["тема"]
context.expect(
data["домашнее задание"] == payload_secondary["домашка"],
"secondary homework mismatch",
)

View File

@@ -0,0 +1,80 @@
import json
TEST_NAME = "lessons:list"
def run(context) -> None:
base_path = f"/api/classes/{context.class_id}/lessons"
status, _, _ = context.send_request("GET", base_path)
context.expect(status == 401, f"expected 401, got {status}")
status, body, _ = context.send_request(
"GET",
base_path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200, got {status}")
data = json.loads(body)
lessons = data.get("уроки", [])
context.expect(len(lessons) >= 2, "expected at least two lessons")
def find_lesson(entry_id: int):
for item in lessons:
if int(item[context.K_IDENTIFIER]) == entry_id:
return item
return None
first_entry = find_lesson(context.lesson_first_id)
context.expect(first_entry is not None, "first lesson missing")
context.expect(
first_entry.get("название") == context.lesson_first_title,
"first lesson title mismatch",
)
filter_path = (
f"/api/classes/{context.class_id}/lessons/date/"
f"{context.lesson_first_date}"
)
status, body, _ = context.send_request(
"GET",
filter_path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200 for filter, got {status}")
filtered = json.loads(body).get("уроки", [])
context.expect(
len(filtered) == 1,
f"expected single lesson in filter, got {len(filtered)}",
)
context.expect(
int(filtered[0][context.K_IDENTIFIER]) == context.lesson_first_id,
"filter returned unexpected lesson",
)
student_headers = context.make_auth(
context.student_two_username,
context.student_two_password,
)
status, body, _ = context.send_request(
"GET",
base_path,
headers=student_headers,
)
context.expect(status == 200, f"expected 200 for student, got {status}")
student_view = json.loads(body).get("уроки", [])
context.expect(
any(
int(item[context.K_IDENTIFIER]) == context.lesson_second_id
for item in student_view
),
"student view missing lesson",
)

View File

@@ -0,0 +1,81 @@
import json
TEST_NAME = "lessons:delete"
def run(context) -> None:
path = f"/api/classes/{context.class_id}/lessons/{context.lesson_first_id}"
status, _, _ = context.send_request("DELETE", path)
context.expect(status == 401, f"expected 401, got {status}")
status, _, _ = context.send_request(
"DELETE",
f"/api/classes/{context.class_id + 999}/lessons/"
f"{context.lesson_first_id}",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 403,
f"expected 403 for foreign class, got {status}",
)
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 204, f"expected 204, got {status}")
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 404, f"expected 404 after delete, got {status}")
filter_path = (
f"/api/classes/{context.class_id}/lessons/date/"
f"{context.lesson_first_date}"
)
status, body, _ = context.send_request(
"GET",
filter_path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200 for filter, got {status}")
filtered = json.loads(body).get("уроки", [])
context.expect(len(filtered) == 0, "filter should be empty after delete")
status, body, _ = context.send_request(
"GET",
f"/api/classes/{context.class_id}/lessons",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 200, f"expected 200 for list, got {status}")
remaining = json.loads(body).get("уроки", [])
context.expect(
any(
int(item[context.K_IDENTIFIER]) == context.lesson_second_id
for item in remaining
),
"second lesson missing after delete",
)
context.lesson_first_id = None

View File

@@ -0,0 +1,55 @@
TEST_NAME = "teachers:remove student from class"
def run(context) -> None:
path = f"/api/classes/{context.class_id}/students/{context.student_two_id}"
status, _, _ = context.send_request("DELETE", path)
context.expect(status == 401, f"expected 401, got {status}")
status, _, _ = context.send_request(
"DELETE",
f"/api/classes/{context.class_id + 999}/students/"
f"{context.student_two_id}",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 403,
f"expected 403 for foreign class, got {status}",
)
status, _, _ = context.send_request(
"DELETE",
f"/api/classes/{context.class_id}/students/"
f"{context.student_two_id + 999}",
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(
status == 404,
f"expected 404 for foreign student, got {status}",
)
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 204, f"expected 204, got {status}")
status, _, _ = context.send_request(
"DELETE",
path,
headers=context.make_auth(
context.teacher_username,
context.teacher_password,
),
)
context.expect(status == 404, f"expected 404 after removal, got {status}")