mirror of
https://github.com/bringout/oca-ocb-test.git
synced 2026-04-22 16:42:01 +02:00
19.0 vanilla
This commit is contained in:
parent
38c6088dcc
commit
d9452d2060
243 changed files with 30797 additions and 10815 deletions
|
|
@ -4,6 +4,7 @@
|
|||
from . import test_controller_args
|
||||
from . import test_custom_snippet
|
||||
from . import test_error
|
||||
from . import test_form
|
||||
from . import test_fuzzy
|
||||
from . import test_image_upload_progress
|
||||
from . import test_is_multilang
|
||||
|
|
@ -13,9 +14,17 @@ from . import test_multi_company
|
|||
from . import test_page_manager
|
||||
from . import test_page
|
||||
from . import test_performance
|
||||
from . import test_qweb
|
||||
from . import test_redirect
|
||||
from . import test_reset_views
|
||||
from . import test_restricted_editor
|
||||
from . import test_session
|
||||
from . import test_settings
|
||||
from . import test_snippet_background_video
|
||||
from . import test_systray
|
||||
from . import test_theme_ir_asset
|
||||
from . import test_translation
|
||||
from . import test_views_during_module_operation
|
||||
from . import test_website_controller_page
|
||||
from . import test_website_page_properties
|
||||
from . import test_website_field_sanitize
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<asset id="theme_default.test_asset_tag_aaa" name="Test asset tag (init active => keep active => update active)">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_aii" name="Test asset tag (init active => make inactive => update inactive)">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_aia" name="Test asset tag (init active => make inactive => update active)">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
<field name="active">True</field> <!-- Take into account during update -->
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_iii" name="Test asset tag (init inactive => keep inactive => update inactive)" active="False">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_iaa" name="Test asset tag (init inactive => make active => update active)" active="False">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_prepend" name="Test asset tag with directive">
|
||||
<bundle directive="prepend">test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
</asset>
|
||||
<asset id="theme_default.test_asset_tag_extra" name="Test asset tag with extra field">
|
||||
<bundle>test_asset_bundle</bundle>
|
||||
<path>theme_default/tests/something.scss</path>
|
||||
<field name="sequence" eval="17"/>
|
||||
</asset>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="test_website.test_template" name="test template 2">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<t t-call-assets="test_website.test_bundle" t-js="False"/>
|
||||
<meta/>
|
||||
<t t-call-assets="test_website.test_bundle" t-css="False"/>
|
||||
</head>
|
||||
<body>
|
||||
<img src="http://test.external.link/img.png"/>
|
||||
<img src="/test_website/static/img.png"/>
|
||||
<a href="http://test.external.link/link">x</a>
|
||||
<a href="/web/content/local_link">x</a>
|
||||
<span t-attf-style="background-image: url('/web/image/2')" t-att-empty="False">xxx</span>
|
||||
<div widget="html" t-field="user.signature"/>
|
||||
<div widget="image" t-field="user.avatar_1920" t-options="{'widget': 'image'}"/>
|
||||
</body>
|
||||
</html>
|
||||
</template>
|
||||
|
||||
<template id="test_website.test_template_tatt_qweb" name="t-att template">
|
||||
<a t-att-href='"/"'>1</a>
|
||||
<a t-att-href='False'>2</a>
|
||||
<a t-att-href='None'>3</a>
|
||||
<a t-att-href=''>4</a>
|
||||
<a t-att-href='""'>5</a>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import odoo.tests
|
||||
from odoo.tools import mute_logger
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@odoo.tests.common.tagged('post_install', '-at_install')
|
||||
|
|
@ -32,9 +33,10 @@ class TestWebsiteControllerArgs(odoo.tests.HttpCase):
|
|||
self.assertEqual(req.status_code, 200)
|
||||
self.assertEqual(req.json(), {'a': 'valueA', 'kw': {'b': 'valueB'}})
|
||||
|
||||
req = self.url_open('/test_website/country/whatever-999999')
|
||||
self.assertEqual(req.status_code, 404,
|
||||
"Model converter record does not exist, return a 404.")
|
||||
with patch.object(self.registry['ir.http'], '_get_error_html', lambda e, code, v: (code, '')):
|
||||
req = self.url_open('/test_website/country/whatever-999999')
|
||||
self.assertEqual(req.status_code, 404,
|
||||
"Model converter record does not exist, return a 404.")
|
||||
|
||||
|
||||
@odoo.tests.common.tagged('post_install', '-at_install')
|
||||
|
|
@ -44,3 +46,8 @@ class TestWebsiteControllers(odoo.tests.TransactionCase):
|
|||
website = self.env['website'].browse(1)
|
||||
locs = website.with_user(website.user_id)._enumerate_pages(query_string='test_website_sitemap')
|
||||
self.assertEqual(len(list(locs)), 1, "The same URL should only be shown once")
|
||||
|
||||
def test_02_search_controller(self):
|
||||
website = self.env['website'].browse(1)
|
||||
res = website._enumerate_pages(query_string="/test_website/country/elgium")
|
||||
self.assertIn('/test_website/country/belgium', next(res).get('loc'))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import tagged, HttpCase
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestForm(HttpCase):
|
||||
|
||||
def test_form_conditional_visibility_record_field(self):
|
||||
self.start_tour(
|
||||
self.env['website'].get_client_action_url('/test_website/model_item/1'),
|
||||
'test_form_conditional_visibility_record_field',
|
||||
login='admin',
|
||||
)
|
||||
|
|
@ -5,7 +5,7 @@ import logging
|
|||
import psycopg2
|
||||
|
||||
from odoo.addons.website.controllers.main import Website
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.addons.http_routing.tests.common import MockRequest
|
||||
import odoo.tests
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
|
@ -108,15 +108,15 @@ class TestAutoComplete(TransactionCase):
|
|||
test_page.name = 'testTotallyUnique'
|
||||
|
||||
# Editor and Designer see pages in result
|
||||
self._autocomplete_page('testTotallyUnique', 1, False)
|
||||
self._autocomplete_page('testTotallyUnique', 1, None)
|
||||
|
||||
test_page.visibility = 'connected'
|
||||
self._autocomplete_page('testTotallyUnique', 1, False)
|
||||
test_page.visibility = False
|
||||
|
||||
test_page.groups_id = self.env.ref('base.group_public')
|
||||
test_page.group_ids = self.env.ref('base.group_public')
|
||||
self._autocomplete_page('testTotallyUnique', 1, False)
|
||||
test_page.groups_id = False
|
||||
test_page.group_ids = False
|
||||
|
||||
# Public user don't see restricted page
|
||||
saved_env = self.env
|
||||
|
|
@ -126,12 +126,12 @@ class TestAutoComplete(TransactionCase):
|
|||
test_page.website_indexed = True
|
||||
self._autocomplete_page('testTotallyUnique', 1, False)
|
||||
|
||||
test_page.groups_id = self.env.ref('base.group_system')
|
||||
test_page.group_ids = self.env.ref('base.group_system')
|
||||
self._autocomplete_page('testTotallyUnique', 0, "Not found")
|
||||
|
||||
test_page.groups_id = self.env.ref('base.group_public')
|
||||
test_page.group_ids = self.env.ref('base.group_public')
|
||||
self._autocomplete_page('testTotallyUnique', 1, False)
|
||||
test_page.groups_id = False
|
||||
test_page.group_ids = False
|
||||
|
||||
test_page.visibility = 'password'
|
||||
self._autocomplete_page('testTotallyUnique', 0, "Not found")
|
||||
|
|
@ -141,3 +141,11 @@ class TestAutoComplete(TransactionCase):
|
|||
|
||||
# restore website env for next tests
|
||||
self.website.env = self.env = saved_env
|
||||
|
||||
def test_indirect(self):
|
||||
self._autocomplete('module', 4, 'model')
|
||||
self._autocomplete('rechord', 3, 'record')
|
||||
self._autocomplete('suborder', 1, 'submodel')
|
||||
# Sub-sub-fields are currently not supported.
|
||||
# Adapt expected result if this becomes a feature.
|
||||
self._autocomplete('tagg', 0, "Not found")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.web_editor.controllers.main import Web_Editor
|
||||
from odoo.addons.html_editor.controllers.main import HTML_Editor
|
||||
from odoo.addons.web_unsplash.controllers.main import Web_Unsplash
|
||||
|
||||
import odoo.tests
|
||||
|
|
@ -18,15 +18,15 @@ class TestImageUploadProgress(odoo.tests.HttpCase):
|
|||
def test_02_image_upload_progress_unsplash(self):
|
||||
BASE_URL = self.base_url()
|
||||
|
||||
@http.route('/web_editor/media_library_search', type='json', auth="user", website=True)
|
||||
@http.route('/html_editor/media_library_search', type='jsonrpc', auth="user", website=True)
|
||||
def media_library_search(self, **params):
|
||||
return {"results": 0, "media": []}
|
||||
# because not preprocessed by ControllerType metaclass
|
||||
media_library_search.original_endpoint.routing_type = 'json'
|
||||
# disable undraw, no third party should be called in tests
|
||||
self.patch(Web_Editor, 'media_library_search', media_library_search)
|
||||
self.patch(HTML_Editor, 'media_library_search', media_library_search)
|
||||
|
||||
@http.route("/web_unsplash/fetch_images", type='json', auth="user")
|
||||
@http.route("/web_unsplash/fetch_images", type='jsonrpc', auth="user")
|
||||
def fetch_unsplash_images(self, **post):
|
||||
return {
|
||||
'total': 1434,
|
||||
|
|
@ -36,11 +36,11 @@ class TestImageUploadProgress(odoo.tests.HttpCase):
|
|||
'alt_description': 'brown fox sitting on green grass field during daytime',
|
||||
'urls': {
|
||||
# 'regular': 'https://images.unsplash.com/photo-1462953491269-9aff00919695?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMDUwOHwwfDF8c2VhcmNofDF8fGZveHxlbnwwfHx8fDE2MzEwMzIzNDE&ixlib=rb-1.2.1&q=80&w=1080',
|
||||
'regular': BASE_URL + '/website/static/src/img/phone.png',
|
||||
'regular': BASE_URL + '/website/static/src/img/user-restricted-image.png',
|
||||
},
|
||||
'links': {
|
||||
# 'download_location': 'https://api.unsplash.com/photos/HQqIOc8oYro/download?ixid=MnwzMDUwOHwwfDF8c2VhcmNofDF8fGZveHxlbnwwfHx8fDE2MzEwMzIzNDE'
|
||||
'download_location': BASE_URL + '/website/static/src/img/phone.png',
|
||||
'download_location': BASE_URL + '/website/static/src/img/user-restricted-image.png',
|
||||
},
|
||||
'user': {
|
||||
'name': 'Mitchell Admin',
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class TestIsMultiLang(odoo.tests.HttpCase):
|
|||
it = self.env.ref('base.lang_it').sudo()
|
||||
en = self.env.ref('base.lang_en').sudo()
|
||||
be = self.env.ref('base.lang_fr_BE').sudo()
|
||||
country1 = self.env['res.country'].create({'name': "My Super Country"})
|
||||
country1 = self.env['res.country'].create({'name': "My Super Country", 'code': 'ZV'})
|
||||
|
||||
it.active = True
|
||||
be.active = True
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from lxml import html
|
||||
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.tests import tagged, HttpCase
|
||||
|
||||
|
||||
|
|
@ -21,6 +20,9 @@ class TestWebsiteMenu(HttpCase):
|
|||
controller_url = '/test_website/model_item/'
|
||||
website = self.env['website'].browse(1)
|
||||
|
||||
# First render to fill the cache.
|
||||
self.url_open(f"{controller_url}{records[0].id}")
|
||||
|
||||
self.env['website.menu'].create([{
|
||||
'name': records[0].name,
|
||||
'url': f"{controller_url}{records[0].id}",
|
||||
|
|
@ -36,10 +38,6 @@ class TestWebsiteMenu(HttpCase):
|
|||
}])
|
||||
for record in records:
|
||||
record_url = f"{controller_url}{record.id}"
|
||||
with MockRequest(self.env, website=website, url_root='', path=record_url):
|
||||
tree = html.fromstring(self.env['ir.qweb']._render('test_website.model_item', {
|
||||
'record': record,
|
||||
'main_object': record,
|
||||
}))
|
||||
menu_link_el = tree.xpath(".//*[@id='top_menu']//a[@href='%s' and contains(@class, 'active')]" % record_url)
|
||||
self.assertEqual(len(menu_link_el), 1, "The menu link related to the current record should be active")
|
||||
tree = html.fromstring(self.url_open(record_url).content)
|
||||
menu_link_el = tree.xpath(".//*[@id='top_menu']//a[@href='%s' and hasclass('active')]" % record_url)
|
||||
self.assertEqual(len(menu_link_el), 1, "The menu link related to the current record should be active")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo.tests.common import HOST
|
||||
from odoo.tools import config, mute_logger
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
|
|
@ -12,7 +11,7 @@ class WithContext(HttpCase):
|
|||
website = self.env['website'].browse([1])
|
||||
website.write({
|
||||
'name': 'Test Website',
|
||||
'domain': f'http://{HOST}:{config["http_port"]}',
|
||||
'domain': self.base_url(),
|
||||
'homepage_url': '/unexisting',
|
||||
})
|
||||
home_url = '/'
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo.tests
|
||||
from odoo.addons.website.tests.common import HttpCaseWithWebsiteUser
|
||||
|
||||
|
||||
@odoo.tests.common.tagged('post_install', '-at_install')
|
||||
class TestWebsitePageManager(odoo.tests.HttpCase):
|
||||
class TestWebsitePageManager(HttpCaseWithWebsiteUser):
|
||||
def test_page_manager_test_model(self):
|
||||
if self.env['website'].search_count([]) == 1:
|
||||
website2 = self.env['website'].create({
|
||||
|
|
@ -21,8 +22,8 @@ class TestWebsitePageManager(odoo.tests.HttpCase):
|
|||
"There should at least be one record without website_id and one for 2 different websites",
|
||||
)
|
||||
self.assertNotIn('website_id', self.env['test.model']._fields)
|
||||
self.start_tour('/web#action=test_website.action_test_model_multi_website', 'test_website_page_manager', login="admin")
|
||||
self.start_tour('/odoo/action-test_website.action_test_model_multi_website', 'test_website_page_manager', login="website_user")
|
||||
# This second test is about ensuring that you can switch from a list
|
||||
# view which has no `website_pages_list` js_class to its kanban view
|
||||
self.start_tour('/web#action=test_website.action_test_model_multi_website_js_class_bug', 'test_website_page_manager_js_class_bug', login="admin")
|
||||
self.start_tour('/web#action=test_website.action_test_model', 'test_website_page_manager_no_website_id', login="admin")
|
||||
self.start_tour('/odoo/action-test_website.action_test_model_multi_website_js_class_bug', 'test_website_page_manager_js_class_bug', login="website_user")
|
||||
self.start_tour('/odoo/action-test_website.action_test_model', 'test_website_page_manager_no_website_id', login="website_user")
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ class TestPerformance(UtilPerf):
|
|||
def test_10_perf_sql_website_controller_minimalist(self):
|
||||
url = '/empty_controller_test'
|
||||
select_tables_perf = {
|
||||
'base_registry_signaling': 1,
|
||||
'orm_signaling_registry': 1,
|
||||
}
|
||||
self._check_url_hot_query(url, 1, select_tables_perf)
|
||||
self.assertEqual(self._get_url_hot_query(url, cache=False), 1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from lxml import etree
|
||||
import re
|
||||
|
||||
from odoo import tools
|
||||
from odoo.addons.base.tests.common import TransactionCaseWithUserDemo
|
||||
from odoo.addons.http_routing.tests.common import MockRequest
|
||||
|
||||
|
||||
class TestQweb(TransactionCaseWithUserDemo):
|
||||
def _load(self, module, filepath):
|
||||
tools.convert_file(self.env, module, filepath, {}, 'init')
|
||||
|
||||
def test_qweb_cdn(self):
|
||||
self._load('test_website', 'tests/template_qweb_test.xml')
|
||||
|
||||
website = self.env.ref('website.default_website')
|
||||
website.write({
|
||||
"cdn_activated": True,
|
||||
"cdn_url": "http://test.cdn"
|
||||
})
|
||||
|
||||
demo = self.env['res.users'].search([('login', '=', 'demo')])[0]
|
||||
demo.write({"signature": '''<span class="toto">
|
||||
span<span class="fa"></span><img src="/web/image/1"/>
|
||||
</span>'''})
|
||||
|
||||
demo_env = self.env(user=demo)
|
||||
|
||||
html = demo_env['ir.qweb']._render('test_website.test_template', {"user": demo}, website_id=website.id)
|
||||
asset_bundle_xmlid = 'test_website.test_bundle'
|
||||
qweb = self.env['ir.qweb']
|
||||
bundle = qweb._get_asset_bundle(asset_bundle_xmlid, css=True, js=True, assets_params={'website_id': website.id})
|
||||
|
||||
asset_version_js = bundle.get_version('js')
|
||||
asset_version_css = bundle.get_version('css')
|
||||
css_url, js_url = bundle.get_links()[-2:]
|
||||
|
||||
html = html.strip()
|
||||
html = re.sub(r'\?unique=[^"]+', '', html).encode('utf8')
|
||||
|
||||
format_data = {
|
||||
"css": css_url,
|
||||
"js": js_url,
|
||||
"user_id": demo.id,
|
||||
"filename": "Marc%20Demo",
|
||||
"alt": "Marc Demo",
|
||||
"asset_xmlid": asset_bundle_xmlid,
|
||||
"asset_version_css": asset_version_css,
|
||||
"asset_version_js": asset_version_js,
|
||||
}
|
||||
self.assertHTMLEqual(html, ("""<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link type="text/css" rel="stylesheet" href="http://test.external.link/style1.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="http://test.external.link/style2.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="http://test.cdn%(css)s"/>
|
||||
<meta/>
|
||||
<script type="text/javascript" src="http://test.external.link/javascript1.js"></script>
|
||||
<script type="text/javascript" src="http://test.external.link/javascript2.js"></script>
|
||||
<script type="text/javascript" src="http://test.cdn%(js)s" onerror="__odooAssetError=1"></script>
|
||||
</head>
|
||||
<body>
|
||||
<img src="http://test.external.link/img.png" loading="lazy"/>
|
||||
<img src="http://test.cdn/test_website/static/img.png" loading="lazy"/>
|
||||
<a href="http://test.external.link/link">x</a>
|
||||
<a href="http://test.cdn/web/content/local_link">x</a>
|
||||
<span style="background-image: url('http://test.cdn/web/image/2')">xxx</span>
|
||||
<div widget="html"><span class="toto">
|
||||
span<span class="fa"></span><img src="http://test.cdn/web/image/1" loading="lazy">
|
||||
</span></div>
|
||||
<div widget="image"><img src="http://test.cdn/web/image/res.users/%(user_id)s/avatar_1920/%(filename)s" class="img img-fluid" alt="%(alt)s" loading="lazy"/></div>
|
||||
</body>
|
||||
</html>""" % format_data).encode('utf8'))
|
||||
|
||||
with MockRequest(self.env, website=website):
|
||||
html = demo_env['ir.qweb']._render('test_website.test_template_tatt_qweb', {}, website_id=website.id)
|
||||
self.assertHTMLEqual(html, ("""
|
||||
<html>
|
||||
<body><a href="/">1</a>
|
||||
<a>2</a>
|
||||
<a>3</a>
|
||||
<a>4</a>
|
||||
<a href="">5</a></body>
|
||||
</html>
|
||||
"""))
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
import odoo
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo.tools import mute_logger
|
||||
from odoo.addons.http_routing.models.ir_http import slug
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ class TestRedirect(HttpCase):
|
|||
'login': 'portal_user',
|
||||
'password': 'portal_user',
|
||||
'email': 'portal_user@mail.com',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])]
|
||||
'group_ids': [(6, 0, [self.env.ref('base.group_portal').id])]
|
||||
})
|
||||
|
||||
def test_01_redirect_308_model_converter(self):
|
||||
|
|
@ -37,7 +36,7 @@ class TestRedirect(HttpCase):
|
|||
- Correct & working redirect as logged in user
|
||||
- Correct replace of url_for() URLs in DOM
|
||||
"""
|
||||
url = '/test_website/country/' + slug(country_ad)
|
||||
url = '/test_website/country/' + self.env['ir.http']._slug(country_ad)
|
||||
redirect_url = url.replace('test_website', 'redirected')
|
||||
|
||||
# [Public User] Open the original url and check redirect OK
|
||||
|
|
@ -57,12 +56,12 @@ class TestRedirect(HttpCase):
|
|||
self.assertTrue(redirect_url in r.text, "Ensure the url_for has replaced the href URL in the DOM")
|
||||
|
||||
def test_redirect_308_by_method_url_rewrite(self):
|
||||
self.env['website.rewrite'].create({
|
||||
self.env['website.rewrite'].create([{
|
||||
'name': 'Test Website Redirect',
|
||||
'redirect_type': '308',
|
||||
'url_from': url_from,
|
||||
'url_to': f'{url_from}_new',
|
||||
} for url_from in ('/get', '/post', '/get_post'))
|
||||
} for url_from in ('/get', '/post', '/get_post')])
|
||||
|
||||
self.env.ref('test_website.test_view').arch = '''
|
||||
<t>
|
||||
|
|
@ -90,7 +89,7 @@ class TestRedirect(HttpCase):
|
|||
rec_published = self.env['test.model'].create({'name': 'name', 'website_published': True})
|
||||
rec_unpublished = self.env['test.model'].create({'name': 'name', 'website_published': False})
|
||||
|
||||
WebsiteHttp = odoo.addons.website.models.ir_http.Http
|
||||
WebsiteHttp = odoo.addons.website.models.ir_http.IrHttp
|
||||
|
||||
def _get_error_html(env, code, value):
|
||||
return str(code).split('_')[-1], f"CUSTOM {code}"
|
||||
|
|
@ -201,7 +200,7 @@ class TestRedirect(HttpCase):
|
|||
'name': '301 test record',
|
||||
'is_published': True,
|
||||
})
|
||||
url_rec1 = '/test_website/200/' + slug(rec1)
|
||||
url_rec1 = '/test_website/200/' + self.env['ir.http']._slug(rec1)
|
||||
r = self.url_open(url_rec1)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
|
|
@ -223,7 +222,7 @@ class TestRedirect(HttpCase):
|
|||
# 4. Accessing unpublished record with redirect to another published
|
||||
# record: expecting redirect to that record
|
||||
rec2 = rec1.copy({'is_published': True})
|
||||
url_rec2 = '/test_website/200/' + slug(rec2)
|
||||
url_rec2 = '/test_website/200/' + self.env['ir.http']._slug(rec2)
|
||||
redirect.url_to = url_rec2
|
||||
r = self.url_open(url_rec1)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
|
@ -264,7 +263,7 @@ class TestRedirect(HttpCase):
|
|||
'name': '301 test record',
|
||||
'is_published': True,
|
||||
})
|
||||
url_rec1 = f"/test_countries_308/{slug(rec1)}"
|
||||
url_rec1 = f"/test_countries_308/{self.env['ir.http']._slug(rec1)}"
|
||||
|
||||
resp = self.url_open("/test_countries_308", allow_redirects=False)
|
||||
self.assertEqual(resp.status_code, 308)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
import odoo.tests
|
||||
from odoo.tools import mute_logger
|
||||
import unittest
|
||||
|
||||
|
||||
def break_view(view, fr='<p>placeholder</p>', to='<p t-field="no_record.exist"/>'):
|
||||
|
|
@ -17,8 +20,10 @@ class TestWebsiteResetViews(odoo.tests.HttpCase):
|
|||
resp = self.url_open(page)
|
||||
self.assertEqual(resp.status_code, 500, "Waiting 500")
|
||||
self.assertTrue('<button data-mode="soft" class="reset_templates_button' in resp.text)
|
||||
data = {'view_id': self.find_template(resp), 'redirect': page, 'mode': mode}
|
||||
resp = self.url_open('/website/reset_template', data)
|
||||
data = {'params': {'view_id': self.find_template(resp), 'mode': mode}}
|
||||
self.url_open('/website/reset_template', data=json.dumps(data), headers={'Content-Type': 'application/json'})
|
||||
resp = self.url_open(page)
|
||||
self.assertTrue(resp.url.endswith(page), "We should be checking the test page")
|
||||
self.assertEqual(resp.status_code, 200, "Waiting 200")
|
||||
|
||||
def find_template(self, response):
|
||||
|
|
@ -104,6 +109,7 @@ class TestWebsiteResetViews(odoo.tests.HttpCase):
|
|||
# Break it again to have a previous arch different than file arch
|
||||
break_view(self.test_page_view.with_context(website_id=1))
|
||||
self.assertEqual(total_views + 1, self.View.search_count([('type', '=', 'qweb')]), "Missing COW view")
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
# soft reset should not be able to reset the view as previous
|
||||
# version is also broken
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import unittest
|
||||
|
||||
import odoo.tests
|
||||
from odoo.tools import mute_logger
|
||||
from odoo.addons.website.tests.common import HttpCaseWithWebsiteUser
|
||||
|
||||
|
||||
@odoo.tests.common.tagged('post_install', '-at_install')
|
||||
class TestRestrictedEditor(HttpCaseWithWebsiteUser):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
website = cls.env['website'].search([], limit=1)
|
||||
fr = cls.env.ref('base.lang_fr').sudo()
|
||||
en = cls.env.ref('base.lang_en').sudo()
|
||||
|
||||
fr.active = True
|
||||
|
||||
website.default_lang_id = en
|
||||
website.language_ids = en + fr
|
||||
|
||||
cls.env['website.menu'].create({
|
||||
'name': 'Model item',
|
||||
'url': '/test_website/model_item/1',
|
||||
'parent_id': website.menu_id.id,
|
||||
'sequence': 100,
|
||||
})
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_01_restricted_editor_only(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'test_restricted_editor_only', login="website_user")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_02_restricted_editor_test_admin(self):
|
||||
self.user_website_user.group_ids += self.env.ref("test_website.group_test_website_admin")
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'test_restricted_editor_test_admin', login="website_user")
|
||||
|
||||
# FIXME the logic of the commit that introduced the fix at 8c41c147a4c6a415e
|
||||
# was reverted, so this test is disabled for now. Branding *on views* as
|
||||
# a restricted editor is something we want in some custo (e.g. odoo.com).
|
||||
# See commit messages for details.
|
||||
@unittest.skip
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_03_restricted_editor_tester(self):
|
||||
"""
|
||||
Tests that restricted users cannot edit ir.ui.view records despite being
|
||||
on a page of a record (main_object) they can edit.
|
||||
"""
|
||||
self.user_website_user.group_ids += self.env.ref("test_website.group_test_website_tester")
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_restricted_editor_tester', login='website_user')
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from lxml import html
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo import http
|
||||
from odoo.addons.website.models.website import Website
|
||||
import odoo.tests
|
||||
|
||||
from odoo.addons.base.tests.common import HttpCaseWithUserDemo
|
||||
|
|
@ -13,27 +16,77 @@ class TestWebsiteSession(HttpCaseWithUserDemo):
|
|||
def test_01_run_test(self):
|
||||
self.start_tour('/', 'test_json_auth')
|
||||
|
||||
def test_02_inactive_session_lang(self):
|
||||
session = self.authenticate(None, None)
|
||||
self.env.ref('base.lang_fr').active = False
|
||||
session.context['lang'] = 'fr_FR'
|
||||
odoo.http.root.session_store.save(session)
|
||||
|
||||
# ensure that _get_current_website_id will be able to match a website
|
||||
current_website_id = self.env["website"]._get_current_website_id(odoo.tests.HOST)
|
||||
self.env["website"].browse(current_website_id).domain = odoo.tests.HOST
|
||||
|
||||
res = self.url_open('/test_website_sitemap') # any auth='public' route would do
|
||||
res.raise_for_status()
|
||||
|
||||
def test_03_totp_login_with_inactive_session_lang(self):
|
||||
session = self.authenticate(None, None)
|
||||
self.env.ref('base.lang_fr').active = False
|
||||
session.context['lang'] = 'fr_FR'
|
||||
odoo.http.root.session_store.save(session)
|
||||
|
||||
# ensure that _get_current_website_id will be able to match a website
|
||||
current_website_id = self.env["website"]._get_current_website_id(odoo.tests.HOST)
|
||||
self.env["website"].browse(current_website_id).domain = odoo.tests.HOST
|
||||
|
||||
with patch.object(self.env.registry["res.users"], "_mfa_url", return_value="/web/login/totp"):
|
||||
res = self.url_open('/web/login', allow_redirects=False, data={
|
||||
'login': 'demo',
|
||||
'password': 'demo',
|
||||
'csrf_token': http.Request.csrf_token(self),
|
||||
})
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.status_code, 303)
|
||||
self.assertTrue(res.next.path_url.startswith("/web/login/totp"))
|
||||
|
||||
def test_04_ensure_website_get_cached_values_can_be_called(self):
|
||||
session = self.authenticate('admin', 'admin')
|
||||
|
||||
# Force a browser language that is not installed
|
||||
session.context['lang'] = 'fr_MC'
|
||||
http.root.session_store.save(session)
|
||||
|
||||
# Disable cache in order to make sure that values would be fetched at any time
|
||||
get_cached_values_without_cache = Website._get_cached_values.__cache__.method
|
||||
with patch.object(Website, '_get_cached_values',
|
||||
side_effect=get_cached_values_without_cache, autospec=True):
|
||||
|
||||
# ensure that permissions on logout are OK
|
||||
res = self.url_open('/web/session/logout')
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
def test_branding_cache(self):
|
||||
def has_branding(html_text):
|
||||
el = html.fromstring(html_text)
|
||||
return el.xpath('//*[@data-oe-model="test.model"]')
|
||||
|
||||
self.user_demo.groups_id += self.env.ref('website.group_website_restricted_editor')
|
||||
self.user_demo.groups_id -= self.env.ref('website.group_website_designer')
|
||||
self.user_demo.group_ids += self.env.ref('website.group_website_restricted_editor')
|
||||
self.user_demo.group_ids += self.env.ref('test_website.group_test_website_admin')
|
||||
self.user_demo.group_ids -= self.env.ref('website.group_website_designer')
|
||||
|
||||
# Create session for demo user.
|
||||
public_session = self.authenticate(None, None)
|
||||
demo_session = self.authenticate('demo', 'demo')
|
||||
record = self.env['test.model'].search([], limit=1)
|
||||
result = self.url_open(f'/test_website/model_item/{record.id}')
|
||||
result = self.url_open(f'/test_website/model_item_sudo/{record.id}')
|
||||
self.assertTrue(has_branding(result.text), "Should have branding for user demo")
|
||||
|
||||
# Public user.
|
||||
self.opener.cookies['session_id'] = public_session.sid
|
||||
result = self.url_open(f'/test_website/model_item/{record.id}')
|
||||
self.opener.cookies.set("session_id", public_session.sid, domain=odoo.tests.common.HOST)
|
||||
result = self.url_open(f'/test_website/model_item_sudo/{record.id}')
|
||||
self.assertFalse(has_branding(result.text), "Should have no branding for public user")
|
||||
|
||||
# Back to demo user.
|
||||
self.opener.cookies['session_id'] = demo_session.sid
|
||||
result = self.url_open(f'/test_website/model_item/{record.id}')
|
||||
self.opener.cookies.set("session_id", demo_session.sid, domain=odoo.tests.common.HOST)
|
||||
result = self.url_open(f'/test_website/model_item_sudo/{record.id}')
|
||||
self.assertTrue(has_branding(result.text), "Should have branding for user demo")
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import odoo.tests
|
|||
|
||||
@odoo.tests.tagged('-at_install', 'post_install')
|
||||
class TestWebsiteSettings(odoo.tests.HttpCase):
|
||||
|
||||
def test_01_multi_website_settings(self):
|
||||
# If not enabled (like in demo data), landing on res.config will try
|
||||
# to disable module_sale_quotation_builder and raise an issue
|
||||
|
|
@ -13,4 +14,4 @@ class TestWebsiteSettings(odoo.tests.HttpCase):
|
|||
if group_order_template:
|
||||
self.env.ref('base.group_user').write({"implied_ids": [(4, group_order_template.id)]})
|
||||
self.env['website'].create({'name': "Website Test Settings", 'specific_user_account': True})
|
||||
self.start_tour("/web", 'website_settings_m2o_dirty', login="admin")
|
||||
self.start_tour("/odoo", 'website_settings_m2o_dirty', login="admin")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo.tests
|
||||
|
||||
|
||||
@odoo.tests.common.tagged('post_install', '-at_install')
|
||||
class TestSnippetBackgroundVideo(odoo.tests.HttpCase):
|
||||
|
||||
def test_snippet_background_video(self):
|
||||
self.start_tour("/", "snippet_background_video", login="admin")
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests.common import HOST, new_test_user, tagged
|
||||
|
|
@ -31,7 +32,8 @@ class TestSystray(HttpCase):
|
|||
</xpath>
|
||||
"""
|
||||
})
|
||||
|
||||
# Remain on page when switching website
|
||||
cls.env['website'].search([]).homepage_url = '/test_model/1'
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_01_admin(self):
|
||||
|
|
@ -39,27 +41,43 @@ class TestSystray(HttpCase):
|
|||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_02_reditor_tester(self):
|
||||
self.user_test.groups_id |= self.group_restricted_editor
|
||||
self.user_test.groups_id |= self.group_tester
|
||||
self.user_test.group_ids |= self.group_restricted_editor
|
||||
self.user_test.group_ids |= self.group_tester
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_reditor_tester', login="testtest")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_03_reditor_not_tester(self):
|
||||
self.user_test.groups_id |= self.group_restricted_editor
|
||||
self.user_test.groups_id = self.user_test.groups_id.filtered(lambda group: group != self.group_tester)
|
||||
self.assertNotIn(self.group_tester.id, self.user_test.groups_id.ids, "User should not be a group_tester")
|
||||
self.user_test.group_ids |= self.group_restricted_editor
|
||||
self.user_test.group_ids = self.user_test.group_ids.filtered(lambda group: group != self.group_tester)
|
||||
self.assertNotIn(self.group_tester.id, self.user_test.group_ids.ids, "User should not be a group_tester")
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_reditor_not_tester', login="testtest")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_04_not_reditor_tester(self):
|
||||
self.user_test.groups_id = self.user_test.groups_id.filtered(lambda group: group != self.group_restricted_editor)
|
||||
self.user_test.groups_id |= self.group_tester
|
||||
self.assertNotIn(self.group_restricted_editor.id, self.user_test.groups_id.ids, "User should not be a group_restricted_editor")
|
||||
self.user_test.group_ids = self.user_test.group_ids.filtered(lambda group: group != self.group_restricted_editor)
|
||||
self.user_test.group_ids |= self.group_tester
|
||||
self.assertNotIn(self.group_restricted_editor.id, self.user_test.group_ids.ids, "User should not be a group_restricted_editor")
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_not_reditor_tester', login="testtest")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_05_not_reditor_not_tester(self):
|
||||
self.user_test.groups_id = self.user_test.groups_id.filtered(lambda group: group not in [self.group_restricted_editor, self.group_tester])
|
||||
self.assertNotIn(self.group_restricted_editor.id, self.user_test.groups_id.ids, "User should not be a group_restricted_editor")
|
||||
self.assertNotIn(self.group_tester.id, self.user_test.groups_id.ids, "User should not be a group_tester")
|
||||
self.user_test.group_ids = self.user_test.group_ids.filtered(lambda group: group not in [self.group_restricted_editor, self.group_tester])
|
||||
self.assertNotIn(self.group_restricted_editor.id, self.user_test.group_ids.ids, "User should not be a group_restricted_editor")
|
||||
self.assertNotIn(self.group_tester.id, self.user_test.group_ids.ids, "User should not be a group_tester")
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_not_reditor_not_tester', login="testtest")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_06_single_website(self):
|
||||
if self.env['website'].search_count([]) > 1:
|
||||
website = self.env['website'].search([], limit=1)
|
||||
websites_to_remove = self.env['website'].search([('id', '!=', website.id)])
|
||||
websites_to_remove.unlink()
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_single_website', login="admin")
|
||||
|
||||
@mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.http')
|
||||
def test_07_multi_website(self):
|
||||
if self.env['website'].search_count([]) == 1:
|
||||
self.env['website'].create({
|
||||
'name': 'My Website 2',
|
||||
})
|
||||
self.start_tour(self.env['website'].get_client_action_url('/test_model/1'), 'test_systray_multi_website', login="admin")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests.common import TransactionCase, tagged
|
||||
from odoo.tools import convert_file
|
||||
from odoo.tools.misc import file_path
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestThemeAsset(TransactionCase):
|
||||
|
||||
def test_theme_asset_tag(self):
|
||||
"""
|
||||
Verify that assets defined with the <asset> tag are properly imported.
|
||||
"""
|
||||
# Load new records
|
||||
convert_file(
|
||||
self.env, 'theme_default',
|
||||
file_path('test_website/tests/asset_tag.xml'),
|
||||
{}, 'init', False,
|
||||
)
|
||||
active_keep_asset = self.env.ref('theme_default.test_asset_tag_aaa')
|
||||
inactive_keep_asset = self.env.ref('theme_default.test_asset_tag_iii')
|
||||
active_switch_asset_reset = self.env.ref('theme_default.test_asset_tag_aia')
|
||||
active_switch_asset_ignore = self.env.ref('theme_default.test_asset_tag_aii')
|
||||
inactive_switch_asset = self.env.ref('theme_default.test_asset_tag_iaa')
|
||||
prepend_asset = self.env.ref('theme_default.test_asset_tag_prepend')
|
||||
asset_with_extra_field = self.env.ref('theme_default.test_asset_tag_extra')
|
||||
|
||||
# Verify initial load
|
||||
self.assertEqual(prepend_asset._name, 'theme.ir.asset', 'Model should be theme.ir.asset')
|
||||
self.assertEqual(prepend_asset.name, 'Test asset tag with directive', 'Name not loaded')
|
||||
self.assertEqual(prepend_asset.directive, 'prepend', 'Directive not loaded')
|
||||
self.assertEqual(prepend_asset.bundle, 'test_asset_bundle', 'Bundle not loaded')
|
||||
self.assertEqual(prepend_asset.path, 'theme_default/tests/something.scss', 'Path not loaded')
|
||||
self.assertEqual(asset_with_extra_field.sequence, 17, 'Sequence not loaded')
|
||||
self.assertTrue(active_keep_asset.active, 'Should be active')
|
||||
self.assertTrue(active_switch_asset_reset.active, 'Should be active')
|
||||
self.assertTrue(active_switch_asset_ignore.active, 'Should be active')
|
||||
self.assertFalse(inactive_keep_asset.active, 'Should be inactive')
|
||||
self.assertFalse(inactive_switch_asset.active, 'Should be inactive')
|
||||
|
||||
# Patch records
|
||||
prepend_asset.name = 'changed'
|
||||
prepend_asset.directive = 'append'
|
||||
prepend_asset.bundle = 'changed'
|
||||
prepend_asset.path = 'theme_default/tests/changed.scss'
|
||||
asset_with_extra_field.sequence = 3
|
||||
active_switch_asset_reset.active = False
|
||||
active_switch_asset_ignore.active = False
|
||||
inactive_switch_asset.active = True
|
||||
|
||||
# Update records
|
||||
convert_file(
|
||||
self.env, 'theme_default',
|
||||
file_path('test_website/tests/asset_tag.xml'),
|
||||
{
|
||||
'theme_default.test_asset_tag_aaa': active_keep_asset.id,
|
||||
'theme_default.test_asset_tag_iii': inactive_keep_asset.id,
|
||||
'theme_default.test_asset_tag_aia': active_switch_asset_reset.id,
|
||||
'theme_default.test_asset_tag_aii': active_switch_asset_ignore.id,
|
||||
'theme_default.test_asset_tag_iaa': inactive_switch_asset.id,
|
||||
'theme_default.test_asset_tag_prepend': prepend_asset.id,
|
||||
'theme_default.test_asset_tag_extra': asset_with_extra_field.id,
|
||||
}, 'update', False,
|
||||
)
|
||||
|
||||
# Verify updated load
|
||||
self.assertEqual(prepend_asset.name, 'Test asset tag with directive', 'Name not restored')
|
||||
self.assertEqual(prepend_asset.directive, 'prepend', 'Directive not restored')
|
||||
self.assertEqual(prepend_asset.bundle, 'test_asset_bundle', 'Bundle not restored')
|
||||
self.assertEqual(prepend_asset.path, 'theme_default/tests/something.scss', 'Path not restored')
|
||||
self.assertEqual(asset_with_extra_field.sequence, 17, 'Sequence not restored')
|
||||
self.assertTrue(active_keep_asset.active, 'Should be active')
|
||||
self.assertTrue(active_switch_asset_reset.active, 'Should be reset to active')
|
||||
self.assertFalse(active_switch_asset_ignore.active, 'Should be kept inactive')
|
||||
self.assertFalse(inactive_keep_asset.active, 'Should be inactive')
|
||||
self.assertTrue(inactive_switch_asset.active, 'Should be kept active')
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import Command
|
||||
from odoo.tests import HttpCase, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install', 'is_tour')
|
||||
class TestTranslation(HttpCase):
|
||||
|
||||
def _single_language_fr_user_fr_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_single_language_fr_user_fr_site', login='admin')
|
||||
|
||||
def _single_language_en_user_fr_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_single_language_en_user_fr_site', login='admin')
|
||||
|
||||
def _single_language_fr_user_en_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_single_language_fr_user_en_site', login='admin')
|
||||
|
||||
def _multi_language_fr_user_fr_en_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_multi_language_fr_user_fr_en_site', login='admin', timeout=250)
|
||||
|
||||
def _multi_language_fr_user_en_fr_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_multi_language_fr_user_en_fr_site', login='admin', timeout=250)
|
||||
|
||||
def _multi_language_en_user_fr_en_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_multi_language_en_user_fr_en_site', login='admin', timeout=250)
|
||||
|
||||
def _multi_language_en_user_en_fr_site(self):
|
||||
self.start_tour(self.env['website'].get_client_action_url('/'), 'translation_multi_language_en_user_en_fr_site', login='admin', timeout=250)
|
||||
|
||||
def _fr_db(self):
|
||||
self._fr_en_db()
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
lang_en.active = False
|
||||
|
||||
def _fr_en_db(self):
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
self.env["base.language.install"].create({
|
||||
'overwrite': True,
|
||||
'lang_ids': [(6, 0, [lang_fr.id])],
|
||||
}).lang_install()
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_fr
|
||||
website.default_lang_id = lang_fr
|
||||
website.language_ids -= lang_en
|
||||
self.env['website'].create({
|
||||
'sequence': 1,
|
||||
'name': 'Test FR Website',
|
||||
'language_ids': [
|
||||
Command.link(lang_fr.id),
|
||||
],
|
||||
'default_lang_id': lang_fr.id,
|
||||
})
|
||||
|
||||
for user in self.env['res.users'].search([]):
|
||||
user.lang = lang_fr.code
|
||||
for partner in self.env['res.partner'].search([]):
|
||||
partner.lang = lang_fr.code
|
||||
for user in self.env['res.users'].with_context(active_test=False).search([]):
|
||||
user.lang = lang_fr.code
|
||||
|
||||
def _en_fr_db(self):
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
self.env["base.language.install"].create({
|
||||
'overwrite': True,
|
||||
'lang_ids': [(6, 0, [lang_fr.id])],
|
||||
}).lang_install()
|
||||
|
||||
def test_fr_db_fr_site(self):
|
||||
self._fr_db()
|
||||
self._single_language_fr_user_fr_site()
|
||||
|
||||
def test_fr_en_db_fr_site(self):
|
||||
self._fr_en_db()
|
||||
self._single_language_fr_user_fr_site()
|
||||
|
||||
def test_fr_en_db_en_site(self):
|
||||
self._fr_en_db()
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_en
|
||||
website.default_lang_id = lang_en
|
||||
website.language_ids -= lang_fr
|
||||
self._single_language_fr_user_en_site()
|
||||
|
||||
def test_fr_en_db_fr_en_site(self):
|
||||
self._fr_en_db()
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_en
|
||||
self._multi_language_fr_user_fr_en_site()
|
||||
|
||||
def test_fr_en_db_en_fr_site(self):
|
||||
self._fr_en_db()
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_en
|
||||
website.default_lang_id = lang_en
|
||||
self._multi_language_fr_user_en_fr_site()
|
||||
|
||||
def test_en_fr_db_fr_site(self):
|
||||
self._en_fr_db()
|
||||
lang_en = self.env.ref('base.lang_en')
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
self.env["base.language.install"].create({
|
||||
'overwrite': True,
|
||||
'lang_ids': [(6, 0, [lang_fr.id])],
|
||||
}).lang_install()
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_fr
|
||||
website.default_lang_id = lang_fr
|
||||
website.language_ids -= lang_en
|
||||
self._single_language_en_user_fr_site()
|
||||
|
||||
def test_en_fr_db_fr_en_site(self):
|
||||
self._en_fr_db()
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_fr
|
||||
website.default_lang_id = lang_fr
|
||||
self._multi_language_en_user_fr_en_site()
|
||||
|
||||
def test_en_fr_db_en_fr_site(self):
|
||||
self._en_fr_db()
|
||||
lang_fr = self.env.ref('base.lang_fr')
|
||||
for website in self.env['website'].search([]):
|
||||
website.language_ids += lang_fr
|
||||
self._multi_language_en_user_en_fr_site()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.website.tools import MockRequest
|
||||
from odoo.addons.http_routing.tests.common import MockRequest
|
||||
from odoo.tests import standalone
|
||||
|
||||
|
||||
|
|
@ -70,8 +70,7 @@ def test_01_cow_views_unlink_on_module_update(env):
|
|||
# Upgrade the module
|
||||
test_website_module = env['ir.module.module'].search([('name', '=', 'test_website')])
|
||||
test_website_module.button_immediate_upgrade()
|
||||
env.reset() # clear the set of environments
|
||||
env = env() # get an environment that refers to the new registry
|
||||
env.transaction.reset() # clear the set of environments
|
||||
|
||||
# Ensure generic views got removed
|
||||
view = env.ref('test_website.update_module_view_to_be_t_called', raise_if_not_found=False)
|
||||
|
|
@ -178,10 +177,22 @@ def test_02_copy_ids_views_unlink_on_module_update(env):
|
|||
|
||||
view_website_1, view_website_2, theme_child_view = _simulate_xml_view()
|
||||
|
||||
old_registry = env.registry
|
||||
|
||||
# Upgrade the module
|
||||
theme_default.button_immediate_upgrade()
|
||||
env.reset() # clear the set of environments
|
||||
env = env() # get an environment that refers to the new registry
|
||||
env.transaction.reset() # clear the set of environments
|
||||
|
||||
# Beware: records do not belong to the correct registry anymore
|
||||
assert env.registry is not old_registry
|
||||
# Therefore we need to re-obtain them
|
||||
View = env['ir.ui.view']
|
||||
ThemeView = env['theme.ir.ui.view']
|
||||
Imd = env['ir.model.data']
|
||||
|
||||
website_1 = env['website'].browse(1)
|
||||
website_2 = env['website'].browse(2)
|
||||
theme_default = env.ref('base.module_theme_default')
|
||||
|
||||
# Ensure the theme.ir.ui.view got removed (since there is an IMD but not
|
||||
# present in XML files)
|
||||
|
|
@ -204,8 +215,7 @@ def test_02_copy_ids_views_unlink_on_module_update(env):
|
|||
# Upgrade the module
|
||||
with MockRequest(env, website=website_1):
|
||||
theme_default.button_immediate_upgrade()
|
||||
env.reset() # clear the set of environments
|
||||
env = env() # get an environment that refers to the new registry
|
||||
env.transaction.reset() # clear the set of environments
|
||||
|
||||
# Ensure the theme.ir.ui.view got removed (since there is an IMD but not
|
||||
# present in XML files)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
from lxml import html
|
||||
|
||||
from odoo.tools import mute_logger
|
||||
from odoo.exceptions import AccessError, ValidationError
|
||||
from odoo.tests import HttpCase, tagged
|
||||
import unittest
|
||||
|
||||
from odoo.addons.website.controllers.model_page import ModelPageController
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestWebsiteControllerPage(HttpCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.model = cls.env["ir.model"]._get("test.model.exposed")
|
||||
|
||||
cls.model_acl = cls.env["ir.model.access"].create({
|
||||
"name": "test acl expose",
|
||||
"model_id": cls.model.id,
|
||||
"group_id": cls.env.ref("website.website_page_controller_expose").id,
|
||||
"perm_read": True,
|
||||
})
|
||||
|
||||
cls.listing_view = cls.env["ir.ui.view"].create({
|
||||
"type": "qweb",
|
||||
"model": cls.model.model,
|
||||
"arch": """<t t-call="website.layout">
|
||||
<t t-set="_activeClasses" t-translation="off">border-primary</t>
|
||||
<div t-attf-class="listing_layout_switcher btn-group ms-3" t-att-data-active-classes="_activeClasses" t-att-data-view-id="view_id">
|
||||
<input type="radio" class="btn-check" name="wstudio_layout" id="o_wstudio_apply_grid" value="grid" t-att-checked="'checked' if layout_mode != 'list' else None"/>
|
||||
<label t-attf-class="btn btn-light #{_activeClasses if layout_mode != 'list' else None} o_wstudio_apply_grid" title="Grid" for="o_wstudio_apply_grid">
|
||||
<i class="fa fa-th-large"/>
|
||||
</label>
|
||||
<input type="radio" class="btn-check" name="wstudio_layout" id="o_wstudio_apply_list" t-att-checked="'checked' if layout_mode == 'list' else None" value="list"/>
|
||||
<label t-attf-class="btn btn-light #{_activeClasses if layout_mode == 'list' else None} o_wstudio_apply_list" title="List" for="o_wstudio_apply_list">
|
||||
<i class="oi oi-view-list"/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div t-attf-class="row mx-n2 mt8 #{'o_website_grid' if layout_mode == 'grid' else 'o_website_list'}">
|
||||
<t t-foreach="records" t-as="record">
|
||||
<a class="test_record_listing" t-out="record.display_name" t-att-href="record_to_url(record)" />
|
||||
</t>
|
||||
</div>
|
||||
</t> """
|
||||
})
|
||||
|
||||
cls.single_view = cls.env["ir.ui.view"].create({
|
||||
"type": "qweb",
|
||||
"model": cls.model.model,
|
||||
"arch": """<t t-call="website.layout">
|
||||
<div class="test_record" t-out="record.display_name" />
|
||||
</t> """
|
||||
})
|
||||
|
||||
cls.listing_controller_page = cls.env["website.controller.page"].create({
|
||||
"name": "Exposed Model",
|
||||
"view_id": cls.listing_view.id,
|
||||
"record_view_id": cls.single_view.id,
|
||||
"record_domain": "[('name', '=ilike', 'test_partner_%')]",
|
||||
"website_published": True,
|
||||
})
|
||||
|
||||
partner_data = {}
|
||||
if "is_published" in cls.env[cls.model.model]._fields:
|
||||
partner_data["is_published"] = True
|
||||
|
||||
records_to_create = [dict(name=f"test_partner_{i}", **partner_data) for i in range(2)]
|
||||
cls.exposed_records = cls.env[cls.model.model].create(records_to_create)
|
||||
|
||||
def test_cannot_bypass_read_rights(self):
|
||||
self.env["ir.model.access"].search([("model_id", "=", self.model.id)]).perm_read = False
|
||||
|
||||
with self.assertRaises(AccessError) as cm:
|
||||
self.env["website.controller.page"].with_user(2).create({
|
||||
"name": "Exposed Model Read",
|
||||
"website_id": False,
|
||||
"view_id": self.single_view.id,
|
||||
"record_domain": "[('name', '=ilike', 'test_partner_%')]",
|
||||
"website_published": True,
|
||||
})
|
||||
self.assertEqual(str(cm.exception).split("\n")[0], "You are not allowed to access 'Website Model Test Exposed' (test.model.exposed) records.")
|
||||
|
||||
def test_access_rights_and_rules(self):
|
||||
self.authenticate(None, None)
|
||||
self.model_acl.active = False
|
||||
with mute_logger("odoo.http"):
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}")
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
self.model_acl.active = True
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 2)
|
||||
|
||||
self.env["ir.rule"].create({
|
||||
"name": "dummy",
|
||||
"model_id": self.model.id,
|
||||
"domain_force": "[('name', '=', 'test_partner_1')]",
|
||||
"groups": self.env.ref("base.group_public"),
|
||||
})
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 1)
|
||||
|
||||
def test_expose_model(self):
|
||||
self.authenticate(None, None)
|
||||
|
||||
slug = self.env['ir.http']._slug
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 2)
|
||||
for n, record in zip(rec_nodes, self.exposed_records):
|
||||
self.assertEqual(n.get("href"), f"/model/{self.listing_controller_page.name_slugified}/{slug(record)}")
|
||||
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}/{slug(self.exposed_records[0])}")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
self.assertEqual(len(tree.xpath("//div[@class='test_record']")), 1)
|
||||
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}/fake-slug-{self.exposed_records[0].id}")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
non_reachable_record = self.env[self.model.model].create({"name": "non_reachable"})
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}/{slug(non_reachable_record)}")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
response = self.url_open("/model/some-other-slug")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
self.listing_controller_page.website_published = False
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_search_listing(self):
|
||||
self.authenticate(None, None)
|
||||
|
||||
slug = self.env['ir.http']._slug
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}?search=1")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 1)
|
||||
self.assertEqual(rec_nodes[0].get("href"), f"/model/{self.listing_controller_page.name_slugified}/{slug(self.exposed_records[1])}")
|
||||
|
||||
self.patch(ModelPageController, "pager_step", 1)
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}/page/2")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 1)
|
||||
self.assertEqual(rec_nodes[0].get("href"), f"/model/{self.listing_controller_page.name_slugified}/{slug(self.exposed_records[1])}")
|
||||
|
||||
response = self.url_open(f"/model/{self.listing_controller_page.name_slugified}/page/2?search={self.exposed_records[0].name}")
|
||||
self.assertEqual(response.url.partition('/model/')[2], f"exposed-model?search={self.exposed_records[0].name}&order=create_date+desc")
|
||||
tree = html.fromstring(response.content.decode())
|
||||
rec_nodes = tree.xpath("//a[@class='test_record_listing']")
|
||||
self.assertEqual(len(rec_nodes), 1)
|
||||
self.assertEqual(rec_nodes[0].get("href"), f"/model/{self.listing_controller_page.name_slugified}/{slug(self.exposed_records[0])}")
|
||||
|
||||
def test_default_layout(self):
|
||||
self.assertEqual(self.listing_controller_page.default_layout, 'grid')
|
||||
self.start_tour('/model/exposed-model', 'website_controller_page_listing_layout', login='admin')
|
||||
self.assertEqual(self.listing_controller_page.default_layout, 'list')
|
||||
#check that the user that has not previously interacted with the layout switcher will prompt on the default layout
|
||||
self.start_tour('/model/exposed-model', 'website_controller_page_default_page_check', login='admin')
|
||||
|
||||
def test_model_constrains(self):
|
||||
def get_model_meta_params(model_name):
|
||||
m = self.env[model_name]
|
||||
return (m._abstract, m._auto, m._transient)
|
||||
|
||||
default_page_vals = {
|
||||
"arch": "<t><div/></t>",
|
||||
"type": "qweb",
|
||||
"name": "some_name"
|
||||
}
|
||||
# Abstract Model
|
||||
self.assertEqual(get_model_meta_params("website.published.mixin"), (True, False, False))
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
self.env["website.controller.page"].create({**default_page_vals, "model": "website.published.mixin"})
|
||||
self.assertEqual(str(cm.exception), "A page must be set to display a concrete model.")
|
||||
|
||||
# Transient Model
|
||||
self.assertEqual(get_model_meta_params("base.partner.merge.automatic.wizard"), (False, True, True))
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
self.env["website.controller.page"].create({**default_page_vals, "model": "base.partner.merge.automatic.wizard"})
|
||||
self.assertEqual(str(cm.exception), "A page must be set to display a concrete model.")
|
||||
|
||||
# _auto = False Model
|
||||
self.assertEqual(get_model_meta_params("res.device"), (False, False, False))
|
||||
with self.assertRaises(ValidationError) as cm:
|
||||
self.env["website.controller.page"].create({**default_page_vals, "model": "res.device"})
|
||||
self.assertEqual(str(cm.exception), "A page must be set to display a concrete model.")
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo
|
||||
import odoo.tests
|
||||
|
||||
|
||||
@odoo.tests.tagged('-at_install', 'post_install')
|
||||
class TestWebsiteFieldSanitize(odoo.tests.HttpCase):
|
||||
def test_sanitize_video_iframe(self):
|
||||
self.env['res.users'].create({
|
||||
'name': 'Restricted Editor',
|
||||
'login': 'restricted',
|
||||
'password': 'restricted',
|
||||
'group_ids': [(6, 0, [
|
||||
self.ref('base.group_user'),
|
||||
self.ref('website.group_website_restricted_editor'),
|
||||
self.ref('test_website.group_test_website_admin'),
|
||||
])]
|
||||
})
|
||||
|
||||
# Add a video to an HTML field (admin).
|
||||
self.start_tour(
|
||||
self.env['website'].get_client_action_url('/test_website/model_item/1'),
|
||||
'website_designer_iframe_video',
|
||||
login='admin'
|
||||
)
|
||||
# Make sure a user can still edit the content (restricted editor).
|
||||
self.start_tour(
|
||||
self.env['website'].get_client_action_url('/test_website/model_item/1'),
|
||||
'website_restricted_editor_iframe_video',
|
||||
login='restricted'
|
||||
)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import HttpCase, tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestWebsitePageProperties(HttpCase):
|
||||
|
||||
def test_website_page_properties_common(self):
|
||||
self.start_tour('/test_view', 'website_page_properties_common', login='admin')
|
||||
|
||||
def test_website_page_properties_can_publish(self):
|
||||
self.start_tour('/test_website/model_item/1', 'website_page_properties_can_publish', login='admin')
|
||||
|
||||
def test_website_page_properties_website_page(self):
|
||||
# Create a website page with a different URL to be tested for dependency
|
||||
# tracking
|
||||
self.env['website.page'].create({
|
||||
'name': 'Base',
|
||||
'type': 'qweb',
|
||||
'arch': '<div><a href="/cool-page">Cool page</a></div>',
|
||||
'key': 'test.cool_page',
|
||||
'url': '/dependency_page',
|
||||
'website_id': self.env['website'].search([], limit=1).id,
|
||||
})
|
||||
|
||||
self.start_tour('/', 'website_page_properties_website_page', login='admin')
|
||||
Loading…
Add table
Add a link
Reference in a new issue