[FIX] base: remove "removal branding" from the <head/> of rendered pages

Since [1], during the call of `apply_inheritance_specs` in charge of
resolving all the xpath of inheriting views and building the whole
primary view, processing instructions were added to mark the locations
where nodes were removed. Before that commit, another system was in
place where the following node next to the removal was marked via a
meta-oe-xpath-replacing attribute.

The problem with that change is that some of those processing
instructions were actually not removed once the branding was distributed
before the view was served... indeed all processing instructions which
were in the `<head/>` or a t-ignore area were ignored instead of removed.

This was actually already the case with the old system of the attribute
"meta-oe-xpath-replacing" but it was never noticed (as either the
attribute was there but had no effect or was indirectly gone if it
landed on a `<t>` node).

After [1], a bug was reported in 15.0 with the website configurator
where the processing instruction actually made some nonsense appear on
top of the page (at least without the work being discussed at [2] which
makes it so processing instructions act as HTML comments as it should
normally be the case).

[1]: https://github.com/odoo/odoo/commit/f67832a3ae0d9a3b5b53129132762e6bc1aed874
[2]: https://github.com/odoo/odoo/pull/92213

closes odoo/odoo#92316

X-original-commit: 4310d012a16f982c2336d084254b5c5617794ee2
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2022-05-25 22:31:16 +02:00
parent 95880ab7b4
commit 2d75013ff0
2 changed files with 73 additions and 1 deletions
+6 -1
View File
@@ -1927,7 +1927,12 @@ actual arch.
if not attrs.intersection(descendant.attrib):
continue
self._pop_view_branding(descendant)
# TODO: find a better name and check if we have a string to boolean helper
# Remove the processing instructions indicating where nodes were
# removed (see apply_inheritance_specs)
for descendant in e.iterdescendants(tag=etree.ProcessingInstruction):
if descendant.target == 'apply-inheritance-specs-node-removal':
descendant.getparent().remove(descendant)
return
node_path = e.get('data-oe-xpath')
+67
View File
@@ -950,6 +950,73 @@ class TestTemplating(ViewCase):
initial.get('data-oe-xpath'),
"The node's xpath position should be correct")
def test_branding_inherit_remove_node_processing_instruction(self):
view1 = self.View.create({
'name': "Base view",
'type': 'qweb',
'arch': """
<html>
<head>
<hello></hello>
</head>
<body>
<world></world>
</body>
</html>
"""
})
self.View.create({
'name': "Extension",
'type': 'qweb',
'inherit_id': view1.id,
'arch': """
<data>
<xpath expr="//hello" position="replace"/>
<xpath expr="//world" position="replace"/>
</data>
"""
})
arch_string = view1.with_context(inherit_branding=True).get_combined_arch()
arch = etree.fromstring(arch_string)
head = arch.xpath('//head')[0]
head_child = head[0]
self.assertEqual(
head_child.target,
'apply-inheritance-specs-node-removal',
"A node was removed at the start of the <head>, a processing instruction should exist as first child node")
self.assertEqual(
head_child.text,
'hello',
"The processing instruction should mention the tag of the node that was removed")
body = arch.xpath('//body')[0]
body_child = body[0]
self.assertEqual(
body_child.target,
'apply-inheritance-specs-node-removal',
"A node was removed at the start of the <body>, a processing instruction should exist as first child node")
self.assertEqual(
body_child.text,
'world',
"The processing instruction should mention the tag of the node that was removed")
self.View.distribute_branding(arch)
# Test that both head and body have their processing instruction
# 'apply-inheritance-specs-node-removal' removed after branding
# distribution. Note: test head and body separately as the code in
# charge of the removal is different in each case.
self.assertEqual(
len(head),
0,
"The processing instruction of the <head> should have been removed")
self.assertEqual(
len(body),
0,
"The processing instruction of the <body> should have been removed")
def test_branding_inherit_top_t_field(self):
view1 = self.View.create({
'name': "Base view",