Coverage for cc_modules/tests/cc_spreadsheet_tests.py: 22%
96 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
1#!/usr/bin/env python
3"""
4camcops_server/cc_modules/tests/cc_spreadsheet_tests.py
6===============================================================================
8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
11 This file is part of CamCOPS.
13 CamCOPS is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 CamCOPS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
26===============================================================================
28"""
30import io
31from typing import Any, Dict
32from unittest import TestCase
33import uuid
34from xml.dom.minidom import parseString
35import zipfile
37from camcops_server.cc_modules.cc_spreadsheet import (
38 SpreadsheetCollection,
39 SpreadsheetPage,
40 XLSX_VIA_PYEXCEL,
41)
43if XLSX_VIA_PYEXCEL:
44 import pyexcel_xlsx # e.g. pip install pyexcel-xlsx==0.5.7
46 openpyxl = XLWorkbook = XLWorksheet = None
47else:
48 import openpyxl
49 from openpyxl.workbook.workbook import Workbook as XLWorkbook
51 pyexcel_xlsx = None
54# =============================================================================
55# Unit tests
56# =============================================================================
59class SpreadsheetCollectionTests(TestCase):
60 def test_xlsx_created_from_zero_rows(self) -> None:
61 page = SpreadsheetPage(name="test", rows=[])
62 coll = SpreadsheetCollection()
63 coll.add_page(page)
65 output = coll.as_xlsx()
67 # https://en.wikipedia.org/wiki/List_of_file_signatures
68 self.assertEqual(output[0], 0x50)
69 self.assertEqual(output[1], 0x4B)
70 self.assertEqual(output[2], 0x03)
71 self.assertEqual(output[3], 0x04)
73 def test_xlsx_worksheet_names_are_page_names(self) -> None:
74 page1 = SpreadsheetPage(name="name 1", rows=[{"test data 1": "row 1"}])
75 page2 = SpreadsheetPage(name="name 2", rows=[{"test data 2": "row 1"}])
76 page3 = SpreadsheetPage(name="name 3", rows=[{"test data 3": "row 1"}])
77 coll = SpreadsheetCollection()
79 coll.add_pages([page1, page2, page3])
81 data = coll.as_xlsx()
82 buffer = io.BytesIO(data)
83 expected_sheetnames = ["name 1", "name 2", "name 3"]
84 if openpyxl:
85 wb = openpyxl.load_workbook(buffer) # type: XLWorkbook
86 self.assertEqual(wb.sheetnames, expected_sheetnames)
87 else:
88 wb = pyexcel_xlsx.get_data(buffer) # type: Dict[str, Any]
89 sheetnames = list(wb.keys())
90 self.assertEqual(sheetnames, expected_sheetnames)
92 def test_xlsx_page_name_exactly_31_chars_not_truncated(self) -> None:
93 page = SpreadsheetPage(
94 name="abcdefghijklmnopqrstuvwxyz78901",
95 rows=[{"test data 1": "row 1"}],
96 )
97 coll = SpreadsheetCollection()
99 self.assertEqual(
100 coll.get_sheet_title(page), "abcdefghijklmnopqrstuvwxyz78901"
101 )
103 def test_xlsx_page_name_over_31_chars_truncated(self) -> None:
104 page = SpreadsheetPage(
105 name="abcdefghijklmnopqrstuvwxyz78901234",
106 rows=[{"test data 1": "row 1"}],
107 )
108 coll = SpreadsheetCollection()
110 self.assertEqual(
111 coll.get_sheet_title(page), "abcdefghijklmnopqrstuvwxyz78..."
112 )
114 def test_xlsx_invalid_chars_in_page_name_replaced(self) -> None:
115 page = SpreadsheetPage(
116 name="[a]b\\c:d/e*f?g'h", rows=[{"test data 1": "row 1"}]
117 )
118 coll = SpreadsheetCollection()
120 self.assertEqual(coll.get_sheet_title(page), "_a_b_c_d_e_f_g_h")
122 def test_ods_page_name_sanitised(self) -> None:
123 # noinspection PyUnresolvedReferences
124 page = SpreadsheetPage(
125 name="What perinatal service have you accessed?",
126 rows=[{"test data 1": "row 1"}],
127 )
128 coll = SpreadsheetCollection()
129 coll.add_pages([page])
131 data = coll.as_ods()
133 zf = zipfile.ZipFile(io.BytesIO(data), "r")
134 content = zf.read("content.xml")
135 doc = parseString(content)
136 sheets = doc.getElementsByTagName("table:table")
137 self.assertEqual(
138 sheets[0].getAttribute("table:name"),
139 "What perinatal service have ...",
140 )
142 def test_worksheet_names_are_not_duplicated(self) -> None:
143 page1 = SpreadsheetPage(
144 name="abcdefghijklmnopqrstuvwxyz78901234",
145 rows=[{"test data 1": "row 1"}],
146 )
147 page2 = SpreadsheetPage(
148 name="ABCDEFGHIJKLMNOPQRSTUVWXYZ789012345",
149 rows=[{"test data 2": "row 1"}],
150 )
151 page3 = SpreadsheetPage(
152 name="abcdefghijklmnopqrstuvwxyz7890123456",
153 rows=[{"test data 3": "row 1"}],
154 )
155 coll = SpreadsheetCollection()
157 coll.add_pages([page1, page2, page3])
159 valid_sheet_names = coll.get_pages_with_valid_sheet_names()
161 names = [v for k, v in valid_sheet_names.items()]
163 self.assertIn("abcdefghijklmnopqrstuvwxyz78...", names)
164 self.assertIn("ABCDEFGHIJKLMNOPQRSTUVWXYZ78..1", names)
165 self.assertIn("abcdefghijklmnopqrstuvwxyz78..2", names)
167 def test_uuid_exported_to_ods_as_string(self) -> None:
168 test_uuid = uuid.UUID("6457cb90-1ca0-47a7-9f40-767567819bee")
170 page = SpreadsheetPage(name="Testing", rows=[{"UUID": test_uuid}])
171 coll = SpreadsheetCollection()
172 coll.add_pages([page])
174 data = coll.as_ods()
175 zf = zipfile.ZipFile(io.BytesIO(data), "r")
176 content = zf.read("content.xml")
177 doc = parseString(content)
178 text_values = [
179 t.firstChild.nodeValue for t in doc.getElementsByTagName("text:p")
180 ]
182 self.assertIn("UUID", text_values)
183 self.assertIn("6457cb90-1ca0-47a7-9f40-767567819bee", text_values)
185 def test_uuid_exported_to_xlsx_as_string(self) -> None:
186 test_uuid = uuid.UUID("6457cb90-1ca0-47a7-9f40-767567819bee")
188 page = SpreadsheetPage(name="Testing", rows=[{"UUID": test_uuid}])
189 coll = SpreadsheetCollection()
190 coll.add_pages([page])
192 data = coll.as_xlsx()
193 buffer = io.BytesIO(data)
194 if openpyxl:
195 self.fail("This test has not been written for openpyxl")
196 else:
197 wb = pyexcel_xlsx.get_data(buffer) # type: Dict[str, Any]
198 self.assertIn(["UUID"], wb["Testing"])
199 self.assertIn(
200 ["6457cb90-1ca0-47a7-9f40-767567819bee"], wb["Testing"]
201 )