|
4 | 4 | from io import BytesIO |
5 | 5 |
|
6 | 6 | from django.contrib.auth.models import AnonymousUser |
| 7 | +from django.core.exceptions import ValidationError |
7 | 8 | from django.core.files.uploadedfile import SimpleUploadedFile |
8 | 9 | from django.db import connection, models |
9 | 10 | from django.test import TestCase, override_settings |
|
15 | 16 |
|
16 | 17 | from ami.exports.models import DataExport |
17 | 18 | from ami.jobs.models import VALID_JOB_TYPES, Job |
| 19 | +from ami.main.api.serializers import ( |
| 20 | + DeploymentListSerializer, |
| 21 | + DeploymentNestedSerializer, |
| 22 | + DeploymentNestedSerializerWithLocationAndCounts, |
| 23 | +) |
18 | 24 | from ami.main.models import ( |
19 | 25 | Classification, |
20 | 26 | Deployment, |
@@ -3744,3 +3750,87 @@ def test_list_pipelines_public_project_non_member(self): |
3744 | 3750 | self.client.force_authenticate(user=non_member) |
3745 | 3751 | response = self.client.get(url) |
3746 | 3752 | self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 3753 | + |
| 3754 | + |
| 3755 | +class TestDeploymentTimeZone(TestCase): |
| 3756 | + """Tests for Deployment.time_zone field validation and serializer exposure.""" |
| 3757 | + |
| 3758 | + @classmethod |
| 3759 | + def setUpTestData(cls): |
| 3760 | + cls.project, cls.deployment = setup_test_project(reuse=False) |
| 3761 | + |
| 3762 | + def test_valid_iana_zones_accepted(self): |
| 3763 | + for tz in ["Europe/London", "Asia/Tokyo", "UTC", "US/Eastern", "Etc/GMT+5"]: |
| 3764 | + self.deployment.time_zone = tz |
| 3765 | + self.deployment.full_clean() |
| 3766 | + |
| 3767 | + def test_invalid_zone_rejected(self): |
| 3768 | + for bad in ["Fake/Zone", "Not_A_Zone", "123"]: |
| 3769 | + self.deployment.time_zone = bad |
| 3770 | + with self.assertRaises(ValidationError): |
| 3771 | + self.deployment.full_clean() |
| 3772 | + |
| 3773 | + def test_empty_string_rejected(self): |
| 3774 | + self.deployment.time_zone = "" |
| 3775 | + with self.assertRaises(ValidationError): |
| 3776 | + self.deployment.full_clean() |
| 3777 | + |
| 3778 | + def test_none_rejected(self): |
| 3779 | + self.deployment.time_zone = None |
| 3780 | + with self.assertRaises(ValidationError): |
| 3781 | + self.deployment.full_clean() |
| 3782 | + |
| 3783 | + def test_whitespace_padded_rejected(self): |
| 3784 | + self.deployment.time_zone = " UTC " |
| 3785 | + with self.assertRaises(ValidationError): |
| 3786 | + self.deployment.full_clean() |
| 3787 | + |
| 3788 | + def test_default_is_america_new_york(self): |
| 3789 | + d = Deployment(name="tz-default-test", project=self.project) |
| 3790 | + self.assertEqual(d.time_zone, "America/New_York") |
| 3791 | + |
| 3792 | + def test_list_serializer_includes_time_zone(self): |
| 3793 | + self.assertIn("time_zone", DeploymentListSerializer.Meta.fields) |
| 3794 | + |
| 3795 | + def test_nested_serializer_includes_time_zone(self): |
| 3796 | + self.assertIn("time_zone", DeploymentNestedSerializer.Meta.fields) |
| 3797 | + |
| 3798 | + def test_nested_with_location_serializer_includes_time_zone(self): |
| 3799 | + self.assertIn("time_zone", DeploymentNestedSerializerWithLocationAndCounts.Meta.fields) |
| 3800 | + |
| 3801 | + |
| 3802 | +class TestDeploymentTimeZoneAPI(APITestCase): |
| 3803 | + """Tests for Deployment.time_zone via the REST API.""" |
| 3804 | + |
| 3805 | + def setUp(self): |
| 3806 | + self.user = User.objects.create_superuser(email="tz-test@insectai.org", is_staff=True) |
| 3807 | + self.client.force_authenticate(user=self.user) |
| 3808 | + self.project, self.deployment = setup_test_project(reuse=False) |
| 3809 | + |
| 3810 | + def test_api_rejects_invalid_time_zone(self): |
| 3811 | + url = f"/api/v2/deployments/{self.deployment.pk}/" |
| 3812 | + response = self.client.patch(url, {"time_zone": "Fake/Zone"}, format="json") |
| 3813 | + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) |
| 3814 | + |
| 3815 | + def test_api_accepts_valid_time_zone(self): |
| 3816 | + url = f"/api/v2/deployments/{self.deployment.pk}/" |
| 3817 | + response = self.client.patch(url, {"time_zone": "Europe/Berlin"}, format="json") |
| 3818 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 3819 | + self.deployment.refresh_from_db() |
| 3820 | + self.assertEqual(self.deployment.time_zone, "Europe/Berlin") |
| 3821 | + |
| 3822 | + def test_api_list_includes_time_zone(self): |
| 3823 | + url = f"/api/v2/deployments/?project_id={self.project.pk}" |
| 3824 | + response = self.client.get(url) |
| 3825 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 3826 | + results = response.data["results"] |
| 3827 | + row = next((r for r in results if r["id"] == self.deployment.pk), None) |
| 3828 | + self.assertIsNotNone(row) |
| 3829 | + self.assertEqual(row["time_zone"], "America/New_York") |
| 3830 | + |
| 3831 | + def test_api_detail_includes_time_zone(self): |
| 3832 | + url = f"/api/v2/deployments/{self.deployment.pk}/" |
| 3833 | + response = self.client.get(url) |
| 3834 | + self.assertEqual(response.status_code, status.HTTP_200_OK) |
| 3835 | + self.assertIn("time_zone", response.data) |
| 3836 | + self.assertEqual(response.data["time_zone"], "America/New_York") |
0 commit comments