The canonical tag is important for SEO, indeed it prevents search engines from indexing duplicate content. Reasoning ========= The choice has been made to create the canonical tag automatically depending on the request path, ignoring the query string, and manually prefixing the appropriate domain and language code. Indeed creating it manually for each resource would create a lot of code and potential mistakes. It is more dangerous to do it the generic way, but after investigation it appears that it is an acceptable trade-off since the vast majority of our routes are well built and already ready for this: - using query string only for minor features that do not change the main content - having the models, the ids, the pager and other important features in the path Override ======== It is still possible to override the default behavior by passing `canonical_params` manually to the view or to the different methods. This is done for `/event` because the only way to display Past Events is to add `date=old`. Languages ========= Fix an issue where it was possible for a bot to be on the URL without language code but to use a language that is not the default language. Adapt hreflang, because it: - must only be present on canonical pages - must always lead to canonical pages - should not be set if there is no alternate language Misc ==== task-1958075 closes #12532 Inspired by OCA module `website_canonical_url` courtesy of Jairo Llopis. closes odoo/odoo#35852 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com> Co-authored-by: Jairo Llopis <jairo.llopis@tecnativa.com> Co-authored-by: Sébastien Theys <seb@odoo.com>
67 lines
2.7 KiB
Python
67 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from lxml.html import document_fromstring
|
|
|
|
import odoo.tests
|
|
|
|
|
|
class TestUrlCommon(odoo.tests.HttpCase):
|
|
def setUp(self):
|
|
super(TestUrlCommon, self).setUp()
|
|
self.domain = 'http://' + odoo.tests.HOST
|
|
self.website = self.env['website'].create({
|
|
'name': 'test base url',
|
|
'domain': self.domain,
|
|
})
|
|
|
|
lang_fr = self.env.ref('base.lang_fr')
|
|
lang_fr.write({'active': True})
|
|
self.website.language_ids = self.env.ref('base.lang_en') + lang_fr
|
|
self.website.default_lang_id = self.env.ref('base.lang_en')
|
|
|
|
def _assertCanonical(self, url, canonical_url):
|
|
res = self.url_open(url)
|
|
canonical_link = document_fromstring(res.content).xpath("/html/head/link[@rel='canonical']")
|
|
self.assertEqual(len(canonical_link), 1)
|
|
self.assertEqual(canonical_link[0].attrib["href"], canonical_url)
|
|
|
|
|
|
@odoo.tests.tagged('-at_install', 'post_install')
|
|
class TestBaseUrl(TestUrlCommon):
|
|
def test_01_base_url(self):
|
|
ICP = self.env['ir.config_parameter']
|
|
icp_base_url = ICP.sudo().get_param('web.base.url')
|
|
|
|
# Test URL is correct for the website itself when the domain is set
|
|
self.assertEqual(self.website.get_base_url(), self.domain)
|
|
|
|
# Test URL is correct for a model without website_id
|
|
without_website_id = self.env['ir.attachment'].create({'name': 'test base url'})
|
|
self.assertEqual(without_website_id.get_base_url(), icp_base_url)
|
|
|
|
# Test URL is correct for a model with website_id...
|
|
with_website_id = self.env['res.partner'].create({'name': 'test base url'})
|
|
|
|
# ...when no website is set on the model
|
|
with_website_id.website_id = False
|
|
self.assertEqual(with_website_id.get_base_url(), icp_base_url)
|
|
|
|
# ...when the website is correctly set
|
|
with_website_id.website_id = self.website
|
|
self.assertEqual(with_website_id.get_base_url(), self.domain)
|
|
|
|
# ...when the set website doesn't have a domain
|
|
self.website.domain = False
|
|
self.assertEqual(with_website_id.get_base_url(), icp_base_url)
|
|
|
|
# Test URL is correct for the website itself when no domain is set
|
|
self.assertEqual(self.website.get_base_url(), icp_base_url)
|
|
|
|
def test_02_canonical_url(self):
|
|
self._assertCanonical('/', self.domain + '/')
|
|
self._assertCanonical('/?debug=1', self.domain + '/')
|
|
self._assertCanonical('/a-page', self.domain + '/a-page')
|
|
self._assertCanonical('/en_US', self.domain + '/')
|
|
self._assertCanonical('/fr_FR', self.domain + '/fr/')
|