diff --git a/addons/bus/controllers/websocket.py b/addons/bus/controllers/websocket.py index 6449d1ee69a..d870b3da29c 100644 --- a/addons/bus/controllers/websocket.py +++ b/addons/bus/controllers/websocket.py @@ -63,9 +63,7 @@ class WebsocketController(Controller): :param str v: Version of the worker, frontend only argument used to prevent new worker versions to be loaded from the browser cache. """ - bundle = 'bus.websocket_worker_assets' - asset = request.env["ir.qweb"]._get_asset_bundle(bundle) - stream = request.env['ir.binary']._get_stream_from(asset.js( - is_minified="assets" not in request.session.debug - )) + bundle_name = 'bus.websocket_worker_assets' + bundle = request.env["ir.qweb"]._get_asset_bundle(bundle_name, debug_assets="assets" in request.session.debug) + stream = request.env['ir.binary']._get_stream_from(bundle.js()) return stream.get_response() diff --git a/addons/bus/tests/test_assetsbundle.py b/addons/bus/tests/test_assetsbundle.py index 2c44b18da6b..0d539942923 100644 --- a/addons/bus/tests/test_assetsbundle.py +++ b/addons/bus/tests/test_assetsbundle.py @@ -14,9 +14,8 @@ class BusWebTests(odoo.tests.HttpCase): i.e. their hash has been recomputed and differ from the attachment's - The interface deals with those bus messages by displaying one notification """ - db_name = self.env.registry.db_name # start from a clean slate - self.env['ir.attachment'].search([('name', 'ilike', 'web.assets_web%')]).unlink() + self.env['ir.attachment'].search([('name', 'ilike', 'web.assets_%')]).unlink() self.env.registry.clear_cache() sendones = [] @@ -28,8 +27,10 @@ class BusWebTests(odoo.tests.HttpCase): self.patch(type(self.env['bus.bus']), '_sendone', patched_sendone) - self.authenticate('admin', 'admin') - self.url_open('/web') + self.url_open('/web/assets/-/web.assets_web.min.js') + self.url_open('/web/assets/ltr/web.assets_web.min.css') + self.url_open('/web/assets/-/web.assets_backend.min.js') + self.url_open('/web/assets/ltr/web.assets_backend.min.css') # One sendone for each asset bundle and for each CSS / JS self.assertEqual( diff --git a/addons/stock/report/stock_traceability.py b/addons/stock/report/stock_traceability.py index 009d8d25742..acede4805e9 100644 --- a/addons/stock/report/stock_traceability.py +++ b/addons/stock/report/stock_traceability.py @@ -211,8 +211,6 @@ class MrpStockReport(models.TransientModel): } context = dict(self.env.context) - if not config['test_enable']: - context['commit_assetsbundle'] = True if context.get('active_id') and context.get('active_model'): rcontext['reference'] = self.env[context.get('active_model')].browse(int(context.get('active_id'))).display_name diff --git a/addons/test_website/tests/test_qweb.py b/addons/test_website/tests/test_qweb.py index 31a2463d91f..610c8b945ed 100644 --- a/addons/test_website/tests/test_qweb.py +++ b/addons/test_website/tests/test_qweb.py @@ -35,22 +35,18 @@ class TestQweb(TransactionCaseWithUserDemo): 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) + 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') - css_attachement = demo_env['ir.attachment'].search([('url', '=like', f'/web/assets/{asset_version_css}/w-{website.id}_ltr/test_website.test_bundle.%')]) - js_attachement = demo_env['ir.attachment'].search([('url', '=like', f'/web/assets/{asset_version_js}/w-{website.id}_-/test_website.test_bundle.%')]) - self.assertEqual(len(css_attachement), 1) - self.assertEqual(len(js_attachement), 1) - format_data = { - "css": css_attachement.url, - "js": js_attachement.url, + "css": css_url, + "js": js_url, "user_id": demo.id, "filename": "Marc%20Demo", "alt": "Marc Demo", diff --git a/addons/web/controllers/binary.py b/addons/web/controllers/binary.py index 509e3947906..95e1cf2ce1a 100644 --- a/addons/web/controllers/binary.py +++ b/addons/web/controllers/binary.py @@ -8,6 +8,8 @@ import logging import os import unicodedata +import werkzeug.exceptions + try: from werkzeug.utils import send_file except ImportError: @@ -15,13 +17,12 @@ except ImportError: import odoo import odoo.modules.registry -from odoo import http, _ +from odoo import SUPERUSER_ID, _, http from odoo.exceptions import AccessError, UserError from odoo.http import request, Response from odoo.tools import file_open, file_path, replace_exceptions -from odoo.tools.mimetypes import guess_mimetype from odoo.tools.image import image_guess_size_from_field_name - +from odoo.tools.mimetypes import guess_mimetype _logger = logging.getLogger(__name__) @@ -83,26 +84,60 @@ class Binary(http.Controller): res.headers['Content-Security-Policy'] = "default-src 'none'" return res - @http.route(['/web/assets/debug//', + @http.route([ '/web/assets//', '/web/assets///'], type='http', auth="public") def content_assets(self, filename=None, unique='%', extra='-', nocache=False): - url = f'/web/assets/{unique}/{extra}/{filename}' - domain = [ - ('public', '=', True), - ('url', '!=', False), - ('url', '=like', url), - ('res_model', '=', 'ir.ui.view'), - ('res_id', '=', 0), - ] - attachment = request.env['ir.attachment'].sudo().search(domain, limit=1) + debug_assets = unique == 'debug' + attachment = None + if unique != 'debug': + url = f'/web/assets/{unique}/{extra}/{filename}' + domain = [ + ('public', '=', True), + ('url', '!=', False), + ('url', '=like', url), + ('res_model', '=', 'ir.ui.view'), + ('res_id', '=', 0), + ('create_uid', '=', SUPERUSER_ID), + ] + attachment = request.env['ir.attachment'].sudo().search(domain, limit=1) + if not attachment: + # try to generate one + with replace_exceptions(ValueError, by=werkzeug.exceptions.BadRequest): + extra_parts = extra.split('+') + params = request.env['ir.asset']._parse_assets_extra(extra_parts) + if debug_assets: + bundle_name, asset_type = filename.rsplit('.', 1) + else: + bundle_name, min_, asset_type = filename.rsplit('.', 2) + if min_ != 'min': + _logger.error("'min' expected in extension in non debug mode") + raise request.not_found() + css = asset_type == 'css' + js = asset_type == 'js' + if not js and not css: + _logger.error('Only js and css assets bundle are supported for now') + raise request.not_found() + bundle = request.env['ir.qweb']._get_asset_bundle( + bundle_name, + css=css, + js=js, + debug_assets=debug_assets, + rtl='rtl' in extra_parts, + assets_params=params, + ) + # check if the version matches. If not, redirect to the last version + if not debug_assets and unique != '%' and unique != bundle.get_version(asset_type): + return request.redirect(bundle.get_link(asset_type)) + if css and bundle.stylesheets: + attachment = bundle.css() + elif js and bundle.javascripts: + attachment = bundle.js() if not attachment: raise request.not_found() - with replace_exceptions(UserError, by=request.not_found()): - stream = request.env['ir.binary']._get_stream_from(attachment, 'raw', filename) - + stream = request.env['ir.binary']._get_stream_from(attachment, 'raw', filename) send_file_kwargs = {'as_attachment': False} - if unique: + if unique and unique != 'debug': send_file_kwargs['immutable'] = True send_file_kwargs['max_age'] = http.STATIC_CACHE_LONG if nocache: diff --git a/addons/web/tests/test_assets.py b/addons/web/tests/test_assets.py index 250e12aaa15..9cba020a5dd 100644 --- a/addons/web/tests/test_assets.py +++ b/addons/web/tests/test_assets.py @@ -27,17 +27,21 @@ class TestAssetsGenerateTimeCommon(odoo.tests.TransactionCase): for key in get_manifest(module).get('assets', []) } - for bundle in bundles: + for bundle_name in bundles: with mute_logger('odoo.addons.base.models.assetsbundle'): for assets_type in 'css', 'js': try: start_t = time.time() css = assets_type == 'css' js = assets_type == 'js' - self.env['ir.qweb']._generate_asset_links(bundle, css=css, js=js) - yield (f'{bundle}.{assets_type}', time.time() - start_t) + bundle = self.env['ir.qweb']._get_asset_bundle(bundle_name, css=css, js=js) + if assets_type == 'css' and bundle.stylesheets: + bundle.css() + if assets_type == 'js' and bundle.javascripts: + bundle.js() + yield (f'{bundle_name}.{assets_type}', time.time() - start_t) except ValueError: - _logger.info('Error detected while generating bundle %r %s', bundle, assets_type) + _logger.info('Error detected while generating bundle %r %s', bundle_name, assets_type) @odoo.tests.tagged('post_install', '-at_install', 'assets_bundle') diff --git a/addons/website/controllers/form.py b/addons/website/controllers/form.py index e1e24ab40d0..a2d1a00212b 100644 --- a/addons/website/controllers/form.py +++ b/addons/website/controllers/form.py @@ -231,7 +231,6 @@ class WebsiteForm(http.Controller): values.update({'reply_to': values.get('email_from'), 'email_from': email_from}) record = request.env[model_name].with_user(SUPERUSER_ID).with_context( mail_create_nosubscribe=True, - commit_assetsbundle=False, ).create(values) if custom or meta: diff --git a/addons/website/models/ir_asset.py b/addons/website/models/ir_asset.py index 231b6922680..90d8eec8cfe 100644 --- a/addons/website/models/ir_asset.py +++ b/addons/website/models/ir_asset.py @@ -9,7 +9,6 @@ class IrAsset(models.Model): key = fields.Char(copy=False) # used to resolve multiple assets in a multi-website environment website_id = fields.Many2one('website', ondelete='cascade') - def _get_asset_params(self): params = super()._get_asset_params() params['website_id'] = self.env['website'].get_current_website(fallback=False).id @@ -22,6 +21,13 @@ class IrAsset(models.Model): website_id_path = website_id and ('website-%s+' % website_id) or '' return website_id_path + extra + def _parse_assets_extra(self, extra_parts): + params = super()._parse_assets_extra(extra_parts) + for extra_part in extra_parts: + if extra_part.startswith('w-'): + params['website_id'] = int(extra_part[2:]) + return params + def _get_related_assets(self, domain, website_id=None, **params): if website_id: domain += self.env['website'].website_domain(website_id) diff --git a/addons/website/tests/test_performance.py b/addons/website/tests/test_performance.py index bd4ffa1b3e8..676c9776497 100644 --- a/addons/website/tests/test_performance.py +++ b/addons/website/tests/test_performance.py @@ -278,8 +278,8 @@ class TestWebsitePerformancePost(UtilPerf): @mute_logger('odoo.http') def test_50_perf_sql_web_assets(self): # assets route /web/assets/.. - self.env['ir.qweb']._generate_asset_links('web.assets_frontend_lazy', css=False, js=True) - assets_url = self.env['ir.attachment'].search([('url', '=like', '/web/assets/%/web.assets_frontend_lazy%.js')], limit=1).url + assets_url = self.env['ir.qweb']._get_asset_bundle('web.assets_frontend_lazy', css=False, js=True).get_links()[0] + self.assertIn('web.assets_frontend_lazy.min.js', assets_url) select_tables_perf = { 'base_registry_signaling': 1, 'ir_attachment': 2, diff --git a/odoo/addons/base/models/assetsbundle.py b/odoo/addons/base/models/assetsbundle.py index 2c38d8d8fe9..74a52ead35b 100644 --- a/odoo/addons/base/models/assetsbundle.py +++ b/odoo/addons/base/models/assetsbundle.py @@ -116,11 +116,9 @@ class AssetsBundle(object): response = [] if self.has_css and self.stylesheets: - self.css(is_minified=not self.is_debug_assets) response.append(self.get_link('css')) if self.has_js and self.javascripts: - self.js(is_minified=not self.is_debug_assets) response.append(self.get_link('js')) return self.external_assets + response @@ -274,22 +272,11 @@ class AssetsBundle(object): 'raw': similar.raw, 'url': url, } - self.add_post_rollback() attachment = self.env['ir.attachment'].with_user(SUPERUSER_ID).create(values) attachment_id = attachment.id - if self.env.context.get('commit_assetsbundle') is True: - self.env.cr.commit() return self.env['ir.attachment'].sudo().browse(attachment_id) - def add_post_rollback(self): - """ - In some rare cases it is possible that an attachment is created during a transaction, added to the ormcache - but the transaction is rollbacked, leading to 404 when getting the attachments. - This postrollback hook will help fix this issue by clearing the cache if it isn't commited. - """ - self.env.cr.postrollback.add(self.env.registry._Registry__caches['assets'].clear) - def save_attachment(self, extension, content): """Record the given bundle in an ir.attachment and delete all other ir.attachments referring to this bundle (with the same name and extension). @@ -331,12 +318,8 @@ class AssetsBundle(object): 'raw': content.encode('utf8'), 'url': url, } - self.add_post_rollback() attachment = ira.with_user(SUPERUSER_ID).create(values) - if self.env.context.get('commit_assetsbundle') is True: - self.env.cr.commit() - self.clean_attachments(extension, url, extra) # For end-user assets (common and backend), send a message on the bus @@ -349,7 +332,8 @@ class AssetsBundle(object): return attachment - def js(self, is_minified=True): + def js(self): + is_minified = not self.is_debug_assets extension = 'min.js' if is_minified else 'js' js_attachment = self.get_attachments(extension) @@ -556,7 +540,8 @@ class AssetsBundle(object): # Returns the string by removing the tag. return etree.tostring(root, encoding='unicode')[6:-7] - def css(self, is_minified=True): + def css(self): + is_minified = not self.is_debug_assets extension = 'min.css' if is_minified else 'css' attachments = self.get_attachments(extension) if attachments: @@ -564,7 +549,7 @@ class AssetsBundle(object): css = self.preprocess_css() if self.css_errors: - error_message = '\n'.join(self.css_errors).replace('"', '\\"').replace('\n', '\A').replace('*', '\*') + error_message = '\n'.join(self.css_errors).replace('"', r'\\"').replace('\n', r'\A').replace('*', r'\*') previous_attachment = self.get_attachments(extension, ignore_version=True) previous_css = previous_attachment.raw.decode() if previous_attachment else '' css_error_message_header = '\n\n/* ## CSS error message ##*/' diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py index 258b0ada3fe..a9016156545 100644 --- a/odoo/addons/base/models/ir_actions_report.py +++ b/odoo/addons/base/models/ir_actions_report.py @@ -724,17 +724,6 @@ class IrActionsReport(models.Model): # https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2083 additional_context = {'debug': False} - # As the assets are generated during the same transaction as the rendering of the - # templates calling them, there is a scenario where the assets are unreachable: when - # you make a request to read the assets while the transaction creating them is not done. - # Indeed, when you make an asset request, the controller has to read the `ir.attachment` - # table. - # This scenario happens when you want to print a PDF report for the first time, as the - # assets are not in cache and must be generated. To workaround this issue, we manually - # commit the writes in the `ir.attachment` table. It is done thanks to a key in the context. - if not config['test_enable'] and 'commit_assetsbundle' not in self.env.context: - additional_context['commit_assetsbundle'] = True - html = self.with_context(**additional_context)._render_qweb_html(report_ref, res_ids_wo_stream, data=data)[0] bodies, html_ids, header, footer, specific_paperformat_args = self.with_context(**additional_context)._prepare_html(html, report_model=report_sudo.model) diff --git a/odoo/addons/base/models/ir_asset.py b/odoo/addons/base/models/ir_asset.py index bc363e859b7..5daa171a9c8 100644 --- a/odoo/addons/base/models/ir_asset.py +++ b/odoo/addons/base/models/ir_asset.py @@ -105,6 +105,10 @@ class IrAsset(models.Model): """ return extra + + def _parse_assets_extra(self, extra_parts): + return {} + @tools.conditional( 'xml' not in tools.config['dev_mode'], tools.ormcache('bundle', 'tuple(sorted(assets_params.items()))', cache='assets'), diff --git a/odoo/addons/base/models/ir_qweb.py b/odoo/addons/base/models/ir_qweb.py index 04dbe8fc17e..651770d8da3 100644 --- a/odoo/addons/base/models/ir_qweb.py +++ b/odoo/addons/base/models/ir_qweb.py @@ -2625,11 +2625,11 @@ class IrQWeb(models.AbstractModel): links = [] start = time.time() for bundle in sorted(js_bundles): - links += self._generate_asset_links(bundle, css=False, js=True) + links += self._get_asset_bundle(bundle, css=False, js=True).js() _logger.info('JS Assets bundles generated in %s seconds', time.time()-start) start = time.time() for bundle in sorted(css_bundles): - links += self._generate_asset_links(bundle, css=True, js=False) + links += self._get_asset_bundle(bundle, css=True, js=False).css() _logger.info('CSS Assets bundles generated in %s seconds', time.time()-start) return links @@ -2650,10 +2650,8 @@ class IrQWeb(models.AbstractModel): js_bundles.add(asset) if css: css_bundles.add(asset) - return (js_bundles, css_bundles) - def render(template_name, values, load, **options): """ Rendering of a qweb template without database and outside the registry. (Widget, field, or asset rendering is not implemented.) diff --git a/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py b/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py index 66aae287584..72b4256856c 100644 --- a/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py +++ b/odoo/addons/test_assetsbundle/tests/test_assetsbundle.py @@ -123,25 +123,6 @@ class FileTouchable(AddonManifestPatched): self.touches[filepath] = touch_time or time.time() return patch('os.path.getmtime', lambda filename: self.touches.get(filename) or GETMTINE(filename)) -@tagged('-at_install', 'post_install') -class Test404(HttpCase): - def get_assets_node_cache(self): - return [e for e in self.env.registry._Registry__caches['assets'].d if e[0] == 'ir.qweb' and '_generate_' in str(e[1])] #_generate_asset_nodes_cache - - def test_rollback(self): - """ - In some rare case, attachments can be generatted, added to the cache but the transaction is rollbacked leading to 404 - this actually tests the add_post_rollback behaviour - """ - self.env['ir.attachment'].search([('url', '=like', '/web/assets/%web.assets_frontend%')]).unlink() - self.env.registry.clear_cache() - self.url_open('/some_404_routes') - self.assertFalse(self.get_assets_node_cache(), 'orm_cache should be emptied by rollback') - self.assertFalse(self.env['ir.attachment'].search([('url', '=like', '/web/assets/%web.assets_frontend%%')]), "attachments should have been rollbacked") - self.url_open('/') - self.assertTrue(self.env['ir.attachment'].search([('url', '=like', '/web/assets/%web.assets_frontend%%')]), "attachments should have been generated as expected") - self.assertTrue(self.get_assets_node_cache(), 'orm_cache should remain populated') - self.env.registry.clear_cache() class TestJavascriptAssetsBundle(FileTouchable): @classmethod @@ -175,7 +156,7 @@ class TestJavascriptAssetsBundle(FileTouchable): """ Checks that a bundle creates an ir.attachment record when its `js` method is called for the first time and this ir.attachment is different depending on `is_minified` param. """ - self.bundle = self._get_asset(self.jsbundle_name) + self.bundle = self._get_asset(self.jsbundle_name, debug_assets=False) # there shouldn't be any minified attachment associated to this bundle self.assertEqual(len(self._any_ira_for_bundle('min.js')), 0, @@ -199,7 +180,8 @@ class TestJavascriptAssetsBundle(FileTouchable): "there shouldn't be any non-minified attachment associated to this bundle") # trigger the first generation and, thus, the first save in database for the non-minified version. - self.bundle.js(is_minified=False) + self.bundle_debug = self._get_asset(self.jsbundle_name, debug_assets=True) + self.bundle_debug.js() # there should be one non-minified attachment associated to this bundle self.assertEqual(len(self._any_ira_for_bundle('js')), 1, @@ -211,7 +193,7 @@ class TestJavascriptAssetsBundle(FileTouchable): """ Checks that the bundle's cache is working, i.e. that the bundle creates only one ir.attachment record when rendered multiple times. """ - bundle0 = self._get_asset(self.jsbundle_name) + bundle0 = self._get_asset(self.jsbundle_name, debug_assets=False) bundle0.js() self.assertEqual(len(self._any_ira_for_bundle('min.js')), 1, @@ -221,7 +203,7 @@ class TestJavascriptAssetsBundle(FileTouchable): ira0 = self._any_ira_for_bundle('min.js') date0 = ira0.create_date - bundle1 = self._get_asset(self.jsbundle_name) + bundle1 = self._get_asset(self.jsbundle_name, debug_assets=False) bundle1.js() self.assertEqual(len(self._any_ira_for_bundle('min.js')), 1, @@ -257,7 +239,7 @@ class TestJavascriptAssetsBundle(FileTouchable): "the version must should because the bundle has changed.") # check if the previous attachment is correctly cleaned - self.assertEqual(len(self._any_ira_for_bundle('min.js')), 1, + self.assertEqual(len(self._any_ira_for_bundle('js')), 1, "there should be one minified attachment associated to this bundle") def test_04_content_invalidation(self): @@ -298,6 +280,7 @@ class TestJavascriptAssetsBundle(FileTouchable): """ debug_bundle = self._get_asset(self.jsbundle_name) content = debug_bundle.get_links() + debug_bundle.js() # there should be a minified file self.assertIn('test_assetsbundle.bundle1.min.js', content[0]) @@ -315,6 +298,7 @@ class TestJavascriptAssetsBundle(FileTouchable): """ debug_bundle = self._get_asset(self.jsbundle_name, debug_assets=True) content = debug_bundle.get_links() + debug_bundle.js() # there should be a minified file self.assertIn('test_assetsbundle.bundle1.js', content[0], "there should be one non-minified assets created in debug assets mode") @@ -390,11 +374,12 @@ class TestJavascriptAssetsBundle(FileTouchable): """ Check that a bundle in debug mode outputs non-minified assets. """ debug_bundle = self._get_asset(self.cssbundle_name, debug_assets=True) - content = debug_bundle.get_links() + links = debug_bundle.get_links() # there should be a minified file - self.assertEqual(content[0], '/web/assets/debug/ltr/test_assetsbundle.bundle2.css') + self.assertEqual(links[0], '/web/assets/debug/ltr/test_assetsbundle.bundle2.css') # there should be one css asset created in debug mode + debug_bundle.css() self.assertEqual(len(self._any_ira_for_bundle('css')), 1, 'there should be one css asset created in debug mode') @@ -441,47 +426,43 @@ class TestJavascriptAssetsBundle(FileTouchable): one for ltr and one for rtl. """ # Assets access for en_US language - ltr_bundle0 = self._get_asset(self.cssbundle_name) + ltr_bundle0 = self._get_asset(self.cssbundle_name, debug_assets=False) ltr_bundle0.css() self.assertEqual(len(self._any_ira_for_bundle('min.css')), 1) ltr_version0 = ltr_bundle0.get_version('css') ltr_ira0 = self._any_ira_for_bundle('min.css') - ltr_date0 = ltr_ira0.create_date + self.assertTrue(ltr_ira0) - ltr_bundle1 = self._get_asset(self.cssbundle_name) + ltr_bundle1 = self._get_asset(self.cssbundle_name, debug_assets=False) ltr_bundle1.css() self.assertEqual(len(self._any_ira_for_bundle('min.css')), 1) ltr_version1 = ltr_bundle1.get_version('css') ltr_ira1 = self._any_ira_for_bundle('min.css') - ltr_date1 = ltr_ira1.create_date + self.assertTrue(ltr_ira1) self.assertEqual(ltr_version0, ltr_version1) - self.assertEqual(ltr_date0, ltr_date1) - rtl_bundle0 = self._get_asset(self.cssbundle_name, rtl=True) + rtl_bundle0 = self._get_asset(self.cssbundle_name, rtl=True, debug_assets=False) rtl_bundle0.css() self.assertEqual(len(self._any_ira_for_bundle('min.css', rtl=True)), 1) rtl_version0 = rtl_bundle0.get_version('css') - rtl_ira0 = self._any_ira_for_bundle('min.css', rtl=True) - rtl_date0 = rtl_ira0.create_date + self._any_ira_for_bundle('min.css', rtl=True) - rtl_bundle1 = self._get_asset(self.cssbundle_name, rtl=True) + rtl_bundle1 = self._get_asset(self.cssbundle_name, rtl=True, debug_assets=False) rtl_bundle1.css() self.assertEqual(len(self._any_ira_for_bundle('min.css', rtl=True)), 1) rtl_version1 = rtl_bundle1.get_version('css') rtl_ira1 = self._any_ira_for_bundle('min.css', rtl=True) - rtl_date1 = rtl_ira1.create_date self.assertEqual(rtl_version0, rtl_version1) - self.assertEqual(rtl_date0, rtl_date1) # Checks rtl and ltr bundles are different self.assertNotEqual(ltr_ira1.id, rtl_ira1.id) @@ -514,7 +495,7 @@ class TestJavascriptAssetsBundle(FileTouchable): ltr_bundle1.css() ltr_last_modified1 = ltr_bundle1.get_checksum('css') ltr_version1 = ltr_bundle1.get_version('css') - ltr_ira1 = self._any_ira_for_bundle('min.css') + ltr_ira1 = self._any_ira_for_bundle('css') self.assertNotEqual(ltr_last_modified0, ltr_last_modified1) self.assertNotEqual(ltr_version0, ltr_version1) @@ -523,7 +504,7 @@ class TestJavascriptAssetsBundle(FileTouchable): rtl_bundle1.css() rtl_last_modified1 = rtl_bundle1.get_checksum('css') rtl_version1 = rtl_bundle1.get_version('css') - rtl_ira1 = self._any_ira_for_bundle('min.css', rtl=True) + rtl_ira1 = self._any_ira_for_bundle('css', rtl=True) self.assertNotEqual(rtl_last_modified0, rtl_last_modified1) self.assertNotEqual(rtl_version0, rtl_version1) @@ -532,7 +513,7 @@ class TestJavascriptAssetsBundle(FileTouchable): # check if the previous attachment is correctly cleaned css_bundles = self.env['ir.attachment'].search([ - ('url', '=like', f'/web/assets/%/{self.cssbundle_name}%.min.css'), + ('url', '=like', f'/web/assets/%/{self.cssbundle_name}%.css'), ]) self.assertEqual(len(css_bundles), 2) @@ -599,6 +580,7 @@ class TestJavascriptAssetsBundle(FileTouchable): self.assertEqual(f'/web/assets/debug/rtl/{self.cssbundle_name}.css', content[0], "there should be an css assets bundle in /debug/rtl if user's lang direction is rtl and debug=assets") + debug_bundle.css() # there should be an css assets bundle created in /rtl if user's lang direction is rtl and debug=assets css_bundle = self.env['ir.attachment'].search([ ('url', '=like', f'/web/assets/%/rtl/{self.cssbundle_name}.css'), @@ -608,51 +590,42 @@ class TestJavascriptAssetsBundle(FileTouchable): def test_20_external_lib_assets(self): html = self.env['ir.ui.view']._render_template('test_assetsbundle.template2') - attachments = self.env['ir.attachment'].search([('url', '=like', '/web/assets/%/test_assetsbundle.bundle4.%')]) - self.assertEqual(len(attachments), 2) - format_data = { - "js": attachments[0].url, - "css": attachments[1].url, - } - self.assertEqual(str(html.strip()), (""" + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + links = bundle.get_links() + self.assertEqual(len(links), 6) + + self.assertEqual(str(html.strip()), (f""" - + - + -""" % format_data)) +""")) def test_21_external_lib_assets_debug_mode(self): html = self.env['ir.ui.view']._render_template('test_assetsbundle.template2', {"debug": "assets"}) - attachments = self.env['ir.attachment'].search([('url', '=like', '%/test_assetsbundle.bundle4.js')]) - self.assertEqual(len(attachments), 1) - - format_data = { - "css": '/web/assets/debug/ltr/test_assetsbundle.bundle4.css', - "js": '/web/assets/debug/-/test_assetsbundle.bundle4.js', - } self.assertEqual(str(html.strip()), (""" - + - + -""" % format_data)) +""")) @tagged('-at_install', 'post_install') @@ -743,13 +716,13 @@ class TestAssetsBundleWithIRAMock(FileTouchable): self.patch(IrAttachment, 'create', create) self.patch(AssetsBundle, '_unlink_attachments', unlink) - def _get_asset(self): + def _get_asset(self, debug_assets=True): with patch.object(type(self.env['ir.asset']), '_get_installed_addons_list', Mock(return_value=self.installed_modules)): - return self.env['ir.qweb']._get_asset_bundle(self.stylebundle_name, debug_assets=True) + return self.env['ir.qweb']._get_asset_bundle(self.stylebundle_name, debug_assets=debug_assets) - def _bundle(self, asset, should_create, should_unlink, reason=''): + def _bundle(self, bundle, should_create, should_unlink, reason=''): self.counter.clear() - asset.get_links() + bundle.css() if should_create: self.assertEqual(self.counter['create'], 2, f'An attachment should have been created {reason}') else: @@ -824,9 +797,8 @@ class TestAssetsManifest(AddonManifestPatched): self.assertEqual(tested, reference) def test_01_globmanifest(self): - view = self.make_asset_view('test_assetsbundle.manifest1') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest1.min.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest1') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -846,9 +818,8 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_02_globmanifest_no_duplicates(self): - view = self.make_asset_view('test_assetsbundle.manifest2') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest2.min.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest2') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -868,9 +839,8 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_03_globmanifest_file_before(self): - view = self.make_asset_view('test_assetsbundle.manifest3') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest3.min.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest3') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -890,14 +860,13 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_04_globmanifest_with_irasset(self): - view = self.make_asset_view('test_assetsbundle.manifest4') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.manifest4', 'path': 'test_assetsbundle/static/src/js/test_jsfile1.js', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4.min.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -911,14 +880,14 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_05_only_irasset(self): - view = self.make_asset_view('test_assetsbundle.irasset1') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.irasset1', 'path': 'test_assetsbundle/static/src/js/test_jsfile1.js', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset1.min.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset1') + attach = bundle.js() + content = attach.raw.decode() self.assertStringEqual( content, @@ -928,8 +897,7 @@ class TestAssetsManifest(AddonManifestPatched): ''' ) - def test_06_replace(self): - view = self.make_asset_view('test_assetsbundle.manifest1') + def test_06_1_replace(self): self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.manifest1', @@ -937,13 +905,12 @@ class TestAssetsManifest(AddonManifestPatched): 'target': 'test_assetsbundle/static/src/js/test_jsfile1.js', 'path': 'http://external.link/external.js', }) - rendered = self.env['ir.qweb']._render(view.id) - html_tree = lxml.etree.fromstring(rendered) - scripts = html_tree.findall('script') + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest1') + scripts = [link for link in bundle.get_links() if link.endswith('js')] self.assertEqual(len(scripts), 2) - self.assertEqual(scripts[0].get('src'), 'http://external.link/external.js') - - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest1')], order='create_date DESC', limit=1) + self.assertEqual(scripts[0], 'http://external.link/external.js') + attach = bundle.js() + self.assertEqual(scripts[1], attach.url) content = attach.raw.decode() self.assertStringEqual( content, @@ -960,7 +927,6 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_06_2_replace(self): - view = self.make_asset_view('test_assetsbundle.manifest4') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.manifest4', @@ -968,7 +934,8 @@ class TestAssetsManifest(AddonManifestPatched): 'path': 'test_assetsbundle/static/src/js/test_jsfile1.js', 'target': 'test_assetsbundle/static/src/js/test_jsfile3.js', }) - self.env['ir.qweb']._render(view.id) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) content = attach.raw.decode() self.assertStringEqual( @@ -980,7 +947,6 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_06_3_replace_globs(self): - view = self.make_asset_view('test_assetsbundle.manifest4') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'directive': 'prepend', @@ -997,8 +963,8 @@ class TestAssetsManifest(AddonManifestPatched): }) # asset is now: js_file1 ; js_file2 ; js_file3 # because js_file is replaced by 1 and 2 - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1015,15 +981,14 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_07_remove(self): - view = self.make_asset_view('test_assetsbundle.manifest5') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.manifest5', 'directive': 'remove', 'path': 'test_assetsbundle/static/src/js/test_jsfile2.js', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest5')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest5') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1046,7 +1011,6 @@ class TestAssetsManifest(AddonManifestPatched): 'path': '/test_assetsbundle/static/src/js/test_jsfile1.js', }) - view = self.make_asset_view('test_assetsbundle.remove_error') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.remove_error', @@ -1054,34 +1018,33 @@ class TestAssetsManifest(AddonManifestPatched): 'path': 'test_assetsbundle/static/src/js/test_doesntexist.js', }) with self.assertRaises(Exception) as cm: - self.env['ir.qweb']._render(view.id) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.remove_error') + bundle.js() self.assertTrue( "['test_assetsbundle/static/src/js/test_doesntexist.js'] not found" in str(cm.exception) ) def test_09_remove_wholeglob(self): - view = self.make_asset_view('test_assetsbundle.manifest2') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'bundle': 'test_assetsbundle.manifest2', 'directive': 'remove', 'path': 'test_assetsbundle/static/src/*/**', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest2.js')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest2') # indeed everything in the bundle matches the glob, so there is no attachment - self.assertFalse(attach) + self.assertFalse(bundle.javascripts) + self.assertFalse(bundle.get_links()) def test_10_prepend(self): - view = self.make_asset_view('test_assetsbundle.manifest4') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'directive': 'prepend', 'bundle': 'test_assetsbundle.manifest4', 'path': 'test_assetsbundle/static/src/js/test_jsfile1.js', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1095,15 +1058,14 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_11_include(self): - view = self.make_asset_view('test_assetsbundle.irasset_include1') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'directive': 'include', 'bundle': 'test_assetsbundle.irasset_include1', 'path': 'test_assetsbundle.manifest6', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset_include1')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset_include1') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1114,9 +1076,8 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_12_include2(self): - view = self.make_asset_view('test_assetsbundle.manifest6') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest6')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest6') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1127,7 +1088,6 @@ class TestAssetsManifest(AddonManifestPatched): ) def test_13_include_circular(self): - view = self.make_asset_view('test_assetsbundle.irasset_include1') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'directive': 'include', @@ -1141,17 +1101,15 @@ class TestAssetsManifest(AddonManifestPatched): 'path': 'test_assetsbundle.irasset_include1', }) - with self.assertRaises(QWebException) as cm: - self.env['ir.qweb']._render(view.id) - error = str(cm.exception.__cause__) + with self.assertRaises(Exception) as cm: + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset_include1') + bundle.js() + error = str(cm.exception) self.assertTrue(error) self.assertFalse(isinstance(error, RecursionError)) - self.assertTrue( - 'Circular assets bundle declaration:' in error - ) + self.assertIn('Circular assets bundle declaration:', error) def test_13_2_include_recursive_sibling(self): - view = self.make_asset_view('test_assetsbundle.irasset_include1') self.env['ir.asset'].create({ 'name': 'test_jsfile4', 'directive': 'include', @@ -1181,8 +1139,8 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irasset_include3', 'path': 'test_assetsbundle/static/src/js/test_jsfile1.js', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset_include1')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset_include1') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1204,9 +1162,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_other.mockmanifest1') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_other.mockmanifest1')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_other.mockmanifest1') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1228,9 +1185,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1255,9 +1211,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1282,9 +1237,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1307,9 +1261,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1331,13 +1284,11 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.manifest4') - rendered = self.env['ir.qweb']._render(view.id) - html_tree = lxml.etree.fromstring(rendered) - scripts = html_tree.findall('script') + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + scripts = [link for link in bundle.get_links() if link.endswith('js')] self.assertEqual(len(scripts), 2) - self.assertEqual(scripts[0].get('src'), 'http://external.link/external.js') - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + self.assertEqual(scripts[0], 'http://external.link/external.js') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1380,9 +1331,6 @@ class TestAssetsManifest(AddonManifestPatched): self.assertEqual(stylesheets[0].get('href'), 'http://external.css/externalstyle.css') self.assertEqual(stylesheets[0].get('media'), 'print') - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset2')], order='create_date DESC', limit=1) - self.assertEqual(len(attach), 1) - def test_20_css_base(self): self.env['ir.asset'].create({ 'name': '1', @@ -1394,20 +1342,10 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irasset2', 'path': 'test_assetsbundle/static/src/scss/test_file1.scss', }) - view = self.make_asset_view('test_assetsbundle.irasset2', { - 't-js': 'false', - 't-css': 'true', - }) - - rendered = self.env['ir.qweb']._render(view.id) - html_tree = lxml.etree.fromstring(rendered) - stylesheets = html_tree.findall('link') + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset2') + stylesheets = [link for link in bundle.get_links() if link.endswith('css')] self.assertEqual(len(stylesheets), 2) - self.assertEqual(stylesheets[0].get('href'), 'http://external.css/externalstyle.css') - for css in stylesheets: - self.assertFalse(css.get('media')) - - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset2')], order='create_date DESC', limit=1) + attach = bundle.css() content = attach.raw.decode() self.assertStringEqual( content, @@ -1430,9 +1368,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1460,9 +1397,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1494,9 +1430,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1524,9 +1459,8 @@ class TestAssetsManifest(AddonManifestPatched): ] } } - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1553,9 +1487,8 @@ class TestAssetsManifest(AddonManifestPatched): 'target': '/test_assetsbundle/static/src/js/test_jsfile3.js', 'directive': 'before', }) - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1582,9 +1515,8 @@ class TestAssetsManifest(AddonManifestPatched): 'target': '/test_assetsbundle/static/src/js/test_jsfile2.js', 'directive': 'after', }) - view = self.make_asset_view('test_assetsbundle.bundle4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1622,15 +1554,9 @@ class TestAssetsManifest(AddonManifestPatched): 't-js': 'true', 't-css': 'true', }) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.bundle4')], order='create_date DESC', limit=2) - attach_css = None - attach_js = None - for a in attach: - if '.css' in a.url: - attach_css = a - elif '.js' in a.url: - attach_js = a + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.bundle4') + attach_css = bundle.css() + attach_js = bundle.js() js_content = attach_js.raw.decode() self.assertStringEqual( @@ -1678,9 +1604,9 @@ class TestAssetsManifest(AddonManifestPatched): 'target': '/test_assetsbundle/static/src/js/doesnt_exist.js', 'directive': 'after', }) - view = self.make_asset_view('test_assetsbundle.wrong_path') with self.assertRaises(Exception) as cm: - self.env['ir.qweb']._render(view.id) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.wrong_path') + bundle.js() self.assertTrue( "test_assetsbundle/static/src/js/doesnt_exist.js not found" in str(cm.exception) ) @@ -1693,9 +1619,8 @@ class TestAssetsManifest(AddonManifestPatched): 'target': '/test_assetsbundle/static/src/js/test_jsfile3.js', 'directive': 'after', }) - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1722,9 +1647,8 @@ class TestAssetsManifest(AddonManifestPatched): 'target': '/test_assetsbundle/static/src/js/test_jsfile3.js', 'directive': 'before', }) - view = self.make_asset_view('test_assetsbundle.manifest4') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.manifest4')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.manifest4') + attach = bundle.js() content = attach.raw.decode() self.assertStringEqual( content, @@ -1755,9 +1679,8 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irassetsec', 'path': '/test_assetsbundle/%s' % path_to_dummy, }) - view = self.make_asset_view('test_assetsbundle.irassetsec') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irassetsec')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irassetsec') + attach = bundle.js() self.assertIn(b"Could not get content for /test_assetsbundle/../../tests/dummy.js", attach.exists().raw) @mute_logger('odoo.addons.base.models.ir_asset') @@ -1804,10 +1727,9 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irassetsec', 'path': '/notinstalled_module/somejsfile.js', }) - view = self.make_asset_view('test_assetsbundle.irassetsec') - with self.assertRaises(QWebException) as cm: - self.env['ir.qweb']._render(view.id) - + with self.assertRaises(Exception) as cm: + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irassetsec') + bundle.js() self.assertTrue('Unallowed to fetch files from addon notinstalled_module' in str(cm.exception)) def test_33bis_notinstalled_not_in_manifests(self): @@ -1827,10 +1749,9 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irassetsec', 'path': '/test_assetsbundle/__manifest__.py', }) - view = self.make_asset_view('test_assetsbundle.irassetsec') - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irassetsec')], order='create_date DESC', limit=1) - self.assertFalse(attach.exists()) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irassetsec') + links = bundle.get_links() + self.assertFalse(links) @mute_logger('odoo.addons.base.models.ir_asset') def test_35(self): @@ -1881,9 +1802,8 @@ class TestAssetsManifest(AddonManifestPatched): 'bundle': 'test_assetsbundle.irasset_custom_attach', 'path': 'test_assetsbundle/my_style_attach.scss', }) - view = self.make_asset_view('test_assetsbundle.irasset_custom_attach', {'t-css': True}) - self.env['ir.qweb']._render(view.id) - attach = self.env['ir.attachment'].search([('name', 'ilike', 'test_assetsbundle.irasset_custom_attach')], order='create_date DESC', limit=1) + bundle = self.env['ir.qweb']._get_asset_bundle('test_assetsbundle.irasset_custom_attach') + attach = bundle.css() content = attach.raw.decode() # The scss should be compiled self.assertStringEqual(