[FIX] handling of setting/resetting ids on records in list collections
[odoo/odoo.git] / addons / web / static / test / list-utils.js
1 $(document).ready(function () {
2     var openerp,
3         create = function (o) {
4             if (typeof Object.create === 'function') {
5                 return Object.create(o);
6             }
7             function Cls() {}
8             Cls.prototype = o;
9             return new Cls;
10         };
11     module('list-events', {
12         setup: function () {
13             openerp = window.openerp.init([]);
14             window.openerp.web.corelib(openerp);
15             window.openerp.web.coresetup(openerp);
16             window.openerp.web.chrome(openerp);
17             // views loader stuff
18             window.openerp.web.data(openerp);
19             window.openerp.web.views(openerp);
20             window.openerp.web.list(openerp);
21         }
22     });
23     test('Simple event triggering', function () {
24         var e = create(openerp.web.list.Events), passed = false;
25         e.bind('foo', function () { passed = true; });
26         e.trigger('foo');
27         ok(passed);
28     });
29     test('Bind all', function () {
30         var e = create(openerp.web.list.Events), event = null;
31         e.bind(null, function (ev) { event = ev; });
32         e.trigger('foo');
33         strictEqual(event, 'foo');
34     });
35     test('Propagate trigger params', function () {
36        var e = create(openerp.web.list.Events), p = false;
37         e.bind(null, function (_, param) { p = param });
38         e.trigger('foo', true);
39         strictEqual(p, true)
40     });
41     test('Bind multiple callbacks', function () {
42         var e = create(openerp.web.list.Events), count;
43         e.bind('foo', function () { count++; })
44          .bind('bar', function () { count++; })
45          .bind(null, function () { count++; })
46          .bind('foo', function () { count++; })
47          .bind(null, function () { count++; })
48          .bind(null, function () { count++; });
49
50         count = 0;
51         e.trigger('foo');
52         strictEqual(count, 5);
53
54         count = 0;
55         e.trigger('bar');
56         strictEqual(count, 4);
57
58         count = 0;
59         e.trigger('baz');
60         strictEqual(count, 3);
61     });
62     test('Mixin events', function () {
63         var cls = openerp.web.Class.extend({
64             method: function () { this.trigger('e'); }
65         });
66         cls.include(openerp.web.list.Events);
67         var instance = new cls, triggered = false;
68
69         instance.bind('e', function () { triggered = true; });
70         instance.method();
71
72         ok(triggered);
73     });
74     test('Unbind all handlers', function () {
75         var e = create(openerp.web.list.Events), passed = 0;
76         e.bind('foo', function () { passed++; });
77         e.trigger('foo');
78         strictEqual(passed, 1);
79         e.unbind('foo');
80         e.trigger('foo');
81         strictEqual(passed, 1);
82     });
83     test('Unbind one handler', function () {
84         var e = create(openerp.web.list.Events), p1 = 0, p2 = 0,
85             h1 = function () { p1++; }, h2 = function () { p2++; };
86         e.bind('foo', h1);
87         e.bind('foo', h2);
88         e.trigger('foo');
89         strictEqual(p1, 1);
90         strictEqual(p2, 1);
91         e.unbind('foo', h1);
92         e.trigger('foo');
93         strictEqual(p1, 1);
94         strictEqual(p2, 2);
95     });
96
97     module('list-records', {
98         setup: function () {
99             openerp = window.openerp.init([]);
100             window.openerp.web.corelib(openerp);
101             window.openerp.web.coresetup(openerp);
102             window.openerp.web.chrome(openerp);
103             // views loader stuff
104             window.openerp.web.data(openerp);
105             window.openerp.web.views(openerp);
106             window.openerp.web.list(openerp);
107         }
108     });
109     test('Basic record initialization', function () {
110         var r = new openerp.web.list.Record({qux: 3});
111         r.set('foo', 1);
112         r.set('bar', 2);
113         strictEqual(r.get('foo'), 1);
114         strictEqual(r.get('bar'), 2);
115         strictEqual(r.get('qux'), 3);
116     });
117     test('Change all the things', function () {
118         var r = new openerp.web.list.Record(), changed = false, field;
119         r.bind('change', function () { changed = true; });
120         r.bind(null, function (e) { field = field || e.split(':')[1]});
121         r.set('foo', 1);
122         strictEqual(r.get('foo'), 1);
123         ok(changed);
124         strictEqual(field, 'foo');
125     });
126     test('Change single field', function () {
127         var r = new openerp.web.list.Record(), changed = 0;
128         r.bind('change:foo', function () { changed++; });
129         r.set('foo', 1);
130         r.set('bar', 1);
131         strictEqual(r.get('foo'), 1);
132         strictEqual(r.get('bar'), 1);
133         strictEqual(changed, 1);
134     });
135
136     module('list-collections-degenerate', {
137         setup: function () {
138             openerp = window.openerp.init([]);
139             window.openerp.web.corelib(openerp);
140             window.openerp.web.coresetup(openerp);
141             window.openerp.web.chrome(openerp);
142             // views loader stuff
143             window.openerp.web.data(openerp);
144             window.openerp.web.views(openerp);
145             window.openerp.web.list(openerp);
146         }
147     });
148     test('Fetch from collection', function () {
149         var c = new openerp.web.list.Collection();
150         strictEqual(c.length, 0);
151         c.add({id: 1, value: 2});
152         c.add({id: 2, value: 3});
153         c.add({id: 3, value: 5});
154         c.add({id: 4, value: 7});
155         strictEqual(c.length, 4);
156         var r = c.at(2), r2 = c.get(1);
157
158         ok(r instanceof openerp.web.list.Record);
159         strictEqual(r.get('id'), 3);
160         strictEqual(r.get('value'), 5);
161
162         ok(r2 instanceof openerp.web.list.Record);
163         strictEqual(r2.get('id'), 1);
164         strictEqual(r2.get('value'), 2);
165     });
166     test('Add at index', function () {
167         var c = new openerp.web.list.Collection([
168             {id: 1, value: 5},
169             {id: 2, value: 10},
170             {id: 3, value: 20}
171         ]);
172         strictEqual(c.at(1).get('value'), 10);
173         equal(c.at(3), undefined);
174         c.add({id:4, value: 55}, {at: 1});
175         strictEqual(c.at(1).get('value'), 55);
176         strictEqual(c.at(3).get('value'), 20);
177     });
178     test('Remove record', function () {
179         var c = new openerp.web.list.Collection([
180             {id: 1, value: 5},
181             {id: 2, value: 10},
182             {id: 3, value: 20}
183         ]);
184         var record = c.get(2);
185         strictEqual(c.length, 3);
186         c.remove(record);
187         strictEqual(c.length, 2);
188         equal(c.get(2), undefined);
189         strictEqual(c.at(1).get('value'), 20);
190     });
191     test('Remove unbind', function () {
192         var changed = false,
193             c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
194         c.bind('change', function () { changed = true; });
195         var record = c.get(1);
196         c.remove(record);
197         record.set('value', 42);
198         ok(!changed, 'removed records should not trigger events in their ' +
199                      'parent collection');
200     });
201     test('Reset', function () {
202         var event, obj, c = new openerp.web.list.Collection([
203             {id: 1, value: 5},
204             {id: 2, value: 10},
205             {id: 3, value: 20}
206         ]);
207         c.bind(null, function (e, instance) { event = e; obj = instance; });
208         c.reset();
209         strictEqual(c.length, 0);
210         strictEqual(event, 'reset');
211         strictEqual(obj, c);
212         c.add([
213             {id: 1, value: 5},
214             {id: 2, value: 10},
215             {id: 3, value: 20}
216         ]);
217         c.reset([{id: 42, value: 55}]);
218         strictEqual(c.length, 1);
219         strictEqual(c.get(42).get('value'), 55);
220     });
221     test('Reset unbind', function () {
222         var changed = false,
223             c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
224         c.bind('change', function () { changed = true; });
225         var record = c.get(1);
226         c.reset();
227         record.set('value', 42);
228         ok(!changed, 'removed records should not trigger events in their ' +
229                      'parent collection');
230     });
231
232     test('Events propagation', function () {
233         var values = [];
234         var c = new openerp.web.list.Collection([
235             {id: 1, value: 5},
236             {id: 2, value: 10},
237             {id: 3, value: 20}
238         ]);
239         c.bind('change:value', function (e, record, value) {
240             values.push(value);
241         });
242         c.get(1).set('value', 6);
243         c.get(2).set('value', 11);
244         c.get(3).set('value', 21);
245         deepEqual(values, [6, 11, 21]);
246     });
247     test('BTree', function () {
248         var root = new openerp.web.list.Collection(),
249             c = root.proxy('admin'),
250             total = 0;
251         c.add({id: 1, name: "Administrator", login: 'admin'});
252         c.add({id: 3, name: "Demo", login: 'demo'});
253         root.bind('change:wealth', function () {
254             total = (root.get(1).get('wealth') || 0) + (root.get(3).get('wealth') || 0);
255         });
256
257         strictEqual(total, 0);
258         c.at(0).set('wealth', 42);
259         strictEqual(total, 42);
260         c.at(1).set('wealth', 5);
261         strictEqual(total, 47);
262     });
263
264     module('list-hofs', {
265         setup: function () {
266             openerp = window.openerp.init([]);
267             window.openerp.web.corelib(openerp);
268             window.openerp.web.coresetup(openerp);
269             window.openerp.web.chrome(openerp);
270             // views loader stuff
271             window.openerp.web.data(openerp);
272             window.openerp.web.views(openerp);
273             window.openerp.web.list(openerp);
274         }
275     });
276     test('each, degenerate', function () {
277         var c = new openerp.web.list.Collection([
278             {id: 1, value: 5},
279             {id: 2, value: 10},
280             {id: 3, value: 20}
281         ]), ids = [];
282         c.each(function (record) {
283             ids.push(record.get('id'));
284         });
285         deepEqual(
286             ids, [1, 2, 3],
287             'degenerate collections should be iterated in record order');
288     });
289     test('each, deep', function () {
290         var root = new openerp.web.list.Collection(),
291             ids = [];
292         root.proxy('foo').add([
293             {id: 1, value: 5},
294             {id: 2, value: 10},
295             {id: 3, value: 20}]);
296         root.proxy('bar').add([
297             {id: 10, value: 5},
298             {id: 20, value: 10},
299             {id: 30, value: 20}]);
300         root.each(function (record) {
301             ids.push(record.get('id'));
302         });
303         // No contract on sub-collection iteration order (for now anyway)
304         ids.sort(function (a, b) { return a - b; });
305         deepEqual(
306             ids, [1, 2, 3, 10, 20, 30],
307             'tree collections should be deeply iterated');
308     });
309     test('map, degenerate', function () {
310         var c = new openerp.web.list.Collection([
311             {id: 1, value: 5},
312             {id: 2, value: 10},
313             {id: 3, value: 20}
314         ]);
315         var ids = c.map(function (record) {
316             return record.get('id');
317         });
318         deepEqual(
319             ids, [1, 2, 3],
320             'degenerate collections should be iterated in record order');
321     });
322     test('map, deep', function () {
323         var root = new openerp.web.list.Collection();
324         root.proxy('foo').add([
325             {id: 1, value: 5},
326             {id: 2, value: 10},
327             {id: 3, value: 20}]);
328         root.proxy('bar').add([
329             {id: 10, value: 5},
330             {id: 20, value: 10},
331             {id: 30, value: 20}]);
332         var ids = root.map(function (record) {
333             return record.get('id');
334         });
335         // No contract on sub-collection iteration order (for now anyway)
336         ids.sort(function (a, b) { return a - b; });
337         deepEqual(
338             ids, [1, 2, 3, 10, 20, 30],
339             'tree collections should be deeply iterated');
340     });
341
342     module("list-weirds", {
343         setup: function () {
344             openerp = window.openerp.init([]);
345             window.openerp.web.corelib(openerp);
346             window.openerp.web.coresetup(openerp);
347             window.openerp.web.chrome(openerp);
348             // views loader stuff
349             window.openerp.web.data(openerp);
350             window.openerp.web.views(openerp);
351             window.openerp.web.list(openerp);
352         }
353     });
354     test('set-from-noid', function () {
355         var root = new openerp.web.list.Collection();
356         root.add({v: 3});
357         root.at(0).set('id', 42);
358         var record = root.get(42);
359         equal(root.length, 1);
360         equal(record.get('v'), 3, "should have fetched the original record");
361     });
362     test('set-from-previd', function () {
363         var root = new openerp.web.list.Collection();
364         root.add({id: 1, v: 2});
365         root.get(1).set('id', 42);
366         var record = root.get(42);
367         equal(root.length, 1);
368         equal(record.get('v'), 2, "should have fetched the original record");
369     });
370 });