Add initial implementations for forms and organization apps with serializers, factories, and admin configurations
Some checks failed
CI/CD Pipeline / Run Tests (push) Failing after 45s
CI/CD Pipeline / Code Quality Checks (push) Failing after 48s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped
Some checks failed
CI/CD Pipeline / Run Tests (push) Failing after 45s
CI/CD Pipeline / Code Quality Checks (push) Failing after 48s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"""Tests for core excel parser."""
|
||||
|
||||
from io import BytesIO
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from apps.core.excel import (
|
||||
BaseExcelParser,
|
||||
@@ -22,80 +21,66 @@ class ValidatorsTest(TestCase):
|
||||
"""Tests for validators."""
|
||||
|
||||
def test_validate_inn_valid_10_digits(self):
|
||||
"""Test valid 10-digit INN."""
|
||||
self.assertEqual(validate_inn("1234567890"), "1234567890")
|
||||
self.assertEqual(validate_inn("1234567890"), (True, ""))
|
||||
|
||||
def test_validate_inn_valid_12_digits(self):
|
||||
"""Test valid 12-digit INN."""
|
||||
self.assertEqual(validate_inn("123456789012"), "123456789012")
|
||||
self.assertEqual(validate_inn("123456789012"), (True, ""))
|
||||
|
||||
def test_validate_inn_strips_whitespace(self):
|
||||
"""Test INN strips whitespace."""
|
||||
self.assertEqual(validate_inn(" 1234567890 "), "1234567890")
|
||||
self.assertEqual(validate_inn(" 1234567890 "), (True, ""))
|
||||
|
||||
def test_validate_inn_invalid_length(self):
|
||||
"""Test INN with invalid length raises ValueError."""
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
validate_inn("12345")
|
||||
self.assertIn("10 или 12", str(ctx.exception))
|
||||
valid, message = validate_inn("12345")
|
||||
self.assertFalse(valid)
|
||||
self.assertIn("10 или 12", message)
|
||||
|
||||
def test_validate_inn_none_returns_none(self):
|
||||
"""Test None INN returns None."""
|
||||
self.assertIsNone(validate_inn(None))
|
||||
def test_validate_inn_none_returns_error(self):
|
||||
self.assertEqual(validate_inn(None), (False, "ИНН обязателен"))
|
||||
|
||||
def test_validate_ogrn_valid_13_digits(self):
|
||||
"""Test valid 13-digit OGRN."""
|
||||
self.assertEqual(validate_ogrn("1234567890123"), "1234567890123")
|
||||
self.assertEqual(validate_ogrn("1234567890123"), (True, ""))
|
||||
|
||||
def test_validate_ogrn_valid_15_digits(self):
|
||||
"""Test valid 15-digit OGRN."""
|
||||
self.assertEqual(validate_ogrn("123456789012345"), "123456789012345")
|
||||
self.assertEqual(validate_ogrn("123456789012345"), (True, ""))
|
||||
|
||||
def test_validate_ogrn_invalid_length(self):
|
||||
"""Test OGRN with invalid length raises ValueError."""
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
validate_ogrn("12345")
|
||||
self.assertIn("13 или 15", str(ctx.exception))
|
||||
valid, message = validate_ogrn("12345")
|
||||
self.assertFalse(valid)
|
||||
self.assertIn("13 или 15", message)
|
||||
|
||||
def test_validate_kpp_valid(self):
|
||||
"""Test valid 9-digit KPP."""
|
||||
self.assertEqual(validate_kpp("123456789"), "123456789")
|
||||
self.assertEqual(validate_kpp("123456789"), (True, ""))
|
||||
|
||||
def test_validate_kpp_invalid_length(self):
|
||||
"""Test KPP with invalid length raises ValueError."""
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
validate_kpp("12345")
|
||||
self.assertIn("9 цифр", str(ctx.exception))
|
||||
valid, message = validate_kpp("12345")
|
||||
self.assertFalse(valid)
|
||||
self.assertIn("9 цифр", message)
|
||||
|
||||
def test_validate_okpo_valid_8_digits(self):
|
||||
"""Test valid 8-digit OKPO."""
|
||||
self.assertEqual(validate_okpo("12345678"), "12345678")
|
||||
self.assertEqual(validate_okpo("12345678"), (True, ""))
|
||||
|
||||
def test_validate_okpo_valid_10_digits(self):
|
||||
"""Test valid 10-digit OKPO."""
|
||||
self.assertEqual(validate_okpo("1234567890"), "1234567890")
|
||||
self.assertEqual(validate_okpo("1234567890"), (True, ""))
|
||||
|
||||
|
||||
class DataclassesTest(TestCase):
|
||||
"""Tests for dataclasses."""
|
||||
|
||||
def test_column_mapping_creation(self):
|
||||
"""Test ColumnMapping creation."""
|
||||
mapping = ColumnMapping(
|
||||
column_index=1,
|
||||
field_name="test_field",
|
||||
header_pattern="Test Header",
|
||||
excel_column=1,
|
||||
excel_header="Test Header",
|
||||
model_field="test_field",
|
||||
)
|
||||
self.assertEqual(mapping.column_index, 1)
|
||||
self.assertEqual(mapping.excel_column, 1)
|
||||
self.assertEqual(mapping.field_name, "test_field")
|
||||
self.assertFalse(mapping.required)
|
||||
|
||||
def test_column_mapping_with_validator(self):
|
||||
"""Test ColumnMapping with validator."""
|
||||
mapping = ColumnMapping(
|
||||
column_index=1,
|
||||
field_name="inn",
|
||||
header_pattern="ИНН",
|
||||
excel_column=1,
|
||||
excel_header="ИНН",
|
||||
model_field="inn",
|
||||
required=True,
|
||||
validator=validate_inn,
|
||||
)
|
||||
@@ -103,16 +88,19 @@ class DataclassesTest(TestCase):
|
||||
self.assertIsNotNone(mapping.validator)
|
||||
|
||||
def test_row_data_creation(self):
|
||||
"""Test RowData creation."""
|
||||
data = RowData(
|
||||
row_number=5,
|
||||
data={"field1": "value1", "field2": 123},
|
||||
organization_name="Тестовая организация",
|
||||
inn="1234567890",
|
||||
ogrn="1234567890123",
|
||||
kpp="123456789",
|
||||
okpo="12345678",
|
||||
fields={"field1": "value1", "field2": 123},
|
||||
)
|
||||
self.assertEqual(data.row_number, 5)
|
||||
self.assertEqual(data.data["field1"], "value1")
|
||||
self.assertEqual(data.fields["field1"], "value1")
|
||||
|
||||
def test_field_error_creation(self):
|
||||
"""Test FieldError creation."""
|
||||
error = FieldError(
|
||||
field="inn",
|
||||
message="Invalid INN",
|
||||
@@ -120,50 +108,60 @@ class DataclassesTest(TestCase):
|
||||
)
|
||||
self.assertEqual(error.field, "inn")
|
||||
self.assertEqual(error.message, "Invalid INN")
|
||||
self.assertEqual(error.value, "12345")
|
||||
|
||||
def test_row_validation_error_creation(self):
|
||||
"""Test RowValidationError creation."""
|
||||
error = RowValidationError(
|
||||
row_number=10,
|
||||
row=10,
|
||||
inn="1234567890",
|
||||
kpp="123456789",
|
||||
organization_name="Тест",
|
||||
errors=[FieldError(field="inn", message="Invalid", value="x")],
|
||||
)
|
||||
self.assertEqual(error.row_number, 10)
|
||||
self.assertEqual(error.row, 10)
|
||||
self.assertEqual(len(error.errors), 1)
|
||||
|
||||
def test_parse_result_creation(self):
|
||||
"""Test ParseResult creation."""
|
||||
result = ParseResult(
|
||||
success=True,
|
||||
records_created=5,
|
||||
records_failed=1,
|
||||
batch_id=123,
|
||||
loaded_count=5,
|
||||
skipped_count=1,
|
||||
errors=[],
|
||||
load_batch="batch-123",
|
||||
)
|
||||
self.assertTrue(result.success)
|
||||
self.assertEqual(result.records_created, 5)
|
||||
self.assertEqual(result.load_batch, "batch-123")
|
||||
self.assertEqual(result.batch_id, 123)
|
||||
self.assertEqual(result.loaded_count, 5)
|
||||
self.assertEqual(result.skipped_count, 1)
|
||||
|
||||
|
||||
class BaseExcelParserTest(TestCase):
|
||||
"""Tests for BaseExcelParser."""
|
||||
|
||||
def test_parser_abstract_methods(self):
|
||||
"""Test parser has abstract methods."""
|
||||
with self.assertRaises(TypeError):
|
||||
BaseExcelParser()
|
||||
|
||||
def test_concrete_parser_implementation(self):
|
||||
"""Test concrete parser implementation."""
|
||||
|
||||
class TestParser(BaseExcelParser):
|
||||
def get_column_mappings(self):
|
||||
return [
|
||||
ColumnMapping(column_index=1, field_name="inn", header_pattern="ИНН", required=True),
|
||||
ColumnMapping(column_index=2, field_name="name", header_pattern="Наименование"),
|
||||
ColumnMapping(
|
||||
excel_column=1,
|
||||
excel_header="ИНН",
|
||||
model_field="inn",
|
||||
required=True,
|
||||
),
|
||||
ColumnMapping(
|
||||
excel_column=2,
|
||||
excel_header="Наименование",
|
||||
model_field="name",
|
||||
),
|
||||
]
|
||||
|
||||
def create_record(self, row_data: dict):
|
||||
return MagicMock(id=1)
|
||||
def get_next_batch_id(self) -> int:
|
||||
return 1
|
||||
|
||||
def create_record(self, row_data, batch_id):
|
||||
return MagicMock(id=1, batch_id=batch_id, row_data=row_data)
|
||||
|
||||
parser = TestParser()
|
||||
mappings = parser.get_column_mappings()
|
||||
|
||||
75
tests/apps/core/test_generate_test_reports_command.py
Normal file
75
tests/apps/core/test_generate_test_reports_command.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Tests for generate_test_reports management command."""
|
||||
|
||||
from io import StringIO
|
||||
|
||||
from apps.form_1.models import FormF1Record
|
||||
from apps.form_2.models import FormF2Record
|
||||
from apps.form_3.models import FormF3Record
|
||||
from apps.form_4.models import FormF4Record
|
||||
from apps.form_5.models import FormF5Record
|
||||
from apps.form_6.models import FormF6Record
|
||||
from apps.organization.models import Organization
|
||||
from apps.registers.models import RegisterUpload, RegistryMembershipPeriod
|
||||
from django.core.management import call_command
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class GenerateTestReportsCommandTest(TestCase):
|
||||
"""Tests for synthetic report generation command."""
|
||||
|
||||
def test_generate_test_reports_creates_records_for_all_forms(self):
|
||||
stdout = StringIO()
|
||||
|
||||
call_command(
|
||||
"generate_test_reports",
|
||||
count=3,
|
||||
prefix="Автотест организация",
|
||||
stdout=stdout,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Organization.objects.filter(name__startswith="Автотест организация").count(),
|
||||
3,
|
||||
)
|
||||
self.assertEqual(FormF1Record.objects.count(), 12)
|
||||
self.assertEqual(FormF2Record.objects.count(), 12)
|
||||
self.assertEqual(FormF3Record.objects.count(), 12)
|
||||
self.assertEqual(FormF4Record.objects.count(), 12)
|
||||
self.assertEqual(FormF5Record.objects.count(), 12)
|
||||
self.assertEqual(FormF6Record.objects.count(), 12)
|
||||
self.assertEqual(FormF1Record.objects.filter(is_active_version=True).count(), 9)
|
||||
self.assertEqual(FormF1Record.objects.filter(is_active_version=False).count(), 3)
|
||||
self.assertEqual(
|
||||
RegistryMembershipPeriod.objects.filter(ended_at__isnull=True).count(),
|
||||
3,
|
||||
)
|
||||
self.assertGreaterEqual(RegisterUpload.objects.count(), 1)
|
||||
|
||||
self.assertIn("Ф-1: создано 12 записей, активных 9, архивных 3", stdout.getvalue())
|
||||
self.assertIn("Ф-6: создано 12 записей, активных 9, архивных 3", stdout.getvalue())
|
||||
self.assertIn("Реестры: актуальных участий создано 3", stdout.getvalue())
|
||||
|
||||
def test_generate_test_reports_dry_run_rolls_back_changes(self):
|
||||
stdout = StringIO()
|
||||
|
||||
call_command(
|
||||
"generate_test_reports",
|
||||
count=2,
|
||||
prefix="DryRun организация",
|
||||
dry_run=True,
|
||||
stdout=stdout,
|
||||
)
|
||||
|
||||
self.assertFalse(
|
||||
Organization.objects.filter(name__startswith="DryRun организация").exists()
|
||||
)
|
||||
self.assertEqual(FormF1Record.objects.count(), 0)
|
||||
self.assertEqual(FormF2Record.objects.count(), 0)
|
||||
self.assertEqual(FormF3Record.objects.count(), 0)
|
||||
self.assertEqual(FormF4Record.objects.count(), 0)
|
||||
self.assertEqual(FormF5Record.objects.count(), 0)
|
||||
self.assertEqual(FormF6Record.objects.count(), 0)
|
||||
self.assertEqual(RegisterUpload.objects.count(), 0)
|
||||
self.assertEqual(RegistryMembershipPeriod.objects.count(), 0)
|
||||
|
||||
self.assertIn("Dry-run: транзакция откачена", stdout.getvalue())
|
||||
@@ -11,7 +11,7 @@ from apps.core.viewsets import (
|
||||
OwnerViewSet,
|
||||
ReadOnlyViewSet,
|
||||
)
|
||||
from apps.parsers.models import Proxy
|
||||
from apps.organization.models import Organization
|
||||
from apps.user.models import Profile, User
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import include, path
|
||||
@@ -21,30 +21,31 @@ from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from tests.apps.parsers.factories import ProxyFactory, fake
|
||||
from tests.apps.organization.factories import OrganizationFactory, fake
|
||||
from tests.apps.user.factories import ProfileFactory, UserFactory
|
||||
|
||||
|
||||
def _proxy_payload() -> dict[str, Any]:
|
||||
proxy = ProxyFactory.build()
|
||||
def _organization_payload() -> dict[str, Any]:
|
||||
organization = OrganizationFactory.build()
|
||||
return {
|
||||
"address": proxy.address,
|
||||
"is_active": proxy.is_active,
|
||||
"fail_count": proxy.fail_count,
|
||||
"description": proxy.description,
|
||||
"name": organization.name,
|
||||
"inn": fake.unique.numerify("##########"),
|
||||
"ogrn": organization.ogrn,
|
||||
"kpp": organization.kpp,
|
||||
"okpo": organization.okpo,
|
||||
}
|
||||
|
||||
|
||||
class ProxySerializer(serializers.ModelSerializer):
|
||||
class OrganizationSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Proxy
|
||||
fields = ["id", "address", "is_active", "fail_count", "description"]
|
||||
model = Organization
|
||||
fields = ["id", "name", "inn", "ogrn", "kpp", "okpo"]
|
||||
|
||||
|
||||
class ProxyListSerializer(serializers.ModelSerializer):
|
||||
class OrganizationListSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Proxy
|
||||
fields = ["id", "address"]
|
||||
model = Organization
|
||||
fields = ["id", "name"]
|
||||
|
||||
|
||||
class ProfileSerializer(serializers.ModelSerializer):
|
||||
@@ -60,27 +61,27 @@ class UserSerializer(serializers.ModelSerializer):
|
||||
fields = ["id", "email", "username"]
|
||||
|
||||
|
||||
class ProxyViewSet(BaseViewSet[Proxy]):
|
||||
queryset = Proxy.objects.all()
|
||||
serializer_class = ProxySerializer
|
||||
serializer_classes = {"list": ProxyListSerializer}
|
||||
only_fields = ["id", "address"]
|
||||
class OrganizationViewSet(BaseViewSet[Organization]):
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
serializer_classes = {"list": OrganizationListSerializer}
|
||||
only_fields = ["id", "name"]
|
||||
|
||||
|
||||
class DeferProxyViewSet(BaseViewSet[Proxy]):
|
||||
queryset = Proxy.objects.all()
|
||||
serializer_class = ProxySerializer
|
||||
defer_fields = ["description"]
|
||||
class DeferOrganizationViewSet(BaseViewSet[Organization]):
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
defer_fields = ["okpo"]
|
||||
|
||||
|
||||
class ReadOnlyProxyViewSet(ReadOnlyViewSet[Proxy]):
|
||||
queryset = Proxy.objects.all()
|
||||
serializer_class = ProxySerializer
|
||||
class ReadOnlyOrganizationViewSet(ReadOnlyViewSet[Organization]):
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
|
||||
|
||||
class NoPaginationProxyViewSet(BaseViewSet[Proxy]):
|
||||
queryset = Proxy.objects.all()
|
||||
serializer_class = ProxySerializer
|
||||
class NoPaginationOrganizationViewSet(BaseViewSet[Organization]):
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
pagination_class = None
|
||||
|
||||
|
||||
@@ -113,9 +114,9 @@ class OwnerProfileViewSet(OwnerViewSet[Profile]):
|
||||
serializer_class = ProfileSerializer
|
||||
|
||||
|
||||
class BulkProxyViewSet(BulkMixin, BaseViewSet[Proxy]):
|
||||
queryset = Proxy.objects.all()
|
||||
serializer_class = ProxySerializer
|
||||
class BulkOrganizationViewSet(BulkMixin, BaseViewSet[Organization]):
|
||||
queryset = Organization.objects.all()
|
||||
serializer_class = OrganizationSerializer
|
||||
bulk_max_items = 2
|
||||
|
||||
@action(detail=False, methods=["post"])
|
||||
@@ -132,16 +133,32 @@ class BulkProxyViewSet(BulkMixin, BaseViewSet[Proxy]):
|
||||
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register("proxies", ProxyViewSet, basename="proxy")
|
||||
router.register("proxies-defer", DeferProxyViewSet, basename="proxy-defer")
|
||||
router.register("proxies-readonly", ReadOnlyProxyViewSet, basename="proxy-readonly")
|
||||
router.register("proxies-nopage", NoPaginationProxyViewSet, basename="proxy-nopage")
|
||||
router.register("organizations", OrganizationViewSet, basename="organization")
|
||||
router.register(
|
||||
"organizations-defer",
|
||||
DeferOrganizationViewSet,
|
||||
basename="organization-defer",
|
||||
)
|
||||
router.register(
|
||||
"organizations-readonly",
|
||||
ReadOnlyOrganizationViewSet,
|
||||
basename="organization-readonly",
|
||||
)
|
||||
router.register(
|
||||
"organizations-nopage",
|
||||
NoPaginationOrganizationViewSet,
|
||||
basename="organization-nopage",
|
||||
)
|
||||
router.register("profiles-select", ProfileSelectViewSet, basename="profile-select")
|
||||
router.register("profiles-old", ProfileOldStyleViewSet, basename="profile-old")
|
||||
router.register("users-prefetch", UserPrefetchViewSet, basename="user-prefetch")
|
||||
router.register("users-old", UserOldStyleViewSet, basename="user-old")
|
||||
router.register("profiles-owner", OwnerProfileViewSet, basename="profile-owner")
|
||||
router.register("bulk-proxies", BulkProxyViewSet, basename="bulk-proxy")
|
||||
router.register(
|
||||
"bulk-organizations",
|
||||
BulkOrganizationViewSet,
|
||||
basename="bulk-organization",
|
||||
)
|
||||
|
||||
urlpatterns = [path("", include(router.urls))]
|
||||
|
||||
@@ -227,22 +244,20 @@ class BaseViewSetIntegrationTest(APITestCase):
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_list_paginated_uses_list_serializer(self):
|
||||
ProxyFactory.create_batch(3)
|
||||
OrganizationFactory.create_batch(3)
|
||||
|
||||
response = self.client.get("/proxies/?page=1&page_size=2")
|
||||
response = self.client.get("/organizations/?page=1&page_size=2")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
self.assertEqual(len(response.data["data"]), 2)
|
||||
self.assertIn("pagination", response.data["meta"])
|
||||
self.assertSetEqual(
|
||||
set(response.data["data"][0].keys()), {"id", "address"}
|
||||
)
|
||||
self.assertSetEqual(set(response.data["data"][0].keys()), {"id", "name"})
|
||||
|
||||
def test_list_without_pagination(self):
|
||||
ProxyFactory.create_batch(2)
|
||||
OrganizationFactory.create_batch(2)
|
||||
|
||||
response = self.client.get("/proxies-nopage/")
|
||||
response = self.client.get("/organizations-nopage/")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
@@ -250,30 +265,30 @@ class BaseViewSetIntegrationTest(APITestCase):
|
||||
self.assertIsNone(response.data["meta"])
|
||||
|
||||
def test_retrieve_uses_default_serializer(self):
|
||||
proxy = ProxyFactory()
|
||||
organization = OrganizationFactory()
|
||||
|
||||
response = self.client.get(f"/proxies/{proxy.pk}/")
|
||||
response = self.client.get(f"/organizations/{organization.pk}/")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertIn("fail_count", response.data["data"])
|
||||
self.assertIn("inn", response.data["data"])
|
||||
|
||||
def test_create_update_delete(self):
|
||||
payload = _proxy_payload()
|
||||
payload = _organization_payload()
|
||||
|
||||
created = self.client.post("/proxies/", payload, format="json")
|
||||
created = self.client.post("/organizations/", payload, format="json")
|
||||
self.assertEqual(created.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
proxy_id = created.data["data"]["id"]
|
||||
new_description = fake.sentence(nb_words=3)
|
||||
organization_id = created.data["data"]["id"]
|
||||
new_name = fake.company()
|
||||
updated = self.client.patch(
|
||||
f"/proxies/{proxy_id}/",
|
||||
{"description": new_description},
|
||||
f"/organizations/{organization_id}/",
|
||||
{"name": new_name},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(updated.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(updated.data["data"]["description"], new_description)
|
||||
self.assertEqual(updated.data["data"]["name"], new_name)
|
||||
|
||||
deleted = self.client.delete(f"/proxies/{proxy_id}/")
|
||||
deleted = self.client.delete(f"/organizations/{organization_id}/")
|
||||
self.assertEqual(deleted.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@@ -284,16 +299,16 @@ class ReadOnlyViewSetIntegrationTest(APITestCase):
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_readonly_list_and_retrieve(self):
|
||||
proxy = ProxyFactory()
|
||||
ProxyFactory.create_batch(2)
|
||||
organization = OrganizationFactory()
|
||||
OrganizationFactory.create_batch(2)
|
||||
|
||||
list_response = self.client.get("/proxies-readonly/")
|
||||
list_response = self.client.get("/organizations-readonly/")
|
||||
self.assertEqual(list_response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(list_response.data["success"])
|
||||
|
||||
detail_response = self.client.get(f"/proxies-readonly/{proxy.pk}/")
|
||||
detail_response = self.client.get(f"/organizations-readonly/{organization.pk}/")
|
||||
self.assertEqual(detail_response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(detail_response.data["data"]["id"], proxy.pk)
|
||||
self.assertEqual(detail_response.data["data"]["id"], str(organization.pk))
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF=__name__)
|
||||
@@ -334,50 +349,52 @@ class BulkMixinIntegrationTest(APITestCase):
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_bulk_create_empty_items(self):
|
||||
response = self.client.post("/bulk-proxies/bulk_create/", {}, format="json")
|
||||
response = self.client.post(
|
||||
"/bulk-organizations/bulk_create/", {}, format="json"
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertFalse(response.data["success"])
|
||||
|
||||
def test_bulk_create_too_many(self):
|
||||
items = [_proxy_payload() for _ in range(3)]
|
||||
items = [_organization_payload() for _ in range(3)]
|
||||
response = self.client.post(
|
||||
"/bulk-proxies/bulk_create/", {"items": items}, format="json"
|
||||
"/bulk-organizations/bulk_create/", {"items": items}, format="json"
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertEqual(response.data["errors"][0]["code"], "too_many_items")
|
||||
|
||||
def test_bulk_create_update_delete(self):
|
||||
items = [_proxy_payload(), _proxy_payload()]
|
||||
items = [_organization_payload(), _organization_payload()]
|
||||
created = self.client.post(
|
||||
"/bulk-proxies/bulk_create/", {"items": items}, format="json"
|
||||
"/bulk-organizations/bulk_create/", {"items": items}, format="json"
|
||||
)
|
||||
self.assertEqual(created.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
created_ids = [item["id"] for item in created.data["data"]]
|
||||
update_items = [
|
||||
{"id": created_ids[0], "description": fake.sentence(nb_words=2)},
|
||||
{"id": created_ids[0], "name": fake.company()},
|
||||
{
|
||||
"id": fake.random_int(min=999999, max=9999999),
|
||||
"description": fake.word(),
|
||||
"id": fake.uuid4(),
|
||||
"name": fake.company(),
|
||||
},
|
||||
]
|
||||
updated = self.client.patch(
|
||||
"/bulk-proxies/bulk_update/", {"items": update_items}, format="json"
|
||||
"/bulk-organizations/bulk_update/", {"items": update_items}, format="json"
|
||||
)
|
||||
self.assertEqual(updated.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(updated.data["data"]["updated"]), 1)
|
||||
self.assertEqual(len(updated.data["data"]["errors"]), 1)
|
||||
|
||||
deleted = self.client.delete(
|
||||
"/bulk-proxies/bulk_delete/", {"ids": created_ids}, format="json"
|
||||
"/bulk-organizations/bulk_delete/", {"ids": created_ids}, format="json"
|
||||
)
|
||||
self.assertEqual(deleted.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(deleted.data["data"]["deleted"], len(created_ids))
|
||||
|
||||
def test_bulk_update_missing_ids(self):
|
||||
response = self.client.patch(
|
||||
"/bulk-proxies/bulk_update/",
|
||||
{"items": [{"address": fake.word()}]},
|
||||
"/bulk-organizations/bulk_update/",
|
||||
{"items": [{"name": fake.company()}]},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
@@ -409,6 +426,6 @@ class QuerysetOptimizationIntegrationTest(APITestCase):
|
||||
self.assertEqual(response_old.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_defer_fields_branch(self):
|
||||
ProxyFactory.create_batch(2)
|
||||
response = self.client.get("/proxies-defer/")
|
||||
OrganizationFactory.create_batch(2)
|
||||
response = self.client.get("/organizations-defer/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
Reference in New Issue
Block a user