Complete selection value in domain parser using contains matcher
Closes #14886
This commit is contained in:
+14
-11
@@ -1588,6 +1588,15 @@
|
||||
}
|
||||
return results;
|
||||
},
|
||||
contains_without_diacritics: function(main, sub) {
|
||||
main = main.normalize('NFD').toLowerCase();
|
||||
sub = sub.normalize('NFD').toLowerCase();
|
||||
|
||||
main = main.replace(/[\u0300-\u036f]/g, '');
|
||||
sub = sub.replace(/[\u0300-\u036f]/g, '');
|
||||
|
||||
return main.includes(sub);
|
||||
},
|
||||
complete_value: function(field, value) {
|
||||
var complete_boolean = function() {
|
||||
if ((value === null) || (value === undefined)) {
|
||||
@@ -1599,18 +1608,15 @@
|
||||
}
|
||||
};
|
||||
|
||||
var complete_selection = function() {
|
||||
var complete_selection = () => {
|
||||
var results = [];
|
||||
var test_value = value !== null ? value : '';
|
||||
if (value instanceof Array) {
|
||||
test_value = value[value.length - 1] || '';
|
||||
}
|
||||
test_value = test_value.replace(/^%*|%*$/g, '');
|
||||
var i, len, svalue, test;
|
||||
for (i=0, len=field.selection.length; i<len; i++) {
|
||||
svalue = field.selection[i][0];
|
||||
test = field.selection[i][1].toLowerCase();
|
||||
if (test.startsWith(test_value.toLowerCase())) {
|
||||
for(let [svalue, test] of field.selection) {
|
||||
if (this.contains_without_diacritics(test, test_value)) {
|
||||
if (value instanceof Array) {
|
||||
results.push(value.slice(0, -1).concat([svalue]));
|
||||
} else {
|
||||
@@ -1628,11 +1634,8 @@
|
||||
test_value = value[value.length - 1];
|
||||
}
|
||||
test_value = test_value.replace(/^%*|%*$/g, '');
|
||||
var i, len, svalue, test;
|
||||
for (i=0, len=field.selection.length; i<len; i++) {
|
||||
svalue = field.selection[i][0];
|
||||
test = field.selection[i][1].toLowerCase();
|
||||
if (test.startsWith(test_value.toLowerCase())) {
|
||||
for (let [svalue, test] of field.selection) {
|
||||
if (this.contains_without_diacritics(test, test_value)) {
|
||||
if (value instanceof Array) {
|
||||
results.push(value.slice(0, -1).concat([svalue]));
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Sao Test Suite</title>
|
||||
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/bootstrap/dist/js/bootstrap.js"></script>
|
||||
|
||||
+21
-2
@@ -2427,6 +2427,25 @@
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test('DomainParser.contains_without_diacritics', function() {
|
||||
let parser = new Sao.common.DomainParser();
|
||||
for (let [main, sub, expected] of [
|
||||
["Café au lait", "cafe", true],
|
||||
["Café au lait", "café", true],
|
||||
["Café au lait", "lait", true],
|
||||
["Café au lait", "the", false],
|
||||
["Héllò Wörld", "hello", true],
|
||||
["Héllò Wörld", "world", true],
|
||||
["Héllò Wörld", "hallo", false],
|
||||
]) {
|
||||
QUnit.assert.strictEqual(
|
||||
parser.contains_without_diacritics(main, sub), expected,
|
||||
'contains_without_diacritics('
|
||||
+ JSON.stringify(main) + ',' + JSON.stringify(sub) + ')');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
QUnit.test('DomainParser.complete_value', function () {
|
||||
var parser = new Sao.common.DomainParser();
|
||||
var field;
|
||||
@@ -2456,7 +2475,7 @@
|
||||
],
|
||||
};
|
||||
[
|
||||
['m', ['male']],
|
||||
['f', ['female']],
|
||||
['test', []],
|
||||
['', ['male', 'female']],
|
||||
[null, ['male', 'female']],
|
||||
@@ -2473,7 +2492,7 @@
|
||||
],
|
||||
};
|
||||
[
|
||||
['m', ['male']],
|
||||
['f', ['female']],
|
||||
['test', []],
|
||||
['', ['male', 'female', '']],
|
||||
[null, ['male', 'female', '']],
|
||||
|
||||
@@ -6,6 +6,7 @@ import gettext
|
||||
import io
|
||||
import locale
|
||||
import math
|
||||
import unicodedata
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
from shlex import shlex
|
||||
@@ -426,6 +427,16 @@ def format_value(field, value, target=None, context=None, _quote_empty=False):
|
||||
lambda: value if value is not None else '')(), empty=_quote_empty)
|
||||
|
||||
|
||||
def contains_without_diacritics(main, sub):
|
||||
main = unicodedata.normalize('NFD', main.lower())
|
||||
sub = unicodedata.normalize('NFD', sub.lower())
|
||||
|
||||
main = ''.join(c for c in main if not unicodedata.combining(c))
|
||||
sub = ''.join(c for c in sub if not unicodedata.combining(c))
|
||||
|
||||
return sub in main
|
||||
|
||||
|
||||
def complete_value(field, value):
|
||||
"Complete value for field"
|
||||
|
||||
@@ -444,7 +455,7 @@ def complete_value(field, value):
|
||||
test_value = value[-1] or ''
|
||||
test_value = test_value.strip('%')
|
||||
for svalue, test in field['selection']:
|
||||
if test.lower().startswith(test_value.lower()):
|
||||
if contains_without_diacritics(test, test_value):
|
||||
if isinstance(value, list):
|
||||
yield value[:-1] + [svalue]
|
||||
else:
|
||||
@@ -454,9 +465,9 @@ def complete_value(field, value):
|
||||
test_value = value if value is not None else ''
|
||||
if isinstance(value, list):
|
||||
test_value = value[-1]
|
||||
test_value = test_value.strip('%')
|
||||
test_value = test_value.strip('%').lower()
|
||||
for svalue, test in field['selection']:
|
||||
if test.lower().startswith(test_value.lower()):
|
||||
if contains_without_diacritics(test, test_value):
|
||||
if isinstance(value, list):
|
||||
yield value[:-1] + [svalue]
|
||||
else:
|
||||
|
||||
@@ -6,8 +6,9 @@ from unittest import TestCase
|
||||
|
||||
from tryton.common import untimezoned_date
|
||||
from tryton.common.domain_parser import (
|
||||
DomainParser, complete_value, convert_value, format_value, group_operator,
|
||||
likify, operatorize, parenthesize, quote, rlist, split_target_value, udlex)
|
||||
DomainParser, complete_value, contains_without_diacritics, convert_value,
|
||||
format_value, group_operator, likify, operatorize, parenthesize, quote,
|
||||
rlist, split_target_value, udlex)
|
||||
|
||||
|
||||
class DomainParserTestCase(TestCase):
|
||||
@@ -433,6 +434,21 @@ class DomainParserTestCase(TestCase):
|
||||
format_value(field, value), result,
|
||||
msg="format_value(%r, %r)" % (field, value))
|
||||
|
||||
def test_contains_without_diacritics(self):
|
||||
"Test contains without diacritics"
|
||||
for main, sub, expected in [
|
||||
("Café au lait", "cafe", True),
|
||||
("Café au lait", "café", True),
|
||||
("Café au lait", "lait", True),
|
||||
("Café au lait", "the", False),
|
||||
("Héllò Wörld", "hello", True),
|
||||
("Héllò Wörld", "world", True),
|
||||
("Héllò Wörld", "hallo", False),
|
||||
]:
|
||||
with self.subTest(main=main, sub=sub):
|
||||
self.assertEqual(
|
||||
contains_without_diacritics(main, sub), expected)
|
||||
|
||||
def test_complete_boolean(self):
|
||||
"Test complete boolean"
|
||||
field = {
|
||||
@@ -457,7 +473,7 @@ class DomainParserTestCase(TestCase):
|
||||
],
|
||||
}
|
||||
for value, result in (
|
||||
('m', ['male']),
|
||||
('f', ['female']),
|
||||
('test', []),
|
||||
('', ['male', 'female']),
|
||||
(None, ['male', 'female']),
|
||||
@@ -472,7 +488,7 @@ class DomainParserTestCase(TestCase):
|
||||
field_with_empty['selection'] = (field_with_empty['selection']
|
||||
+ [('', '')])
|
||||
for value, result in (
|
||||
('m', ['male']),
|
||||
('f', ['female']),
|
||||
('test', []),
|
||||
('', ['male', 'female', '']),
|
||||
(None, ['male', 'female', '']),
|
||||
|
||||
Reference in New Issue
Block a user