---
test_name: tasks-all-fields-postgre
strict: false
marks:
  - usefixtures:
      - django_live_url
  - skipif: "'default' not in '{tavern.env_vars.DJANGO_DB}'"
stages:

  - id: signup
    type: ref

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: create_filter_tasks
    request:
      files:
        json_file: tests/data_manager/tasks_annotations_predictions.json
      headers:
        content-type: multipart/form-data
      method: POST
      url: '{django_live_url}/api/projects/{project_pk}/import'
    response:
      json:
        annotation_count: 4
        prediction_count: 3
        task_count: 6
      status_code: 201

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:data.text",
                "operator": "equal",
                "type": "String",
                "value": "Test example phrase 1"
              },
              {
                "filter": "filter:tasks:data.text",
                "operator": "contains",
                "type": "String",
                "value": "x"
              },
              {
                "filter": "filter:tasks:annotations_results",
                "operator": "contains",
                "type": "String",
                "value": "TESTING"
              },
              {
                "filter": "filter:tasks:predictions_results",
                "operator": "contains",
                "type": "String",
                "value": "PREDICTIONS"
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 4,
        "total_predictions": 3,
        "total": 4,
        "tasks": [
        {
          "cancelled_annotations": 0,
          "storage_filename": null,
          "annotations_results": "",
          "data": {
            "text": "opop",
            "int_field": 42
          },

          "predictions_results": !raw "[{type:choices, value:{choices:[class_PREDICTIONS_TESTING]}, to_name:text, from_name:text_class}]",
          "predictions_score": null,
          "total_annotations": 0,
          "total_predictions": 1,
          "annotations_ids": "",
          "annotations": [],
          "predictions": [
          {
            "model_version": "undefined",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_PREDICTIONS_TESTING"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0
          }
          ],
          "drafts": [],
          "annotators": [],
          "avg_lead_time": null

        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,
          "annotations_results": !raw "[{type:choices, value:{choices:[class_A]}, to_name:text, from_name:text_class}]",
          "data": {
            "text": "Test example phrase 1",
            "int_field": 1
          },

          "predictions_results": !raw "[{type:choices, value:{choices:[class_A]}, to_name:text, from_name:text_class}]",
          "predictions_score": null,
          "total_annotations": 1,
          "total_predictions": 1,
          "annotations_ids": !anystr "",
          "annotations": [
          {

            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,
            "lead_time": 3.0
          }
          ],
          "predictions": [
          {
            "model_version": "model_version_A",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0
          }
          ],
          "drafts": [],
          "annotators": [
            !int "{created_by}"
          ],
          "avg_lead_time": 3.0
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,
          "annotations_results": !anystr "",
          "data": {
            "text": "x2",
            "int_field": 20
          },
          "predictions_results": !anystr "",
          "predictions_score": null,
          "total_annotations": 2,
          "total_predictions": 1,
          "annotations_ids": !anystr "",
          "annotations": [
          {
            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,
            "lead_time": 3.0
          },
          {
            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,
            "lead_time": 5.0
          }
          ],
          "predictions": [
          {

            "model_version": "model_version_A",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0
          }
          ],
          "drafts": [],
          "annotators": [
            !int "{created_by}"
          ],
          "avg_lead_time": 4.0
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "annotations_results": !raw "[{type:choices, value:{choices:[class_TESTING]}, to_name:text, from_name:text_class}]",
          "data": {
            "text": "yoyo",
            "int_field": "99"
          },

          "predictions_results": "",
          "predictions_score": null,
          "total_annotations": 1,
          "total_predictions": 0,
          "annotations_ids": !anystr "",
          "annotations": [
          {
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "type": "choices",
              "value": {
                "choices": [
                  "class_TESTING"
                ]
              },
              "to_name": "text",
              "from_name": "text_class"
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,
            "lead_time": null

          }
          ],
          "predictions": [],
          "drafts": [],

          "annotators": [
            !int "{created_by}"
          ]

        }
        ]
      }

---
test_name: tasks-all-fields-sqlite
strict: false
marks:
  - skipif: "'default' in '{tavern.env_vars.DJANGO_DB}'"
  - usefixtures:
      - django_live_url
stages:

  - id: signup
    type: ref

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: create_filter_tasks
    request:
      files:
        json_file: tests/data_manager/tasks_annotations_predictions.json
      headers:
        content-type: multipart/form-data
      method: POST
      url: '{django_live_url}/api/projects/{project_pk}/import'
    response:
      json:
        annotation_count: 4
        prediction_count: 3
        task_count: 6
      status_code: 201

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:data.text",
                "operator": "equal",
                "type": "String",
                "value": "Test example phrase 1"
              },
              {
                "filter": "filter:tasks:data.text",
                "operator": "contains",
                "type": "String",
                "value": "x"
              },
              {
                "filter": "filter:tasks:annotations_results",
                "operator": "contains",
                "type": "String",
                "value": "TESTING"
              },
              {
                "filter": "filter:tasks:predictions_results",
                "operator": "contains",
                "type": "String",
                "value": "PREDICTIONS"
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      # verify_response_with:
      #  function: label_studio.tests.utils:save_response
      json:
        {
          "total_annotations": 4,
          "total_predictions": 3,
          "total": 4,
          "tasks": [
          {
            "cancelled_annotations": 0,
            "storage_filename": null,
            "annotations_results": !raw "[{from_name: text_class, to_name: text, type: choices, value: {choices: [class_A]}}]",
            "data": {
              "text": "Test example phrase 1",
              "int_field": 1
            },
            "predictions_results": !raw "[{from_name: text_class, to_name: text, type: choices, value: {choices: [class_A]}}]",
            "predictions_score": null,
            "total_annotations": 1,
            "total_predictions": 1,
            "annotations_ids": !anystr "",
            "annotations": [
            {

              "created_username": " test_suites_user@heartex.com, {created_by}",
              "created_ago": "0\u00a0minutes",
              "completed_by": !int "{created_by}",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_A"
                  ]
                }
              }
              ],
              "was_cancelled": false,
              "ground_truth": true,

              "lead_time": 3.0

            }
            ],
            "predictions": [
            {

              "model_version": "model_version_A",
              "created_ago": "0\u00a0minutes",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_A"
                  ]
                }
              }
              ],
              "score": null,
              "cluster": null,
              "neighbors": null,
              "mislabeling": 0.0,


            }
            ],
            "drafts": [],
            "annotators": [
              !int "{created_by}"
            ],
            "project": !int "{project_pk}"
          },
          {
            "cancelled_annotations": 0,
            "storage_filename": null,
            "annotations_results": "",
            "data": {
              "int_field": 42,
              "text": "opop"
            },
            "predictions_results": !raw "[{from_name: text_class, to_name: text, type: choices, value: {choices: [class_PREDICTIONS_TESTING]}}]",
            "predictions_score": null,
            "total_annotations": 0,
            "total_predictions": 1,
            "annotations_ids": !anystr "",
            "annotations": [],
            "predictions": [
            {

              "model_version": "undefined",
              "created_ago": "0\u00a0minutes",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_PREDICTIONS_TESTING"
                  ]
                }
              }
              ],
              "score": null,
              "cluster": null,
              "neighbors": null,
              "mislabeling": 0.0,


            }
            ],
            "drafts": [],
            "annotators": [],
            "project": !int "{project_pk}"
          },
          {
            "cancelled_annotations": 0,
            "storage_filename": null,
            "annotations_results": !anystr "",
            "data": {
              "int_field": 20,
              "text": "x2"
            },
            "predictions_results": !anystr "",
            "predictions_score": null,
            "total_annotations": 2,
            "total_predictions": 1,
            "annotations_ids": !anystr "",
            "annotations": [
            {

              "created_username": " test_suites_user@heartex.com, {created_by}",
              "created_ago": "0\u00a0minutes",
              "completed_by": !int "{created_by}",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_A"
                  ]
                }
              }
              ],
              "was_cancelled": false,
              "ground_truth": true,

              "lead_time": 3.0

            },
            {

              "created_username": " test_suites_user@heartex.com, {created_by}",
              "created_ago": "0\u00a0minutes",
              "completed_by": !int "{created_by}",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_A"
                  ]
                }
              }
              ],
              "was_cancelled": false,
              "ground_truth": true,

              "lead_time": 5.0

            }
            ],
            "predictions": [
            {

              "model_version": "model_version_A",
              "created_ago": "0\u00a0minutes",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_A"
                  ]
                }
              }
              ],
              "score": null,
              "cluster": null,
              "neighbors": null,
              "mislabeling": 0.0,


            }
            ],
            "drafts": [],
            "annotators": [
              !int "{created_by}"
            ],
            "project": !int "{project_pk}"
          },
          {
            "cancelled_annotations": 0,
            "storage_filename": null,
            "annotations_results": !raw "[{from_name: text_class, to_name: text, type: choices, value: {choices: [class_TESTING]}}]",
            "data": {
              "int_field": "99",
              "text": "yoyo"
            },
            "predictions_results": "",
            "predictions_score": null,
            "total_annotations": 1,
            "total_predictions": 0,
            "annotations_ids": !anystr "",
            "annotations": [
            {

              "created_username": " test_suites_user@heartex.com, {created_by}",
              "created_ago": "0\u00a0minutes",
              "completed_by": !int "{created_by}",
              "result": [
              {
                "from_name": "text_class",
                "to_name": "text",
                "type": "choices",
                "value": {
                  "choices": [
                    "class_TESTING"
                  ]
                }
              }
              ],
              "was_cancelled": false,
              "ground_truth": true,

              "lead_time": null

            }
            ],
            "predictions": [],
            "drafts": [],
            "annotators": [
              !int "{created_by}"
            ],
            "project": !int "{project_pk}"
          }
          ]
        }

---
test_name: tasks-annotators
strict: false
marks:
  - usefixtures:
      - django_live_url
stages:

  - id: signup
    type: ref

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: create_filter_tasks
    request:
      files:
        json_file: tests/data_manager/tasks_annotations_predictions.json
      headers:
        content-type: multipart/form-data
      method: POST
      url: '{django_live_url}/api/projects/{project_pk}/import'
    response:
      json:
        annotation_count: 4
        prediction_count: 3
        task_count: 6
      status_code: 201

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:annotators",
                "operator": "not_contains",
                "type": "List",
                "value": "{created_by}"
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 0,
        "total_predictions": 1,
        "total": 3,
        "tasks": [
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "annotations_results": "",
          "data": {
            "int_field": 42,
            "text": "opop"
          },


          "predictions_score": null,
          "total_annotations": 0,
          "total_predictions": 1,
          "annotations_ids": !anystr "",
          "annotations": [],
          "predictions": [
          {

            "model_version": "undefined",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_PREDICTIONS_TESTING"
                ]
              }
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0,


          }
          ],
          "drafts": [],

          "annotators": [],
          "project": !int "{project_pk}"
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "annotations_results": "",
          "data": {
            "text": "vivi"
          },

          "predictions_results": "",
          "predictions_score": null,
          "total_annotations": 0,
          "total_predictions": 0,
          "annotations_ids": !anystr "",
          "annotations": [],
          "predictions": [],
          "drafts": [],

          "annotators": [],
          "project": !int "{project_pk}"
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "annotations_results": "",
          "data": {
            "text": "zzz"
          },

          "predictions_results": "",
          "predictions_score": null,
          "total_annotations": 0,
          "total_predictions": 0,
          "annotations_ids": !anystr "",
          "annotations": [],
          "predictions": [],
          "drafts": [],

          "annotators": [],
          "project": !int "{project_pk}"
        }
        ]
      }

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:annotators",
                "operator": "contains",
                "type": "List",
                "value": "{created_by}"
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks_after_setup
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 4,
        "total_predictions": 2,
        "total": 3,
        "tasks": [
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "data": {
            "text": "Test example phrase 1",
            "int_field": 1
          },


          "predictions_score": null,
          "total_annotations": 1,
          "total_predictions": 1,
          "annotations_ids": !anystr "",
          "annotations": [
          {

            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              }
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,

            "lead_time": 3.0

          }
          ],
          "predictions": [
          {

            "model_version": "model_version_A",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              }
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0,


          }
          ],
          "drafts": [],

          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "data": {
            "int_field": 20,
            "text": "x2"
          },


          "predictions_score": null,
          "total_annotations": 2,
          "total_predictions": 1,
          "annotations_ids": !anystr "",
          "annotations": [
          {

            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              }
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,

            "lead_time": 3.0

          },
          {

            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              }
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,

            "lead_time": 5.0

          }
          ],
          "predictions": [
          {

            "model_version": "model_version_A",
            "created_ago": "0\u00a0minutes",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_A"
                ]
              }
            }
            ],
            "score": null,
            "cluster": null,
            "neighbors": null,
            "mislabeling": 0.0,

          }
          ],
          "drafts": [],
          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        },
        {
          "cancelled_annotations": 0,
          "storage_filename": null,

          "data": {
            "int_field": "99",
            "text": "yoyo"
          },

          "predictions_results": "",
          "predictions_score": null,
          "total_annotations": 1,
          "total_predictions": 0,
          "annotations_ids": !anystr "",
          "annotations": [
          {

            "created_username": " test_suites_user@heartex.com, {created_by}",
            "created_ago": "0\u00a0minutes",
            "completed_by": !int "{created_by}",
            "result": [
            {
              "from_name": "text_class",
              "to_name": "text",
              "type": "choices",
              "value": {
                "choices": [
                  "class_TESTING"
                ]
              }
            }
            ],
            "was_cancelled": false,
            "ground_truth": true,

            "lead_time": null

          }
          ],
          "predictions": [],
          "drafts": [],

          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        }
        ]
      }

---
test_name: tasks-minimal-fields
strict: false
marks:
  - usefixtures:
      - django_live_url
stages:

  - id: signup
    type: ref

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: create_filter_tasks
    request:
      files:
        json_file: tests/data_manager/tasks_annotations_predictions.json
      headers:
        content-type: multipart/form-data
      method: POST
      url: '{django_live_url}/api/projects/{project_pk}/import'
    response:
      json:
        annotation_count: 4
        prediction_count: 3
        task_count: 6
      status_code: 201

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:annotators",
                "operator": "empty",
                "type": "List",
                "value": false
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 4,
        "total_predictions": 2,
        "total": 3,
        "tasks": [
        {

          "annotations_results": "",
          "data": {
            "text": "Test example phrase 1",
            "int_field": 1
          },

          "predictions_results": "",
          "total_annotations": 1,
          "annotations_ids": !anystr "",
          "drafts": [],
          "file_upload": null,
          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        },
        {

          "annotations_results": "",
          "data": {
            "int_field": 20,
            "text": "x2"
          },

          "predictions_results": "",
          "total_annotations": 2,
          "annotations_ids": !anystr "",
          "drafts": [],
          "file_upload": null,
          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        },
        {

          "annotations_results": "",
          "data": {
            "int_field": "99",
            "text": "yoyo"
          },

          "predictions_results": "",
          "total_annotations": 1,
          "annotations_ids": !anystr "",
          "drafts": [],
          "file_upload": null,
          "annotators": [
            !int "{created_by}"
          ],
          "project": !int "{project_pk}"
        }
        ]
      }

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "and",
            "items": [
              {
                "filter": "filter:tasks:predictions_results",
                "operator": "equal",
                "type": "String",
                "value": "PREDICTIONS"
              },
              {
                "filter": "filter:tasks:annotations_results",
                "operator": "not_equal",
                "type": "String",
                "value": "PREDICTIONS"
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 0,
        "total_predictions": 0,
        "total": 0,
        }

  - name: get_tasks_with_page
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}&page=1'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 0,
        "total_predictions": 0,
        "total": 0,
      }

  - name: get_first_task
    request:
      method: GET
      url: '{django_live_url}/api/projects/{project_pk}/next'
    response:
      save:
        json:
          first_task_id: id
      status_code: 200

  - name: create_annotation_first_task
    request:
      headers:
        content-type: application/json
      json:
        lead_time: 5
        result:
        - from_name: label
          to_name: text
          type: choices
          value:
            choices:
            - class_B
      method: POST
      url: '{django_live_url}/api/tasks/{first_task_id}/annotations'
    response:
      save:
        json:
          annotation_pk: id
      status_code: 201

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:updated_by",
                "operator": "contains",
                "type": "List",
                "value": !int "{created_by}",
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 1,
        "total_predictions": 0,
        "total": 1,
      }

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:updated_by",
                "operator": "not_contains",
                "type": "List",
                "value": !int "{created_by}",
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 4,
        "total_predictions": 3,
        "total": 5,
      }

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {
            "conjunction": "or",
            "items": [
              {
                "filter": "filter:tasks:updated_by",
                "operator": "equal",
                "type": "List",
                "value": !int "{created_by}",
              }
            ]
          },
          "ordering": [
            "tasks:data.text"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?view={view.id}'
    response:
      status_code: 200
      verify_response_with:
        function: label_studio.tests.utils:save_response
      json: {
        "total_annotations": 1,
        "total_predictions": 0,
        "total": 1,
      }

---

test_name: tasks-storage-filename-s3
strict: false
marks:
  - usefixtures:
      - django_live_url
stages:

  - id: signup
    type: ref

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: Add S3 storage
    request:
      data:
        bucket: pytest-s3-images
        project: '{project_pk}'
        title: Testing S3 storage (bucket from conftest.py)
        use_blob_urls: true
        presign_ttl: 3600
        recursive_scan: true
      method: POST
      url: '{django_live_url}/api/storages/s3'
    response:
      save:
        json:
          storage_pk: id
      status_code: 201

  - name: Sync S3 storage
    request:
      method: POST
      url: '{django_live_url}/api/storages/s3/{storage_pk}/sync'
    response:
      json:
        last_sync_count: 4
      status_code: 200

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters": {},
          "ordering": [
            "tasks:storage_filename"
          ]
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      json: {
        "total_annotations": 0,
        "total_predictions": 0,
        "total": 4,
        "tasks": [
        {
          "storage_filename": "image1.jpg",
          "project": !int "{project_pk}"
        },
        {
          "storage_filename": "subdir/another/image2.jpg",
          "project": !int "{project_pk}"
        },
        {
          "storage_filename": "subdir/image1.jpg",
          "project": !int "{project_pk}"
        },
        {
          "storage_filename": "subdir/image2.jpg",
          "project": !int "{project_pk}"
        }
        ]
      }

---

test_name: tasks-storage-filename-local
strict: false
marks:
  - skipif: '"Windows" in platform.system()'
  - usefixtures:
    - django_live_url
    - local_files_storage
    - local_files_document_root_tempdir
stages:

  - id: signup
    name: Sign up
    request:
      url: "{django_live_url}/user/signup"
      data:
        email: test_suites_user@heartex.com
        password: 12345678
      method: POST
    response:
      status_code: 302
      save:
        $ext:
          function: tests.utils:os_independent_path
          extra_kwargs:
            path: 'files/subdir/test_image2.png'
            add_tempdir: true

  - id: create_project
    name: create_project
    request:
      data:
        title: Test Draft 1
        show_collab_predictions: true
        label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
      method: POST
      url: '{django_live_url}/api/projects'
    response:
      save:
        json:
          project_pk: id
          created_by: created_by.id
      status_code: 201

  - name: create local storage
    request:
      json:
        project: "{project_pk}"
        title: test
        regex_filter: ".*png"
        path: "{os_independent_path_parent}"
        use_blob_urls: true
      method: POST
      url: '{django_live_url}/api/storages/localfiles'
    response:
      save:
        json:
          storage_pk: id
      status_code: 201

  - name: sync local storage
    request:
      method: POST
      url: '{django_live_url}/api/storages/localfiles/{storage_pk}/sync'
    response:
      json:
        last_sync_count: 1
      status_code: 200

  - name: setup_views
    request:
      method: POST
      url: '{django_live_url}/api/dm/views/?project={project_pk}'
      json: {
        "data": {
          "filters":{
            "conjunction": "and",
            "items": [{
              "filter": "filter:tasks:storage_filename",
              "operator": "contains",
              "type": "String",
              "value": ".png"
            }]
          },
          "ordering": []
        },
        "project": !int "{project_pk}"
      }
    response:
      save:
        json:
          view: "@"
      status_code: 201

  - name: get_tasks
    request:
      method: GET
      url: '{django_live_url}/api/tasks?fields=all&view={view.id}'
    response:
      status_code: 200
      json: {
        "total_annotations": 0,
        "total_predictions": 0,
        "total": 1,
        "tasks": [
        {
          "storage_filename": "/tmp/files/subdir/test_image2.png",
          "project": !int "{project_pk}"
        }
        ]
      }

---

# See FilterSerializer; test logic preventing exploit that traverses the ORM
# to leak sensitive data character-by-character
test_name: tasks_api_filter_security_restrictions
strict: false
marks:
- usefixtures:
  - django_live_url
stages:

- id: signup
  type: ref

- id: create_project
  name: create_project
  request:
    data:
      title: Test Draft 1
      show_collab_predictions: true
      label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
    method: POST
    url: '{django_live_url}/api/projects'
  response:
    save:
      json:
        project_pk: id
        created_by: created_by.id
    status_code: 201

- name: create view with exploit filter should fail
  request:
    method: POST
    url: '{django_live_url}/api/dm/views'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:updated_by__sensitive_field"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 400
    json:
      validation_errors:
        filter_group:
          filters:
            - column:
              - '"__" is not generally allowed in filters. Consider asking your administrator to add "updated_by__sensitive_field" to DATA_MANAGER_FILTER_ALLOWLIST, but note that some filter expressions may pose a security risk'

- name: create view with allowlisted filter should succeed
  request:
    method: POST
    url: '{django_live_url}/api/dm/views'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:updated_by__active_organization"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 201
    save:
      json:
        view_pk: id

- name: change filter to typical column succeeds
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:updated_by"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 200

- name: change filter to unexpected prefix fails
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "tasks:filter:annotations_results"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 400
    json:
      validation_errors:
        filter_group:
          filters:
            - column:
              - 'Filter "tasks:filter:annotations_results" should start with "filter:tasks:"'

- name: change filter to include direction marker succeeds
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:-annotations_results"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 200

- name: invalid filter with direction marker fails, but suggests correct allowlist
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:-updated_by__sensitive_field"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 400
    json:
      validation_errors:
        filter_group:
          filters:
            - column:
              - '"__" is not generally allowed in filters. Consider asking your administrator to add "updated_by__sensitive_field" to DATA_MANAGER_FILTER_ALLOWLIST, but note that some filter expressions may pose a security risk'

- name: change filter to dotted data field with underscores succeeds
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "filter:tasks:data.images__0"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 200

- name: change filter to valid column without prefix fails
  request:
    method: PUT
    url: '{django_live_url}/api/dm/views/{view_pk}?interaction=filter&project={project_pk}'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            - filter: "annotations_results"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 400
    json:
      validation_errors:
        filter_group:
          filters:
            - column:
              - 'Filter "annotations_results" should start with "filter:tasks:"'

---

# Regression test preventing replace-all of prefixes from being used to construct exploit filters
test_name: tasks_api_prevent_prefix_regression
strict: false
marks:
- usefixtures:
  - django_live_url
stages:

- id: signup
  type: ref

- id: create_project
  name: create_project
  request:
    data:
      title: Test Draft 1
      show_collab_predictions: true
      label_config: '<View><Text name="text" value="$text"/><Choices name="text_class" toName="text"><Choice value="class_A"/><Choice value="class_B"/><Choice value="class_TESTING"/><Choice value="class_PREDICTIONS_TESTING"/></Choices></View>'
    method: POST
    url: '{django_live_url}/api/projects'
  response:
    save:
      json:
        project_pk: id
        created_by: created_by.id
    status_code: 201

# Perhaps our validation should be further improved, but for now, it's
# garbage in, garbage out.
- name: create view with prefix in middle of filter should succeed
  request:
    method: POST
    url: '{django_live_url}/api/dm/views'
    json:
      project: '{project_pk}'
      data:
        filters:
          conjunction: and
          items:
            # in an earlier version, preprocess_field_name would have
            # transformed this to updated_by__sensitive_field
            - filter: "filter:tasks:updated_by_tasks:_sensitive_field"
              operator: empty
              value: "true"
              type: String
  response:
    status_code: 201
    save:
      json:
        view_pk: id

- name: get_tasks fails because "updated_by_tasks:_sensitive_field" doesn't resolve to a field
  request:
    method: GET
    url: '{django_live_url}/api/tasks?view={view_pk}'
  response:
    # 500 actually expected here
    status_code: 500
