|
1 #!/usr/bin/python |
|
2 # |
|
3 # Copyright (C) 2008 Google Inc. |
|
4 # |
|
5 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 # you may not use this file except in compliance with the License. |
|
7 # You may obtain a copy of the License at |
|
8 # |
|
9 # http://www.apache.org/licenses/LICENSE-2.0 |
|
10 # |
|
11 # Unless required by applicable law or agreed to in writing, software |
|
12 # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 # See the License for the specific language governing permissions and |
|
15 # limitations under the License. |
|
16 |
|
17 """Tests for the gviz_api module.""" |
|
18 |
|
19 __author__ = "Amit Weinstein" |
|
20 |
|
21 from datetime import date |
|
22 from datetime import datetime |
|
23 from datetime import time |
|
24 import re |
|
25 import unittest |
|
26 |
|
27 from gviz_api import DataTable |
|
28 from gviz_api import DataTableException |
|
29 |
|
30 |
|
31 class DataTableTest(unittest.TestCase): |
|
32 |
|
33 def testSingleValueToJS(self): |
|
34 # We first check that given an unknown type it raises exception |
|
35 self.assertRaises(DataTableException, |
|
36 DataTable.SingleValueToJS, 1, "no_such_type") |
|
37 |
|
38 # If we give a type which does not match the value, we expect it to fail |
|
39 self.assertRaises(DataTableException, |
|
40 DataTable.SingleValueToJS, "a", "number") |
|
41 self.assertRaises(DataTableException, |
|
42 DataTable.SingleValueToJS, "b", "timeofday") |
|
43 self.assertRaises(DataTableException, |
|
44 DataTable.SingleValueToJS, 10, "date") |
|
45 |
|
46 # A tuple for value and formatted value should be of length 2 |
|
47 self.assertRaises(DataTableException, |
|
48 DataTable.SingleValueToJS, (5, "5$", "6$"), "string") |
|
49 |
|
50 # Some good examples from all the different types |
|
51 self.assertEqual("true", DataTable.SingleValueToJS(True, "boolean")) |
|
52 self.assertEqual("false", DataTable.SingleValueToJS(False, "boolean")) |
|
53 self.assertEqual("true", DataTable.SingleValueToJS(1, "boolean")) |
|
54 self.assertEqual("null", DataTable.SingleValueToJS(None, "boolean")) |
|
55 self.assertEqual(("false", "'a'"), |
|
56 DataTable.SingleValueToJS((False, "a"), "boolean")) |
|
57 |
|
58 self.assertEqual("1", DataTable.SingleValueToJS(1, "number")) |
|
59 self.assertEqual("1.0", DataTable.SingleValueToJS(1., "number")) |
|
60 self.assertEqual("-5", DataTable.SingleValueToJS(-5, "number")) |
|
61 self.assertEqual("null", DataTable.SingleValueToJS(None, "number")) |
|
62 self.assertEqual(("5", "'5$'"), |
|
63 DataTable.SingleValueToJS((5, "5$"), "number")) |
|
64 |
|
65 self.assertEqual("'-5'", DataTable.SingleValueToJS(-5, "string")) |
|
66 self.assertEqual("'abc'", DataTable.SingleValueToJS("abc", "string")) |
|
67 self.assertEqual("null", DataTable.SingleValueToJS(None, "string")) |
|
68 |
|
69 self.assertEqual("new Date(2010,0,2)", |
|
70 DataTable.SingleValueToJS(date(2010, 1, 2), "date")) |
|
71 self.assertEqual("new Date(2001,1,3)", |
|
72 DataTable.SingleValueToJS(datetime(2001, 2, 3, 4, 5, 6), |
|
73 "date")) |
|
74 self.assertEqual("null", DataTable.SingleValueToJS(None, "date")) |
|
75 |
|
76 self.assertEqual("[10,11,12]", |
|
77 DataTable.SingleValueToJS(time(10, 11, 12), "timeofday")) |
|
78 self.assertEqual("[3,4,5]", |
|
79 DataTable.SingleValueToJS(datetime(2010, 1, 2, 3, 4, 5), |
|
80 "timeofday")) |
|
81 self.assertEqual("null", DataTable.SingleValueToJS(None, "timeofday")) |
|
82 |
|
83 self.assertEqual("new Date(2001,1,3,4,5,6)", |
|
84 DataTable.SingleValueToJS(datetime(2001, 2, 3, 4, 5, 6), |
|
85 "datetime")) |
|
86 self.assertEqual("null", DataTable.SingleValueToJS(None, "datetime")) |
|
87 self.assertEqual(("null", "'none'"), |
|
88 DataTable.SingleValueToJS((None, "none"), "string")) |
|
89 |
|
90 def testDifferentStrings(self): |
|
91 # Checking escaping of strings |
|
92 problematic_strings = ["control", "new\nline", "", |
|
93 "single'quote", 'double"quote', |
|
94 r"one\slash", r"two\\slash", u"unicode eng", |
|
95 u"unicode \u05e2\u05d1\u05e8\u05d9\u05ea"] |
|
96 for s in problematic_strings: |
|
97 js_value = DataTable.SingleValueToJS(s, "string") |
|
98 if isinstance(js_value, unicode): |
|
99 js_value = "u%s" % js_value |
|
100 self.assertEquals(s, eval(js_value)) |
|
101 |
|
102 js_value = DataTable.SingleValueToJS(("str", s), "string")[1] |
|
103 if isinstance(js_value, unicode): |
|
104 js_value = "u%s" % js_value |
|
105 self.assertEquals(s, eval(js_value)) |
|
106 |
|
107 def testDifferentCustomProperties(self): |
|
108 # Checking escaping of custom properties |
|
109 problematic_cps = [{"control": "test"}, {u"unicode": "value"}, |
|
110 {"key": u"unicode"}, {u"unicode": u"unicode"}, |
|
111 {"regular": "single'quote"}, {"unicode": u"s'quote"}] |
|
112 for cp in problematic_cps: |
|
113 js_value = DataTable._EscapeCustomProperties(cp) |
|
114 self.assertEquals(cp, eval(js_value)) |
|
115 |
|
116 def testColumnTypeParser(self): |
|
117 # Checking several wrong formats |
|
118 self.assertRaises(DataTableException, |
|
119 DataTable.ColumnTypeParser, 5) |
|
120 self.assertRaises(DataTableException, |
|
121 DataTable.ColumnTypeParser, ("a", "b", "c", "d")) |
|
122 self.assertRaises(DataTableException, |
|
123 DataTable.ColumnTypeParser, ("a", 5, "c")) |
|
124 |
|
125 # Checking several legal formats |
|
126 self.assertEqual({"id": "abc", "label": "abc", "type": "string", |
|
127 "custom_properties": {}}, |
|
128 DataTable.ColumnTypeParser("abc")) |
|
129 self.assertEqual({"id": "abc", "label": "abc", "type": "string", |
|
130 "custom_properties": {}}, |
|
131 DataTable.ColumnTypeParser(("abc",))) |
|
132 self.assertEqual({"id": "abc", "label": "bcd", "type": "string", |
|
133 "custom_properties": {}}, |
|
134 DataTable.ColumnTypeParser(("abc", "string", "bcd"))) |
|
135 self.assertEqual({"id": "a", "label": "b", "type": "number", |
|
136 "custom_properties": {}}, |
|
137 DataTable.ColumnTypeParser(("a", "number", "b"))) |
|
138 self.assertEqual({"id": "a", "label": "a", "type": "number", |
|
139 "custom_properties": {}}, |
|
140 DataTable.ColumnTypeParser(("a", "number"))) |
|
141 self.assertEqual({"id": "i", "label": "l", "type": "string", |
|
142 "custom_properties": {"key": "value"}}, |
|
143 DataTable.ColumnTypeParser(("i", "string", "l", |
|
144 {"key": "value"}))) |
|
145 |
|
146 def testTableDescriptionParser(self): |
|
147 # We expect it to fail with empty lists or dictionaries |
|
148 self.assertRaises(DataTableException, |
|
149 DataTable.TableDescriptionParser, {}) |
|
150 self.assertRaises(DataTableException, |
|
151 DataTable.TableDescriptionParser, []) |
|
152 self.assertRaises(DataTableException, |
|
153 DataTable.TableDescriptionParser, {"a": []}) |
|
154 self.assertRaises(DataTableException, |
|
155 DataTable.TableDescriptionParser, {"a": {"b": {}}}) |
|
156 |
|
157 # We expect it to fail if we give a non-string at the lowest level |
|
158 self.assertRaises(DataTableException, |
|
159 DataTable.TableDescriptionParser, {"a": 5}) |
|
160 self.assertRaises(DataTableException, |
|
161 DataTable.TableDescriptionParser, [("a", "number"), 6]) |
|
162 |
|
163 # Some valid examples which mixes both dictionaries and lists |
|
164 self.assertEqual( |
|
165 [{"id": "a", "label": "a", "type": "date", |
|
166 "depth": 0, "container": "iter", "custom_properties": {}}, |
|
167 {"id": "b", "label": "b", "type": "timeofday", |
|
168 "depth": 0, "container": "iter", "custom_properties": {}}], |
|
169 DataTable.TableDescriptionParser([("a", "date"), ("b", "timeofday")])) |
|
170 |
|
171 self.assertEqual( |
|
172 [{"id": "a", "label": "a", "type": "string", |
|
173 "depth": 0, "container": "dict", "custom_properties": {}}, |
|
174 {"id": "b", "label": "b", "type": "number", |
|
175 "depth": 1, "container": "iter", "custom_properties": {}}, |
|
176 {"id": "c", "label": "column c", "type": "string", |
|
177 "depth": 1, "container": "iter", "custom_properties": {}}], |
|
178 DataTable.TableDescriptionParser({"a": [("b", "number"), |
|
179 ("c", "string", "column c")]})) |
|
180 |
|
181 self.assertEqual( |
|
182 [{"id": "a", "label": "column a", "type": "number", |
|
183 "depth": 0, "container": "dict", "custom_properties": {}}, |
|
184 {"id": "b", "label": "b", "type": "number", |
|
185 "depth": 1, "container": "dict", "custom_properties": {}}, |
|
186 {"id": "c", "label": "c", "type": "string", |
|
187 "depth": 1, "container": "dict", "custom_properties": {}}], |
|
188 DataTable.TableDescriptionParser({("a", "number", "column a"): |
|
189 {"b": "number", "c": "string"}})) |
|
190 |
|
191 self.assertEqual( |
|
192 [{"id": "a", "label": "column a", "type": "number", |
|
193 "depth": 0, "container": "dict", "custom_properties": {}}, |
|
194 {"id": "b", "label": "column b", "type": "string", |
|
195 "depth": 1, "container": "scalar", "custom_properties": {}}], |
|
196 DataTable.TableDescriptionParser({("a", "number", "column a"): |
|
197 ("b", "string", "column b")})) |
|
198 |
|
199 def testAppendData(self): |
|
200 # We check a few examples where the format of the data does not match the |
|
201 # description and hen a few valid examples. The test for the content itself |
|
202 # is done inside the ToJSCode and ToJSon functions. |
|
203 table = DataTable([("a", "number"), ("b", "string")]) |
|
204 self.assertEqual(0, table.NumberOfRows()) |
|
205 self.assertRaises(DataTableException, |
|
206 table.AppendData, [[1, "a", True]]) |
|
207 self.assertRaises(DataTableException, |
|
208 table.AppendData, {1: ["a"], 2: ["b"]}) |
|
209 self.assertEquals(None, table.AppendData([[1, "a"], [2, "b"]])) |
|
210 self.assertEqual(2, table.NumberOfRows()) |
|
211 self.assertEquals(None, table.AppendData([[3, "c"], [4]])) |
|
212 self.assertEqual(4, table.NumberOfRows()) |
|
213 |
|
214 table = DataTable({"a": "number", "b": "string"}) |
|
215 self.assertEqual(0, table.NumberOfRows()) |
|
216 self.assertRaises(DataTableException, |
|
217 table.AppendData, [[1, "a"]]) |
|
218 self.assertRaises(DataTableException, |
|
219 table.AppendData, {5: {"b": "z"}}) |
|
220 self.assertEquals(None, table.AppendData([{"a": 1, "b": "z"}])) |
|
221 self.assertEqual(1, table.NumberOfRows()) |
|
222 |
|
223 table = DataTable({("a", "number"): [("b", "string")]}) |
|
224 self.assertEqual(0, table.NumberOfRows()) |
|
225 self.assertRaises(DataTableException, |
|
226 table.AppendData, [[1, "a"]]) |
|
227 self.assertRaises(DataTableException, |
|
228 table.AppendData, {5: {"b": "z"}}) |
|
229 self.assertEquals(None, table.AppendData({5: ["z"], 6: ["w"]})) |
|
230 self.assertEqual(2, table.NumberOfRows()) |
|
231 |
|
232 table = DataTable({("a", "number"): {"b": "string", "c": "number"}}) |
|
233 self.assertEqual(0, table.NumberOfRows()) |
|
234 self.assertRaises(DataTableException, |
|
235 table.AppendData, [[1, "a"]]) |
|
236 self.assertRaises(DataTableException, |
|
237 table.AppendData, {1: ["a", 2]}) |
|
238 self.assertEquals(None, table.AppendData({5: {"b": "z", "c": 6}, |
|
239 7: {"c": 8}, |
|
240 9: {}})) |
|
241 self.assertEqual(3, table.NumberOfRows()) |
|
242 |
|
243 def testToJSCode(self): |
|
244 table = DataTable([("a", "number", "A"), "b", ("c", "timeofday")], |
|
245 [[1], |
|
246 [None, "z", time(1, 2, 3)], |
|
247 [(2, "2$"), "w", time(2, 3, 4)]]) |
|
248 self.assertEqual(3, table.NumberOfRows()) |
|
249 self.assertEqual(("var mytab = new google.visualization.DataTable();\n" |
|
250 "mytab.addColumn('number', 'A', 'a');\n" |
|
251 "mytab.addColumn('string', 'b', 'b');\n" |
|
252 "mytab.addColumn('timeofday', 'c', 'c');\n" |
|
253 "mytab.addRows(3);\n" |
|
254 "mytab.setCell(0, 0, 1);\n" |
|
255 "mytab.setCell(1, 1, 'z');\n" |
|
256 "mytab.setCell(1, 2, [1,2,3]);\n" |
|
257 "mytab.setCell(2, 0, 2, '2$');\n" |
|
258 "mytab.setCell(2, 1, 'w');\n" |
|
259 "mytab.setCell(2, 2, [2,3,4]);\n"), |
|
260 table.ToJSCode("mytab")) |
|
261 |
|
262 table = DataTable({("a", "number"): {"b": "date", "c": "datetime"}}, |
|
263 {1: {}, |
|
264 2: {"b": date(1, 2, 3)}, |
|
265 3: {"c": datetime(1, 2, 3, 4, 5, 6)}}) |
|
266 self.assertEqual(3, table.NumberOfRows()) |
|
267 self.assertEqual(("var mytab2 = new google.visualization.DataTable();\n" |
|
268 "mytab2.addColumn('datetime', 'c', 'c');\n" |
|
269 "mytab2.addColumn('date', 'b', 'b');\n" |
|
270 "mytab2.addColumn('number', 'a', 'a');\n" |
|
271 "mytab2.addRows(3);\n" |
|
272 "mytab2.setCell(0, 2, 1);\n" |
|
273 "mytab2.setCell(1, 1, new Date(1,1,3));\n" |
|
274 "mytab2.setCell(1, 2, 2);\n" |
|
275 "mytab2.setCell(2, 0, new Date(1,1,3,4,5,6));\n" |
|
276 "mytab2.setCell(2, 2, 3);\n"), |
|
277 table.ToJSCode("mytab2", columns_order=["c", "b", "a"])) |
|
278 |
|
279 def testToJSon(self): |
|
280 # The json of the initial data we load to the table. |
|
281 init_data_json = ("{cols:" |
|
282 "[{id:'a',label:'A',type:'number'}," |
|
283 "{id:'b',label:'b',type:'string'}," |
|
284 "{id:'c',label:'c',type:'boolean'}]," |
|
285 "rows:[" |
|
286 "{c:[{v:1},,{v:null}]}," |
|
287 "{c:[,{v:'z'},{v:true}]}" |
|
288 "]}") |
|
289 table = DataTable([("a", "number", "A"), "b", ("c", "boolean")], |
|
290 [[1], |
|
291 [None, "z", True]]) |
|
292 self.assertEqual(2, table.NumberOfRows()) |
|
293 self.assertEqual(init_data_json, |
|
294 table.ToJSon()) |
|
295 table.AppendData([[-1, "w", False]]) |
|
296 self.assertEqual(3, table.NumberOfRows()) |
|
297 self.assertEqual(init_data_json[:-2] + ",{c:[{v:-1},{v:'w'},{v:false}]}]}", |
|
298 table.ToJSon()) |
|
299 |
|
300 cols_json = ("{cols:" |
|
301 "[{id:'t',label:'T',type:'timeofday'}," |
|
302 "{id:'d',label:'d',type:'date'}," |
|
303 "{id:'dt',label:'dt',type:'datetime'}],") |
|
304 table = DataTable({("d", "date"): [("t", "timeofday", "T"), |
|
305 ("dt", "datetime")]}) |
|
306 table.LoadData({date(1, 2, 3): [time(1, 2, 3)]}) |
|
307 self.assertEqual(1, table.NumberOfRows()) |
|
308 self.assertEqual(cols_json + |
|
309 "rows:[{c:[{v:[1,2,3]},{v:new Date(1,1,3)},{v:null}]}]}", |
|
310 table.ToJSon(columns_order=["t", "d", "dt"])) |
|
311 table.LoadData({date(2, 3, 4): [(time(2, 3, 4), "time 2 3 4"), |
|
312 datetime(1, 2, 3, 4, 5, 6)], |
|
313 date(3, 4, 5): []}) |
|
314 self.assertEqual(2, table.NumberOfRows()) |
|
315 self.assertEqual((cols_json + "rows:[" |
|
316 "{c:[{v:[2,3,4],f:'time 2 3 4'},{v:new Date(2,2,4)}," |
|
317 "{v:new Date(1,1,3,4,5,6)}]}," |
|
318 "{c:[,{v:new Date(3,3,5)},{v:null}]}]}"), |
|
319 table.ToJSon(columns_order=["t", "d", "dt"])) |
|
320 |
|
321 json = ("{cols:[{id:'a',label:'a',type:'string'}," |
|
322 "{id:'b',label:'b',type:'number'}]," |
|
323 "rows:[{c:[{v:'a1'},{v:1}]},{c:[{v:'a2'},{v:2}]}," |
|
324 "{c:[{v:'a3'},{v:3}]}]}") |
|
325 table = DataTable({"a": ("b", "number")}, |
|
326 {"a1": 1, "a2": 2, "a3": 3}) |
|
327 self.assertEqual(3, table.NumberOfRows()) |
|
328 self.assertEqual(json, |
|
329 table.ToJSon()) |
|
330 |
|
331 def testCustomProperties(self): |
|
332 # The json of the initial data we load to the table. |
|
333 json = ("{cols:" |
|
334 "[{id:'a',label:'A',type:'number',p:{'col_cp':'col_v'}}," |
|
335 "{id:'b',label:'b',type:'string'}," |
|
336 "{id:'c',label:'c',type:'boolean'}]," |
|
337 "rows:[" |
|
338 "{c:[{v:1},,{v:null,p:{'null_cp':'null_v'}}],p:{'row_cp':'row_v'}}," |
|
339 "{c:[,{v:'z',p:{'cell_cp':'cell_v'}},{v:true}]}," |
|
340 "{c:[{v:3},,{v:null}],p:{'row_cp2':'row_v2'}}]," |
|
341 "p:{'global_cp':'global_v'}" |
|
342 "}") |
|
343 jscode = ("var mytab = new google.visualization.DataTable();\n" |
|
344 "mytab.setTableProperties({'global_cp':'global_v'});\n" |
|
345 "mytab.addColumn('number', 'A', 'a');\n" |
|
346 "mytab.setColumnProperties(0, {'col_cp':'col_v'});\n" |
|
347 "mytab.addColumn('string', 'b', 'b');\n" |
|
348 "mytab.addColumn('boolean', 'c', 'c');\n" |
|
349 "mytab.addRows(3);\n" |
|
350 "mytab.setCell(0, 0, 1);\n" |
|
351 "mytab.setCell(0, 2, null, null, {'null_cp':'null_v'});\n" |
|
352 "mytab.setRowProperties(0, {'row_cp':'row_v'});\n" |
|
353 "mytab.setCell(1, 1, 'z', null, {'cell_cp':'cell_v'});\n" |
|
354 "mytab.setCell(1, 2, true);\n" |
|
355 "mytab.setCell(2, 0, 3);\n" |
|
356 "mytab.setRowProperties(2, {'row_cp2':'row_v2'});\n") |
|
357 |
|
358 table = DataTable([("a", "number", "A", {"col_cp": "col_v"}), "b", |
|
359 ("c", "boolean")], |
|
360 custom_properties={"global_cp": "global_v"}) |
|
361 table.AppendData([[1, None, (None, None, {"null_cp": "null_v"})]], |
|
362 custom_properties={"row_cp": "row_v"}) |
|
363 table.AppendData([[None, ("z", None, {"cell_cp": "cell_v"}), True], [3]]) |
|
364 table.SetRowsCustomProperties(2, {"row_cp2": "row_v2"}) |
|
365 self.assertEqual(json, table.ToJSon()) |
|
366 self.assertEqual(jscode, table.ToJSCode("mytab")) |
|
367 |
|
368 def testToCsv(self): |
|
369 init_data_csv = "\n".join(['"A", "b", "c"', |
|
370 '1, "", ""', |
|
371 '"", "zz\'top", true']) |
|
372 table = DataTable([("a", "number", "A"), "b", ("c", "boolean")], |
|
373 [[(1, "$1")], [None, "zz'top", True]]) |
|
374 self.assertEqual(init_data_csv, table.ToCsv()) |
|
375 table.AppendData([[-1, "w", False]]) |
|
376 init_data_csv = "%s\n%s" % (init_data_csv, '-1, "w", false') |
|
377 self.assertEquals(init_data_csv, table.ToCsv()) |
|
378 |
|
379 init_data_csv = "\n".join([ |
|
380 '"T", "d", "dt"', |
|
381 '"[1,2,3]", "new Date(1,1,3)", ""', |
|
382 '"time ""2 3 4""", "new Date(2,2,4)", "new Date(1,1,3,4,5,6)"', |
|
383 '"", "new Date(3,3,5)", ""']) |
|
384 table = DataTable({("d", "date"): [("t", "timeofday", "T"), |
|
385 ("dt", "datetime")]}) |
|
386 table.LoadData({date(1, 2, 3): [time(1, 2, 3)], |
|
387 date(2, 3, 4): [(time(2, 3, 4), 'time "2 3 4"'), |
|
388 datetime(1, 2, 3, 4, 5, 6)], |
|
389 date(3, 4, 5): []}) |
|
390 self.assertEqual(init_data_csv, table.ToCsv(columns_order=["t", "d", "dt"])) |
|
391 |
|
392 def testToTsvExcel(self): |
|
393 table = DataTable({("d", "date"): [("t", "timeofday", "T"), |
|
394 ("dt", "datetime")]}) |
|
395 table.LoadData({date(1, 2, 3): [time(1, 2, 3)], |
|
396 date(2, 3, 4): [(time(2, 3, 4), 'time "2 3 4"'), |
|
397 datetime(1, 2, 3, 4, 5, 6)], |
|
398 date(3, 4, 5): []}) |
|
399 self.assertEqual(table.ToCsv().replace(", ", "\t").encode("UTF-16LE"), |
|
400 table.ToTsvExcel()) |
|
401 |
|
402 def testToHtml(self): |
|
403 html_table_header = "<html><body><table border='1'>" |
|
404 html_table_footer = "</table></body></html>" |
|
405 init_data_html = html_table_header + ( |
|
406 "<thead><tr>" |
|
407 "<th>A</th><th>b</th><th>c</th>" |
|
408 "</tr></thead>" |
|
409 "<tbody>" |
|
410 "<tr><td>'$1'</td><td></td><td></td></tr>" |
|
411 "<tr><td></td><td>'<z>'</td><td>true</td></tr>" |
|
412 "</tbody>") + html_table_footer |
|
413 table = DataTable([("a", "number", "A"), "b", ("c", "boolean")], |
|
414 [[(1, "$1")], [None, "<z>", True]]) |
|
415 self.assertEqual(init_data_html.replace("\n", ""), table.ToHtml()) |
|
416 |
|
417 init_data_html = html_table_header + ( |
|
418 "<thead><tr>" |
|
419 "<th>T</th><th>d</th><th>dt</th>" |
|
420 "</tr></thead>" |
|
421 "<tbody>" |
|
422 "<tr><td>[1,2,3]</td><td>new Date(1,1,3)</td><td></td></tr>" |
|
423 "<tr><td>'time 2 3 4'</td><td>new Date(2,2,4)</td>" |
|
424 "<td>new Date(1,1,3,4,5,6)</td></tr>" |
|
425 "<tr><td></td><td>new Date(3,3,5)</td><td></td></tr>" |
|
426 "</tbody>") + html_table_footer |
|
427 table = DataTable({("d", "date"): [("t", "timeofday", "T"), |
|
428 ("dt", "datetime")]}) |
|
429 table.LoadData({date(1, 2, 3): [time(1, 2, 3)], |
|
430 date(2, 3, 4): [(time(2, 3, 4), "time 2 3 4"), |
|
431 datetime(1, 2, 3, 4, 5, 6)], |
|
432 date(3, 4, 5): []}) |
|
433 self.assertEqual(init_data_html.replace("\n", ""), |
|
434 table.ToHtml(columns_order=["t", "d", "dt"])) |
|
435 |
|
436 def testOrderBy(self): |
|
437 data = [("b", 3), ("a", 3), ("a", 2), ("b", 1)] |
|
438 description = ["col1", ("col2", "number", "Second Column")] |
|
439 table = DataTable(description, data) |
|
440 |
|
441 table_num_sorted = DataTable(description, |
|
442 sorted(data, key=lambda x: (x[1], x[0]))) |
|
443 |
|
444 table_str_sorted = DataTable(description, |
|
445 sorted(data, key=lambda x: x[0])) |
|
446 |
|
447 table_diff_sorted = DataTable(description, |
|
448 sorted(sorted(data, key=lambda x: x[1]), |
|
449 key=lambda x: x[0], reverse=True)) |
|
450 |
|
451 self.assertEqual(table_num_sorted.ToJSon(), |
|
452 table.ToJSon(order_by=("col2", "col1"))) |
|
453 self.assertEqual(table_num_sorted.ToJSCode("mytab"), |
|
454 table.ToJSCode("mytab", order_by=("col2", "col1"))) |
|
455 |
|
456 self.assertEqual(table_str_sorted.ToJSon(), table.ToJSon(order_by="col1")) |
|
457 self.assertEqual(table_str_sorted.ToJSCode("mytab"), |
|
458 table.ToJSCode("mytab", order_by="col1")) |
|
459 |
|
460 self.assertEqual(table_diff_sorted.ToJSon(), |
|
461 table.ToJSon(order_by=[("col1", "desc"), "col2"])) |
|
462 self.assertEqual(table_diff_sorted.ToJSCode("mytab"), |
|
463 table.ToJSCode("mytab", |
|
464 order_by=[("col1", "desc"), "col2"])) |
|
465 |
|
466 def testToJSonResponse(self): |
|
467 description = ["col1", "col2", "col3"] |
|
468 data = [("1", "2", "3"), ("a", "b", "c"), ("One", "Two", "Three")] |
|
469 req_id = 4 |
|
470 table = DataTable(description, data) |
|
471 |
|
472 start_str_default = r"google.visualization.Query.setResponse" |
|
473 start_str_handler = r"MyHandlerFunction" |
|
474 default_params = (r"\s*'version'\s*:\s*'0.6'\s*,\s*'reqId'\s*:\s*'%s'\s*," |
|
475 r"\s*'status'\s*:\s*'OK'\s*" % req_id) |
|
476 regex1 = re.compile("%s\(\s*\{%s,\s*'table'\s*:\s*{(.*)}\s*\}\s*\);" % |
|
477 (start_str_default, default_params)) |
|
478 regex2 = re.compile("%s\(\s*\{%s,\s*'table'\s*:\s*{(.*)}\s*\}\s*\);" % |
|
479 (start_str_handler, default_params)) |
|
480 |
|
481 json_str = table.ToJSon().strip() |
|
482 |
|
483 json_response = table.ToJSonResponse(req_id=req_id) |
|
484 match = regex1.findall(json_response) |
|
485 self.assertEquals(len(match), 1) |
|
486 # We want to match against the json_str without the curly brackets. |
|
487 self.assertEquals(match[0], json_str[1:-1]) |
|
488 |
|
489 json_response = table.ToJSonResponse(req_id=req_id, |
|
490 response_handler=start_str_handler) |
|
491 match = regex2.findall(json_response) |
|
492 self.assertEquals(len(match), 1) |
|
493 # We want to match against the json_str without the curly brackets. |
|
494 self.assertEquals(match[0], json_str[1:-1]) |
|
495 |
|
496 def testToResponse(self): |
|
497 description = ["col1", "col2", "col3"] |
|
498 data = [("1", "2", "3"), ("a", "b", "c"), ("One", "Two", "Three")] |
|
499 table = DataTable(description, data) |
|
500 |
|
501 self.assertEquals(table.ToResponse(), table.ToJSonResponse()) |
|
502 self.assertEquals(table.ToResponse(tqx="out:csv"), table.ToCsv()) |
|
503 self.assertEquals(table.ToResponse(tqx="out:html"), table.ToHtml()) |
|
504 self.assertRaises(DataTableException, table.ToResponse, tqx="version:0.1") |
|
505 self.assertEquals(table.ToResponse(tqx="reqId:4;responseHandler:handle"), |
|
506 table.ToJSonResponse(req_id=4, response_handler="handle")) |
|
507 self.assertEquals(table.ToResponse(tqx="out:csv;reqId:4"), table.ToCsv()) |
|
508 self.assertEquals(table.ToResponse(order_by="col2"), |
|
509 table.ToJSonResponse(order_by="col2")) |
|
510 self.assertEquals(table.ToResponse(tqx="out:html", |
|
511 columns_order=("col3", "col2", "col1")), |
|
512 table.ToHtml(columns_order=("col3", "col2", "col1"))) |
|
513 self.assertRaises(ValueError, table.ToResponse, tqx="SomeWrongTqxFormat") |
|
514 self.assertRaises(DataTableException, table.ToResponse, tqx="out:bad") |
|
515 |
|
516 |
|
517 if __name__ == "__main__": |
|
518 unittest.main() |