Files
site_aegisone/py_service/tests/test_03_crud_operations.py
T
angel bd048ea23d v1.5.4: test infrastructure + bug fixes + CI/CD + deploy gate
- 6 new test files: route discovery, strict permissions, role switch,
  CRUD operations, 500 error protection
- permission_config.py: central permission definitions for all 110+ routes
- Bug fixes: is_active checkbox in users_edit, int(id) 500 crash,
  missing validation in users_create/users_delete
- Pre-commit hooks: lint + static routing tests
- GitHub Actions CI: full pytest suite on push
- Deploy gate: pytest runs before deploy, aborts on failure
- All 3 deploy scripts: --skip-tests flag support
2026-05-22 20:45:27 +03:00

176 lines
6.4 KiB
Python

"""CRUD operation tests — create, edit, delete for all entities.
Each test creates a unique entity, verifies the operation returns a redirect,
and cleans up where possible. No HTML parsing — just HTTP status checks.
"""
import pytest
import time
class TestUserCRUD:
ID = None
def test_create_user(self, owner_client):
ts = int(time.time() * 1000)
resp = owner_client.post("/service/users/create", data={
"login": f"test_user_{ts}",
"password": "TestPass123!",
"full_name": f"Test User {ts}",
"role": "technician",
"phone": "+7-123-456-7890",
"email": f"test_{ts}@example.com",
"is_active": "1",
})
assert resp.status_code == 302, f"Create user failed: {resp.status_code}"
# Follow redirect should succeed
assert resp.headers.get("location") == "/service/users"
def test_edit_user(self, owner_client):
ts = int(time.time() * 1000)
# First create a user to edit
resp = owner_client.post("/service/users/create", data={
"login": f"edit_user_{ts}",
"password": "TestPass123!",
"full_name": f"Edit User {ts}",
"role": "technician",
"is_active": "1",
})
assert resp.status_code == 302
location = resp.headers.get("location", "")
# Extract ID from redirect or use default — the redirect goes to /service/users
# We need the user ID. We'll need to find it from the list page.
# For now, edit by fetching the users page and extracting an ID
resp = owner_client.get("/service/users")
assert resp.status_code == 200
body = resp.text
import re
# Find our user in the HTML to get their ID
# Pattern: <tr data-id="(\d+)">.*edit_user_{ts}
match = re.search(rf"data-id=['\"](\d+)['\"][^>]*>.*?edit_user_{ts}", body, re.DOTALL)
if not match:
# Try alternative pattern: look for the login in a more flexible way
match = re.search(rf"edit_user_{ts}.*?data-id=['\"](\d+)['\"]", body, re.DOTALL)
if match:
user_id = match.group(1)
else:
# Fallback: find any user ID with role technician
match = re.search(r"data-id=['\"](\d+)['\"]", body)
if not match:
pytest.skip("Could not find a user to edit")
user_id = match.group(1)
resp = owner_client.post("/service/users/edit", data={
"id": user_id,
"full_name": f"Updated User {ts}",
"role": "technician",
"phone": "+7-999-888-7766",
"email": f"updated_{ts}@example.com",
"is_active": "1",
})
assert resp.status_code == 302, f"Edit user returned {resp.status_code}"
def test_delete_user(self, owner_client):
ts = int(time.time() * 1000)
# Create user to delete
resp = owner_client.post("/service/users/create", data={
"login": f"del_user_{ts}",
"password": "TestPass123!",
"full_name": f"Delete User {ts}",
"role": "technician",
"is_active": "1",
})
assert resp.status_code == 302
# Find user ID
resp = owner_client.get("/service/users")
body = resp.text
import re
match = re.search(rf"data-id=['\"](\d+)['\"][^>]*>.*?del_user_{ts}", body, re.DOTALL)
if not match:
match = re.search(rf"del_user_{ts}.*?data-id=['\"](\d+)['\"]", body, re.DOTALL)
if match:
user_id = match.group(1)
resp = owner_client.post("/service/users/delete", data={"id": user_id})
assert resp.status_code == 302
class TestCustomerCRUD:
def test_create_customer(self, owner_client):
ts = int(time.time() * 1000)
inn = str(1000000000 + (ts % 8999999999))
resp = owner_client.post("/service/customers/create", data={
"name": f"Test Customer {ts}",
"inn": inn[:10],
})
assert resp.status_code == 302
def test_edit_customer(self, owner_client):
ts = int(time.time() * 1000)
inn = str(1000000000 + (ts % 8999999999))
resp = owner_client.post("/service/customers/create", data={
"name": f"Edit Customer {ts}",
"inn": inn[:10],
})
assert resp.status_code == 302
resp = owner_client.get("/service/customers")
assert resp.status_code == 200
body = resp.text
import re
match = re.search(rf"data-id=['\"](\d+)['\"]", body)
if match:
cid = match.group(1)
resp = owner_client.post("/service/customers/edit", data={
"id": cid,
"name": f"Updated Customer {ts}",
"inn": inn[:10],
})
assert resp.status_code == 302
class TestBlogCRUD:
def test_create_blog_post(self, owner_client):
ts = int(time.time() * 1000)
resp = owner_client.post("/service/blog/create", data={
"title": f"Test Blog Post {ts}",
"content": f"Content for test blog post {ts}",
})
assert resp.status_code == 302
def test_edit_blog_post(self, owner_client):
ts = int(time.time() * 1000)
resp = owner_client.post("/service/blog/create", data={
"title": f"Edit Blog Post {ts}",
"content": f"Content {ts}",
})
assert resp.status_code == 302
resp = owner_client.get("/service/blog")
assert resp.status_code == 200
body = resp.text
import re
match = re.search(rf"Edit Blog Post {ts}.*?data-id=['\"](\d+)['\"]", body, re.DOTALL)
if match:
post_id = match.group(1)
resp = owner_client.post("/service/blog/edit", data={
"id": post_id,
"title": f"Updated Blog Post {ts}",
"content": f"Updated content {ts}",
})
assert resp.status_code == 302
class TestQuestionnaireConfigCRUD:
def test_create_questionnaire_config(self, owner_client):
ts = int(time.time() * 1000)
resp = owner_client.post("/service/questionnaire-config/create", data={
"key": f"test_key_{ts}",
"label": f"Test Label {ts}",
"question_text": f"Test question? {ts}",
})
assert resp.status_code == 302