]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/test/specs/data/reader/Json.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / test / specs / data / reader / Json.js
CommitLineData
6527f429
DM
1describe("Ext.data.reader.Json", function() {\r
2 var reader, data1, data2, result1, result2, result3;\r
3\r
4 beforeEach(function() {\r
5 Ext.ClassManager.enableNamespaceParseCache = false;\r
6 Ext.data.Model.schema.setNamespace('spec');\r
7 Ext.define('spec.JsonReader', {\r
8 extend: 'Ext.data.Model',\r
9 fields: [\r
10 {name: 'inter', type: 'int'}\r
11 ]\r
12 });\r
13\r
14 reader = new Ext.data.JsonReader({\r
15 rootProperty: 'data',\r
16 totalProperty: 'totalProp',\r
17 messageProperty: 'messageProp',\r
18 successProperty: 'successProp',\r
19 model: 'spec.JsonReader'\r
20 });\r
21 });\r
22\r
23 afterEach(function(){\r
24 if (reader) {\r
25 reader.destroy();\r
26 }\r
27 \r
28 reader = null;\r
29 \r
30 Ext.ClassManager.enableNamespaceParseCache = true;\r
31 Ext.undefine('spec.JsonReader');\r
32 Ext.data.Model.schema.clear(true);\r
33 });\r
34 \r
35 describe("raw data", function() {\r
36 var data, rec;\r
37 \r
38 beforeEach(function() {\r
39 data = {\r
40 inter: 1\r
41 };\r
42 });\r
43 \r
44 afterEach(function() {\r
45 rec = null;\r
46 });\r
47 \r
48 it("should not set raw data reference by default", function() {\r
49 rec = reader.readRecords([data]).getRecords()[0];\r
50 \r
51 expect(rec.raw).not.toBeDefined();\r
52 });\r
53 \r
54 it('should set raw data reference for a TreeStore record', function () {\r
55 // Simulate TreeStore node\r
56 spec.JsonReader.prototype.isNode = true;\r
57 \r
58 rec = reader.readRecords([data]).getRecords()[0];\r
59 \r
60 expect(rec.raw).toBe(data);\r
61 });\r
62 });\r
63\r
64 describe("copyFrom", function() {\r
65 var Model, copy;\r
66 \r
67 beforeEach(function() {\r
68 Model = Ext.define(null, {\r
69 extend: 'Ext.data.Model'\r
70 });\r
71 \r
72 reader.destroy();\r
73 reader = null;\r
74 });\r
75 \r
76 afterEach(function() {\r
77 copy.destroy();\r
78 Model = copy = null;\r
79 });\r
80\r
81 it("should copy the model", function() {\r
82 reader = new Ext.data.reader.Json({\r
83 model: Model\r
84 });\r
85 copy = new Ext.data.reader.Json();\r
86 copy.copyFrom(reader);\r
87 expect(copy.getModel()).toBe(Model);\r
88 });\r
89\r
90 it("should copy the record", function() {\r
91 reader = new Ext.data.reader.Json({\r
92 model: Model,\r
93 record: 'foo'\r
94 });\r
95 copy = new Ext.data.reader.Json();\r
96 copy.copyFrom(reader);\r
97 expect(copy.getRecord()).toBe('foo');\r
98\r
99 var result = reader.read([{\r
100 foo: {\r
101 x: 1\r
102 }\r
103 }]);\r
104 expect(result.getRecords()[0].get('x')).toBe(1);\r
105 });\r
106\r
107 it("should copy the totalProperty", function() {\r
108 reader = new Ext.data.reader.Json({\r
109 model: Model,\r
110 totalProperty: 'aTotal'\r
111 });\r
112 copy = new Ext.data.reader.Json();\r
113 copy.copyFrom(reader);\r
114 expect(copy.getTotalProperty()).toBe('aTotal');\r
115\r
116 var result = reader.read({\r
117 aTotal: 1000\r
118 });\r
119 expect(result.getTotal()).toBe(1000);\r
120 });\r
121\r
122 it("should copy the successProperty", function() {\r
123 reader = new Ext.data.reader.Json({\r
124 model: Model,\r
125 successProperty: 'aSuccess'\r
126 });\r
127 copy = new Ext.data.reader.Json();\r
128 copy.copyFrom(reader);\r
129 expect(copy.getSuccessProperty()).toBe('aSuccess');\r
130\r
131 var result = reader.read({\r
132 aSuccess: false\r
133 });\r
134 expect(result.getSuccess()).toBe(false);\r
135 });\r
136\r
137 it("should copy the messageProperty", function() {\r
138 reader = new Ext.data.reader.Json({\r
139 model: Model,\r
140 messageProperty: 'aMessage'\r
141 });\r
142 copy = new Ext.data.reader.Json();\r
143 copy.copyFrom(reader);\r
144 expect(copy.getMessageProperty()).toBe('aMessage');\r
145\r
146 var result = reader.read({\r
147 aMessage: 'Some Message'\r
148 });\r
149 expect(result.getMessage()).toBe('Some Message');\r
150 });\r
151\r
152 it("should copy the rootProperty", function() {\r
153 reader = new Ext.data.reader.Json({\r
154 model: Model,\r
155 rootProperty: 'aRoot'\r
156 });\r
157 copy = new Ext.data.reader.Json();\r
158 copy.copyFrom(reader);\r
159 expect(copy.getRootProperty()).toBe('aRoot');\r
160\r
161 var result = reader.read({\r
162 aRoot: [{}, {}, {}, {}]\r
163 });\r
164 expect(result.getCount()).toBe(4);\r
165 });\r
166 });\r
167\r
168 describe("preserveRawData", function() {\r
169 it("should not use the raw data object for the model if set to true", function() {\r
170 reader.setPreserveRawData(true);\r
171 var o = {\r
172 inter: 1\r
173 };\r
174 \r
175 var rec = reader.readRecords([o]).getRecords()[0];\r
176 \r
177 rec.set('inter', 2);\r
178 expect(o.inter).toBe(1);\r
179 });\r
180 \r
181 it("should be able to modify the raw data object for the model if set to false", function() {\r
182 reader.setPreserveRawData(false);\r
183 var o = {\r
184 inter: 1\r
185 };\r
186 \r
187 var rec = reader.readRecords([o]).getRecords()[0];\r
188 \r
189 rec.set('inter', 2);\r
190 expect(o.inter).toBe(2);\r
191 });\r
192 });\r
193 \r
194 describe("extractors", function() {\r
195 var createReader;\r
196 \r
197 beforeEach(function(){\r
198 createReader = function(cfg){\r
199 cfg = cfg || {};\r
200 reader = new Ext.data.reader.Json(Ext.applyIf({\r
201 model: 'spec.JsonReader'\r
202 }, cfg));\r
203 reader.buildExtractors(true);\r
204 };\r
205 });\r
206 \r
207 afterEach(function(){\r
208 createReader = null;\r
209 });\r
210 \r
211 it("should run function extractors in the reader scope", function(){\r
212 var actual;\r
213 \r
214 createReader({\r
215 successProperty: function(){\r
216 actual = this;\r
217 return true;\r
218 }\r
219 });\r
220 reader.getSuccess({\r
221 success: true\r
222 });\r
223 expect(actual).toBe(reader);\r
224 });\r
225 \r
226 /**\r
227 * While testing all of these individually is a bit redundant, it's for completeness\r
228 * to ensure that all of them are run through the proper extractors.\r
229 */\r
230 describe("getTotal", function(){\r
231 it("should default to total", function(){\r
232 createReader();\r
233 expect(reader.getTotal({\r
234 total: 5\r
235 })).toBe(5);\r
236 });\r
237 \r
238 it("should have no getTotal method if the totalProperty isn't specified", function(){\r
239 createReader({\r
240 totalProperty: ''\r
241 });\r
242 expect(reader.getTotal).toBeUndefined();\r
243 });\r
244 \r
245 it("should read the specified property name", function(){\r
246 createReader({\r
247 totalProperty: 'foo'\r
248 });\r
249 expect(reader.getTotal({\r
250 foo: 10\r
251 })).toBe(10);\r
252 });\r
253 \r
254 it("should accept a function configuration", function(){\r
255 createReader({\r
256 totalProperty: function(data){\r
257 return data.big.chain.total;\r
258 }\r
259 });\r
260 expect(reader.getTotal({\r
261 big: {\r
262 chain: {\r
263 total: 65\r
264 }\r
265 }\r
266 })).toBe(65);\r
267 });\r
268 \r
269 describe("JSON", function(){\r
270 it("should read dot notation", function(){\r
271 createReader({\r
272 totalProperty: 'big.chain.total'\r
273 });\r
274 expect(reader.getTotal({\r
275 big: {\r
276 chain: {\r
277 total: 43\r
278 }\r
279 }\r
280 })).toBe(43);\r
281 });\r
282 \r
283 it("should read array notation for numeric values", function(){\r
284 createReader({\r
285 totalProperty: 'values[0]'\r
286 });\r
287 expect(reader.getTotal({\r
288 values: [9]\r
289 })).toBe(9);\r
290 });\r
291 \r
292 it("should read array notation for property names", function(){\r
293 createReader({\r
294 totalProperty: '["foo-bar"]'\r
295 });\r
296 expect(reader.getTotal({\r
297 'foo-bar': 16\r
298 })).toBe(16);\r
299 });\r
300 \r
301 it("should read array/dot notation", function(){\r
302 createReader({\r
303 totalProperty: 'big[0].chain.total'\r
304 });\r
305 expect(reader.getTotal({\r
306 big: [{\r
307 chain: {\r
308 total: 17\r
309 }\r
310 }]\r
311 })).toBe(17);\r
312 });\r
313 \r
314 it("should not read dot chains if simple accessors are used", function(){\r
315 createReader({\r
316 totalProperty: 'some.big.chain',\r
317 useSimpleAccessors: true\r
318 });\r
319 expect(reader.getTotal({\r
320 'some.big.chain': 88\r
321 })).toBe(88);\r
322 });\r
323 }); \r
324 });\r
325 \r
326 describe("success", function(){\r
327 it("should default to success", function(){\r
328 createReader();\r
329 expect(reader.getSuccess({\r
330 success: true\r
331 })).toBe(true);\r
332 });\r
333 \r
334 it("should have no getSuccess method if the successProperty isn't specified", function(){\r
335 createReader({\r
336 successProperty: ''\r
337 });\r
338 expect(reader.getSuccess).toBeUndefined();\r
339 });\r
340 \r
341 it("should read the specified property name", function(){\r
342 createReader({\r
343 successProperty: 'foo'\r
344 });\r
345 expect(reader.getSuccess({\r
346 foo: false\r
347 })).toBe(false);\r
348 });\r
349 \r
350 it("should accept a function configuration", function(){\r
351 createReader({\r
352 successProperty: function(data){\r
353 return data.big.chain.success;\r
354 }\r
355 });\r
356 expect(reader.getSuccess({\r
357 big: {\r
358 chain: {\r
359 success: true\r
360 }\r
361 }\r
362 })).toBe(true);\r
363 });\r
364 \r
365 describe("JSON", function(){\r
366 it("should read dot notation", function(){\r
367 createReader({\r
368 successProperty: 'big.chain.success'\r
369 });\r
370 expect(reader.getSuccess({\r
371 big: {\r
372 chain: {\r
373 success: true\r
374 }\r
375 }\r
376 })).toBe(true);\r
377 });\r
378 \r
379 it("should read array notation for numeric values", function(){\r
380 createReader({\r
381 successProperty: 'values[0]'\r
382 });\r
383 expect(reader.getSuccess({\r
384 values: [false]\r
385 })).toBe(false);\r
386 });\r
387 \r
388 it("should read array notation for property names", function(){\r
389 createReader({\r
390 successProperty: '["foo-bar"]'\r
391 });\r
392 expect(reader.getSuccess({\r
393 'foo-bar': false\r
394 })).toBe(false);\r
395 });\r
396 \r
397 it("should read array/dot notation", function(){\r
398 createReader({\r
399 successProperty: 'big[0].chain.success'\r
400 });\r
401 expect(reader.getSuccess({\r
402 big: [{\r
403 chain: {\r
404 success: true\r
405 }\r
406 }]\r
407 })).toBe(true);\r
408 });\r
409 \r
410 it("should not read dot chains if simple accessors are used", function(){\r
411 createReader({\r
412 successProperty: 'some.big.chain',\r
413 useSimpleAccessors: true\r
414 });\r
415 expect(reader.getSuccess({\r
416 'some.big.chain': true\r
417 })).toBe(true);\r
418 });\r
419 });\r
420 });\r
421 \r
422 describe("message", function(){\r
423 it("should default to undefined", function(){\r
424 createReader();\r
425 expect(reader.getMessage).toBeUndefined();\r
426 });\r
427 \r
428 it("should have no getMessage method if the messageProperty isn't specified", function(){\r
429 createReader({\r
430 successProperty: ''\r
431 });\r
432 expect(reader.getSuccess).toBeUndefined();\r
433 });\r
434 \r
435 it("should read the specified property name", function(){\r
436 createReader({\r
437 messageProperty: 'foo'\r
438 });\r
439 expect(reader.getMessage({\r
440 foo: false\r
441 })).toBe(false);\r
442 });\r
443 \r
444 it("should accept a function configuration", function(){\r
445 createReader({\r
446 messageProperty: function(data){\r
447 return data.big.chain.message;\r
448 }\r
449 });\r
450 expect(reader.getMessage({\r
451 big: {\r
452 chain: {\r
453 message: 'msg'\r
454 }\r
455 }\r
456 })).toBe('msg');\r
457 });\r
458 \r
459 describe("JSON", function(){\r
460 it("should read dot notation", function(){\r
461 createReader({\r
462 messageProperty: 'big.chain.message'\r
463 });\r
464 expect(reader.getMessage({\r
465 big: {\r
466 chain: {\r
467 message: 'some message'\r
468 }\r
469 }\r
470 })).toBe('some message');\r
471 });\r
472 \r
473 it("should read array notation for numeric values", function(){\r
474 createReader({\r
475 messageProperty: 'values[0]'\r
476 });\r
477 expect(reader.getMessage({\r
478 values: ['a message']\r
479 })).toBe('a message');\r
480 });\r
481 \r
482 it("should read array notation for property names", function(){\r
483 createReader({\r
484 messageProperty: '["foo-bar"]'\r
485 });\r
486 expect(reader.getMessage({\r
487 'foo-bar': 'new msg'\r
488 })).toBe('new msg');\r
489 });\r
490 \r
491 it("should read array/dot notation", function(){\r
492 createReader({\r
493 messageProperty: 'big[0].chain.message'\r
494 });\r
495 expect(reader.getMessage({\r
496 big: [{\r
497 chain: {\r
498 message: 'stuff'\r
499 }\r
500 }]\r
501 })).toBe('stuff');\r
502 });\r
503 \r
504 it("should not read dot chains if simple accessors are used", function(){\r
505 createReader({\r
506 messageProperty: 'some.big.chain',\r
507 useSimpleAccessors: true\r
508 });\r
509 expect(reader.getMessage({\r
510 'some.big.chain': 'data'\r
511 })).toBe('data');\r
512 });\r
513 });\r
514 });\r
515 \r
516 describe("root", function(){\r
517 it("should default to a function returning the main object", function(){\r
518 var data = [];\r
519 createReader();\r
520 expect(reader.getRoot(data)).toBe(data);\r
521 });\r
522 \r
523 it("default to a function returning the main object root isn't specified", function(){\r
524 var data = [];\r
525 createReader({\r
526 rootProperty: ''\r
527 });\r
528 expect(reader.getRoot(data)).toBe(data);\r
529 });\r
530 \r
531 it("should read the specified property name", function(){\r
532 var data = [];\r
533 createReader({\r
534 rootProperty: 'foo'\r
535 });\r
536 expect(reader.getRoot({\r
537 foo: data\r
538 })).toBe(data);\r
539 });\r
540 \r
541 it("should accept a function configuration", function(){\r
542 var data = [];\r
543 createReader({\r
544 rootProperty: function(data){\r
545 return data.big.chain.root;\r
546 }\r
547 });\r
548 expect(reader.getRoot({\r
549 big: {\r
550 chain: {\r
551 root: data\r
552 }\r
553 }\r
554 })).toBe(data);\r
555 });\r
556 \r
557 describe("JSON", function(){\r
558 it("should read dot notation", function(){\r
559 var data = [];\r
560 createReader({\r
561 rootProperty: 'big.chain.root'\r
562 });\r
563 expect(reader.getRoot({\r
564 big: {\r
565 chain: {\r
566 root: data\r
567 }\r
568 }\r
569 })).toBe(data);\r
570 });\r
571 \r
572 it("should read array notation for numeric values", function(){\r
573 var data = [];\r
574 createReader({\r
575 rootProperty: 'values[0]'\r
576 });\r
577 expect(reader.getRoot({\r
578 values: [data]\r
579 })).toBe(data);\r
580 });\r
581 \r
582 it("should read array notation for property names", function(){\r
583 var data = [];\r
584 createReader({\r
585 rootProperty: '["foo-bar"]'\r
586 });\r
587 expect(reader.getRoot({\r
588 'foo-bar': data\r
589 })).toBe(data);\r
590 });\r
591 \r
592 it("should read array/dot notation", function(){\r
593 var data = [];\r
594 createReader({\r
595 rootProperty: 'big[0].chain.root'\r
596 });\r
597 expect(reader.getRoot({\r
598 big: [{\r
599 chain: {\r
600 root: data\r
601 }\r
602 }]\r
603 })).toBe(data);\r
604 });\r
605 \r
606 it("should not read dot chains if simple accessors are used", function(){\r
607 var data = [];\r
608 createReader({\r
609 rootProperty: 'some.big.chain',\r
610 useSimpleAccessors: true\r
611 });\r
612 expect(reader.getRoot({\r
613 'some.big.chain': data\r
614 })).toBe(data);\r
615 });\r
616 });\r
617 });\r
618 \r
619 describe("fields", function(){\r
620 var rawOptions = {\r
621 recordCreator: Ext.identityFn\r
622 };\r
623 \r
624 beforeEach(function(){\r
625 createReader = function(fields, simple){\r
626 Ext.define('spec.JsonFieldTest', {\r
627 extend: 'Ext.data.Model',\r
628 fields: fields\r
629 });\r
630 reader = new Ext.data.reader.Json({\r
631 model: 'spec.JsonFieldTest',\r
632 fields: fields,\r
633 useSimpleAccessors: simple || false\r
634 });\r
635 };\r
636 });\r
637 \r
638 afterEach(function() {\r
639 Ext.undefine('spec.JsonFieldTest');\r
640 });\r
641 \r
642 it("should read the name if no mapping is specified", function(){\r
643 createReader(['field']);\r
644 var result = reader.readRecords([{field: 'val'}], rawOptions).getRecords()[0];\r
645 expect(result.field).toBe('val');\r
646 });\r
647 \r
648 it("should give precedence to the mapping", function(){\r
649 createReader([{\r
650 name: 'field',\r
651 mapping: 'somethingElse'\r
652 }]);\r
653 var result = reader.readRecords([{somethingElse: 'a value'}], rawOptions).getRecords()[0];\r
654 expect(result.field).toEqual('a value');\r
655 });\r
656 \r
657 it("should accept a function", function(){\r
658 createReader([{\r
659 name: 'field',\r
660 mapping: function(o){\r
661 return o.complex.chain.value;\r
662 }\r
663 }]);\r
664 var result = reader.readRecords([{\r
665 complex: {\r
666 chain: {\r
667 value: 2\r
668 }\r
669 }\r
670 }], rawOptions).getRecords()[0];\r
671 expect(result.field).toBe(2);\r
672 });\r
673 \r
674 it("should ignore certain falsy mapping values", function(){\r
675 createReader([{\r
676 name: 'field',\r
677 mapping: undefined\r
678 }, {\r
679 name: 'field2',\r
680 mapping: null\r
681 }, {\r
682 name: 'field3',\r
683 mapping: ''\r
684 }]);\r
685 var result = reader.readRecords([{\r
686 field: 'val',\r
687 field2: 'val2',\r
688 field3: 'val3'\r
689 }], rawOptions).getRecords()[0];\r
690 \r
691 expect(result.field).toBe('val');\r
692 expect(result.field2).toBe('val2');\r
693 expect(result.field3).toBe('val3');\r
694 });\r
695\r
696 it("should allow zero value for mapping", function(){\r
697 createReader([{\r
698 name: 'field',\r
699 mapping: 0\r
700 }]);\r
701 var result1 = reader.readRecords([{\r
702 0: 'woo'\r
703 }], rawOptions).getRecords()[0];\r
704 var result2 = reader.readRecords([['T']], rawOptions).getRecords()[0];\r
705 expect(result1.field).toBe('woo');\r
706 expect(result2.field).toBe('T');\r
707 });\r
708\r
709 it("should not include a mapping where the value doesn't exist", function() {\r
710 createReader([{\r
711 name: 'field',\r
712 mapping: 'foo'\r
713 }]);\r
714 var result = reader.readRecords([{\r
715 notFoo: 'x'\r
716 }], rawOptions).getRecords()[0];\r
717 expect(result).toEqual({\r
718 notFoo: 'x'\r
719 });\r
720 expect(result.hasOwnProperty('field')).toBe(false);\r
721 });\r
722\r
723 describe("JSON", function(){\r
724 it("should read dot notation", function(){\r
725 createReader([{\r
726 name: 'field',\r
727 mapping: 'some.value'\r
728 }]);\r
729 var result = reader.readRecords([{\r
730 some: {\r
731 value: 'mapped'\r
732 }\r
733 }], rawOptions).getRecords()[0];\r
734 expect(result.field).toBe('mapped');\r
735 });\r
736 \r
737 it("should handle dot notation with an undefined property", function(){\r
738 createReader([{\r
739 name: 'field',\r
740 mapping: 'some.value'\r
741 }]);\r
742 var result = reader.readRecords([{\r
743 some: {\r
744 // 'value' is undefined\r
745 }\r
746 }], rawOptions).getRecords()[0];\r
747 expect(result.field).toBeUndefined(); // default value\r
748 });\r
749 \r
750 it("should handle dot notation with nested undefined properties", function(){\r
751 createReader([{\r
752 name: 'field',\r
753 mapping: 'some.deep.nested.value'\r
754 }]);\r
755 var result = reader.readRecords([{\r
756 some: {\r
757 // 'deep' and children are undefined\r
758 }\r
759 }], rawOptions).getRecords()[0];\r
760 expect(result.field).toBeUndefined(); // default value\r
761 });\r
762 \r
763 it("should read array notation for numeric values", function(){\r
764 createReader([{\r
765 name: 'field',\r
766 mapping: 'values[0]'\r
767 }]);\r
768 var result = reader.readRecords([{\r
769 values: ['a']\r
770 }], rawOptions).getRecords()[0];\r
771 expect(result.field).toBe('a');\r
772 });\r
773 \r
774 it("should read array notation for property names", function(){\r
775 createReader([{\r
776 name: 'field',\r
777 mapping: '["a-prop"]'\r
778 }]);\r
779 var result = reader.readRecords([{\r
780 'a-prop': 'woo'\r
781 }], rawOptions).getRecords()[0];\r
782 expect(result.field).toBe('woo');\r
783 });\r
784 \r
785 it("should read array/dot notation", function(){\r
786 createReader([{\r
787 name: 'field',\r
788 mapping: 'big[0].chain.value'\r
789 }]);\r
790 var result = reader.readRecords([{\r
791 big: [{\r
792 chain: {\r
793 value: 45\r
794 }\r
795 }]\r
796 }], rawOptions).getRecords()[0];\r
797 expect(result.field).toBe(45);\r
798 });\r
799 \r
800 it("should handle array/dot notation with nested undefined properties", function(){\r
801 createReader([{\r
802 name: 'field',\r
803 mapping: 'big[0].deep.chain.value'\r
804 }]);\r
805 var result = reader.readRecords([{\r
806 big: [{\r
807 deep: {\r
808 // 'chain' and children are undefined\r
809 }\r
810 }]\r
811 }], rawOptions).getRecords()[0];\r
812 expect(result.field).toBeUndefined(); // default value\r
813 });\r
814 \r
815 it("should not read dot chains if simple accessors are used", function(){\r
816 createReader([{\r
817 name: 'field',\r
818 mapping: 'a.long.name'\r
819 }], true);\r
820 var result = reader.readRecords([{\r
821 'a.long.name': 'sixty'\r
822 }], rawOptions).getRecords()[0];\r
823 \r
824 expect(result.field).toBe('sixty');\r
825 });\r
826 \r
827 it("should handle dot chains with undefined values if simple accessors are used", function(){\r
828 createReader([{\r
829 name: 'field',\r
830 mapping: 'a.long.name'\r
831 }], true);\r
832 var result = reader.readRecords([{\r
833 // 'a.long.name' is undefined\r
834 }], rawOptions).getRecords()[0];\r
835 expect(result.field).toBeUndefined();\r
836 });\r
837\r
838 it("should read dotted properties inside a bracketed block", function() {\r
839 createReader([{\r
840 name: 'field',\r
841 mapping: '["foo.bar.baz"]'\r
842 }]);\r
843\r
844 var result = reader.readRecords([{\r
845 'foo.bar.baz': 'x'\r
846 }], rawOptions).getRecords()[0];\r
847 expect(result.field).toBe('x');\r
848 });\r
849\r
850 it("should read [arrayIndex].property", function() {\r
851 createReader([{\r
852 name: 'field',\r
853 mapping: '[2].foo'\r
854 }]);\r
855\r
856 var result = reader.readRecords([\r
857 [1, 2, {\r
858 foo: 'x'\r
859 }]\r
860 ], rawOptions).getRecords()[0];\r
861 expect(result.field).toBe('x');\r
862 });\r
863\r
864 it("should read [arrayIndex]['property']", function() {\r
865 createReader([{\r
866 name: 'field',\r
867 mapping: '[2]["complex-name"]'\r
868 }]);\r
869\r
870 var result = reader.readRecords([\r
871 [1, 2, {\r
872 'complex-name': 'x'\r
873 }]\r
874 ], rawOptions).getRecords()[0];\r
875 expect(result.field).toBe('x');\r
876 });\r
877\r
878 it("should read [arrayIndex][arrayIndex]", function() {\r
879 createReader([{\r
880 name: 'field',\r
881 mapping: '[2][1]'\r
882 }]);\r
883\r
884 var result = reader.readRecords([\r
885 [1, 2, [3, 4, 5, 6]]\r
886 ], rawOptions).getRecords()[0];\r
887 expect(result.field).toBe(4);\r
888 });\r
889\r
890 it("should read property.property", function() {\r
891 createReader([{\r
892 name: 'field',\r
893 mapping: 'foo.bar'\r
894 }]);\r
895\r
896 var result = reader.readRecords([{\r
897 foo: {\r
898 bar: 'x'\r
899 }\r
900 }], rawOptions).getRecords()[0];\r
901 expect(result.field).toBe('x');\r
902 });\r
903\r
904 it("should read property['property']", function() {\r
905 createReader([{\r
906 name: 'field',\r
907 mapping: 'foo["complex-name"]'\r
908 }]);\r
909\r
910 var result = reader.readRecords([{\r
911 foo: {\r
912 'complex-name': 'x'\r
913 }\r
914 }], rawOptions).getRecords()[0];\r
915 expect(result.field).toBe('x');\r
916 });\r
917\r
918 it("should read property[arrayIndex]", function() {\r
919 createReader([{\r
920 name: 'field',\r
921 mapping: 'foo[2]'\r
922 }]);\r
923\r
924 var result = reader.readRecords([{\r
925 foo: [1, 2, 3, 4]\r
926 }], rawOptions).getRecords()[0];\r
927 expect(result.field).toBe(3);\r
928 });\r
929\r
930 it("should read ['property'].property", function() {\r
931 createReader([{\r
932 name: 'field',\r
933 mapping: '["complex-name"].foo'\r
934 }]);\r
935\r
936 var result = reader.readRecords([{\r
937 'complex-name': {\r
938 foo: 'x'\r
939 }\r
940 }], rawOptions).getRecords()[0];\r
941 expect(result.field).toBe('x');\r
942 });\r
943\r
944 it("should read ['property']['property']", function() {\r
945 createReader([{\r
946 name: 'field',\r
947 mapping: '["complex-name"]["other-prop"]'\r
948 }]);\r
949\r
950 var result = reader.readRecords([{\r
951 'complex-name': {\r
952 'other-prop': 'x'\r
953 }\r
954 }], rawOptions).getRecords()[0];\r
955 expect(result.field).toBe('x');\r
956 });\r
957\r
958 it("should read ['property'][arrayIndex]", function() {\r
959 createReader([{\r
960 name: 'field',\r
961 mapping: '["complex-name"][1]'\r
962 }]);\r
963\r
964 var result = reader.readRecords([{\r
965 'complex-name': [1, 2, 3, 4]\r
966 }], rawOptions).getRecords()[0];\r
967 expect(result.field).toBe(2);\r
968 });\r
969\r
970 it("should read property['property'][arrayIndex]", function() {\r
971 createReader([{\r
972 name: 'field',\r
973 mapping: 'foo["complex-name"][2]'\r
974 }]);\r
975\r
976 var result = reader.readRecords([{\r
977 foo: {\r
978 'complex-name': [1, 2, 3, 4]\r
979 }\r
980 }], rawOptions).getRecords()[0];\r
981 expect(result.field).toBe(3);\r
982 });\r
983\r
984 it("should handle property[arrayIndex]['property']", function() {\r
985 createReader([{\r
986 name: 'field',\r
987 mapping: 'foo[1]["complex-name"]'\r
988 }]);\r
989\r
990 var result = reader.readRecords([{\r
991 foo: [1, {\r
992 'complex-name': 'x'\r
993 }]\r
994 }], rawOptions).getRecords()[0];\r
995 expect(result.field).toBe('x');\r
996 });\r
997\r
998 it("should handle ['property'].property[arrayIndex]", function() {\r
999 createReader([{\r
1000 name: 'field',\r
1001 mapping: '["complex-name"].foo[1]'\r
1002 }]);\r
1003\r
1004 var result = reader.readRecords([{\r
1005 'complex-name': {\r
1006 foo: [1, 2, 3]\r
1007 }\r
1008 }], rawOptions).getRecords()[0];\r
1009 expect(result.field).toBe(2);\r
1010 });\r
1011\r
1012 it("should handle ['property'][arrayIndex].property", function() {\r
1013 createReader([{\r
1014 name: 'field',\r
1015 mapping: '["complex-name"][1].foo'\r
1016 }]);\r
1017\r
1018 var result = reader.readRecords([{\r
1019 'complex-name': [1, {\r
1020 foo: 'x'\r
1021 }]\r
1022 }], rawOptions).getRecords()[0];\r
1023 expect(result.field).toBe('x');\r
1024 });\r
1025\r
1026 it("should handle [arrayIndex].property['property']", function() {\r
1027 createReader([{\r
1028 name: 'field',\r
1029 mapping: '[1].foo["complex-name"]'\r
1030 }]);\r
1031\r
1032 var result = reader.readRecords([\r
1033 [1, {\r
1034 foo: {\r
1035 'complex-name': 'x'\r
1036 }\r
1037 }]\r
1038 ], rawOptions).getRecords()[0];\r
1039 expect(result.field).toBe('x');\r
1040 });\r
1041\r
1042 it("should handle [arrayIndex]['property'].property", function() {\r
1043 createReader([{\r
1044 name: 'field',\r
1045 mapping: '[1]["complex-name"].foo'\r
1046 }]);\r
1047\r
1048 var result = reader.readRecords([\r
1049 [1, {\r
1050 'complex-name': {\r
1051 foo: 'x'\r
1052 }\r
1053 }]\r
1054 ], rawOptions).getRecords()[0];\r
1055 expect(result.field).toBe('x');\r
1056 });\r
1057 });\r
1058 });\r
1059 });\r
1060\r
1061 describe("reading records", function() {\r
1062 beforeEach(function() {\r
1063 Ext.define("spec.JsonReaderTest", {\r
1064 extend: 'Ext.data.Model',\r
1065 fields: [\r
1066 {name: 'id'},\r
1067 {name: 'floater', type: 'float'},\r
1068 {name: 'bool', type: 'boolean'},\r
1069 {name: 'inter', type: 'integer'},\r
1070 {name: 'class', type: 'string'},\r
1071 {\r
1072 name: 'string', \r
1073 type: 'string', \r
1074 convert: function(v) {\r
1075 return "modified/" + v;\r
1076 }\r
1077 }, {\r
1078 name: 'withMap',\r
1079 mapping: 'someMap'\r
1080 }\r
1081 ]\r
1082 });\r
1083 \r
1084 // Created in global beforeEach\r
1085 reader.destroy();\r
1086\r
1087 reader = new Ext.data.reader.Json({\r
1088 rootProperty: 'data',\r
1089 idProperty: 'id',\r
1090 successProperty: 'successProp',\r
1091 totalProperty: 'totalProp',\r
1092 messageProperty: 'message',\r
1093 model: "spec.JsonReaderTest"\r
1094 });\r
1095\r
1096 data1 = {\r
1097 id : 1,\r
1098 bool : true,\r
1099 inter : 8675,\r
1100 floater: 1.23,\r
1101 string : 'Ed',\r
1102 'class': 'person'\r
1103 };\r
1104\r
1105 data2 = {\r
1106 id : 2,\r
1107 bool : false,\r
1108 inter : 309,\r
1109 floater: 4.56,\r
1110 string : 'Nick',\r
1111 'class': 'person'\r
1112 };\r
1113\r
1114 result1 = reader.readRecords({\r
1115 data : [data1],\r
1116 successProp: true,\r
1117 totalProp : 2\r
1118 });\r
1119\r
1120 result2 = reader.readRecords({\r
1121 data : [data2],\r
1122 successProp: false,\r
1123 totalProp : 6,\r
1124 message : 'Failed'\r
1125 });\r
1126 \r
1127 result3 = reader.readRecords({\r
1128 data : data2,\r
1129 successProp: true,\r
1130 totalProp : 6\r
1131 });\r
1132 });\r
1133 \r
1134 afterEach(function() {\r
1135 Ext.undefine("spec.JsonReaderTest");\r
1136 });\r
1137\r
1138 it("should read the success property", function() {\r
1139 expect(result1.getSuccess()).toBe(true);\r
1140 expect(result2.getSuccess()).toBe(false);\r
1141 });\r
1142\r
1143 it("should read the total record count", function() {\r
1144 expect(result1.getTotal()).toBe(2);\r
1145 expect(result2.getTotal()).toBe(6);\r
1146 });\r
1147\r
1148 it("should read records correctly", function() {\r
1149 var recData = result1.getRecords()[0].getData();\r
1150\r
1151 expect(recData.id).toBe(data1.id);\r
1152 expect(recData.floater).toBe(data1.floater);\r
1153 expect(recData.bool).toBe(data1.bool);\r
1154 expect(recData.inter).toBe(data1.inter);\r
1155 });\r
1156 \r
1157 it("should be able to have fields as reserved words", function(){\r
1158 var recData = result1.getRecords()[0].getData();\r
1159 expect(recData['class']).toBe('person'); \r
1160 });\r
1161 \r
1162 it("should read records correctly if there was just a single object instead of an array of data", function() {\r
1163 var recData = result3.getRecords()[0].getData();\r
1164 \r
1165 expect(recData.id).toBe(data2.id);\r
1166 expect(recData.floater).toBe(data2.floater);\r
1167 expect(recData.bool).toBe(data2.bool);\r
1168 expect(recData.inter).toBe(data2.inter);\r
1169 });\r
1170 \r
1171 it("should still read on failure by default", function(){\r
1172 expect(result2.getRecords()[0].getId()).toBe(2);\r
1173 });\r
1174 \r
1175 it("should ignore values records/total when success is false & readRecordsOnFailure is false", function(){\r
1176 reader.setReadRecordsOnFailure(false);\r
1177 result2 = reader.readRecords({\r
1178 data : [data2],\r
1179 successProp: false,\r
1180 totalProp : 6,\r
1181 message : 'Failed'\r
1182 });\r
1183 expect(result2.getRecords()).toEqual([]);\r
1184 expect(result2.getTotal()).toBe(0);\r
1185 expect(result2.getMessage()).toBe('Failed');\r
1186 });\r
1187\r
1188 it("should respect the field's convert function", function() {\r
1189 var recData = result1.getRecords()[0].getData();\r
1190\r
1191 expect(recData.string).toBe('modified/Ed');\r
1192 });\r
1193 \r
1194 it("should be able to load a single record", function(){\r
1195 var data = reader.readRecords({\r
1196 data: data1\r
1197 }).getRecords()[0].getData();\r
1198 \r
1199 expect(data.id).toBe(data1.id);\r
1200 expect(data.floater).toBe(data1.floater);\r
1201 expect(data.bool).toBe(data1.bool);\r
1202 expect(data.inter).toBe(data1.inter);\r
1203 });\r
1204 \r
1205 it("should handle record instances being in the data", function(){\r
1206 var data = reader.readRecords({\r
1207 data : [data1, new spec.JsonReaderTest(data2)],\r
1208 successProp: true\r
1209 }).getRecords()[1].getData();\r
1210 \r
1211 expect(data.id).toBe(data2.id);\r
1212 expect(data.floater).toBe(data2.floater);\r
1213 expect(data.bool).toBe(data2.bool);\r
1214 expect(data.inter).toBe(data2.inter);\r
1215 });\r
1216 \r
1217 describe("readOptions", function() {\r
1218 it("should return what we construct when we pass recordCreator", function() {\r
1219 var records = reader.readRecords({\r
1220 data: [data1, data2]\r
1221 }, {\r
1222 recordCreator: function(o) {\r
1223 return o;\r
1224 }\r
1225 }).getRecords();\r
1226 expect(records[0]).toEqual(data1);\r
1227 expect(records[1]).toEqual(data2);\r
1228 }); \r
1229 \r
1230 it("should process mappings", function() {\r
1231 var records = reader.readRecords({\r
1232 data: [{\r
1233 someMap: 'foo'\r
1234 }]\r
1235 }, {\r
1236 recordCreator: function(o) {\r
1237 return o;\r
1238 }\r
1239 }).getRecords();\r
1240 expect(records[0]).toEqual({\r
1241 withMap: 'foo',\r
1242 someMap: 'foo'\r
1243 });\r
1244 });\r
1245 });\r
1246 });\r
1247\r
1248 describe("loading with a 'record' property", function() {\r
1249 var data, resultSet;\r
1250\r
1251 beforeEach(function() {\r
1252 Ext.define('spec.User', {\r
1253 extend: 'Ext.data.Model',\r
1254 fields: [\r
1255 'id', 'name', 'email'\r
1256 ]\r
1257 });\r
1258 \r
1259 // Created in global beforeEach\r
1260 reader.destroy();\r
1261\r
1262 reader = new Ext.data.reader.Json({\r
1263 model: 'spec.User',\r
1264 rootProperty: 'users',\r
1265 record: 'user'\r
1266 });\r
1267\r
1268 data = {\r
1269 users: [\r
1270 {\r
1271 user: {\r
1272 id: 1,\r
1273 name: 'Ed Spencer',\r
1274 email: 'ed@sencha.com'\r
1275 }\r
1276 },\r
1277 {\r
1278 user: {\r
1279 id: 2,\r
1280 name: 'Abe Elias',\r
1281 email: 'abe@sencha.com'\r
1282 }\r
1283 }\r
1284 ]\r
1285 };\r
1286\r
1287 resultSet = reader.readRecords(data);\r
1288 });\r
1289 \r
1290 afterEach(function() {\r
1291 Ext.undefine('spec.User');\r
1292 });\r
1293\r
1294 it("should parse the correct number of results", function() {\r
1295 expect(resultSet.getCount()).toEqual(2);\r
1296 });\r
1297\r
1298 it("should parse each record correctly", function() {\r
1299 var records = resultSet.getRecords(),\r
1300 record1 = records[0],\r
1301 record2 = records[1];\r
1302\r
1303 expect(record1.get('name')).toBe('Ed Spencer');\r
1304 expect(record2.get('name')).toBe('Abe Elias');\r
1305 });\r
1306 });\r
1307\r
1308 describe("calling model onLoad", function() {\r
1309 beforeEach(function() {\r
1310 Ext.define('spec.User', {\r
1311 extend: 'Ext.data.Model',\r
1312 fields: ['name'],\r
1313 onLoad: function() {}\r
1314 });\r
1315\r
1316 // Created in global beforeEach\r
1317 reader.destroy();\r
1318 });\r
1319\r
1320 afterEach(function() {\r
1321 Ext.undefine('spec.User');\r
1322 });\r
1323\r
1324 it("should call the template method for each record", function() {\r
1325 var spy = spyOn(spec.User.prototype, 'onLoad');\r
1326 reader = new Ext.data.reader.Json({\r
1327 model: 'spec.User'\r
1328 });\r
1329 reader.read([\r
1330 {id: 1},\r
1331 {id: 2},\r
1332 {id: 3},\r
1333 {id: 4},\r
1334 {id: 5},\r
1335 {id: 6},\r
1336 {id: 7}\r
1337 ]);\r
1338 expect(spy.callCount).toBe(7);\r
1339 });\r
1340\r
1341 it("should call the template method after processing associations", function() {\r
1342 var count;\r
1343 spyOn(spec.User.prototype, 'onLoad').andCallFake(function() {\r
1344 count = this.orders().getCount();\r
1345 });\r
1346 Ext.define('spec.Order', {\r
1347 extend: 'Ext.data.Model',\r
1348 fields: [{\r
1349 name: 'userId',\r
1350 reference: 'User'\r
1351 }]\r
1352 });\r
1353 reader = new Ext.data.reader.Json({\r
1354 model: 'spec.User'\r
1355 });\r
1356 reader.read([{\r
1357 id: 1,\r
1358 orders: [{\r
1359 id: 1\r
1360 }]\r
1361 }]);\r
1362 expect(count).toBe(1);\r
1363 Ext.undefine('spec.Order');\r
1364 });\r
1365 });\r
1366\r
1367 describe("loading nested data", function() {\r
1368 var nestedLoadData = {\r
1369 "users": [\r
1370 {\r
1371 "id": 123,\r
1372 "name": "Ed",\r
1373 "addresses": [\r
1374 {\r
1375 "line1": "525 University Avenue",\r
1376 "line2": "Suite 23",\r
1377 "town" : "Palo Alto"\r
1378 }\r
1379 ],\r
1380 "orders": [\r
1381 {\r
1382 "id": 50,\r
1383 "total": 100,\r
1384 "order_items": [\r
1385 {\r
1386 "id" : 20,\r
1387 "price" : 40,\r
1388 "quantity": 2,\r
1389 "product" : {\r
1390 "id": 1000,\r
1391 "name": "MacBook Pro"\r
1392 }\r
1393 },\r
1394 {\r
1395 "id" : 21,\r
1396 "price" : 20,\r
1397 "quantity": 1,\r
1398 "product" : {\r
1399 "id": 1001,\r
1400 "name": "iPhone"\r
1401 }\r
1402 }\r
1403 ]\r
1404 },\r
1405 {\r
1406 "id": 51,\r
1407 "total": 10,\r
1408 "order_items": [\r
1409 {\r
1410 "id": 22,\r
1411 "price": 10,\r
1412 "quantity": 1,\r
1413 "product": {\r
1414 "id" : 1002,\r
1415 "name": "iPad"\r
1416 }\r
1417 }\r
1418 ]\r
1419 }\r
1420 ]\r
1421 }\r
1422 ]\r
1423 };\r
1424\r
1425 beforeEach(function() {\r
1426 //We have five models - User, Address, Order, OrderItem and Product\r
1427 Ext.define("spec.User", {\r
1428 extend: 'Ext.data.Model',\r
1429 fields: [\r
1430 'id', 'name'\r
1431 ],\r
1432\r
1433 hasMany: [\r
1434 {model: 'spec.Order', name: 'orders'},\r
1435 {model: 'spec.Address', name: 'addresses'}\r
1436 ],\r
1437\r
1438 proxy: {\r
1439 type: 'rest',\r
1440 reader: {\r
1441 type: 'json',\r
1442 rootProperty: 'users'\r
1443 }\r
1444 }\r
1445 });\r
1446 \r
1447 spyOn(Ext.log, 'warn');\r
1448\r
1449 Ext.define('spec.Address', {\r
1450 extend: 'Ext.data.Model',\r
1451 fields: [\r
1452 'id', 'line1', 'line2', 'town'\r
1453 ],\r
1454\r
1455 belongsTo: 'spec.User'\r
1456 });\r
1457\r
1458 Ext.define("spec.Order", {\r
1459 extend: 'Ext.data.Model',\r
1460 fields: [\r
1461 'id', 'total'\r
1462 ],\r
1463\r
1464 hasMany : {model: 'spec.OrderItem', name: 'orderItems', associationKey: 'order_items'},\r
1465 belongsTo: 'spec.User'\r
1466 });\r
1467\r
1468 Ext.define("spec.OrderItem", {\r
1469 extend: 'Ext.data.Model',\r
1470 fields: [\r
1471 'id', 'price', 'quantity', 'order_id', 'product_id'\r
1472 ],\r
1473\r
1474 belongsTo: ['spec.Order', {model: 'spec.Product', getterName: 'getProduct', associationKey: 'product'}]\r
1475 });\r
1476\r
1477 Ext.define("spec.Product", {\r
1478 extend: 'Ext.data.Model',\r
1479 fields: [\r
1480 'id', 'name'\r
1481 ],\r
1482\r
1483 hasMany: {model: 'spec.OrderItem', name: 'orderItems'}\r
1484 });\r
1485 \r
1486 // Created in global beforeEach\r
1487 reader.destroy();\r
1488 });\r
1489 \r
1490 afterEach(function() {\r
1491 Ext.undefine('spec.User');\r
1492 Ext.undefine('spec.Address');\r
1493 Ext.undefine('spec.Order');\r
1494 Ext.undefine('spec.OrderItem');\r
1495 Ext.undefine('spec.Product');\r
1496 });\r
1497\r
1498 function createReader(config) {\r
1499 return new Ext.data.reader.Json(Ext.apply({}, config, {\r
1500 model: "spec.User",\r
1501 rootProperty: "users"\r
1502 }));\r
1503 }\r
1504\r
1505 it("should set implicitIncludes to true by default", function() {\r
1506 reader = createReader();\r
1507\r
1508 expect(reader.getImplicitIncludes()).toBe(true);\r
1509 });\r
1510\r
1511 it("should not parse includes if implicitIncludes is set to false", function() {\r
1512 reader = createReader({implicitIncludes: false});\r
1513\r
1514 var resultSet = reader.read(Ext.clone(nestedLoadData)),\r
1515 user = resultSet.getRecords()[0],\r
1516 orders = user.orders();\r
1517\r
1518 expect(orders.getCount()).toBe(0);\r
1519 });\r
1520\r
1521 describe("when reading nested data", function() {\r
1522 var resultSet, user, orders, orderItems, product, addresses;\r
1523\r
1524 beforeEach(function() {\r
1525 reader = createReader();\r
1526 resultSet = reader.read(Ext.clone(nestedLoadData));\r
1527 user = resultSet.getRecords()[0];\r
1528 addresses = user.addresses();\r
1529 orders = user.orders();\r
1530 orderItems = orders.first().orderItems();\r
1531 product = orderItems.first().getProduct();\r
1532 });\r
1533\r
1534 it("should populate first-order associations", function() {\r
1535 expect(orders.getCount()).toBe(2);\r
1536 expect(addresses.getCount()).toBe(1);\r
1537 });\r
1538\r
1539 it("should populate second-order associations", function() {\r
1540 expect(orderItems.getCount()).toBe(2);\r
1541 });\r
1542\r
1543 it("should populate belongsTo associations", function() {\r
1544 expect(product.get('name')).toBe('MacBook Pro');\r
1545 });\r
1546\r
1547 it("should ignore associations where the model isn't yet loaded", function() {\r
1548 Ext.define('spec.Employee', {\r
1549 extend: 'Ext.data.Model',\r
1550 fields: ['id', 'name', {\r
1551 name: 'projectId',\r
1552 reference: 'Project'\r
1553 }]\r
1554 });\r
1555 reader = new Ext.data.reader.Json({\r
1556 model: 'spec.Employee'\r
1557 });\r
1558 expect(function() {\r
1559 reader.read({\r
1560 id: 1,\r
1561 name: 'Foo'\r
1562 });\r
1563 }).not.toThrow();\r
1564 });\r
1565 });\r
1566 });\r
1567\r
1568 describe("reconfiguring via metadata", function() {\r
1569\r
1570 it("should call onMetaChange", function() {\r
1571 var meta = {some: 'meta data'};\r
1572 \r
1573 spyOn(reader, 'onMetaChange').andReturn();\r
1574 spyOn(reader, 'getRoot').andReturn([]);\r
1575 \r
1576 reader.readRecords({metaData: meta});\r
1577 expect(reader.onMetaChange).toHaveBeenCalledWith(meta);\r
1578 });\r
1579 \r
1580 it("should accept a custom meta property", function(){\r
1581 reader.setMetaProperty('foo.bar.baz');\r
1582 reader.buildExtractors(true);\r
1583 \r
1584 spyOn(reader, 'onMetaChange').andReturn();\r
1585 spyOn(reader, 'getRoot').andReturn([]);\r
1586 \r
1587 var o = {};\r
1588 var meta = {\r
1589 foo: {\r
1590 bar: {\r
1591 baz: o\r
1592 }\r
1593 }\r
1594 };\r
1595 reader.readRecords(meta);\r
1596 expect(reader.onMetaChange).toHaveBeenCalledWith(o);\r
1597 });\r
1598 \r
1599 });\r
1600\r
1601 describe("reading xhr", function() {\r
1602 var goodResponse = {\r
1603 responseText: '{ "success": true, "users": [{"name": "Ben", "location": "Boston"}, {"name": "Mike", "location": "Redwood City"}, {"name": "Nick", "location": "Kansas City"}] }'\r
1604 },\r
1605 badResponse = {\r
1606 responseText: 'this is not JSON'\r
1607 };\r
1608\r
1609 beforeEach(function() {\r
1610 Ext.define('spec.User', {\r
1611 extend: 'Ext.data.Model',\r
1612 fields: ['name', 'location']\r
1613 });\r
1614\r
1615 // Created in global beforeEach\r
1616 reader.destroy();\r
1617\r
1618 reader = new Ext.data.reader.Json({\r
1619 rootProperty: 'users',\r
1620 model: 'spec.User',\r
1621 listeners: {\r
1622 exception: function (reader, response, errorMsg, eOpts) {\r
1623 }\r
1624 }\r
1625 });\r
1626 });\r
1627 \r
1628 afterEach(function() {\r
1629 Ext.undefine('spec.User');\r
1630 });\r
1631 \r
1632 function doRead(response) {\r
1633 return reader.read(response);\r
1634 }\r
1635\r
1636 describe("if there is a responseText property", function() {\r
1637 describe("if there is valid JSON", function() { \r
1638 it("should be successful", function() {\r
1639 expect(doRead(goodResponse).getSuccess()).toBe(true);\r
1640 });\r
1641\r
1642 it("should return the expected number of records", function() {\r
1643 expect(doRead(goodResponse).getCount()).toBe(3);\r
1644 });\r
1645 \r
1646 it("should not return a non-empty dataset", function() {\r
1647 expect(doRead(goodResponse).getRecords().length).toBe(3);\r
1648 });\r
1649 });\r
1650\r
1651 describe("if there is invalid JSON", function() {\r
1652 beforeEach(function() {\r
1653 spyOn(Ext, 'log');\r
1654 spyOn(Ext.Logger, 'warn');\r
1655 });\r
1656 \r
1657 it("should not be successful", function() {\r
1658 expect(doRead(badResponse).getSuccess()).toBe(false);\r
1659 });\r
1660\r
1661 it("should not return any records", function() {\r
1662 expect(doRead(badResponse).getTotal()).toBe(0);\r
1663 });\r
1664 \r
1665 it("should return any empty dataset", function() {\r
1666 expect(doRead(badResponse).getRecords().length).toBe(0);\r
1667 });\r
1668\r
1669 it("should fire the exception event", function() {\r
1670 var spy = jasmine.createSpy();\r
1671 reader.on('exception', spy);\r
1672 doRead(badResponse);\r
1673 expect(spy.callCount).toBe(1);\r
1674 });\r
1675 });\r
1676 });\r
1677\r
1678 describe("if there is no responseText property", function() { \r
1679 it("should return an empty dataset", function() {\r
1680 expect(doRead("something").getCount()).toBe(0);\r
1681 });\r
1682 });\r
1683 });\r
1684});\r