mise-en-production
[auf_framonde.git] / project / cmsplugin_contact_plus / jsonfield / tests.py
1 from decimal import Decimal
2 from django.core.serializers import deserialize, serialize
3 from django.core.serializers.base import DeserializationError
4 from django.db import models
5 from django.test import TestCase
6 try:
7 import json
8 except ImportError:
9 from django.utils import simplejson as json
10
11 from .fields import JSONField, JSONCharField
12 from django.forms.util import ValidationError
13
14 from collections import OrderedDict
15
16 class JsonModel(models.Model):
17 json = JSONField()
18 default_json = JSONField(default={"check":12})
19 complex_default_json = JSONField(default=[{"checkcheck": 1212}])
20 empty_default = JSONField(default={})
21
22 class JsonCharModel(models.Model):
23 json = JSONCharField(max_length=100)
24 default_json = JSONCharField(max_length=100, default={"check":34})
25
26 class ComplexEncoder(json.JSONEncoder):
27 def default(self, obj):
28 if isinstance(obj, complex):
29 return {
30 '__complex__': True,
31 'real': obj.real,
32 'imag': obj.imag,
33 }
34
35 return json.JSONEncoder.default(self, obj)
36
37 def as_complex(dct):
38 if '__complex__' in dct:
39 return complex(dct['real'], dct['imag'])
40 return dct
41
42 class JSONModelCustomEncoders(models.Model):
43 # A JSON field that can store complex numbers
44 json = JSONField(
45 dump_kwargs={'cls': ComplexEncoder, "indent": 4},
46 load_kwargs={'object_hook': as_complex},
47 )
48
49 class JSONFieldTest(TestCase):
50 """JSONField Wrapper Tests"""
51
52 json_model = JsonModel
53
54 def test_json_field_create(self):
55 """Test saving a JSON object in our JSONField"""
56 json_obj = {
57 "item_1": "this is a json blah",
58 "blergh": "hey, hey, hey"}
59
60 obj = self.json_model.objects.create(json=json_obj)
61 new_obj = self.json_model.objects.get(id=obj.id)
62
63 self.assertEqual(new_obj.json, json_obj)
64
65 def test_string_in_json_field(self):
66 """Test saving an ordinary Python string in our JSONField"""
67 json_obj = 'blah blah'
68 obj = self.json_model.objects.create(json=json_obj)
69 new_obj = self.json_model.objects.get(id=obj.id)
70
71 self.assertEqual(new_obj.json, json_obj)
72
73 def test_float_in_json_field(self):
74 """Test saving a Python float in our JSONField"""
75 json_obj = 1.23
76 obj = self.json_model.objects.create(json=json_obj)
77 new_obj = self.json_model.objects.get(id=obj.id)
78
79 self.assertEqual(new_obj.json, json_obj)
80
81 def test_int_in_json_field(self):
82 """Test saving a Python integer in our JSONField"""
83 json_obj = 1234567
84 obj = self.json_model.objects.create(json=json_obj)
85 new_obj = self.json_model.objects.get(id=obj.id)
86
87 self.assertEqual(new_obj.json, json_obj)
88
89 def test_decimal_in_json_field(self):
90 """Test saving a Python Decimal in our JSONField"""
91 json_obj = Decimal(12.34)
92 obj = self.json_model.objects.create(json=json_obj)
93 new_obj = self.json_model.objects.get(id=obj.id)
94
95 # here we must know to convert the returned string back to Decimal,
96 # since json does not support that format
97 self.assertEqual(Decimal(new_obj.json), json_obj)
98
99 def test_json_field_modify(self):
100 """Test modifying a JSON object in our JSONField"""
101 json_obj_1 = {'a': 1, 'b': 2}
102 json_obj_2 = {'a': 3, 'b': 4}
103
104 obj = self.json_model.objects.create(json=json_obj_1)
105 self.assertEqual(obj.json, json_obj_1)
106 obj.json = json_obj_2
107
108 self.assertEqual(obj.json, json_obj_2)
109 obj.save()
110 self.assertEqual(obj.json, json_obj_2)
111
112 self.assertTrue(obj)
113
114 def test_json_field_load(self):
115 """Test loading a JSON object from the DB"""
116 json_obj_1 = {'a': 1, 'b': 2}
117 obj = self.json_model.objects.create(json=json_obj_1)
118 new_obj = self.json_model.objects.get(id=obj.id)
119
120 self.assertEqual(new_obj.json, json_obj_1)
121
122 def test_json_list(self):
123 """Test storing a JSON list"""
124 json_obj = ["my", "list", "of", 1, "objs", {"hello": "there"}]
125
126 obj = self.json_model.objects.create(json=json_obj)
127 new_obj = self.json_model.objects.get(id=obj.id)
128 self.assertEqual(new_obj.json, json_obj)
129
130 def test_empty_objects(self):
131 """Test storing empty objects"""
132 for json_obj in [{}, [], 0, '', False]:
133 obj = self.json_model.objects.create(json=json_obj)
134 new_obj = self.json_model.objects.get(id=obj.id)
135 self.assertEqual(json_obj, obj.json)
136 self.assertEqual(json_obj, new_obj.json)
137
138 def test_custom_encoder(self):
139 """Test encoder_cls and object_hook"""
140 value = 1 + 3j # A complex number
141
142 obj = JSONModelCustomEncoders.objects.create(json=value)
143 new_obj = JSONModelCustomEncoders.objects.get(pk=obj.pk)
144 self.assertEqual(value, new_obj.json)
145
146 def test_django_serializers(self):
147 """Test serializing/deserializing jsonfield data"""
148 for json_obj in [{}, [], 0, '', False, {'key': 'value', 'num': 42,
149 'ary': list(range(5)),
150 'dict': {'k': 'v'}}]:
151 obj = self.json_model.objects.create(json=json_obj)
152 new_obj = self.json_model.objects.get(id=obj.id)
153 self.assert_(new_obj)
154
155 queryset = self.json_model.objects.all()
156 ser = serialize('json', queryset)
157 for dobj in deserialize('json', ser):
158 obj = dobj.object
159 pulled = self.json_model.objects.get(id=obj.pk)
160 self.assertEqual(obj.json, pulled.json)
161
162 def test_default_parameters(self):
163 """Test providing a default value to the model"""
164 model = JsonModel()
165 model.json = {"check": 12}
166 self.assertEqual(model.json, {"check": 12})
167 self.assertEqual(type(model.json), dict)
168
169 self.assertEqual(model.default_json, {"check": 12})
170 self.assertEqual(type(model.default_json), dict)
171
172 def test_invalid_json(self):
173 # invalid json data {] in the json and default_json fields
174 ser = '[{"pk": 1, "model": "jsonfield.jsoncharmodel", ' \
175 '"fields": {"json": "{]", "default_json": "{]"}}]'
176 with self.assertRaises(DeserializationError) as cm:
177 next(deserialize('json', ser))
178 inner = cm.exception.args[0]
179 self.assertTrue(isinstance(inner, ValidationError))
180 self.assertEqual('Enter valid JSON', inner.messages[0])
181
182 def test_integer_in_string_in_json_field(self):
183 """Test saving the Python string '123' in our JSONField"""
184 json_obj = '123'
185 obj = self.json_model.objects.create(json=json_obj)
186 new_obj = self.json_model.objects.get(id=obj.id)
187
188 self.assertEqual(new_obj.json, json_obj)
189
190 def test_boolean_in_string_in_json_field(self):
191 """Test saving the Python string 'true' in our JSONField"""
192 json_obj = 'true'
193 obj = self.json_model.objects.create(json=json_obj)
194 new_obj = self.json_model.objects.get(id=obj.id)
195
196 self.assertEqual(new_obj.json, json_obj)
197
198
199 def test_pass_by_reference_pollution(self):
200 """Make sure the default parameter is copied rather than passed by reference"""
201 model = JsonModel()
202 model.default_json["check"] = 144
203 model.complex_default_json[0]["checkcheck"] = 144
204 self.assertEqual(model.default_json["check"], 144)
205 self.assertEqual(model.complex_default_json[0]["checkcheck"], 144)
206
207 # Make sure when we create a new model, it resets to the default value
208 # and not to what we just set it to (it would be if it were passed by reference)
209 model = JsonModel()
210 self.assertEqual(model.default_json["check"], 12)
211 self.assertEqual(model.complex_default_json[0]["checkcheck"], 1212)
212
213 def test_normal_regex_filter(self):
214 """Make sure JSON model can filter regex"""
215
216 JsonModel.objects.create(json={"boom": "town"})
217 JsonModel.objects.create(json={"move": "town"})
218 JsonModel.objects.create(json={"save": "town"})
219
220 self.assertEqual(JsonModel.objects.count(), 3)
221
222 self.assertEqual(JsonModel.objects.filter(json__regex=r"boom").count(), 1)
223 self.assertEqual(JsonModel.objects.filter(json__regex=r"town").count(), 3)
224
225 def test_save_blank_object(self):
226 """Test that JSON model can save a blank object as none"""
227
228 model = JsonModel()
229 self.assertEqual(model.empty_default, {})
230
231 model.save()
232 self.assertEqual(model.empty_default, {})
233
234 model1 = JsonModel(empty_default={"hey": "now"})
235 self.assertEqual(model1.empty_default, {"hey": "now"})
236
237 model1.save()
238 self.assertEqual(model1.empty_default, {"hey": "now"})
239
240
241
242 class JSONCharFieldTest(JSONFieldTest):
243 json_model = JsonCharModel
244
245
246 class OrderedJsonModel(models.Model):
247 json = JSONField(load_kwargs={'object_pairs_hook': OrderedDict})
248
249
250 class OrderedDictSerializationTest(TestCase):
251 ordered_dict = OrderedDict([
252 ('number', [1, 2, 3, 4]),
253 ('notes', True),
254 ])
255 expected_key_order = ['number', 'notes']
256
257 def test_ordered_dict_differs_from_normal_dict(self):
258 self.assertEqual(list(self.ordered_dict.keys()), self.expected_key_order)
259 self.assertNotEqual(dict(self.ordered_dict).keys(), self.expected_key_order)
260
261 def test_default_behaviour_loses_sort_order(self):
262 mod = JsonModel.objects.create(json=self.ordered_dict)
263 self.assertEqual(list(mod.json.keys()), self.expected_key_order)
264 mod_from_db = JsonModel.objects.get(id=mod.id)
265
266 # mod_from_db lost ordering information during json.loads()
267 self.assertNotEqual(mod_from_db.json.keys(), self.expected_key_order)
268
269 def test_load_kwargs_hook_does_not_lose_sort_order(self):
270 mod = OrderedJsonModel.objects.create(json=self.ordered_dict)
271 self.assertEqual(list(mod.json.keys()), self.expected_key_order)
272 mod_from_db = OrderedJsonModel.objects.get(id=mod.id)
273 self.assertEqual(list(mod_from_db.json.keys()), self.expected_key_order)