From 2e3ac54700663c1a779d8e0b1390db0a1872c35b Mon Sep 17 00:00:00 2001 From: Anna Shamray Date: Thu, 12 Dec 2024 16:12:35 +0100 Subject: [PATCH] :white_check_mark: [#472] add more tests for 'data_attr' filter --- src/objects/tests/v2/test_filters.py | 321 ++++++++++++++++++++++++++- 1 file changed, 320 insertions(+), 1 deletion(-) diff --git a/src/objects/tests/v2/test_filters.py b/src/objects/tests/v2/test_filters.py index 19c714fe..9c3e2318 100644 --- a/src/objects/tests/v2/test_filters.py +++ b/src/objects/tests/v2/test_filters.py @@ -261,7 +261,10 @@ def test_filter_invalid_param(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( - response.json(), ["not enough values to unpack (expected 3, got 2)"] + response.json(), + [ + "Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'" + ], ) def test_filter_nested_attr(self): @@ -443,6 +446,308 @@ def setUpTestData(cls): token_auth=cls.token_auth, ) + def test_filter_exact_string(self): + record = ObjectRecordFactory.create( + data={"name": "demo"}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"name": "demo2"}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "name__exact__demo"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_exact_number(self): + record = ObjectRecordFactory.create( + data={"diameter": 4}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 6}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "diameter__exact__4"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_exact_date(self): + record = ObjectRecordFactory.create( + data={"date": "2000-11-01"}, object__object_type=self.object_type + ) + + response = self.client.get(self.url, {"data_attr": "date__exact__2000-11-01"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_lte(self): + record1 = ObjectRecordFactory.create( + data={"diameter": 4}, object__object_type=self.object_type + ) + record2 = ObjectRecordFactory.create( + data={"diameter": 5}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 6}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "diameter__lte__5"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + data = sorted(data, key=lambda x: x["record"]["data"]["diameter"]) + + self.assertEqual(len(data), 2) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record1.object.uuid])}", + ) + self.assertEqual( + data[1]["url"], + f"http://testserver{reverse('object-detail', args=[record2.object.uuid])}", + ) + + def test_filter_lt(self): + record = ObjectRecordFactory.create( + data={"diameter": 4}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 5}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 6}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "diameter__lt__5"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_lte_not_numerical(self): + response = self.client.get(self.url, {"data_attr": "diameter__lt__value"}) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.json(), ["Operator `lt` supports only dates and/or numeric values"] + ) + + def test_filter_lte_date(self): + record = ObjectRecordFactory.create( + data={"date": "2000-11-01"}, object__object_type=self.object_type + ) + + response = self.client.get(self.url, {"data_attr": "date__lte__2000-12-01"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + response = self.client.get(self.url, {"data_attr": "date__lte__2000-10-01"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 0) + + response = self.client.get(self.url, {"data_attr": "date__lte__2000-11-01"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_invalid_operator(self): + response = self.client.get(self.url, {"data_attr": "diameter__not__value"}) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(response.json(), ["Comparison operator `not` is unknown"]) + + def test_filter_invalid_param(self): + response = self.client.get(self.url, {"data_attr": "diameter__exact"}) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.json(), + [ + "Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'" + ], + ) + + def test_filter_nested_attr(self): + record = ObjectRecordFactory.create( + data={"dimensions": {"diameter": 4}}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"dimensions": {"diameter": 5}}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 4}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get( + self.url, {"data_attr": "dimensions__diameter__exact__4"} + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_icontains_string(self): + record = ObjectRecordFactory.create( + data={"name": "Something important"}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"name": "Nothing important"}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "name__icontains__some"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_icontains_numeric(self): + record = ObjectRecordFactory.create( + data={"diameter": 45}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"diameter": 6}, object__object_type=self.object_type + ) + ObjectRecordFactory.create(data={}, object__object_type=self.object_type) + + response = self.client.get(self.url, {"data_attr": "diameter__icontains__4"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + + def test_filter_exclude_old_records(self): + record_old = ObjectRecordFactory.create( + data={"diameter": 45}, + object__object_type=self.object_type, + start_at=date.today() - timedelta(days=10), + end_at=date.today() - timedelta(days=1), + ) + ObjectRecordFactory.create( + data={"diameter": 50}, object=record_old.object, start_at=record_old.end_at + ) + + response = self.client.get(self.url, {"data_attr": "diameter__exact__45"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + self.assertEqual(len(data), 0) + + def test_filter_date_field_gte(self): + ObjectRecordFactory.create( + data={"dateField": "2000-10-10"}, object__object_type=self.object_type + ) + + response = self.client.get( + self.url, {"data_attr": "dateField__gte__2000-10-10"} + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 1) + + response = self.client.get( + self.url, {"data_attr": "dateField__gte__2000-10-11"} + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 0) + + def test_filter_in_string(self): + record = ObjectRecordFactory.create( + data={"name": "demo1"}, object__object_type=self.object_type + ) + record2 = ObjectRecordFactory.create( + data={"name": "demo2"}, object__object_type=self.object_type + ) + ObjectRecordFactory.create( + data={"name": "demo3"}, object__object_type=self.object_type + ) + + response = self.client.get(self.url, {"data_attr": "name__in__demo1|demo2"}) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json()["results"] + + self.assertEqual(len(data), 2) + self.assertEqual( + data[0]["url"], + f"http://testserver{reverse('object-detail', args=[record2.object.uuid])}", + ) + self.assertEqual( + data[1]["url"], + f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", + ) + def test_filter_icontains_string_with_comma(self): """ regression test for https://github.com/maykinmedia/objects-api/issues/472 @@ -499,6 +804,20 @@ def test_filter_two_icontains_with_comma(self): f"http://testserver{reverse('object-detail', args=[record.object.uuid])}", ) + def test_filter_comma_separated_invalid(self): + response = self.client.get( + self.url, {"data_attr": "dimensions__diameter__exact__4,name__exact__demo"} + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual( + response.json(), + [ + "Filter expression 'dimensions__diameter__exact__4,name__exact__demo' " + "doesn't have the shape 'key__operator__value'" + ], + ) + class FilterDateTests(TokenAuthMixin, APITestCase): @classmethod