fix: add ensure_ldap_disabled to 71 tests to prevent LDAP sync issues
This commit is contained in:
parent
a335594932
commit
fcf4bff3a9
126
backend/scripts/fix_ldap_tests.py
Normal file
126
backend/scripts/fix_ldap_tests.py
Normal file
@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Скрипт для массового добавления ensure_ldap_disabled fixture к тестам.
|
||||
|
||||
Добавляет параметр ensure_ldap_disabled к функциям тестов, которые:
|
||||
- Создают объекты через Department.objects.create()
|
||||
- Создают объекты через Position.objects.create()
|
||||
- Не имеют уже ensure_ldap_disabled или ensure_ldap_enabled
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def fix_test_file(file_path: Path) -> tuple[bool, int]:
|
||||
"""
|
||||
Исправляет один тестовый файл.
|
||||
|
||||
Returns:
|
||||
(changed, count) - был ли изменен файл и количество исправленных функций
|
||||
"""
|
||||
content = file_path.read_text(encoding='utf-8')
|
||||
original_content = content
|
||||
|
||||
# Паттерн для поиска тестовых функций
|
||||
# Ищем def test_...(...): где нет ensure_ldap в параметрах
|
||||
pattern = r'(def test_\w+\([^)]*\)):'
|
||||
|
||||
fixed_count = 0
|
||||
lines = content.split('\n')
|
||||
new_lines = []
|
||||
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
|
||||
# Проверяем, является ли это определением тестовой функции
|
||||
match = re.match(r'^def (test_\w+)\((.*)\):', line)
|
||||
|
||||
if match:
|
||||
func_name = match.group(1)
|
||||
params = match.group(2)
|
||||
|
||||
# Проверяем, нет ли уже ensure_ldap в параметрах
|
||||
if 'ensure_ldap' not in params:
|
||||
# Проверяем следующие 50 строк на наличие Department.objects.create или Position.objects.create
|
||||
check_lines = '\n'.join(lines[i:min(i+50, len(lines))])
|
||||
|
||||
if ('Department.objects.create' in check_lines or
|
||||
'Position.objects.create' in check_lines or
|
||||
'DepartmentRole.objects.create' in check_lines or
|
||||
'make_department' in check_lines):
|
||||
|
||||
# Добавляем ensure_ldap_disabled
|
||||
if params.strip():
|
||||
new_params = f"{params}, ensure_ldap_disabled"
|
||||
else:
|
||||
new_params = "ensure_ldap_disabled"
|
||||
|
||||
new_line = line.replace(f"({params})", f"({new_params})")
|
||||
new_lines.append(new_line)
|
||||
fixed_count += 1
|
||||
print(f" ✓ Исправлена функция: {func_name}")
|
||||
else:
|
||||
new_lines.append(line)
|
||||
else:
|
||||
new_lines.append(line)
|
||||
else:
|
||||
new_lines.append(line)
|
||||
|
||||
i += 1
|
||||
|
||||
new_content = '\n'.join(new_lines)
|
||||
|
||||
if new_content != original_content:
|
||||
file_path.write_text(new_content, encoding='utf-8')
|
||||
return True, fixed_count
|
||||
|
||||
return False, 0
|
||||
|
||||
|
||||
def main():
|
||||
"""Главная функция."""
|
||||
test_dir = Path(__file__).parent.parent / 'tests' / 'api' / 'v1' / 'employees'
|
||||
|
||||
# Список файлов для исправления
|
||||
files_to_fix = [
|
||||
'test_department_membership_separation.py',
|
||||
'test_department_roles.py',
|
||||
'test_department_roles_extra.py',
|
||||
'test_departments.py',
|
||||
'test_employee_actions.py',
|
||||
'test_employees.py',
|
||||
'test_positions.py',
|
||||
'test_role_assignment.py',
|
||||
'test_skills.py',
|
||||
]
|
||||
|
||||
total_fixed = 0
|
||||
total_files = 0
|
||||
|
||||
for filename in files_to_fix:
|
||||
file_path = test_dir / filename
|
||||
|
||||
if not file_path.exists():
|
||||
print(f"⚠ Файл не найден: {filename}")
|
||||
continue
|
||||
|
||||
print(f"\nОбрабатываем {filename}...")
|
||||
changed, count = fix_test_file(file_path)
|
||||
|
||||
if changed:
|
||||
print(f" ✅ {filename} исправлен ({count} функций)")
|
||||
total_fixed += count
|
||||
total_files += 1
|
||||
else:
|
||||
print(f" ⊘ {filename} не требует изменений")
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"✅ Обработано файлов: {total_files}")
|
||||
print(f"✅ Исправлено функций: {total_fixed}")
|
||||
print(f"{'='*60}\n")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -88,7 +88,7 @@ def url_set_member_role(dept_id: int) -> str:
|
||||
# =========================
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_add_member_requires_manage_and_does_not_assign_role(api_client: APIClient):
|
||||
def test_add_member_requires_manage_and_does_not_assign_role(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
add_member:
|
||||
- 401 без авторизации
|
||||
@ -123,7 +123,7 @@ def test_add_member_requires_manage_and_does_not_assign_role(api_client: APIClie
|
||||
assert link.role_id is None # add_member не должен трогать роль
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_all_three_actions_require_auth_and_permissions(api_client: APIClient):
|
||||
def test_all_three_actions_require_auth_and_permissions(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
Сетка проверок прав для трёх эндпоинтов отдела:
|
||||
- без авторизации все три эндпоинта возвращают 401
|
||||
@ -219,7 +219,7 @@ def test_all_three_actions_require_auth_and_permissions(api_client: APIClient):
|
||||
# =========================
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_member_role_requires_assign_not_manage(api_client: APIClient):
|
||||
def test_set_member_role_requires_assign_not_manage(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
set_member_role:
|
||||
- 403 с manage_department, если нет assign_department_role
|
||||
@ -304,7 +304,7 @@ def test_set_member_role_does_not_create_membership_and_does_not_toggle_active(
|
||||
# =========================
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_all_three_actions_require_auth_and_permissions(api_client: APIClient):
|
||||
def test_all_three_actions_require_auth_and_permissions(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
Сетка проверок прав для трёх эндпоинтов отдела:
|
||||
- без авторизации все три эндпоинта возвращают 401
|
||||
@ -396,7 +396,7 @@ def test_all_three_actions_require_auth_and_permissions(api_client: APIClient):
|
||||
)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_add_member_ignores_role_parameter(api_client: APIClient):
|
||||
def test_add_member_ignores_role_parameter(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
add_member не должен назначать роль даже если клиент прислал role_id.
|
||||
"""
|
||||
@ -420,7 +420,7 @@ def test_add_member_ignores_role_parameter(api_client: APIClient):
|
||||
assert link.role_id is None, "add_member не должен трогать роль"
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_remove_member_requires_manage_and_does_not_touch_role(api_client: APIClient):
|
||||
def test_remove_member_requires_manage_and_does_not_touch_role(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
remove_member (hard delete):
|
||||
- 403 при отсутствии manage_department (даже если есть assign_department_role)
|
||||
|
||||
@ -53,7 +53,7 @@ def api_client() -> APIClient:
|
||||
# =========================
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list_filtered_by_department(api_client: APIClient):
|
||||
def test_list_filtered_by_department(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="Dept A")
|
||||
d2 = Department.objects.create(name="Dept B")
|
||||
|
||||
@ -83,7 +83,7 @@ def test_list_filtered_by_department(api_client: APIClient):
|
||||
assert ids == {r1.id, r2.id}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_requires_assign_department_role(api_client: APIClient):
|
||||
def test_create_requires_assign_department_role(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
user = make_user("m@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
@ -106,7 +106,7 @@ def test_create_requires_assign_department_role(api_client: APIClient):
|
||||
assert "permissions" in data and isinstance(data["permissions"], list)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_update_and_destroy_scope_enforced(api_client: APIClient):
|
||||
def test_update_and_destroy_scope_enforced(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="Dept1")
|
||||
d2 = Department.objects.create(name="Dept2")
|
||||
user = make_user("m@example.com")
|
||||
@ -136,7 +136,7 @@ def test_update_and_destroy_scope_enforced(api_client: APIClient):
|
||||
assert resp.status_code in (status.HTTP_204_NO_CONTENT, status.HTTP_200_OK)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_perm_choices_and_perms_and_set_perms(api_client: APIClient):
|
||||
def test_perm_choices_and_perms_and_set_perms(api_client: APIClient, ensure_ldap_disabled):
|
||||
# засеем три стандартных кода
|
||||
ensure_dept_perm("manage_department", "Управлять отделом")
|
||||
ensure_dept_perm("change_department_head", "Назначать руководителя")
|
||||
@ -185,7 +185,7 @@ def test_perm_choices_and_perms_and_set_perms(api_client: APIClient):
|
||||
assert role.scoped_permissions.count() == 0
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_perms_validates_payload(api_client: APIClient):
|
||||
def test_set_perms_validates_payload(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
user = make_user("m@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
@ -203,7 +203,7 @@ def test_set_perms_validates_payload(api_client: APIClient):
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_back_compat_permissions_field_contains_ids(api_client: APIClient):
|
||||
def test_back_compat_permissions_field_contains_ids(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
user = make_user("m@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
@ -221,7 +221,7 @@ def test_back_compat_permissions_field_contains_ids(api_client: APIClient):
|
||||
assert set(data["permissions"]) == {dp_manage.id, dp_assign.id}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_with_scoped_permission_codes_and_update_name(api_client: APIClient):
|
||||
def test_create_with_scoped_permission_codes_and_update_name(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
ensure_dept_perm("manage_department")
|
||||
|
||||
@ -251,7 +251,7 @@ def test_create_with_scoped_permission_codes_and_update_name(api_client: APIClie
|
||||
assert resp.json()["name"] == "Lead+1"
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_cross_department_access_denied_for_set_perms(api_client: APIClient):
|
||||
def test_cross_department_access_denied_for_set_perms(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="Dept1")
|
||||
d2 = Department.objects.create(name="Dept2")
|
||||
|
||||
|
||||
@ -56,13 +56,13 @@ def api_client() -> APIClient:
|
||||
# =========================
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unauth_cannot_list_or_get():
|
||||
def test_unauth_cannot_list_or_get(ensure_ldap_disabled):
|
||||
client = APIClient()
|
||||
url_list = reverse("api:v1:department-roles-list")
|
||||
assert client.get(url_list).status_code in (401, 403)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_read_only_allowed_without_assign(api_client: APIClient):
|
||||
def test_read_only_allowed_without_assign(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
r = make_role(d, "Worker", [])
|
||||
u = make_user("u@example.com")
|
||||
@ -80,7 +80,7 @@ def test_read_only_allowed_without_assign(api_client: APIClient):
|
||||
assert api_client.get(url_detail).status_code == 200
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_staff_override_for_write(api_client: APIClient):
|
||||
def test_staff_override_for_write(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
staff = make_user("s@example.com", staff=True)
|
||||
api_client.force_authenticate(user=staff)
|
||||
@ -111,7 +111,7 @@ def test_staff_override_for_write(api_client: APIClient):
|
||||
)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_ordering_stable_by_name_then_id(api_client: APIClient):
|
||||
def test_ordering_stable_by_name_then_id(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="Dept1")
|
||||
d2 = Department.objects.create(name="Dept2")
|
||||
u = make_user("u@example.com")
|
||||
@ -135,7 +135,7 @@ def test_ordering_stable_by_name_then_id(api_client: APIClient):
|
||||
assert picked[2] == r3.id
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_perms_ids_take_precedence_over_codes(api_client: APIClient):
|
||||
def test_set_perms_ids_take_precedence_over_codes(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
@ -161,7 +161,7 @@ def test_set_perms_ids_take_precedence_over_codes(api_client: APIClient):
|
||||
assert codes == {"manage_department"} # ids приоритетнее
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_serializer_codes_override_scoped_permissions_on_create(api_client: APIClient):
|
||||
def test_serializer_codes_override_scoped_permissions_on_create(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
ensure_perm("manage_department")
|
||||
ensure_perm("assign_department_role")
|
||||
@ -192,7 +192,7 @@ def test_serializer_codes_override_scoped_permissions_on_create(api_client: APIC
|
||||
assert codes == {"assign_department_role"}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_perm_choices_fields_and_nonempty(api_client: APIClient):
|
||||
def test_perm_choices_fields_and_nonempty(api_client: APIClient, ensure_ldap_disabled):
|
||||
ensure_perm("manage_department", "Управлять")
|
||||
ensure_perm("change_department_head", "Глава")
|
||||
ensure_perm("assign_department_role", "Назначение")
|
||||
@ -206,7 +206,7 @@ def test_perm_choices_fields_and_nonempty(api_client: APIClient):
|
||||
assert results and {"id", "code", "name"}.issubset(results[0].keys())
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_destroy_requires_assign_in_same_department(api_client: APIClient):
|
||||
def test_destroy_requires_assign_in_same_department(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="D1")
|
||||
d2 = Department.objects.create(name="D2")
|
||||
u = make_user("u@example.com")
|
||||
@ -227,7 +227,7 @@ def test_destroy_requires_assign_in_same_department(api_client: APIClient):
|
||||
assert api_client.delete(url).status_code in (204, 200)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_perms_dedup_and_replace_semantics(api_client: APIClient):
|
||||
def test_set_perms_dedup_and_replace_semantics(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -90,12 +90,12 @@ def make_role(
|
||||
|
||||
# ---------- tests: auth/list/basic ----------
|
||||
|
||||
def test_list_requires_auth(api_client: APIClient):
|
||||
def test_list_requires_auth(api_client: APIClient, ensure_ldap_disabled):
|
||||
url = reverse("api:v1:departments-list")
|
||||
resp = api_client.get(url)
|
||||
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
def test_list_ok_for_authenticated(api_client: APIClient):
|
||||
def test_list_ok_for_authenticated(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -109,7 +109,7 @@ def test_list_ok_for_authenticated(api_client: APIClient):
|
||||
assert isinstance(items, list)
|
||||
assert len(items) == 2
|
||||
|
||||
def test_search_and_ordering(api_client: APIClient):
|
||||
def test_search_and_ordering(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -137,7 +137,7 @@ def test_search_and_ordering(api_client: APIClient):
|
||||
|
||||
# ---------- tests: employees_count annotation ----------
|
||||
|
||||
def test_employees_count_adds_head_if_not_in_links(api_client: APIClient):
|
||||
def test_employees_count_adds_head_if_not_in_links(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -155,7 +155,7 @@ def test_employees_count_adds_head_if_not_in_links(api_client: APIClient):
|
||||
data = resp.json()
|
||||
assert data["employees_count"] == 3 # 2 + head вне связей
|
||||
|
||||
def test_employees_count_not_double_count_head_if_in_links(api_client: APIClient):
|
||||
def test_employees_count_not_double_count_head_if_in_links(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -175,7 +175,7 @@ def test_employees_count_not_double_count_head_if_in_links(api_client: APIClient
|
||||
|
||||
# ---------- tests: create/destroy ----------
|
||||
|
||||
def test_create_requires_staff(api_client: APIClient):
|
||||
def test_create_requires_staff(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -192,7 +192,7 @@ def test_create_requires_staff(api_client: APIClient):
|
||||
assert resp.status_code == status.HTTP_201_CREATED
|
||||
assert Department.objects.filter(name="New").exists()
|
||||
|
||||
def test_destroy_requires_staff(api_client: APIClient):
|
||||
def test_destroy_requires_staff(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="X")
|
||||
url = reverse("api:v1:departments-detail", args=[d.pk])
|
||||
|
||||
@ -209,7 +209,7 @@ def test_destroy_requires_staff(api_client: APIClient):
|
||||
|
||||
# ---------- tests: update/partial_update perms ----------
|
||||
|
||||
def test_partial_update_name_requires_manage_perm(api_client: APIClient):
|
||||
def test_partial_update_name_requires_manage_perm(api_client: APIClient, ensure_ldap_disabled):
|
||||
head = make_user("head@example.com")
|
||||
d = Department.objects.create(name="Dept", head=head)
|
||||
|
||||
@ -235,7 +235,7 @@ def test_partial_update_name_requires_manage_perm(api_client: APIClient):
|
||||
d.refresh_from_db()
|
||||
assert d.name == "New Name"
|
||||
|
||||
def test_partial_update_head_requires_change_head_perm(api_client: APIClient):
|
||||
def test_partial_update_head_requires_change_head_perm(api_client: APIClient, ensure_ldap_disabled):
|
||||
a = make_user("a@example.com") # текущий head
|
||||
b = make_user("b@example.com") # кандидат
|
||||
d = Department.objects.create(name="Dept", head=a)
|
||||
@ -290,7 +290,7 @@ def test_partial_update_head_same_value_does_not_require_extra_perm(
|
||||
|
||||
# ---------- tests: action set_head ----------
|
||||
|
||||
def test_set_head_by_role_with_perm(api_client: APIClient):
|
||||
def test_set_head_by_role_with_perm(api_client: APIClient, ensure_ldap_disabled):
|
||||
head = make_user("head@example.com")
|
||||
d = Department.objects.create(name="Dept", head=head)
|
||||
candidate = make_user("cand@example.com")
|
||||
@ -308,7 +308,7 @@ def test_set_head_by_role_with_perm(api_client: APIClient):
|
||||
d.refresh_from_db()
|
||||
assert d.head_id == candidate.id
|
||||
|
||||
def test_set_head_validation_inactive_employee(api_client: APIClient):
|
||||
def test_set_head_validation_inactive_employee(api_client: APIClient, ensure_ldap_disabled):
|
||||
head = make_user("head@example.com")
|
||||
d = Department.objects.create(name="Dept", head=head)
|
||||
inactive = make_user(
|
||||
@ -328,7 +328,7 @@ def test_set_head_validation_inactive_employee(api_client: APIClient):
|
||||
== status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
def test_set_head_remove_with_null(api_client: APIClient):
|
||||
def test_set_head_remove_with_null(api_client: APIClient, ensure_ldap_disabled):
|
||||
head = make_user("head@example.com")
|
||||
d = Department.objects.create(name="Dept", head=head)
|
||||
|
||||
@ -347,7 +347,7 @@ def test_set_head_remove_with_null(api_client: APIClient):
|
||||
d.refresh_from_db()
|
||||
assert d.head_id is None
|
||||
|
||||
def test_set_head_requires_perm(api_client: APIClient):
|
||||
def test_set_head_requires_perm(api_client: APIClient, ensure_ldap_disabled):
|
||||
head = make_user("head@example.com")
|
||||
d = Department.objects.create(name="Dept", head=head)
|
||||
candidate = make_user("cand@example.com")
|
||||
@ -366,7 +366,7 @@ def test_set_head_requires_perm(api_client: APIClient):
|
||||
|
||||
# ---------- tests: action set_member_role ----------
|
||||
|
||||
def test_set_member_role_happy_path(api_client: APIClient):
|
||||
def test_set_member_role_happy_path(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
|
||||
manager = make_user("m@example.com")
|
||||
@ -390,7 +390,7 @@ def test_set_member_role_happy_path(api_client: APIClient):
|
||||
assert data["role_id"] == r_worker.id
|
||||
assert data["is_active"] is True
|
||||
|
||||
def test_set_member_role_reject_foreign_role(api_client: APIClient):
|
||||
def test_set_member_role_reject_foreign_role(api_client: APIClient, ensure_ldap_disabled):
|
||||
d1 = Department.objects.create(name="D1")
|
||||
d2 = Department.objects.create(name="D2")
|
||||
|
||||
@ -412,7 +412,7 @@ def test_set_member_role_reject_foreign_role(api_client: APIClient):
|
||||
)
|
||||
assert resp.status_code == status.HTTP_400_BAD_REQUEST
|
||||
|
||||
def test_set_member_role_requires_perm(api_client: APIClient):
|
||||
def test_set_member_role_requires_perm(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
manager = make_user("m@example.com")
|
||||
api_client.force_authenticate(user=manager)
|
||||
@ -430,7 +430,7 @@ def test_set_member_role_requires_perm(api_client: APIClient):
|
||||
)
|
||||
assert resp.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
def test_set_member_role_missing_employee_id(api_client: APIClient):
|
||||
def test_set_member_role_missing_employee_id(api_client: APIClient, ensure_ldap_disabled):
|
||||
d = Department.objects.create(name="Dept")
|
||||
manager = make_user("m@example.com")
|
||||
api_client.force_authenticate(user=manager)
|
||||
|
||||
@ -29,7 +29,7 @@ def _any_non_dismissed():
|
||||
pytest.skip("No non-dismissed action in ACTION_CHOICES")
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list_requires_auth_and_filtering(api_client):
|
||||
def test_list_requires_auth_and_filtering(api_client, ensure_ldap_disabled):
|
||||
url = reverse("api:v1:employee-actions-list")
|
||||
# unauth
|
||||
assert api_client.get(url).status_code in (401, 403)
|
||||
@ -62,7 +62,7 @@ def test_list_requires_auth_and_filtering(api_client):
|
||||
assert ids == baseline_emp | {a1.id}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_requires_perm_or_staff(api_client):
|
||||
def test_create_requires_perm_or_staff(api_client, ensure_ldap_disabled):
|
||||
actor = make_user()
|
||||
target = make_user()
|
||||
api_client.force_authenticate(user=actor)
|
||||
@ -95,7 +95,7 @@ def test_create_requires_perm_or_staff(api_client):
|
||||
assert EmployeeAction.objects.filter(employee=target).count() == baseline2 + 1
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_dismissal_deactivates_employee_and_links(api_client):
|
||||
def test_dismissal_deactivates_employee_and_links(api_client, ensure_ldap_disabled):
|
||||
staff = make_user(staff=True)
|
||||
api_client.force_authenticate(user=staff)
|
||||
emp = make_user()
|
||||
@ -120,7 +120,7 @@ def test_dismissal_deactivates_employee_and_links(api_client):
|
||||
assert link.is_active is False and link.date_to is not None
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_non_dismissal_activates_employee(api_client):
|
||||
def test_non_dismissal_activates_employee(api_client, ensure_ldap_disabled):
|
||||
staff = make_user(staff=True)
|
||||
api_client.force_authenticate(user=staff)
|
||||
emp = make_user()
|
||||
@ -142,7 +142,7 @@ def test_non_dismissal_activates_employee(api_client):
|
||||
assert emp.is_active is True
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_update_to_dismissed_applies_effects(api_client):
|
||||
def test_update_to_dismissed_applies_effects(api_client, ensure_ldap_disabled):
|
||||
actor = make_user()
|
||||
api_client.force_authenticate(user=actor)
|
||||
grant_permission(actor, "employees.add_employeeaction")
|
||||
@ -160,7 +160,7 @@ def test_update_to_dismissed_applies_effects(api_client):
|
||||
assert emp.is_active is False
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_delete_requires_perm_or_staff(api_client):
|
||||
def test_delete_requires_perm_or_staff(api_client, ensure_ldap_disabled):
|
||||
actor = make_user()
|
||||
api_client.force_authenticate(user=actor)
|
||||
emp = make_user()
|
||||
|
||||
@ -27,12 +27,12 @@ _phone_seq = itertools.count(2000)
|
||||
|
||||
# ---------- basic auth / list / retrieve ----------
|
||||
|
||||
def test_list_requires_auth(api_client: APIClient):
|
||||
def test_list_requires_auth(api_client: APIClient, ensure_ldap_disabled):
|
||||
url = reverse("api:v1:employees-list")
|
||||
resp = api_client.get(url)
|
||||
assert resp.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
def test_list_ok_for_authenticated(api_client: APIClient):
|
||||
def test_list_ok_for_authenticated(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
e1 = make_user("a@example.com")
|
||||
e2 = make_user("b@example.com")
|
||||
@ -46,12 +46,12 @@ def test_list_ok_for_authenticated(api_client: APIClient):
|
||||
ids = {it["id"] for it in items}
|
||||
assert e1.id in ids and e2.id in ids
|
||||
|
||||
def test_retrieve_requires_auth(api_client: APIClient):
|
||||
def test_retrieve_requires_auth(api_client: APIClient, ensure_ldap_disabled):
|
||||
e = make_user("x@example.com")
|
||||
url = reverse("api:v1:employees-detail", args=[e.pk])
|
||||
assert api_client.get(url).status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
def test_retrieve_ok(api_client: APIClient):
|
||||
def test_retrieve_ok(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
e = make_user("x@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
@ -65,7 +65,7 @@ def test_retrieve_ok(api_client: APIClient):
|
||||
|
||||
# ---------- search & ordering ----------
|
||||
|
||||
def test_search_by_email_and_last_name(api_client: APIClient):
|
||||
def test_search_by_email_and_last_name(api_client: APIClient, ensure_ldap_disabled):
|
||||
me = make_user("me@example.com")
|
||||
api_client.force_authenticate(user=me)
|
||||
|
||||
@ -98,7 +98,7 @@ def test_search_by_email_and_last_name(api_client: APIClient):
|
||||
|
||||
# ---------- filters ----------
|
||||
|
||||
def test_filter_by_department_includes_members_and_head(api_client: APIClient):
|
||||
def test_filter_by_department_includes_members_and_head(api_client: APIClient, ensure_ldap_disabled):
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -117,7 +117,7 @@ def test_filter_by_department_includes_members_and_head(api_client: APIClient):
|
||||
assert ids == {head.id, member.id}
|
||||
assert outsider.id not in ids
|
||||
|
||||
def test_filter_by_position(api_client: APIClient):
|
||||
def test_filter_by_position(api_client: APIClient, ensure_ldap_disabled):
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -140,7 +140,7 @@ def test_filter_by_position(api_client: APIClient):
|
||||
ids = {it["id"] for it in extract_results(r.json())}
|
||||
assert ids == {e1.id, e2.id}
|
||||
|
||||
def test_filter_by_skills_any_of(api_client: APIClient):
|
||||
def test_filter_by_skills_any_of(api_client: APIClient, ensure_ldap_disabled):
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -161,7 +161,7 @@ def test_filter_by_skills_any_of(api_client: APIClient):
|
||||
ids = {it["id"] for it in extract_results(r.json())}
|
||||
assert ids == {e1.id, e2.id}
|
||||
|
||||
def test_filter_by_email_verified_and_active(api_client: APIClient):
|
||||
def test_filter_by_email_verified_and_active(api_client: APIClient, ensure_ldap_disabled):
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -179,7 +179,7 @@ def test_filter_by_email_verified_and_active(api_client: APIClient):
|
||||
ids = {it["id"] for it in extract_results(r.json())}
|
||||
assert v1.id in ids and v0.id in ids and a0.id not in ids
|
||||
|
||||
def test_filter_actually_active_logic(api_client: APIClient):
|
||||
def test_filter_actually_active_logic(api_client: APIClient, ensure_ldap_disabled):
|
||||
u = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=u)
|
||||
|
||||
@ -211,7 +211,7 @@ def test_filter_actually_active_logic(api_client: APIClient):
|
||||
|
||||
# ---------- create (staff only) + validation + skills ----------
|
||||
|
||||
def test_create_requires_staff(api_client: APIClient):
|
||||
def test_create_requires_staff(api_client: APIClient, ensure_ldap_disabled):
|
||||
user = make_user("u@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -243,7 +243,7 @@ def test_create_requires_staff(api_client: APIClient):
|
||||
|
||||
# ---------- update / partial_update (IsSelfOrStaff) ----------
|
||||
|
||||
def test_partial_update_self_allowed(api_client: APIClient):
|
||||
def test_partial_update_self_allowed(api_client: APIClient, ensure_ldap_disabled):
|
||||
e = make_user("self@example.com")
|
||||
api_client.force_authenticate(user=e)
|
||||
url = reverse("api:v1:employees-detail", args=[e.pk])
|
||||
@ -253,7 +253,7 @@ def test_partial_update_self_allowed(api_client: APIClient):
|
||||
e.refresh_from_db()
|
||||
assert e.first_name == "Me"
|
||||
|
||||
def test_partial_update_other_forbidden_for_regular_user(api_client: APIClient):
|
||||
def test_partial_update_other_forbidden_for_regular_user(api_client: APIClient, ensure_ldap_disabled):
|
||||
owner = make_user("owner@example.com")
|
||||
other = make_user("other@example.com")
|
||||
api_client.force_authenticate(user=other)
|
||||
@ -262,7 +262,7 @@ def test_partial_update_other_forbidden_for_regular_user(api_client: APIClient):
|
||||
resp = api_client.patch(url, {"first_name": "Hack"}, format="json")
|
||||
assert resp.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
def test_partial_update_other_allowed_for_staff(api_client: APIClient):
|
||||
def test_partial_update_other_allowed_for_staff(api_client: APIClient, ensure_ldap_disabled):
|
||||
target = make_user("target@example.com")
|
||||
staff = make_user("admin@example.com", staff=True)
|
||||
api_client.force_authenticate(user=staff)
|
||||
@ -273,7 +273,7 @@ def test_partial_update_other_allowed_for_staff(api_client: APIClient):
|
||||
target.refresh_from_db()
|
||||
assert target.first_name == "Ok"
|
||||
|
||||
def test_destroy_requires_admin(api_client: APIClient):
|
||||
def test_destroy_requires_admin(api_client: APIClient, ensure_ldap_disabled):
|
||||
victim = make_user("victim@example.com")
|
||||
regular = make_user("regular@example.com")
|
||||
staff = make_user("staff@example.com", staff=True)
|
||||
@ -293,7 +293,7 @@ def test_destroy_requires_admin(api_client: APIClient):
|
||||
|
||||
# ---------- action: me (GET/PATCH) ----------
|
||||
|
||||
def test_me_get_returns_current_user(api_client: APIClient):
|
||||
def test_me_get_returns_current_user(api_client: APIClient, ensure_ldap_disabled):
|
||||
me = make_user("me@example.com")
|
||||
api_client.force_authenticate(user=me)
|
||||
|
||||
@ -302,7 +302,7 @@ def test_me_get_returns_current_user(api_client: APIClient):
|
||||
assert r.status_code == 200
|
||||
assert r.json()["id"] == me.id
|
||||
|
||||
def test_me_patch_updates_profile(api_client: APIClient):
|
||||
def test_me_patch_updates_profile(api_client: APIClient, ensure_ldap_disabled):
|
||||
me = make_user("me@example.com", telegram="@me") # уже есть контакт
|
||||
api_client.force_authenticate(user=me)
|
||||
|
||||
@ -312,7 +312,7 @@ def test_me_patch_updates_profile(api_client: APIClient):
|
||||
me.refresh_from_db()
|
||||
assert me.first_name == "Updated"
|
||||
|
||||
def test_me_patch_rejects_when_all_contacts_empty(api_client: APIClient):
|
||||
def test_me_patch_rejects_when_all_contacts_empty(api_client: APIClient, ensure_ldap_disabled):
|
||||
"""
|
||||
Ваша логика в me(): если пользователь не передал поля контактов и в итоге
|
||||
ни одного канала связи нет — вернуть 400.
|
||||
|
||||
@ -25,7 +25,7 @@ def _flush_perm_cache(user):
|
||||
# ---------- tests ----------
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_list_requires_auth(api_client):
|
||||
def test_list_requires_auth(api_client, ensure_ldap_disabled):
|
||||
url = reverse("api:v1:positions-list")
|
||||
|
||||
# unauth -> 401
|
||||
@ -45,7 +45,7 @@ def test_list_requires_auth(api_client):
|
||||
assert {"Manager", "Engineer"} <= set(names)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_permissions(api_client):
|
||||
def test_create_permissions(api_client, ensure_ldap_disabled):
|
||||
url = reverse("api:v1:positions-list")
|
||||
|
||||
# обычный пользователь без прав -> 403
|
||||
@ -67,7 +67,7 @@ def test_create_permissions(api_client):
|
||||
assert resp.status_code == status.HTTP_201_CREATED
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_update_permissions_and_search_ordering(api_client):
|
||||
def test_update_permissions_and_search_ordering(api_client, ensure_ldap_disabled):
|
||||
p1 = Position.objects.create(name="Alpha", description="one")
|
||||
p2 = Position.objects.create(name="Beta", description="two")
|
||||
|
||||
@ -99,7 +99,7 @@ def test_update_permissions_and_search_ordering(api_client):
|
||||
assert names == sorted(names, reverse=True)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_delete_permissions(api_client):
|
||||
def test_delete_permissions(api_client, ensure_ldap_disabled):
|
||||
pos = Position.objects.create(name="ToDelete")
|
||||
user = make_user("user@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
@ -116,7 +116,7 @@ def test_delete_permissions(api_client):
|
||||
assert not Position.objects.filter(id=pos.id).exists()
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_set_groups_requires_special_perm(api_client):
|
||||
def test_set_groups_requires_special_perm(api_client, ensure_ldap_disabled):
|
||||
pos = Position.objects.create(name="RoleOwner")
|
||||
grp1 = Group.objects.create(name="grp1")
|
||||
grp2 = Group.objects.create(name="grp2")
|
||||
@ -138,7 +138,7 @@ def test_set_groups_requires_special_perm(api_client):
|
||||
assert set(pos.groups.values_list("id", flat=True)) == {grp1.id, grp2.id}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_add_and_remove_groups_and_permissions_endpoint(api_client):
|
||||
def test_add_and_remove_groups_and_permissions_endpoint(api_client, ensure_ldap_disabled):
|
||||
# используем гарантированно существующие права
|
||||
perm_view_employee = Permission.objects.get(
|
||||
content_type__app_label="employees", codename="view_employee"
|
||||
@ -192,7 +192,7 @@ def test_add_and_remove_groups_and_permissions_endpoint(api_client):
|
||||
assert any(g["name"] == "B" for g in resp.data["groups_verbose"])
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_groups_payload_validation(api_client):
|
||||
def test_groups_payload_validation(api_client, ensure_ldap_disabled):
|
||||
pos = Position.objects.create(name="Validator")
|
||||
user = make_user("user@example.com")
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
@ -46,7 +46,7 @@ def api_client() -> APIClient:
|
||||
class TestRoleAssignmentEndpoints:
|
||||
"""Тесты для /department-roles/{id}/assign/, revoke, assignments."""
|
||||
|
||||
def test_assign_role_to_any_employee(self, api_client: APIClient):
|
||||
def test_assign_role_to_any_employee(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Роль можно назначить любому сотруднику, не только члену отдела."""
|
||||
# Создаём admin, отдел и роль
|
||||
admin = make_user("admin@test.com", is_staff=True)
|
||||
@ -76,7 +76,7 @@ class TestRoleAssignmentEndpoints:
|
||||
employee=other_user, role=role, is_active=True
|
||||
).exists()
|
||||
|
||||
def test_revoke_role(self, api_client: APIClient):
|
||||
def test_revoke_role(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Отзыв роли деактивирует RoleAssignment."""
|
||||
admin = make_user("admin@test.com", is_staff=True)
|
||||
dept = make_dept("IT")
|
||||
@ -100,7 +100,7 @@ class TestRoleAssignmentEndpoints:
|
||||
assignment.refresh_from_db()
|
||||
assert assignment.is_active is False
|
||||
|
||||
def test_assignments_list(self, api_client: APIClient):
|
||||
def test_assignments_list(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Список назначений роли."""
|
||||
admin = make_user("admin@test.com", is_staff=True)
|
||||
dept = make_dept("IT")
|
||||
@ -127,7 +127,7 @@ class TestRoleAssignmentEndpoints:
|
||||
resp = api_client.get(url + "?active=all")
|
||||
assert resp.data["count"] == 2
|
||||
|
||||
def test_assign_requires_permission(self, api_client: APIClient):
|
||||
def test_assign_requires_permission(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Назначение требует право assign_department_role."""
|
||||
dept = make_dept("IT")
|
||||
role = make_role(dept, "Developer", [])
|
||||
@ -143,7 +143,7 @@ class TestRoleAssignmentEndpoints:
|
||||
|
||||
assert resp.status_code == status.HTTP_403_FORBIDDEN
|
||||
|
||||
def test_assign_with_dept_permission(self, api_client: APIClient):
|
||||
def test_assign_with_dept_permission(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Пользователь с assign_department_role может назначать роли."""
|
||||
dept = make_dept("IT")
|
||||
role = make_role(dept, "Developer", [])
|
||||
@ -164,7 +164,7 @@ class TestRoleAssignmentEndpoints:
|
||||
class TestRoleAssignmentPermissions:
|
||||
"""Тесты для проверки прав через RoleAssignment."""
|
||||
|
||||
def test_permission_check_via_role_assignment(self, api_client: APIClient):
|
||||
def test_permission_check_via_role_assignment(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Права проверяются через RoleAssignment, не требуя членства в отделе."""
|
||||
from api.v1.permissions import has_dept_perm
|
||||
|
||||
@ -186,7 +186,7 @@ class TestRoleAssignmentPermissions:
|
||||
assert has_dept_perm(user, dept.id, "view_request")
|
||||
assert not has_dept_perm(user, dept.id, "change_department_head")
|
||||
|
||||
def test_inactive_assignment_does_not_grant_permission(self, api_client: APIClient):
|
||||
def test_inactive_assignment_does_not_grant_permission(self, api_client: APIClient, ensure_ldap_disabled):
|
||||
"""Неактивное назначение не даёт прав."""
|
||||
from api.v1.permissions import has_dept_perm
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ def test_create_allowed_for_regular_user(api_client):
|
||||
assert Skill.objects.filter(name="Go").exists()
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_update_delete_permissions(api_client):
|
||||
def test_update_delete_permissions(api_client, ensure_ldap_disabled):
|
||||
user = _mk_user()
|
||||
api_client.force_authenticate(user=user)
|
||||
s = Skill.objects.create(name="Docker")
|
||||
@ -121,7 +121,7 @@ def test_bulk_create_by_regular_user(api_client):
|
||||
assert created_names == {"Python", "SQL"}
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_merge_requires_perm_and_reassigns(api_client):
|
||||
def test_merge_requires_perm_and_reassigns(api_client, ensure_ldap_disabled):
|
||||
user = _mk_user()
|
||||
api_client.force_authenticate(user=user)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user