Merge lp:~openerp-dev/openerp-web/7.0-integer-fields-search-odo into lp:openerp-web/7.0

Proposed by Olivier Dony (Odoo)
Status: Merged
Merged at revision: 3901
Proposed branch: lp:~openerp-dev/openerp-web/7.0-integer-fields-search-odo
Merge into: lp:openerp-web/7.0
Diff against target: 104 lines (+69/-14)
2 files modified
addons/web/static/src/js/search.js (+16/-14)
addons/web/static/test/search.js (+53/-0)
To merge this branch: bzr merge lp:~openerp-dev/openerp-web/7.0-integer-fields-search-odo
Reviewer Review Type Date Requested Status
Xavier (Open ERP) (community) Needs Fixing
Review via email: mp+155942@code.launchpad.net

Description of the change

integer/float fields were not offering auto-completion in search views, making them unsearchable except via advanced search.

I added the missing complete() function and removed the incorrect value_from() function that did not conform to the 7.0 search view API. It seemed to be a leftover of the 6.1 search field implementation of get_value(), wrongly renamed for 7.0.

To post a comment you must log in.
Revision history for this message
Xavier (Open ERP) (xmo-deactivatedaccount) wrote :

* probably no need to escape the value: after parse() has run, we've got either an actual number or a NaN which gets filtered out, numbers shouldn't be able to contain HTML.
* not completing on !val means we can't complete on a 0, is that normal?
* could benefit from a new test or two in search.completions, they seem to be missing.

review: Needs Fixing
3870. By Olivier Dony (Odoo)

[FIX] web search: correct previous fix to properly handle searching for 0 on number fields

Also removed useless HTML escaping and added basic tests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'addons/web/static/src/js/search.js'
2--- addons/web/static/src/js/search.js 2013-03-28 06:33:46 +0000
3+++ addons/web/static/src/js/search.js 2013-03-28 15:37:24 +0000
4@@ -1346,20 +1346,22 @@
5 }
6 });
7 instance.web.search.NumberField = instance.web.search.Field.extend(/** @lends instance.web.search.NumberField# */{
8- value_from: function () {
9- if (!this.$el.val()) {
10- return null;
11- }
12- var val = this.parse(this.$el.val()),
13- check = Number(this.$el.val());
14- if (isNaN(val) || val !== check) {
15- this.$el.addClass('error');
16- throw new instance.web.search.Invalid(
17- this.attrs.name, this.$el.val(), this.error_message);
18- }
19- this.$el.removeClass('error');
20- return val;
21- }
22+ complete: function (value) {
23+ var val = this.parse(value);
24+ if (isNaN(val)) { return $.when(); }
25+ var label = _.str.sprintf(
26+ _t("Search %(field)s for: %(value)s"), {
27+ field: '<em>' + this.attrs.string + '</em>',
28+ value: '<strong>' + _.str.escapeHTML(value) + '</strong>'});
29+ return $.when([{
30+ label: label,
31+ facet: {
32+ category: this.attrs.string,
33+ field: this,
34+ values: [{label: value, value: val}]
35+ }
36+ }]);
37+ },
38 });
39 /**
40 * @class
41
42=== modified file 'addons/web/static/test/search.js'
43--- addons/web/static/test/search.js 2013-03-21 15:51:23 +0000
44+++ addons/web/static/test/search.js 2013-03-28 15:37:24 +0000
45@@ -614,6 +614,59 @@
46 {relation: 'dummy.model'}, view);
47 return f.complete("bob");
48 });
49+ test('Integer: invalid', {asserts: 1}, function (instance) {
50+ var view = {inputs: []};
51+ var f = new instance.web.search.IntegerField(
52+ {attrs: {string: "Dummy"}}, {}, view);
53+ return f.complete("qux")
54+ .done(function (completions) {
55+ ok(!completions, "non-number => no completion");
56+ });
57+ });
58+ test('Integer: non-zero', {asserts: 5}, function (instance) {
59+ var view = {inputs: []};
60+ var f = new instance.web.search.IntegerField(
61+ {attrs: {string: "Dummy"}}, {}, view);
62+ return f.complete("-2")
63+ .done(function (completions) {
64+ equal(completions.length, 1, "number fields provide 1 completion only");
65+ var facet = new instance.web.search.Facet(completions[0].facet);
66+ equal(facet.get('category'), f.attrs.string);
67+ equal(facet.get('field'), f);
68+ var value = facet.values.at(0);
69+ equal(value.get('label'), "-2");
70+ equal(value.get('value'), -2);
71+ });
72+ });
73+ test('Integer: zero', {asserts: 3}, function (instance) {
74+ var view = {inputs: []};
75+ var f = new instance.web.search.IntegerField(
76+ {attrs: {string: "Dummy"}}, {}, view);
77+ return f.complete("0")
78+ .done(function (completions) {
79+ equal(completions.length, 1, "number fields provide 1 completion only");
80+ var facet = new instance.web.search.Facet(completions[0].facet);
81+ var value = facet.values.at(0);
82+ equal(value.get('label'), "0");
83+ equal(value.get('value'), 0);
84+ });
85+ });
86+ test('Float: non-zero', {asserts: 5}, function (instance) {
87+ var view = {inputs: []};
88+ var f = new instance.web.search.FloatField(
89+ {attrs: {string: "Dummy"}}, {}, view);
90+ return f.complete("42.37")
91+ .done(function (completions) {
92+ equal(completions.length, 1, "float fields provide 1 completion only");
93+ var facet = new instance.web.search.Facet(completions[0].facet);
94+ equal(facet.get('category'), f.attrs.string);
95+ equal(facet.get('field'), f);
96+ var value = facet.values.at(0);
97+ equal(value.get('label'), "42.37");
98+ equal(value.get('value'), 42.37);
99+ });
100+ });
101+
102 });
103 openerp.testing.section('search.serialization', {
104 dependencies: ['web.search'],