Added some tests for jsonrpc
[odoo/odoo.git] / addons / web / static / test / framework.js
1 (function() {
2
3 var ropenerp = window.openerp;
4
5 var openerp = ropenerp.declare($, _, QWeb2);
6
7 ropenerp.testing.section('class', {
8     dependencies: ['web.corelib']
9 }, function (test) {
10     test('Basic class creation', function () {
11         var C = openerp.web.Class.extend({
12             foo: function () {
13                 return this.somevar;
14             }
15         });
16         var i = new C();
17         i.somevar = 3;
18
19         ok(i instanceof C);
20         strictEqual(i.foo(), 3);
21     });
22     test('Class initialization', function () {
23         var C1 = openerp.web.Class.extend({
24             init: function () {
25                 this.foo = 3;
26             }
27         });
28         var C2 = openerp.web.Class.extend({
29             init: function (arg) {
30                 this.foo = arg;
31             }
32         });
33
34         var i1 = new C1(),
35             i2 = new C2(42);
36
37         strictEqual(i1.foo, 3);
38         strictEqual(i2.foo, 42);
39     });
40     test('Inheritance', function () {
41         var C0 = openerp.web.Class.extend({
42             foo: function () {
43                 return 1;
44             }
45         });
46         var C1 = C0.extend({
47             foo: function () {
48                 return 1 + this._super();
49             }
50         });
51         var C2 = C1.extend({
52             foo: function () {
53                 return 1 + this._super();
54             }
55         });
56
57         strictEqual(new C0().foo(), 1);
58         strictEqual(new C1().foo(), 2);
59         strictEqual(new C2().foo(), 3);
60     });
61     test('In-place extension', function () {
62         var C0 = openerp.web.Class.extend({
63             foo: function () {
64                 return 3;
65             },
66             qux: function () {
67                 return 3;
68             },
69             bar: 3
70         });
71         C0.include({
72             foo: function () {
73                 return 5;
74             },
75             qux: function () {
76                 return 2 + this._super();
77             },
78             bar: 5,
79             baz: 5
80         });
81
82         strictEqual(new C0().bar, 5);
83         strictEqual(new C0().baz, 5);
84         strictEqual(new C0().foo(), 5);
85         strictEqual(new C0().qux(), 5);
86     });
87     test('In-place extension and inheritance', function () {
88         var C0 = openerp.web.Class.extend({
89             foo: function () { return 1; },
90             bar: function () { return 1; }
91         });
92         var C1 = C0.extend({
93             foo: function () { return 1 + this._super(); }
94         });
95         strictEqual(new C1().foo(), 2);
96         strictEqual(new C1().bar(), 1);
97
98         C1.include({
99             foo: function () { return 2 + this._super(); },
100             bar: function () { return 1 + this._super(); }
101         });
102         strictEqual(new C1().foo(), 4);
103         strictEqual(new C1().bar(), 2);
104     });
105     test('In-place extensions alter existing instances', function () {
106         var C0 = openerp.web.Class.extend({
107             foo: function () { return 1; },
108             bar: function () { return 1; }
109         });
110         var i = new C0();
111         strictEqual(i.foo(), 1);
112         strictEqual(i.bar(), 1);
113
114         C0.include({
115             foo: function () { return 2; },
116             bar: function () { return 2 + this._super(); }
117         });
118         strictEqual(i.foo(), 2);
119         strictEqual(i.bar(), 3);
120     });
121     test('In-place extension of subclassed types', function () {
122         var C0 = openerp.web.Class.extend({
123             foo: function () { return 1; },
124             bar: function () { return 1; }
125         });
126         var C1 = C0.extend({
127             foo: function () { return 1 + this._super(); },
128             bar: function () { return 1 + this._super(); }
129         });
130         var i = new C1();
131         strictEqual(i.foo(), 2);
132         C0.include({
133             foo: function () { return 2; },
134             bar: function () { return 2 + this._super(); }
135         });
136         strictEqual(i.foo(), 3);
137         strictEqual(i.bar(), 4);
138     });
139 });
140
141
142 ropenerp.testing.section('Widget.proxy', {
143 }, function (test) {
144     test('(String)', function () {
145         var W = openerp.web.Widget.extend({
146             exec: function () {
147                 this.executed = true;
148             }
149         });
150         var w = new W();
151         var fn = w.proxy('exec');
152         fn();
153         ok(w.executed, 'should execute the named method in the right context');
154     });
155     test('(String)(*args)', function () {
156         var W = openerp.web.Widget.extend({
157             exec: function (arg) {
158                 this.executed = arg;
159             }
160         });
161         var w = new W();
162         var fn = w.proxy('exec');
163         fn(42);
164         ok(w.executed, "should execute the named method in the right context");
165         equal(w.executed, 42, "should be passed the proxy's arguments");
166     });
167     test('(String), include', function () {
168         // the proxy function should handle methods being changed on the class
169         // and should always proxy "by name", to the most recent one
170         var W = openerp.web.Widget.extend({
171             exec: function () {
172                 this.executed = 1;
173             }
174         });
175         var w = new W();
176         var fn = w.proxy('exec');
177         W.include({
178             exec: function () { this.executed = 2; }
179         });
180
181         fn();
182         equal(w.executed, 2, "should be lazily resolved");
183     });
184
185     test('(Function)', function () {
186         var w = new (openerp.web.Widget.extend({ }))();
187
188         var fn = w.proxy(function () { this.executed = true; });
189         fn();
190         ok(w.executed, "should set the function's context (like Function#bind)");
191     });
192     test('(Function)(*args)', function () {
193         var w = new (openerp.web.Widget.extend({ }))();
194
195         var fn = w.proxy(function (arg) { this.executed = arg; });
196         fn(42);
197         equal(w.executed, 42, "should be passed the proxy's arguments");
198     });
199 });
200 ropenerp.testing.section('Widget.renderElement', {
201     setup: function () {
202         openerp.web.qweb = new QWeb2.Engine();
203         openerp.web.qweb.add_template(
204             '<no>' +
205                 '<t t-name="test.widget.template">' +
206                     '<ol>' +
207                         '<li t-foreach="5" t-as="counter" ' +
208                             't-attf-class="class-#{counter}">' +
209                             '<input/>' +
210                             '<t t-esc="counter"/>' +
211                         '</li>' +
212                     '</ol>' +
213                 '</t>' +
214                 '<t t-name="test.widget.template-value">' +
215                     '<p><t t-esc="widget.value"/></p>' +
216                 '</t>' +
217             '</no>');
218     }
219 }, function (test) {
220     test('no template, default', function () {
221         var w = new (openerp.web.Widget.extend({ }))();
222
223         var $original = w.$el;
224         ok($original, "should initially have a root element");
225         w.renderElement();
226         ok(w.$el, "should have generated a root element");
227         ok($original !== w.$el, "should have generated a new root element");
228         strictEqual(w.$el, w.$el, "should provide $el alias");
229         ok(w.$el.is(w.el), "should provide raw DOM alias");
230
231         equal(w.el.nodeName, 'DIV', "should have generated the default element");
232         equal(w.el.attributes.length, 0, "should not have generated any attribute");
233         ok(_.isEmpty(w.$el.html(), "should not have generated any content"));
234     });
235     test('no template, custom tag', function () {
236         var w = new (openerp.web.Widget.extend({
237             tagName: 'ul'
238         }))();
239         w.renderElement();
240
241         equal(w.el.nodeName, 'UL', "should have generated the custom element tag");
242     });
243     test('no template, @id', function () {
244         var w = new (openerp.web.Widget.extend({
245             id: 'foo'
246         }))();
247         w.renderElement();
248
249         equal(w.el.attributes.length, 1, "should have one attribute");
250         equal(w.$el.attr('id'), 'foo', "should have generated the id attribute");
251         equal(w.el.id, 'foo', "should also be available via property");
252     });
253     test('no template, @className', function () {
254         var w = new (openerp.web.Widget.extend({
255             className: 'oe_some_class'
256         }))();
257         w.renderElement();
258
259         equal(w.el.className, 'oe_some_class', "should have the right property");
260         equal(w.$el.attr('class'), 'oe_some_class', "should have the right attribute");
261     });
262     test('no template, bunch of attributes', function () {
263         var w = new (openerp.web.Widget.extend({
264             attributes: {
265                 'id': 'some_id',
266                 'class': 'some_class',
267                 'data-foo': 'data attribute',
268                 'clark': 'gable',
269                 'spoiler': 'snape kills dumbledore'
270             }
271         }))();
272         w.renderElement();
273
274         equal(w.el.attributes.length, 5, "should have all the specified attributes");
275
276         equal(w.el.id, 'some_id');
277         equal(w.$el.attr('id'), 'some_id');
278
279         equal(w.el.className, 'some_class');
280         equal(w.$el.attr('class'), 'some_class');
281
282         equal(w.$el.attr('data-foo'), 'data attribute');
283         equal(w.$el.data('foo'), 'data attribute');
284
285         equal(w.$el.attr('clark'), 'gable');
286         equal(w.$el.attr('spoiler'), 'snape kills dumbledore');
287     });
288
289     test('template', function () {
290         var w = new (openerp.web.Widget.extend({
291             template: 'test.widget.template'
292         }))();
293         w.renderElement();
294
295         equal(w.el.nodeName, 'OL');
296         equal(w.$el.children().length, 5);
297         equal(w.el.textContent, '01234');
298     });
299     test('repeated', { asserts: 4 }, function (_unused, $fix) {
300         var w = new (openerp.web.Widget.extend({
301             template: 'test.widget.template-value'
302         }))();
303         w.value = 42;
304         return w.appendTo($fix)
305             .done(function () {
306                 equal($fix.find('p').text(), '42', "DOM fixture should contain initial value");
307                 equal(w.$el.text(), '42', "should set initial value");
308                 w.value = 36;
309                 w.renderElement();
310                 equal($fix.find('p').text(), '36', "DOM fixture should use new value");
311                 equal(w.$el.text(), '36', "should set new value");
312             });
313     });
314 });
315 ropenerp.testing.section('Widget.$', {
316     setup: function () {
317         openerp.web.qweb = new QWeb2.Engine();
318         openerp.web.qweb.add_template(
319             '<no>' +
320                 '<t t-name="test.widget.template">' +
321                     '<ol>' +
322                         '<li t-foreach="5" t-as="counter" ' +
323                             't-attf-class="class-#{counter}">' +
324                             '<input/>' +
325                             '<t t-esc="counter"/>' +
326                         '</li>' +
327                     '</ol>' +
328                 '</t>' +
329             '</no>');
330     }
331 }, function (test) {
332     test('basic-alias', function () {
333         var w = new (openerp.web.Widget.extend({
334             template: 'test.widget.template'
335         }))();
336         w.renderElement();
337
338         ok(w.$('li:eq(3)').is(w.$el.find('li:eq(3)')),
339            "should do the same thing as calling find on the widget root");
340     });
341 });
342 ropenerp.testing.section('Widget.events', {
343     setup: function () {
344         openerp.web.qweb = new QWeb2.Engine();
345         openerp.web.qweb.add_template(
346             '<no>' +
347                 '<t t-name="test.widget.template">' +
348                     '<ol>' +
349                         '<li t-foreach="5" t-as="counter" ' +
350                             't-attf-class="class-#{counter}">' +
351                             '<input/>' +
352                             '<t t-esc="counter"/>' +
353                         '</li>' +
354                     '</ol>' +
355                 '</t>' +
356             '</no>');
357     }
358 }, function (test) {
359     test('delegate', function () {
360         var a = [];
361         var w = new (openerp.web.Widget.extend({
362             template: 'test.widget.template',
363             events: {
364                 'click': function () {
365                     a[0] = true;
366                     strictEqual(this, w, "should trigger events in widget");
367                 },
368                 'click li.class-3': 'class3',
369                 'change input': function () { a[2] = true; }
370             },
371             class3: function () { a[1] = true; }
372         }))();
373         w.renderElement();
374
375         w.$el.click();
376         w.$('li:eq(3)').click();
377         w.$('input:last').val('foo').change();
378
379         for(var i=0; i<3; ++i) {
380             ok(a[i], "should pass test " + i);
381         }
382     });
383     test('undelegate', function () {
384         var clicked = false, newclicked = false;
385         var w = new (openerp.web.Widget.extend({
386             template: 'test.widget.template',
387             events: { 'click li': function () { clicked = true; } }
388         }))();
389         w.renderElement();
390         w.$el.on('click', 'li', function () { newclicked = true; });
391
392         w.$('li').click();
393         ok(clicked, "should trigger bound events");
394         ok(newclicked, "should trigger bound events");
395         clicked = newclicked = false;
396
397         w.undelegateEvents();
398         w.$('li').click();
399         ok(!clicked, "undelegate should unbind events delegated");
400         ok(newclicked, "undelegate should only unbind events it created");
401     });
402 });
403
404 })();