Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions docker/scripts/odoo_website_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ def _write_existing_fields(record: Any, values: dict[str, object]) -> None:
record.sudo().write(filtered_values)


def _homepage_values(website: Any, *, homepage_url: str, homepage_page: Any | None) -> dict[str, object]:
values: dict[str, object] = {}
if homepage_page and "homepage_id" in website._fields:
values["homepage_id"] = homepage_page.id
if homepage_url and "homepage_url" in website._fields:
values["homepage_url"] = homepage_url
if homepage_url and homepage_page is None and "homepage_id" in website._fields:
values["homepage_id"] = False
return values


def _module_is_installed(env: Any, module_name: object) -> bool:
normalized_module_name = str(module_name or "").strip()
if not normalized_module_name:
Expand Down Expand Up @@ -156,21 +167,23 @@ def apply_website_bootstrap(env: Any, parsed_payload: dict[str, object] | None)
if "website_id" in homepage_page._fields:
page_values["website_id"] = website.id
_write_existing_fields(homepage_page, page_values)
_write_existing_fields(website, {"homepage_id": homepage_page.id})
elif primary_page_xmlid:
raise RuntimeError(f"Website bootstrap primary page XML ID not found: {primary_page_xmlid}")
_write_existing_fields(website, _homepage_values(website, homepage_url=homepage_url, homepage_page=homepage_page))

raw_routes_source = website_payload.get("routes_source")
routes_source = raw_routes_source if isinstance(raw_routes_source, dict) else {}
fallback_module = str(routes_source.get("module") or "").strip()
if homepage_url and not homepage_page:
_verify_route(
route_page = _verify_route(
env, website, {"url": homepage_url, "module": fallback_module, "published": True}, fallback_module=fallback_module
)
_write_existing_fields(website, _homepage_values(website, homepage_url=homepage_url, homepage_page=route_page))
for route_payload in website_payload.get("routes") or []:
if isinstance(route_payload, dict):
route_page = _verify_route(env, website, route_payload, fallback_module=fallback_module)
if route_page and bool(route_payload.get("homepage")):
_write_existing_fields(website, {"homepage_id": route_page.id})
if bool(route_payload.get("homepage")):
route_url = str(route_payload.get("url") or "").strip()
_write_existing_fields(website, _homepage_values(website, homepage_url=route_url, homepage_page=route_page))

print("website_bootstrap_applied=true")
122 changes: 122 additions & 0 deletions tests/test_odoo_website_bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from __future__ import annotations

import importlib.util
import sys
import types
import unittest
from pathlib import Path
from typing import Any


def _load_bootstrap_module() -> types.ModuleType:
module_path = Path(__file__).resolve().parents[1] / "docker" / "scripts" / "odoo_website_bootstrap.py"
spec = importlib.util.spec_from_file_location("odoo_devkit_website_bootstrap_test_module", module_path)
if spec is None or spec.loader is None:
raise RuntimeError(f"Unable to load module from {module_path}")
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module


website_bootstrap = _load_bootstrap_module()


class FakeRecord:
def __init__(self, *, record_id: int = 1, fields: tuple[str, ...] = (), truthy: bool = True) -> None:
self.id = record_id
self._fields = set(fields)
self.writes: list[dict[str, object]] = []
self.truthy = truthy

def __bool__(self) -> bool:
return self.truthy

def sudo(self) -> FakeRecord:
return self

def write(self, values: dict[str, object]) -> None:
self.writes.append(values)


class FakeModel:
def __init__(self, *, record: FakeRecord | None = None, fields: tuple[str, ...] = ()) -> None:
self.record = record if record is not None else FakeRecord(truthy=False)
self._fields = set(fields)

def sudo(self) -> FakeModel:
return self

def search(self, *unused_args: object, **unused_kwargs: object) -> FakeRecord:
return self.record

def create(self, values: dict[str, object]) -> FakeRecord:
self.record = FakeRecord(fields=tuple(self._fields))
self.record.write(values)
return self.record


class FakeConfigParameter:
def __init__(self) -> None:
self.values: dict[str, str] = {}

def sudo(self) -> FakeConfigParameter:
return self

def set_param(self, key: str, value: str) -> None:
self.values[key] = value


class FakeEnv:
def __init__(self) -> None:
self.website = FakeRecord(fields=("name", "domain", "homepage_id", "homepage_url"))
self.config_parameter = FakeConfigParameter()
self.modules = FakeModel(record=FakeRecord(fields=(), truthy=True))
self.pages = FakeModel(record=FakeRecord(fields=(), truthy=False))
self.langs = FakeModel(record=FakeRecord(fields=(), truthy=False))
self.registry = {"website": object()}

def __getitem__(self, model_name: str) -> Any:
return {
"website": FakeModel(record=self.website, fields=("name", "domain", "homepage_id", "homepage_url")),
"ir.config_parameter": self.config_parameter,
"ir.module.module": self.modules,
"website.page": self.pages,
"res.lang": self.langs,
"ir.http": FakeModel(record=FakeRecord()),
}[model_name]

@staticmethod
def ref(*unused_args: object, **unused_kwargs: object) -> None:
return None


class WebsiteBootstrapHelperTests(unittest.TestCase):
def test_controller_homepage_route_persists_homepage_url_and_clears_stale_page_homepage(self) -> None:
env = FakeEnv()
payload = {
"website_bootstrap": {
"name": "OPW",
"canonical_url": "https://opw-testing.example.com",
"homepage_url": "/shop",
"routes_source": {"module": "website_sale"},
"routes": [
{
"name": "Shop",
"url": "/shop",
"module": "website_sale",
"published": True,
"homepage": True,
}
],
}
}

website_bootstrap.apply_website_bootstrap(env, payload)

self.assertIn({"homepage_url": "/shop", "homepage_id": False}, env.website.writes)
self.assertEqual(env.config_parameter.values["web.base.url"], "https://opw-testing.example.com")


if __name__ == "__main__":
unittest.main()
Loading