Skip to content

Commit

Permalink
Improve tests naming and codestyle
Browse files Browse the repository at this point in the history
  • Loading branch information
Eg0ra committed Oct 21, 2024
1 parent ee35255 commit dc0ce20
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 53 deletions.
17 changes: 11 additions & 6 deletions import_export_extensions/admin/model_admins/export_job_admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

from http import HTTPStatus

from django.contrib import admin, messages
from django.core.handlers.wsgi import WSGIRequest
from django.db.models import QuerySet
Expand Down Expand Up @@ -92,7 +94,10 @@ def export_job_progress_view(
id=job_id,
)
except self.export_job_model.DoesNotExist as error:
return JsonResponse(dict(validation_error=error.args[0]))
return JsonResponse(
dict(validation_error=error.args[0]),
status=HTTPStatus.NOT_FOUND,
)

response_data = dict(status=job.export_status.title())

Expand All @@ -103,12 +108,12 @@ def export_job_progress_view(
total = 0
current = 0
job_progress = job.progress
info = job_progress["info"]
progress_info = job_progress["info"]

if info and info["total"]:
percent = int(100 / info["total"] * info["current"])
total = info["total"]
current = info["current"]
if progress_info and progress_info["total"]:
total = progress_info["total"]
current = progress_info["current"]
percent = int(100 / total * current)

response_data.update(
dict(
Expand Down
12 changes: 11 additions & 1 deletion import_export_extensions/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,17 @@ class Meta:


class TaskStateInfo(typing.TypedDict):
"""Class representing task state dict."""
"""Class representing task state dict.
Possible states:
1. PENDING
2. STARTED
3. SUCCESS
4. EXPORTING - custom status that also set export info
https://docs.celeryproject.org/en/latest/userguide/tasks.html#states
"""

state: str
info: dict[str, int] | None
Expand Down
19 changes: 1 addition & 18 deletions import_export_extensions/models/export_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,24 +157,7 @@ def export_filename(self) -> str:

@property
def progress(self) -> TaskStateInfo | None:
"""Return dict with parsing state.
Example for celery (celery) mode::
{
'state': 'EXPORTING',
'info': {'current': 15, 'total': 100}
}
Possible states:
1. PENDING
2. STARTED
3. SUCCESS
4. EXPORTING - custom status that also set export info
https://docs.celeryproject.org/en/latest/userguide/tasks.html#states
"""
"""Return dict with export state."""
if (
self.export_task_id
and self.export_status == self.ExportStatus.EXPORTING
Expand Down
65 changes: 42 additions & 23 deletions test_project/tests/integration_tests/test_admin/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,30 @@ def test_export_using_admin_model(client: Client, superuser: User):


@pytest.mark.django_db(transaction=True)
def test_export_progress_for_sync_mode(
def test_export_progress_during_export(
client: Client,
superuser: User,
mocker: pytest_mock.MockerFixture,
):
"""Test export job admin progress page."""
"""Test export job admin progress page during export."""
client.force_login(superuser)

# Prepare data to imitate intermediate task state
fake_progress_info = {
"current": 2,
"total": 3,
}
mocker.patch(
"celery.result.AsyncResult.info",
new=fake_progress_info,
)
expected_percent = int(
fake_progress_info["current"] / fake_progress_info["total"] * 100,
)

artist_export_job = ArtistExportJobFactory()
artist_export_job.refresh_from_db()
artist_export_job.export_status = ExportJob.ExportStatus.EXPORTING
artist_export_job.save()

response = client.post(
path=reverse(
Expand All @@ -72,27 +87,26 @@ def test_export_progress_for_sync_mode(
),
)
assert response.status_code == status.HTTP_200_OK
assert response.json()["status"] == artist_export_job.export_status.title()
json_data = response.json()

assert json_data == {
"status": ExportJob.ExportStatus.EXPORTING.title(),
"state": "SUCCESS",
"percent": expected_percent,
**fake_progress_info,
}


@pytest.mark.django_db(transaction=True)
def test_export_progress_for_async_mode(
def test_export_progress_after_complete_export(
client: Client,
superuser: User,
mocker: pytest_mock.MockerFixture,
):
"""Test export job admin progress page."""
"""Test export job admin progress page after complete export."""
client.force_login(superuser)

# Prepare data to imitate intermediate task state
mocker.patch(
"celery.result.AsyncResult.info",
new={"current": 2, "total": 3},
)
expected_percent = 66
artist_export_job = ArtistExportJobFactory()
artist_export_job.export_status = ExportJob.ExportStatus.EXPORTING
artist_export_job.save()
artist_export_job.refresh_from_db()

response = client.post(
path=reverse(
Expand All @@ -101,10 +115,9 @@ def test_export_progress_for_async_mode(
),
)
assert response.status_code == status.HTTP_200_OK
json_data = response.json()
assert "total" in json_data
assert "current" in json_data
assert response.json()["percent"] == expected_percent
assert response.json() == {
"status": artist_export_job.export_status.title(),
}


@pytest.mark.django_db(transaction=True)
Expand All @@ -113,7 +126,11 @@ def test_export_progress_with_deleted_export_job(
superuser: User,
mocker: pytest_mock.MockerFixture,
):
"""Test export job admin progress page with deleted export job."""
"""Test export job admin progress page with deleted export job.
Check that page available, but return an error message.
"""
client.force_login(superuser)

mocker.patch("import_export_extensions.tasks.export_data_task.apply_async")
Expand All @@ -132,7 +149,7 @@ def test_export_progress_with_deleted_export_job(
),
)

assert response.status_code == status.HTTP_200_OK
assert response.status_code == status.HTTP_404_NOT_FOUND
assert response.json()["validation_error"] == expected_error_message


Expand All @@ -142,16 +159,17 @@ def test_export_progress_with_failed_celery_task(
superuser: User,
mocker: pytest_mock.MockerFixture,
):
"""Test export job admin progress page with deleted export job."""
"""Test than after celery fail ExportJob will be in export error status."""
client.force_login(superuser)

expected_error_message = "Mocked Error Message"
mocker.patch(
"celery.result.AsyncResult.state",
new=states.FAILURE,
)
mocker.patch(
"celery.result.AsyncResult.info",
new="Mocked Error Message",
new=ValueError(expected_error_message),
)
artist_export_job = ArtistExportJobFactory()
artist_export_job.export_status = ExportJob.ExportStatus.EXPORTING
Expand All @@ -172,3 +190,4 @@ def test_export_progress_with_failed_celery_task(
assert (
artist_export_job.export_status == ExportJob.ExportStatus.EXPORT_ERROR
)
assert artist_export_job.error_message == expected_error_message
6 changes: 1 addition & 5 deletions test_project/tests/test_import_job/test_import_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,8 @@ def test_import_create_with_max_rows(
skip_parse_step=True,
is_valid_file=False,
)
expected_error_message = (
"Too many rows `2`(Max: 1). Input file may be broken. If it's "
"spreadsheet file, please delete empty rows."
)

import_job.import_data()
import_job.refresh_from_db()
assert import_job.import_status == import_job.ImportStatus.IMPORT_ERROR
assert import_job.error_message in expected_error_message
assert "Too many rows `2`" in import_job.error_message

0 comments on commit dc0ce20

Please sign in to comment.