[FIX] website, *: unescape URL parameters when used in autocomplete

*: web_tour, website_blog

Since [1] when the search box autocomplete was introduced, the URL
parameters are implicitly included into the RPC that fetches the
autocompletion results.
Those parameters were not correctly unescaped before being sent to the
RPC call.
Because of this, a timestamp such as "2023-01-01 23:00:00" was sent as
"2023-01-01+23%3A00%3A00" to the server. If that string reached the SQL
layer, the "+" was interpreted as defining a timezone.

This commit unescapes the URL parameters before using them in the RPC.
Note that javascript's `decodeURIComponent` does not handle the '+'
encoding of spaces inside URL parameters.

For testing purpose, the following updates were needed to make it
possible to select the `<option>` within the Archive month `<select>`:
- because the `option`s are in a tree, the tool was adapted to take all
`option`s into consideration instead of only the direct children of the
`select`.
- because the `option` text is dynamically created from the date of the
test execution, the tool was adapted to allow targeting an `option`
based on its index by specifying the tour step's `run` as
`'text index N'`, `N` being the index of the `option`.

Steps to reproduce:
- Enable the sidebar of the `/blog` page.
- Select a month in the sidebar.
- Type something in the search box.

=> Did show an error popup while obtaining the autocompletion records.

[1]: https://github.com/odoo/odoo/commit/7559626c54e34b41e1549e28276a650accec6986

task-3213916

closes odoo/odoo#114913

X-original-commit: 115fc399461c37b57127684cf5c28f05443fbb54
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Benoit Socias (bso) <bso@odoo.com>
This commit is contained in:
Benoit Socias
2023-03-13 09:45:56 +01:00
parent 708f5997c5
commit 80b85bf818
4 changed files with 46 additions and 4 deletions
@@ -102,14 +102,22 @@ var RunningTourActionHelper = core.Class.extend({
bubbles: true,
}));
} else if (values.$element.is("select")) {
var $options = values.$element.children("option");
var $options = values.$element.find("option");
$options.prop("selected", false).removeProp("selected");
var $selectedOption = $options.filter(function () { return $(this).val() === text; });
if ($selectedOption.length === 0) {
$selectedOption = $options.filter(function () { return $(this).text().trim() === text; });
}
const regex = /option\s+([0-9]+)/;
if ($selectedOption.length === 0 && regex.test(text)) {
// Extract position as 1-based, as the nth selectors.
const position = parseInt(regex.exec(text)[1]);
$selectedOption = $options.eq(position - 1); // eq is 0-based.
}
$selectedOption.prop("selected", true);
this._click(values);
// For situations where an `oninput` is defined.
values.$element.trigger("input");
} else {
values.$element.focusIn();
values.$element.trigger($.Event( "keydown", {key: '_', keyCode: 95}));
@@ -64,15 +64,16 @@ publicWidget.registry.searchBar = publicWidget.Widget.extend({
for (const keyValue of urlParams.split('&')) {
const [key, value] = keyValue.split('=');
if (value && key !== 'search') {
this.options[key] = value;
// Decode URI parameters: revert + to space then decodeURIComponent.
this.options[decodeURIComponent(key.replace(/\+/g, '%20'))] = decodeURIComponent(value.replace(/\+/g, '%20'));
}
}
}
const pathParts = urlPath.split('/');
for (const index in pathParts) {
const value = pathParts[index];
const value = decodeURIComponent(pathParts[index]);
if (index > 0 && /-[0-9]+$/.test(value)) { // is sluggish
this.options[pathParts[index - 1]] = value;
this.options[decodeURIComponent(pathParts[index - 1])] = value;
}
}
@@ -0,0 +1,28 @@
/** @odoo-module **/
import tour from 'web_tour.tour';
/**
* Makes sure that blog search can be used with the date filtering.
*/
tour.register('blog_autocomplete_with_date', {
test: true,
url: '/blog',
}, [{
content: "Select first month",
trigger: 'select[name=archive]',
run: 'text option 2',
}, {
content: "Enter search term",
trigger: '.o_searchbar_form input',
extra_trigger: '#o_wblog_posts_loop span:has(i.fa-calendar-o):has(a[href="/blog"])',
run: 'text a',
}, {
content: "Wait for suggestions then click on search icon",
extra_trigger: '.o_searchbar_form .o_dropdown_menu .o_search_result_item',
trigger: '.o_searchbar_form button:has(i.oi-search)',
}, {
content: "Ensure both filters are applied",
trigger: '#o_wblog_posts_loop:has(span:has(i.fa-calendar-o):has(a[href="/blog?search=a"])):has(span:has(i.fa-search):has(a[href^="/blog?date_begin"]))',
run: () => {}, // This is a check.
}]);
+5
View File
@@ -23,3 +23,8 @@ class TestUi(odoo.tests.HttpCase):
def test_blog_post_tags(self):
self.start_tour(self.env['website'].get_client_action_url('/blog'), 'blog_tags', login='admin')
def test_autocomplete_with_date(self):
self.env.ref('website_blog.opt_blog_sidebar_show').active = True
self.env.ref('website_blog.opt_sidebar_blog_index_follow_us').active = False
self.start_tour("/blog", 'blog_autocomplete_with_date')