Coverage for cc_modules/tests/cc_tsv_tests.py : 24%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
3"""
4camcops_server/cc_modules/tests/cc_tsv_tests.py
6===============================================================================
8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).
10 This file is part of CamCOPS.
12 CamCOPS is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
17 CamCOPS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
25===============================================================================
27"""
29import io
30from typing import Any, Dict
31from unittest import TestCase
32import uuid
33from xml.dom.minidom import parseString
34import zipfile
36from camcops_server.cc_modules.cc_tsv import (
37 ODS_VIA_PYEXCEL,
38 TsvCollection,
39 TsvPage,
40 XLSX_VIA_PYEXCEL,
41)
43if ODS_VIA_PYEXCEL:
44 import pyexcel_ods3 # e.g. pip install pyexcel-ods3==0.5.3
45 ODSWriter = ODSSheet = None
46else:
47 from odswriter import ODSWriter, Sheet as ODSSheet # noqa
48 pyexcel_ods3 = None
50if XLSX_VIA_PYEXCEL:
51 import pyexcel_xlsx # e.g. pip install pyexcel-xlsx==0.5.7
52 openpyxl = XLWorkbook = XLWorksheet = None
53else:
54 from openpyxl.workbook.workbook import Workbook as XLWorkbook
55 pyexcel_xlsx = None
58# =============================================================================
59# Unit tests
60# =============================================================================
62class TsvCollectionTests(TestCase):
63 def test_xlsx_created_from_zero_rows(self) -> None:
64 page = TsvPage(name="test", rows=[])
65 coll = TsvCollection()
66 coll.add_page(page)
68 output = coll.as_xlsx()
70 # https://en.wikipedia.org/wiki/List_of_file_signatures
71 self.assertEqual(output[0], 0x50)
72 self.assertEqual(output[1], 0x4B)
73 self.assertEqual(output[2], 0x03)
74 self.assertEqual(output[3], 0x04)
76 def test_xlsx_worksheet_names_are_page_names(self) -> None:
77 page1 = TsvPage(name="name 1",
78 rows=[{"test data 1": "row 1"}])
79 page2 = TsvPage(name="name 2",
80 rows=[{"test data 2": "row 1"}])
81 page3 = TsvPage(name="name 3",
82 rows=[{"test data 3": "row 1"}])
83 coll = TsvCollection()
85 coll.add_pages([page1, page2, page3])
87 data = coll.as_xlsx()
88 buffer = io.BytesIO(data)
89 expected_sheetnames = ["name 1", "name 2", "name 3"]
90 if openpyxl:
91 wb = openpyxl.load_workbook(buffer) # type: XLWorkbook
92 self.assertEqual(wb.sheetnames, expected_sheetnames)
93 else:
94 wb = pyexcel_xlsx.get_data(buffer) # type: Dict[str, Any]
95 sheetnames = list(wb.keys())
96 self.assertEqual(sheetnames, expected_sheetnames)
98 def test_xlsx_page_name_exactly_31_chars_not_truncated(self) -> None:
99 page = TsvPage(name="abcdefghijklmnopqrstuvwxyz78901",
100 rows=[{"test data 1": "row 1"}])
101 coll = TsvCollection()
103 self.assertEqual(
104 coll.get_sheet_title(page),
105 "abcdefghijklmnopqrstuvwxyz78901"
106 )
108 def test_xlsx_page_name_over_31_chars_truncated(self) -> None:
109 page = TsvPage(name="abcdefghijklmnopqrstuvwxyz78901234",
110 rows=[{"test data 1": "row 1"}])
111 coll = TsvCollection()
113 self.assertEqual(
114 coll.get_sheet_title(page),
115 "abcdefghijklmnopqrstuvwxyz78..."
116 )
118 def test_xlsx_invalid_chars_in_page_name_replaced(self) -> None:
119 page = TsvPage(name="[a]b\\c:d/e*f?g'h",
120 rows=[{"test data 1": "row 1"}])
121 coll = TsvCollection()
123 self.assertEqual(
124 coll.get_sheet_title(page),
125 "_a_b_c_d_e_f_g_h"
126 )
128 def test_ods_page_name_sanitised(self) -> None:
129 # noinspection PyUnresolvedReferences
130 page = TsvPage(name="What perinatal service have you accessed?",
131 rows=[{"test data 1": "row 1"}])
132 coll = TsvCollection()
133 coll.add_pages([page])
135 data = coll.as_ods()
137 zf = zipfile.ZipFile(io.BytesIO(data), "r")
138 content = zf.read('content.xml')
139 doc = parseString(content)
140 sheets = doc.getElementsByTagName('table:table')
141 self.assertEqual(sheets[0].getAttribute("table:name"),
142 "What perinatal service have ...")
144 def test_worksheet_names_are_not_duplicated(self) -> None:
145 page1 = TsvPage(name="abcdefghijklmnopqrstuvwxyz78901234",
146 rows=[{"test data 1": "row 1"}])
147 page2 = TsvPage(name="ABCDEFGHIJKLMNOPQRSTUVWXYZ789012345",
148 rows=[{"test data 2": "row 1"}])
149 page3 = TsvPage(name="abcdefghijklmnopqrstuvwxyz7890123456",
150 rows=[{"test data 3": "row 1"}])
151 coll = TsvCollection()
153 coll.add_pages([page1, page2, page3])
155 valid_sheet_names = coll.get_pages_with_valid_sheet_names()
157 names = [v for k, v in valid_sheet_names.items()]
159 self.assertIn("abcdefghijklmnopqrstuvwxyz78...", names)
160 self.assertIn("ABCDEFGHIJKLMNOPQRSTUVWXYZ78..1", names)
161 self.assertIn("abcdefghijklmnopqrstuvwxyz78..2", names)
163 def test_uuid_exported_to_ods_as_string(self) -> None:
164 test_uuid = uuid.UUID("6457cb90-1ca0-47a7-9f40-767567819bee")
166 page = TsvPage(name="Testing",
167 rows=[{"UUID": test_uuid}])
168 coll = TsvCollection()
169 coll.add_pages([page])
171 data = coll.as_ods()
172 zf = zipfile.ZipFile(io.BytesIO(data), "r")
173 content = zf.read('content.xml')
174 doc = parseString(content)
175 text_values = [t.firstChild.nodeValue
176 for t in doc.getElementsByTagName("text:p")]
178 self.assertIn("UUID", text_values)
179 self.assertIn("6457cb90-1ca0-47a7-9f40-767567819bee", text_values)
181 def test_uuid_exported_to_xlsx_as_string(self) -> None:
182 test_uuid = uuid.UUID("6457cb90-1ca0-47a7-9f40-767567819bee")
184 page = TsvPage(name="Testing",
185 rows=[{"UUID": test_uuid}])
186 coll = TsvCollection()
187 coll.add_pages([page])
189 data = coll.as_xlsx()
190 buffer = io.BytesIO(data)
191 if openpyxl:
192 self.fail("This test has not been written for openpyxl")
193 else:
194 wb = pyexcel_xlsx.get_data(buffer) # type: Dict[str, Any]
195 self.assertIn(["UUID"], wb["Testing"])
196 self.assertIn(["6457cb90-1ca0-47a7-9f40-767567819bee"],
197 wb["Testing"])