"""This file and its contents are licensed under the Apache License 2.0. Please see the included NOTICE for copyright information and LICENSE for a copy of the license. """ import json import pytest from django.conf import settings from projects.functions.utils import recalculate_created_annotations_and_labels_from_scratch from projects.models import Project, ProjectSummary from ..utils import make_task, project_id # noqa def get_filtered_task_ids(business_client, view_id): response = business_client.get(f'/api/tasks/?view={view_id}') response_data = response.json() assert 'tasks' in response_data, response_data return [task['id'] for task in response_data['tasks']] def apply_filter_and_get_view_id(business_client, project_id, filters): payload = { 'project': project_id, 'data': {'filters': filters}, } response = business_client.post( '/api/dm/views/', data=json.dumps(payload), content_type='application/json', ) assert response.status_code == 201, response.content return response.json()['id'] @pytest.mark.django_db def test_views_filters_with_undefined(business_client, project_id): """ 1. Import task 1: {"$undefined$": "photo1.jpg"} 2. Filter by `data` with value `photo` 3. It should return task 1 4. Set labeling config 5. Filter by `image` with value `photo` 6. It should return task 1 7. Add task 2: {"$undefined$": "photo2.jpg", "extra": "123"} 8. Filter by "extra": "123" 9. It should return task 2 10. Filter by "image" with value `photo` 11. It should return task 1 and task 2 12. Update task 1 with {"extra": "456"} 13. Check project.summary.common_data_columns, there should be ["$undefined$", "extra"] 14. Filter by "image" with "photo" should return task 1 and task 2 """ project = Project.objects.get(pk=project_id) project.label_config = '' project.save() # Step 1: Import task 1: {"$undefined$": "photo1.jpg"} task_data_field_name = settings.DATA_UNDEFINED_NAME # "$undefined$" task_1 = make_task({'data': {task_data_field_name: 'photo1.jpg'}}, project) task_id_1 = task_1.id # Step 2-3: Filter by `data` with value `photo`, should return task 1 filters = { 'conjunction': 'and', 'items': [ { # data default name when label config is not yet set # and a file is uploaded directly 'filter': 'filter:tasks:data.data', 'operator': 'contains', 'type': 'String', 'value': 'photo', } ], } view_id = apply_filter_and_get_view_id(business_client, project_id, filters) response_ids = get_filtered_task_ids(business_client, view_id) assert set(response_ids) == {task_id_1}, f'Expected {[task_id_1]}, got {response_ids}' # Step 4: Set labeling config project.label_config = ' ' project.save() # Step 5-6: Filter by `image` with value `photo`, should return task 1 filters['items'][0]['filter'] = 'filter:tasks:data.image' view_id = apply_filter_and_get_view_id(business_client, project_id, filters) response_ids = get_filtered_task_ids(business_client, view_id) assert set(response_ids) == {task_id_1}, f'Expected {[task_id_1]}, got {response_ids}' # Step 7: Add task 2: {"$undefined$": "photo2.jpg", "extra": "123"} task_2 = make_task({'data': {task_data_field_name: 'photo2.jpg', 'extra': '123'}}, project) task_id_2 = task_2.id # Step 8-9: Filter by "extra": "123", should return task 2 filters['items'][0]['filter'] = 'filter:tasks:data.extra' filters['items'][0]['value'] = '123' view_id = apply_filter_and_get_view_id(business_client, project_id, filters) response_ids = get_filtered_task_ids(business_client, view_id) assert set(response_ids) == {task_id_2}, f'Expected {[task_id_2]}, got {response_ids}' # Step 10-11: Filter by "image" with value `photo`, should return task 1 and task 2 filters['items'][0]['filter'] = 'filter:tasks:data.image' filters['items'][0]['value'] = 'photo' view_id = apply_filter_and_get_view_id(business_client, project_id, filters) response_ids = get_filtered_task_ids(business_client, view_id) assert set(response_ids) == {task_id_1, task_id_2}, f'Expected {[task_id_1, task_id_2]}, got {response_ids}' # Step 12: Update task 1 with {"extra": "456"} task_1.data['extra'] = '456' task_1.save() # we need to fully reset cache, because summary.update_data_columns() # can't work incrementally recalculate_created_annotations_and_labels_from_scratch(project, project.summary, 1) # Step 13: Check project.summary.common_data_columns, there should be ["$undefined$", "extra"] project.refresh_from_db() summary = ProjectSummary.objects.get(project=project) assert set(summary.common_data_columns) == { task_data_field_name, 'extra', }, f"Expected {[task_data_field_name, 'extra']}, got {summary.common_data_columns}" # Step 14: Filter by "image" with "photo" should return task 1 and task 2 # The filter is already set to 'photo' for 'data.image' from previous steps view_id = apply_filter_and_get_view_id(business_client, project_id, filters) response_ids = get_filtered_task_ids(business_client, view_id) assert set(response_ids) == {task_id_1, task_id_2}, f'Expected {[task_id_1, task_id_2]}, got {response_ids}'