Skip to content

Commit e363602

Browse files
authored
Merge pull request #91 from browniebroke/increase-test-coverage
Increase utilities test coverage to 100%
2 parents 9fd90de + fd9180c commit e363602

File tree

2 files changed

+198
-5
lines changed

2 files changed

+198
-5
lines changed

drf_excel/utilities.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.conf import settings as django_settings
2-
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE
2+
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE, Cell
33
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
44

55
ESCAPE_CHARS = ("=", "-", "+", "@", "\t", "\r", "\n")
@@ -86,7 +86,7 @@ def sanitize_value(value):
8686
return value
8787

8888

89-
def set_cell_style(cell, style: XLSXStyle):
89+
def set_cell_style(cell: Cell, style: XLSXStyle):
9090
# We are not applying the whole style directly, otherwise we cannot override any part of it
9191
if style:
9292
# Only set properties that are provided

tests/test_utilities.py

Lines changed: 196 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,198 @@
1-
from drf_excel.utilities import get_setting
1+
from types import SimpleNamespace
22

3+
import pytest
4+
import datetime as dt
35

4-
def test_get_setting_not_found():
5-
assert get_setting("INTEGER_FORMAT") is None
6+
from openpyxl.cell import Cell
7+
from openpyxl.styles import Font, PatternFill, Alignment, Border, Color, Side
8+
from openpyxl.workbook import Workbook
9+
from openpyxl.worksheet.worksheet import Worksheet
10+
11+
from drf_excel.utilities import (
12+
get_setting,
13+
XLSXStyle,
14+
get_attribute,
15+
sanitize_value,
16+
set_cell_style,
17+
)
18+
19+
20+
class TestXLSXStyle:
21+
def test_no_style_dict(self):
22+
style = XLSXStyle()
23+
assert style.font is None
24+
assert style.fill is None
25+
assert style.alignment is None
26+
assert style.number_format is None
27+
assert style.border is None
28+
29+
def test_with_font_style(self):
30+
style = XLSXStyle(
31+
{
32+
"font": {"name": "Arial", "size": 14, "bold": True},
33+
}
34+
)
35+
36+
assert isinstance(style.font, Font)
37+
assert style.font.name == "Arial"
38+
assert style.font.size == 14
39+
assert style.font.bold is True
40+
41+
def test_with_fill_style(self):
42+
style = XLSXStyle(
43+
{
44+
"fill": {
45+
"fill_type": "solid",
46+
"start_color": "FFCCFFCC",
47+
},
48+
}
49+
)
50+
51+
assert isinstance(style.fill, PatternFill)
52+
assert style.fill.fill_type == "solid"
53+
assert isinstance(style.fill.start_color, Color)
54+
assert style.fill.start_color.value == "FFCCFFCC"
55+
assert style.fill.start_color.type == "rgb"
56+
57+
def test_with_alignment_style(self):
58+
style = XLSXStyle(
59+
{
60+
"alignment": {
61+
"horizontal": "center",
62+
"wrap_text": True,
63+
"text_rotation": 20,
64+
},
65+
}
66+
)
67+
68+
assert isinstance(style.alignment, Alignment)
69+
assert style.alignment.horizontal == "center"
70+
assert style.alignment.wrap_text is True
71+
assert style.alignment.text_rotation == 20
72+
73+
def test_with_border_style(self):
74+
style = XLSXStyle(
75+
{"border_side": {"border_style": "thin", "color": "FF000000"}}
76+
)
77+
78+
assert isinstance(style.border, Border)
79+
assert isinstance(style.border.left, Side)
80+
assert style.border.left.border_style == "thin"
81+
assert isinstance(style.border.left.color, Color)
82+
assert style.border.left.color.value == "FF000000"
83+
assert style.border.left.color.type == "rgb"
84+
assert (
85+
style.border.left
86+
== style.border.right
87+
== style.border.top
88+
== style.border.bottom
89+
)
90+
91+
def test_with_number_format_style(self):
92+
style = XLSXStyle({"format": "0.00E+00"})
93+
94+
assert style.number_format == "0.00E+00"
95+
96+
97+
class TestGetAttribute:
98+
def test_existing(self):
99+
obj = SimpleNamespace(a=1)
100+
assert get_attribute(obj, "a") == 1
101+
102+
def test_non_existing(self):
103+
obj = SimpleNamespace(a=1)
104+
assert get_attribute(obj, "b") is None
105+
106+
def test_non_existing_with_default(self):
107+
obj = SimpleNamespace(a=1)
108+
assert get_attribute(obj, "b", default="c") == "c"
109+
110+
def test_from_getter_method(self):
111+
class Foo:
112+
def get_b(self):
113+
return 1
114+
115+
obj = Foo()
116+
assert get_attribute(obj, "b") == 1
117+
118+
119+
class TestGetSetting:
120+
def test_not_defined(self):
121+
assert get_setting("DUMMY") is None
122+
123+
def test_not_defined_with_default(self):
124+
assert get_setting("DUMMY", "default") == "default"
125+
126+
def test_defined(self, settings):
127+
settings.DRF_EXCEL_DUMMY = "custom-value"
128+
assert get_setting("DUMMY") == "custom-value"
129+
130+
131+
@pytest.mark.parametrize(
132+
("value", "expected_output"),
133+
[
134+
# Regular values without illegal characters
135+
(None, None),
136+
("test", "test"),
137+
(True, "True"),
138+
(False, False), # Bug?
139+
(1, "1"),
140+
(dt.date(2020, 1, 1), "2020-01-01"),
141+
(dt.datetime(2020, 1, 1, 1, 1, 1), "2020-01-01 01:01:01"),
142+
# With illegal characters
143+
("test\000", "test"),
144+
("t\001est", "test"),
145+
("test\005er", "tester"),
146+
("tes\010t", "test"),
147+
("test\013 me", "test me"),
148+
("test\014", "test"),
149+
("test\016", "test"),
150+
("test\020", "test"),
151+
("test\030", "test"),
152+
("test\037", "test"),
153+
# Escape if starts with these characters
154+
("=test", "'=test"),
155+
("-example", "'-example"),
156+
("+foo", "'+foo"),
157+
("@bar", "'@bar"),
158+
("\tbaz", "'\tbaz"),
159+
("\nqux", "'\nqux"),
160+
("\rquux", "'\rquux"),
161+
],
162+
)
163+
def test_sanitize_value(value, expected_output):
164+
assert sanitize_value(value) == expected_output
165+
166+
167+
class TestSetCellStyle:
168+
@pytest.fixture
169+
def cell(self):
170+
worksheet = Worksheet(Workbook())
171+
return Cell(worksheet)
172+
173+
def test_no_style(self, cell):
174+
set_cell_style(cell, None)
175+
assert cell.font is not None
176+
177+
def test_with_styles(self, cell):
178+
style = XLSXStyle(
179+
{
180+
"font": {"name": "Arial"},
181+
"fill": {"fill_type": "solid"},
182+
"alignment": {"horizontal": "center"},
183+
"border_side": {"border_style": "thin"},
184+
"format": "0.00",
185+
},
186+
)
187+
set_cell_style(cell, style)
188+
assert cell.font.name == "Arial"
189+
assert cell.fill.fill_type == "solid"
190+
assert cell.alignment.horizontal == "center"
191+
assert cell.border.left.border_style == "thin"
192+
assert cell.number_format == "0.00"
193+
194+
def test_with_partial_styles(self, cell):
195+
style = XLSXStyle({"font": {"name": "Arial"}})
196+
set_cell_style(cell, style)
197+
assert cell.font.name == "Arial"
198+
assert cell.number_format == "General"

0 commit comments

Comments
 (0)