from lxml import html from odoo.tools import mute_logger from odoo.exceptions import AccessError from odoo.tests import HttpCase, tagged 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": """ border-primary
""" }) cls.single_view = cls.env["ir.ui.view"].create({ "type": "qweb", "model": cls.model.model, "arch": """
""" }) 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", "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])}") 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')