Skip to content

Commit

Permalink
Merge pull request #55 from saritasa-nest/feature/improve-coverage
Browse files Browse the repository at this point in the history
Add tests for views and actions
  • Loading branch information
Eg0ra authored Oct 18, 2024
2 parents 6c6146a + 325e1fe commit 4f465a7
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 14 deletions.
8 changes: 2 additions & 6 deletions import_export_extensions/api/views/import_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,7 @@ def confirm(self, *args, **kwargs):
try:
job.confirm_import()
except ValueError as error:
raise exceptions.ValidationError(
f"Wrong import job status: {job.import_status}",
) from error
raise exceptions.ValidationError(error.args[0]) from error

serializer = self.get_serializer(instance=job)
return response.Response(
Expand All @@ -173,9 +171,7 @@ def cancel(self, *args, **kwargs):
try:
job.cancel_import()
except ValueError as error:
raise exceptions.ValidationError(
f"Wrong import job status: {job.import_status}",
) from error
raise exceptions.ValidationError(error.args[0]) from error

serializer = self.get_serializer(instance=job)
return response.Response(
Expand Down
8 changes: 4 additions & 4 deletions import_export_extensions/models/export_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ def cancel_export(self) -> None:
"""
self._check_export_status_correctness(
expected_statuses=[
self.ExportStatus.CREATED.value,
self.ExportStatus.EXPORTING.value,
],
expected_statuses=( # type: ignore
self.ExportStatus.CREATED,
self.ExportStatus.EXPORTING,
),
)

# send signal to celery to revoke task
Expand Down
74 changes: 74 additions & 0 deletions test_project/tests/integration_tests/test_api/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,77 @@ def test_export_api_detail(
)
assert response.status_code == status.HTTP_200_OK, response.data
assert response.data["export_finished"]


@pytest.mark.django_db(transaction=True)
@pytest.mark.parametrize(
argnames=["allowed_cancel_status"],
argvalues=[
pytest.param(
ExportJob.ExportStatus.CREATED,
id="Cancel job with `CREATED` status",
),
pytest.param(
ExportJob.ExportStatus.EXPORTING,
id="Cancel job with `EXPORTING` status",
),
],
)
def test_export_api_cancel(
admin_api_client: test.APIClient,
artist_export_job: ExportJob,
allowed_cancel_status: ExportJob.ExportStatus,
):
"""Ensure that export canceled with allowed statuses."""
artist_export_job.export_status = allowed_cancel_status
artist_export_job.save()
response = admin_api_client.post(
path=reverse(
"export-artist-cancel",
kwargs={"pk": artist_export_job.pk},
),
)
assert response.status_code == status.HTTP_200_OK, response.data
assert response.data["export_status"] == ExportJob.ExportStatus.CANCELLED
assert not response.data["export_finished"]


@pytest.mark.django_db(transaction=True)
@pytest.mark.parametrize(
argnames=["incorrect_job_status"],
argvalues=[
pytest.param(
ExportJob.ExportStatus.EXPORT_ERROR,
id="Cancel export job with `EXPORT_ERROR` status",
),
pytest.param(
ExportJob.ExportStatus.EXPORTED,
id="Cancel export job with `EXPORTED` status",
),
pytest.param(
ExportJob.ExportStatus.CANCELLED,
id="Cancel export job with `CANCELLED` status",
),
],
)
def test_export_api_cancel_with_errors(
admin_api_client: test.APIClient,
artist_export_job: ExportJob,
incorrect_job_status: ExportJob.ExportStatus,
):
"""Ensure that export job with incorrect statuses cannot be canceled."""
artist_export_job.export_status = incorrect_job_status
artist_export_job.save()
response = admin_api_client.post(
path=reverse(
"export-artist-cancel",
kwargs={"pk": artist_export_job.pk},
),
)
expected_error_message = (
f"ExportJob with id {artist_export_job.pk} has incorrect status: "
f"`{incorrect_job_status.value}`. Expected statuses: "
"['CREATED', 'EXPORTING']"
)
assert response.status_code == status.HTTP_400_BAD_REQUEST, response.data
assert str(response.data[0]) == expected_error_message
183 changes: 179 additions & 4 deletions test_project/tests/integration_tests/test_api/test_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def test_import_api_detail_with_row_errors(
"""Ensure import detail api shows row errors."""
expected_error_message = "Instrument matching query does not exist."
invalid_row_values = [
str(existing_artist.id),
str(existing_artist.pk),
existing_artist.external_id,
existing_artist.name,
str(existing_artist.instrument_id),
Expand All @@ -123,7 +123,7 @@ def test_import_api_detail_with_row_errors(
response = admin_api_client.get(
path=reverse(
"import-artist-detail",
kwargs={"pk": import_artist_job.id},
kwargs={"pk": import_artist_job.pk},
),
)

Expand All @@ -149,7 +149,7 @@ def test_import_api_detail_with_base_errors(
# Create file with missing external_id header
file_content = django_files.ContentFile(
"id,name,instrument\n"
f"{existing_artist.id},{existing_artist.name},"
f"{existing_artist.pk},{existing_artist.name},"
f"{existing_artist.instrument_id}\n",
)
uploaded_file = django_files.File(file_content.file, "data.csv")
Expand All @@ -164,7 +164,7 @@ def test_import_api_detail_with_base_errors(
response = admin_api_client.get(
path=reverse(
"import-artist-detail",
kwargs={"pk": import_artist_job.id},
kwargs={"pk": import_artist_job.pk},
),
)

Expand All @@ -174,3 +174,178 @@ def test_import_api_detail_with_base_errors(
response.data["input_error"]["base_errors"][0]
== expected_error_message
)


@pytest.mark.django_db(transaction=True)
def test_import_api_confirm_parsed_job(
admin_api_client: APIClient,
artist_import_job: ImportJob,
):
"""Check that parsed import job can be confirmed."""
artist_import_job.parse_data()
artist_import_job.refresh_from_db()
response = admin_api_client.post(
path=reverse(
"import-artist-confirm",
kwargs={"pk": artist_import_job.pk},
),
)

assert response.status_code == status.HTTP_200_OK, response.data
assert response.data["import_status"] == ImportJob.ImportStatus.CONFIRMED


@pytest.mark.django_db(transaction=True)
@pytest.mark.parametrize(
argnames=["incorrect_job_status"],
argvalues=[
pytest.param(
ImportJob.ImportStatus.CREATED,
id="Confirm import job with `CREATED` status",
),
pytest.param(
ImportJob.ImportStatus.PARSING,
id="Confirm import job with `PARSING` status",
),
pytest.param(
ImportJob.ImportStatus.PARSE_ERROR,
id="Confirm import job with `PARSE_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.CONFIRMED,
id="Confirm import job with `CONFIRMED` status",
),
pytest.param(
ImportJob.ImportStatus.INPUT_ERROR,
id="Confirm import job with `INPUT_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORTING,
id="Confirm import job with `IMPORTING` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORT_ERROR,
id="Confirm import job with `IMPORT_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORTED,
id="Confirm import job with `IMPORTED` status",
),
pytest.param(
ImportJob.ImportStatus.CANCELLED,
id="Confirm import job with `CANCELLED` status",
),
],
)
def test_import_api_confirm_incorrect_job_status(
admin_api_client: APIClient,
artist_import_job: ImportJob,
incorrect_job_status: ImportJob.ImportStatus,
):
"""Ensure that not parsed job can't be confirmed."""
artist_import_job.import_status = incorrect_job_status
artist_import_job.save()

response = admin_api_client.post(
path=reverse(
"import-artist-confirm",
kwargs={"pk": artist_import_job.pk},
),
)
expected_error_message = (
f"ImportJob with id {artist_import_job.pk} has incorrect status: "
f"`{incorrect_job_status.value}`. Expected statuses: ['PARSED']"
)
assert response.status_code == status.HTTP_400_BAD_REQUEST, response.data
assert str(response.data[0]) == expected_error_message


@pytest.mark.django_db(transaction=True)
@pytest.mark.parametrize(
argnames=["allowed_cancel_status"],
argvalues=[
pytest.param(
ImportJob.ImportStatus.CREATED,
id="Cancel import job with `CREATED` status",
),
pytest.param(
ImportJob.ImportStatus.PARSING,
id="Cancel import job with `PARSING` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORTING,
id="Cancel import job with `IMPORTING` status",
),
pytest.param(
ImportJob.ImportStatus.CONFIRMED,
id="Cancel import job with `CONFIRMED` status",
),
],
)
def test_import_api_cancel_job(
admin_api_client: APIClient,
artist_import_job: ImportJob,
allowed_cancel_status: ImportJob.ImportStatus,
):
"""Check that import job with allowed statuses can be cancelled."""
artist_import_job.import_status = allowed_cancel_status
artist_import_job.save()
response = admin_api_client.post(
path=reverse(
"import-artist-cancel",
kwargs={"pk": artist_import_job.pk},
),
)

assert response.status_code == status.HTTP_200_OK, response.data
assert response.data["import_status"] == ImportJob.ImportStatus.CANCELLED


@pytest.mark.django_db(transaction=True)
@pytest.mark.parametrize(
argnames=["incorrect_job_status"],
argvalues=[
pytest.param(
ImportJob.ImportStatus.INPUT_ERROR,
id="Cancel import job with `INPUT_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.PARSE_ERROR,
id="Cancel import job with `PARSE_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORT_ERROR,
id="Cancel import job with `IMPORT_ERROR` status",
),
pytest.param(
ImportJob.ImportStatus.IMPORTED,
id="Cancel import job with `IMPORTED` status",
),
pytest.param(
ImportJob.ImportStatus.CANCELLED,
id="Cancel import job with `CANCELLED` status",
),
],
)
def test_import_api_cancel_incorrect_job_status(
admin_api_client: APIClient,
artist_import_job: ImportJob,
incorrect_job_status: ImportJob.ImportStatus,
):
"""Ensure that import job with incorrect statuses cannot be canceled."""
artist_import_job.import_status = incorrect_job_status
artist_import_job.save()

response = admin_api_client.post(
path=reverse(
"import-artist-cancel",
kwargs={"pk": artist_import_job.pk},
),
)
expected_error_message = (
f"ImportJob with id {artist_import_job.pk} has incorrect status: "
f"`{incorrect_job_status.value}`. Expected statuses: "
"['CREATED', 'PARSING', 'CONFIRMED', 'IMPORTING']"
)
assert response.status_code == status.HTTP_400_BAD_REQUEST, response.data
assert str(response.data[0]) == expected_error_message
32 changes: 32 additions & 0 deletions test_project/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sys

from rest_framework import viewsets

import pytest
import pytest_mock

from import_export_extensions.api.views import (
ExportJobViewSet,
ImportJobViewSet,
)
from test_project.fake_app.resources import SimpleArtistResource


@pytest.mark.parametrize(
argnames="viewset_class",
argvalues=[
ExportJobViewSet,
ImportJobViewSet,
],
)
def test_new_viewset_class(
viewset_class: type[viewsets.GenericViewSet],
mocker: pytest_mock.MockerFixture,
):
"""Check that if drf_spectacular is not set it will not raise an error."""
mocker.patch.dict(sys.modules, {"drf_spectacular.utils": None})

class TestViewSet(viewset_class):
resource_class = SimpleArtistResource

assert TestViewSet is not None

0 comments on commit 4f465a7

Please sign in to comment.