"""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}'