Skip to content

Commit

Permalink
Merge pull request #93 from browniebroke/test-coverage-renderers
Browse files Browse the repository at this point in the history
Increase test coverage for renderers.py
  • Loading branch information
FlipperPA authored Oct 10, 2024
2 parents dd6a7d1 + d2d88ad commit 339e088
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 16 deletions.
6 changes: 3 additions & 3 deletions drf_excel/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Render `data` into XLSX workbook, returning a workbook.
"""
if not self._check_validation_data(data):
return json.dumps(data)

if data is None:
return bytes()

if not self._check_validation_data(data):
return json.dumps(data)

wb = Workbook()
self.ws = wb.active

Expand Down
13 changes: 13 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import io
from typing import Union, Callable

import pytest
from openpyxl.reader.excel import load_workbook
from openpyxl.workbook import Workbook
from openpyxl.worksheet.worksheet import Worksheet

Expand All @@ -11,3 +15,12 @@ def workbook() -> Workbook:
@pytest.fixture
def worksheet(workbook: Workbook) -> Worksheet:
return Worksheet(workbook)


@pytest.fixture
def workbook_reader() -> Callable[[Union[bytes, str]], Workbook]:
def reader_func(buffer: Union[bytes, str]) -> Workbook:
io_buffer = io.BytesIO(buffer)
return load_workbook(io_buffer, read_only=True)

return reader_func
50 changes: 50 additions & 0 deletions tests/test_renderers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from PIL import Image
from rest_framework import serializers
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from drf_excel.renderers import XLSXRenderer


class MySerializer(serializers.Serializer):
title = serializers.CharField()


class MyBaseView(GenericAPIView):
serializer_class = MySerializer

def retrieve(self, request, *args, **kwargs):
return Response({"title": "example"})


class TestXLSXRenderer:
renderer = XLSXRenderer()

def test_validation_error(self):
assert self.renderer.render({"detail": "invalid"}) == '{"detail": "invalid"}'

def test_none(self):
assert self.renderer.render(None) == b""

def test_with_header_attribute(self, tmp_path, workbook_reader):
image_path = tmp_path / "image.png"
with Image.new(mode="RGB", size=(100, 100), color="blue") as img:
img.save(image_path, format="png")

class MyView(MyBaseView):
header = {
"use_header": True,
"header_title": "My Header",
"tab_title": "My Tab",
"img": str(image_path),
"style": {"font": {"name": "Arial"}},
}

result = self.renderer.render({}, renderer_context={"view": MyView})
wb = workbook_reader(result)
sheet = wb.worksheets[0]
rows = list(sheet.rows)
assert len(rows) == 1
row0_col0 = rows[0][0]
assert row0_col0.value == "My Header"
assert row0_col0.font.name == "Arial"
58 changes: 49 additions & 9 deletions tests/test_viewset_mixin.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import io
import datetime as dt

import pytest
from openpyxl.reader.excel import load_workbook
from rest_framework.test import APIClient
from time_machine import TimeMachineFixture

from tests.testapp.models import ExampleModel
from tests.testapp.models import ExampleModel, AllFieldsModel, Tag

pytestmark = pytest.mark.django_db


@pytest.fixture
def api_client():
return APIClient()


@pytest.mark.django_db
def test_simple_viewset_model(api_client):
def test_simple_viewset_model(api_client, workbook_reader):
ExampleModel.objects.create(title="test 1", description="This is a test")
ExampleModel.objects.create(title="test 2", description="Another test")
ExampleModel.objects.create(title="test 3", description="Testing this out")
Expand All @@ -29,11 +30,10 @@ def test_simple_viewset_model(api_client):
response.headers["content-disposition"] == "attachment; filename=my_export.xlsx"
)

workbook_buffer = io.BytesIO(response.content)
workbook = load_workbook(workbook_buffer, read_only=True)
wb = workbook_reader(response.content)

assert len(workbook.worksheets) == 1
sheet = workbook.worksheets[0]
assert len(wb.worksheets) == 1
sheet = wb.worksheets[0]
rows = list(sheet.rows)
assert len(rows) == 4
r0, r1, r2, r3 = rows
Expand All @@ -53,3 +53,43 @@ def test_simple_viewset_model(api_client):
assert len(r3) == 2
assert r3[0].value == "test 3"
assert r3[1].value == "Testing this out"


def test_all_fields_viewset(
api_client, time_machine: TimeMachineFixture, workbook_reader
):
time_machine.move_to(dt.datetime(2023, 9, 10, 15, 44, 37))
instance = AllFieldsModel.objects.create(title="Hello", age=36, is_active=True)
instance.tags.set(
[
Tag.objects.create(name="test"),
Tag.objects.create(name="example"),
]
)
response = api_client.get("/all-fields/")
assert response.status_code == 200

wb = workbook_reader(response.content)
sheet = wb.worksheets[0]
rows = list(sheet.rows)
assert len(rows) == 2
r0, r1 = rows

assert [col.value for col in r0] == [
"title",
"created_at",
"updated_date",
"updated_time",
"age",
"is_active",
"tags",
]
assert [col.value for col in r1] == [
"Hello",
dt.datetime(2023, 9, 10, 15, 44, 37),
dt.datetime(2023, 9, 10, 0, 0),
dt.time(15, 44, 37),
36,
True,
"test, example",
]
23 changes: 23 additions & 0 deletions tests/testapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,26 @@ class ExampleModel(models.Model):

def __str__(self):
return self.title


class Tag(models.Model):
name = models.CharField(max_length=100)

def __str__(self):
return self.name


class AllFieldsModel(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_date = models.DateField(auto_now=True)
updated_time = models.TimeField(auto_now=True)
age = models.IntegerField()
is_active = models.BooleanField(default=True)
tags = models.ManyToManyField(Tag, related_name="all_fields")

def __str__(self):
return self.title

def get_tag_names(self):
return [tag.name for tag in self.tags.all()]
18 changes: 17 additions & 1 deletion tests/testapp/serializers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
from rest_framework import serializers

from .models import ExampleModel
from .models import ExampleModel, AllFieldsModel


class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ("title", "description")


class AllFieldsSerializer(serializers.ModelSerializer):
tags = serializers.ListField(source="get_tag_names")

class Meta:
model = AllFieldsModel
fields = (
"title",
"created_at",
"updated_date",
"updated_time",
"age",
"is_active",
"tags",
)
11 changes: 9 additions & 2 deletions tests/testapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
from drf_excel.mixins import XLSXFileMixin
from drf_excel.renderers import XLSXRenderer

from .models import ExampleModel
from .serializers import ExampleSerializer
from .models import ExampleModel, AllFieldsModel
from .serializers import ExampleSerializer, AllFieldsSerializer


class ExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
renderer_classes = (XLSXRenderer,)
filename = "my_export.xlsx"


class AllFieldsViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
queryset = AllFieldsModel.objects.all()
serializer_class = AllFieldsSerializer
renderer_classes = (XLSXRenderer,)
filename = "al_fileds.xlsx"
3 changes: 2 additions & 1 deletion tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from rest_framework import routers

from .testapp.views import ExampleViewSet
from .testapp.views import ExampleViewSet, AllFieldsViewSet

router = routers.SimpleRouter()
router.register(r"examples", ExampleViewSet)
router.register(r"all-fields", AllFieldsViewSet)

urlpatterns = router.urls
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ deps =

djangorestframework
openpyxl
Pillow

pytest
pytest-django
pytest-cov
django-coverage-plugin
time-machine

commands = {posargs:python -m pytest}

0 comments on commit 339e088

Please sign in to comment.