From 128c02e8e310e5d84b5f145edceaf879c0492f5a Mon Sep 17 00:00:00 2001 From: trisdoan Date: Mon, 14 Oct 2024 11:10:05 +0700 Subject: [PATCH] [MIG] base_report_to_printer: Migration to 18.0 --- base_report_to_printer/README.rst | 7 + base_report_to_printer/__manifest__.py | 2 +- base_report_to_printer/data/printing_data.xml | 16 +- .../models/ir_actions_report.py | 2 +- .../models/printing_action.py | 4 +- .../models/printing_printer.py | 2 +- .../models/printing_report_xml_action.py | 2 +- base_report_to_printer/models/res_users.py | 14 +- base_report_to_printer/readme/CONTRIBUTORS.md | 1 + base_report_to_printer/readme/CREDITS.md | 1 + .../static/description/index.html | 11 +- .../static/src/js/qweb_action_manager.esm.js | 5 +- .../tests/test_ir_actions_report.py | 207 ++++++++++-------- .../tests/test_printing_job.py | 25 ++- .../tests/test_printing_printer.py | 84 ++++--- .../tests/test_printing_printer_tray.py | 18 +- .../tests/test_printing_printer_wizard.py | 24 +- .../tests/test_printing_server.py | 65 +++--- base_report_to_printer/tests/test_report.py | 61 ++++-- base_report_to_printer/views/printing_job.xml | 4 +- .../views/printing_printer.xml | 6 +- .../views/printing_report.xml | 4 +- .../views/printing_server.xml | 6 +- .../wizards/print_attachment_report.xml | 4 +- .../wizards/printing_printer_update_wizard.py | 2 +- 25 files changed, 345 insertions(+), 232 deletions(-) create mode 100644 base_report_to_printer/readme/CREDITS.md diff --git a/base_report_to_printer/README.rst b/base_report_to_printer/README.rst index 944717e9b9b..825b54bf6e8 100644 --- a/base_report_to_printer/README.rst +++ b/base_report_to_printer/README.rst @@ -175,6 +175,13 @@ Contributors - Hughes Damry - Akim Juillerat - Jacques-Etienne Baudoux (BCIM) +- Tris Doan + +Other credits +------------- + +The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp. Maintainers ----------- diff --git a/base_report_to_printer/__manifest__.py b/base_report_to_printer/__manifest__.py index 8ba86006cec..e688e3c4e3d 100644 --- a/base_report_to_printer/__manifest__.py +++ b/base_report_to_printer/__manifest__.py @@ -7,7 +7,7 @@ { "name": "Report to printer", - "version": "17.0.1.0.1", + "version": "18.0.1.0.0", "category": "Generic Modules/Base", "author": "Agile Business Group & Domsense, Pegueroles SCP, NaN," " LasLabs, Camptocamp, Odoo Community Association (OCA)," diff --git a/base_report_to_printer/data/printing_data.xml b/base_report_to_printer/data/printing_data.xml index c008aa5214a..f9304756ec0 100644 --- a/base_report_to_printer/data/printing_data.xml +++ b/base_report_to_printer/data/printing_data.xml @@ -9,25 +9,19 @@ Send to Client client - - - property_printing_action_id - - - Update Printers Jobs 1 minutes - -1 - code model.action_update_jobs() + diff --git a/base_report_to_printer/models/ir_actions_report.py b/base_report_to_printer/models/ir_actions_report.py index 6c35126d8fd..0844184d5af 100644 --- a/base_report_to_printer/models/ir_actions_report.py +++ b/base_report_to_printer/models/ir_actions_report.py @@ -157,7 +157,7 @@ def print_document(self, record_ids, data=None): _("This report type (%s) is not supported by direct printing!") % str(self.report_type) ) - method_name = "_render_qweb_%s" % (report_type) + method_name = f"_render_qweb_{report_type}" document, doc_format = getattr( self.with_context(must_skip_send_to_printer=True), method_name )(self.report_name, record_ids, data=data) diff --git a/base_report_to_printer/models/printing_action.py b/base_report_to_printer/models/printing_action.py index aa180802a22..b6e7a63deb4 100644 --- a/base_report_to_printer/models/printing_action.py +++ b/base_report_to_printer/models/printing_action.py @@ -5,14 +5,14 @@ # Copyright (C) 2013-2014 Camptocamp () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import fields, models class PrintingAction(models.Model): _name = "printing.action" _description = "Print Job Action" - @api.model + @property def _available_action_types(self): return [ ("server", "Send to Printer"), diff --git a/base_report_to_printer/models/printing_printer.py b/base_report_to_printer/models/printing_printer.py index a7e25872499..ac312866d1c 100644 --- a/base_report_to_printer/models/printing_printer.py +++ b/base_report_to_printer/models/printing_printer.py @@ -178,7 +178,7 @@ def print_options(self, report=None, **print_opts): options = {} for option, value in print_opts.items(): try: - options.update(getattr(self, "_set_option_%s" % option)(report, value)) + options.update(getattr(self, f"_set_option_{option}")(report, value)) except AttributeError: options[option] = str(value) return options diff --git a/base_report_to_printer/models/printing_report_xml_action.py b/base_report_to_printer/models/printing_report_xml_action.py index cac2a0b39b7..06d7a965ffe 100644 --- a/base_report_to_printer/models/printing_report_xml_action.py +++ b/base_report_to_printer/models/printing_report_xml_action.py @@ -22,7 +22,7 @@ class PrintingReportXmlAction(models.Model): comodel_name="res.users", string="User", required=True, ondelete="cascade" ) action = fields.Selection( - selection=lambda s: s.env["printing.action"]._available_action_types(), + selection=lambda s: s.env["printing.action"]._available_action_types, required=True, ) printer_id = fields.Many2one(comodel_name="printing.printer", string="Printer") diff --git a/base_report_to_printer/models/res_users.py b/base_report_to_printer/models/res_users.py index cb088ed0d1f..2ba1cd89276 100644 --- a/base_report_to_printer/models/res_users.py +++ b/base_report_to_printer/models/res_users.py @@ -11,19 +11,27 @@ class ResUsers(models.Model): _inherit = "res.users" - @api.model + @property def _user_available_action_types(self): return [ (code, string) - for code, string in self.env["printing.action"]._available_action_types() + for code, string in self.env["printing.action"]._available_action_types if code != "user_default" ] - printing_action = fields.Selection(selection=_user_available_action_types) + printing_action = fields.Selection( + selection=lambda self: self._user_available_action_types + ) printing_printer_id = fields.Many2one( comodel_name="printing.printer", string="Default Printer" ) + @api.constrains("printing_action") + def _check_printing_action(self): + for rec in self: + if rec.printing_action == "user_default": + raise ValueError("user_default should not be available") + @property def SELF_READABLE_FIELDS(self): return super().SELF_READABLE_FIELDS + ["printing_action", "printing_printer_id"] diff --git a/base_report_to_printer/readme/CONTRIBUTORS.md b/base_report_to_printer/readme/CONTRIBUTORS.md index 2e89c72169c..84cef65de94 100644 --- a/base_report_to_printer/readme/CONTRIBUTORS.md +++ b/base_report_to_printer/readme/CONTRIBUTORS.md @@ -15,3 +15,4 @@ - Hughes Damry \<\> - Akim Juillerat \<\> - Jacques-Etienne Baudoux (BCIM) \<\> +- Tris Doan \<\> diff --git a/base_report_to_printer/readme/CREDITS.md b/base_report_to_printer/readme/CREDITS.md new file mode 100644 index 00000000000..83b3ec91f7d --- /dev/null +++ b/base_report_to_printer/readme/CREDITS.md @@ -0,0 +1 @@ +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. diff --git a/base_report_to_printer/static/description/index.html b/base_report_to_printer/static/description/index.html index 928c4b8fc8c..bde5f1b8dae 100644 --- a/base_report_to_printer/static/description/index.html +++ b/base_report_to_printer/static/description/index.html @@ -409,7 +409,8 @@

Report to printer

  • Credits
  • @@ -528,10 +529,16 @@

    Contributors

  • Hughes Damry <hughes.damry@acsone.eu>
  • Akim Juillerat <akim.juillerat@camptocamp.com>
  • Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
  • +
  • Tris Doan <tridm@trobz.com>
  • +
    +

    Other credits

    +

    The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp.

    +
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association diff --git a/base_report_to_printer/static/src/js/qweb_action_manager.esm.js b/base_report_to_printer/static/src/js/qweb_action_manager.esm.js index 2d110dc74d7..3d8677a3464 100644 --- a/base_report_to_printer/static/src/js/qweb_action_manager.esm.js +++ b/base_report_to_printer/static/src/js/qweb_action_manager.esm.js @@ -1,5 +1,4 @@ -/** @odoo-module */ -import {Markup} from "web.utils"; +import {markup} from "@odoo/owl"; import {_t} from "@web/core/l10n/translation"; import {registry} from "@web/core/registry"; @@ -45,7 +44,7 @@ async function cupsReportActionHandler(action, options, env) { issue_on: env._t("Issue on"), }; const notificationRemove = env.services.notification.add( - Markup( + markup( `

    ${terms.the_report} ${action.name} ${terms.couldnt_be_printed}

    ` ), { diff --git a/base_report_to_printer/tests/test_ir_actions_report.py b/base_report_to_printer/tests/test_ir_actions_report.py index 4e1e77d9e1b..84aa816c596 100644 --- a/base_report_to_printer/tests/test_ir_actions_report.py +++ b/base_report_to_printer/tests/test_ir_actions_report.py @@ -2,6 +2,7 @@ # Copyright 2016 SYLEAM # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from unittest import mock from odoo.tests.common import TransactionCase @@ -57,14 +58,14 @@ def new_tray(self, vals=None, defaults=None): def test_print_action_for_report_name_gets_report(self): """It should get report by name""" - with mock.patch("%s._get_report_from_name" % model) as mk: + with mock.patch(f"{model}._get_report_from_name") as mk: expect = "test" self.Model.print_action_for_report_name(expect) mk.assert_called_once_with(expect) def test_print_action_for_report_name_returns_if_no_report(self): """It should return empty dict when no matching report""" - with mock.patch("%s._get_report_from_name" % model) as mk: + with mock.patch(f"{model}._get_report_from_name") as mk: expect = "test" mk.return_value = False res = self.Model.print_action_for_report_name(expect) @@ -72,7 +73,7 @@ def test_print_action_for_report_name_returns_if_no_report(self): def test_print_action_for_report_name_returns_if_report(self): """It should return correct serializable result for behaviour""" - with mock.patch("%s._get_report_from_name" % model) as mk: + with mock.patch(f"{model}._get_report_from_name") as mk: res = self.Model.print_action_for_report_name("test") behaviour = mk().behaviour() expect = { @@ -102,14 +103,19 @@ def test_behaviour_user_values(self): report = self.Model.search([], limit=1) self.env.user.printing_action = "client" self.env.user.printing_printer_id = self.new_printer() - self.assertEqual( - report.behaviour(), - { - "action": "client", - "printer": self.env.user.printing_printer_id, - "tray": False, - }, - ) + with ( + self.assertLogs(level=logging.WARNING) as logs, + ): + self.assertEqual( + report.behaviour(), + { + "action": "client", + "printer": self.env.user.printing_printer_id, + "tray": False, + }, + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_behaviour_report_values(self): """It should return the action and printer from report""" @@ -117,14 +123,19 @@ def test_behaviour_report_values(self): self.env.user.printing_action = "client" report.property_printing_action_id = self.new_action() report.printing_printer_id = self.new_printer() - self.assertEqual( - report.behaviour(), - { - "action": report.property_printing_action_id.action_type, - "printer": report.printing_printer_id, - "tray": False, - }, - ) + with ( + self.assertLogs(level=logging.WARNING) as logs, + ): + self.assertEqual( + report.behaviour(), + { + "action": report.property_printing_action_id.action_type, + "printer": report.printing_printer_id, + "tray": False, + }, + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_behaviour_user_action(self): """It should return the action and printer from user action""" @@ -188,14 +199,19 @@ def test_behaviour_printing_action_with_printer(self): printing_action = self.new_printing_action() printing_action.user_id = self.env.user printing_action.printer_id = self.new_printer() - self.assertEqual( - report.behaviour(), - { - "action": printing_action.action, - "printer": printing_action.printer_id, - "tray": False, - }, - ) + with ( + self.assertLogs(level=logging.WARNING) as logs, + ): + self.assertEqual( + report.behaviour(), + { + "action": printing_action.action, + "printer": printing_action.printer_id, + "tray": False, + }, + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_behaviour_printing_action_user_defaults(self): """It should return the action and printer from user with printing @@ -215,57 +231,71 @@ def test_print_tray_behaviour(self): """ It should return the correct tray """ - report = self.Model.search([], limit=1) - action = self.env["printing.report.xml.action"].create( - {"user_id": self.env.user.id, "report_id": report.id, "action": "server"} - ) - printer = self.new_printer() - tray_vals = {"name": "Tray", "system_name": "Tray", "printer_id": printer.id} - user_tray = self.new_tray({"system_name": "User tray"}, tray_vals) - report_tray = self.new_tray({"system_name": "Report tray"}, tray_vals) - action_tray = self.new_tray({"system_name": "Action tray"}, tray_vals) - - # No report passed - self.env.user.printer_tray_id = False - options = printer.print_options() - self.assertFalse("InputSlot" in options) - - # No tray defined - self.env.user.printer_tray_id = False - report.printer_tray_id = False - action.printer_tray_id = False - options = report.behaviour() - self.assertTrue("tray" in options) - - # Only user tray is defined - self.env.user.printer_tray_id = user_tray - report.printer_tray_id = False - action.printer_tray_id = False - self.assertEqual("User tray", report.behaviour()["tray"]) - - # Only report tray is defined - self.env.user.printer_tray_id = False - report.printer_tray_id = report_tray - action.printer_tray_id = False - self.assertEqual("Report tray", report.behaviour()["tray"]) - - # Only action tray is defined - self.env.user.printer_tray_id = False - report.printer_tray_id = False - action.printer_tray_id = action_tray - self.assertEqual("Action tray", report.behaviour()["tray"]) - - # User and report tray defined - self.env.user.printer_tray_id = user_tray - report.printer_tray_id = report_tray - action.printer_tray_id = False - self.assertEqual("Report tray", report.behaviour()["tray"]) - - # All trays are defined - self.env.user.printer_tray_id = user_tray - report.printer_tray_id = report_tray - action.printer_tray_id = action_tray - self.assertEqual("Action tray", report.behaviour()["tray"]) + with ( + self.assertLogs(level=logging.WARNING) as logs, + ): + report = self.Model.search([], limit=1) + action = self.env["printing.report.xml.action"].create( + { + "user_id": self.env.user.id, + "report_id": report.id, + "action": "server", + } + ) + printer = self.new_printer() + tray_vals = { + "name": "Tray", + "system_name": "Tray", + "printer_id": printer.id, + } + user_tray = self.new_tray({"system_name": "User tray"}, tray_vals) + report_tray = self.new_tray({"system_name": "Report tray"}, tray_vals) + action_tray = self.new_tray({"system_name": "Action tray"}, tray_vals) + + # No report passed + self.env.user.printer_tray_id = False + options = printer.print_options() + self.assertFalse("InputSlot" in options) + + # No tray defined + self.env.user.printer_tray_id = False + report.printer_tray_id = False + action.printer_tray_id = False + options = report.behaviour() + self.assertTrue("tray" in options) + + # Only user tray is defined + self.env.user.printer_tray_id = user_tray + report.printer_tray_id = False + action.printer_tray_id = False + self.assertEqual("User tray", report.behaviour()["tray"]) + + # Only report tray is defined + self.env.user.printer_tray_id = False + report.printer_tray_id = report_tray + action.printer_tray_id = False + self.assertEqual("Report tray", report.behaviour()["tray"]) + + # Only action tray is defined + self.env.user.printer_tray_id = False + report.printer_tray_id = False + action.printer_tray_id = action_tray + self.assertEqual("Action tray", report.behaviour()["tray"]) + + # User and report tray defined + self.env.user.printer_tray_id = user_tray + report.printer_tray_id = report_tray + action.printer_tray_id = False + self.assertEqual("Report tray", report.behaviour()["tray"]) + + # All trays are defined + self.env.user.printer_tray_id = user_tray + report.printer_tray_id = report_tray + action.printer_tray_id = action_tray + self.assertEqual("Action tray", report.behaviour()["tray"]) + self.assertEqual(len(logs.records), 6) + for record in logs.records: + self.assertEqual(record.levelno, logging.WARNING) def test_onchange_printer_tray_id_empty(self): action = self.Model.new({"printer_tray_id": False}) @@ -305,11 +335,16 @@ def test_print_in_new_thread(self): printing_action.user_id = self.env.user printing_action.printer_id = self.new_printer() printing_action.printer_id.multi_thread = True - self.assertEqual( - report.behaviour(), - { - "action": printing_action.action, - "printer": printing_action.printer_id, - "tray": False, - }, - ) + with ( + self.assertLogs(level=logging.WARNING) as logs, + ): + self.assertEqual( + report.behaviour(), + { + "action": printing_action.action, + "printer": printing_action.printer_id, + "tray": False, + }, + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) diff --git a/base_report_to_printer/tests/test_printing_job.py b/base_report_to_printer/tests/test_printing_job.py index dd02a1011ba..35ba786dc79 100644 --- a/base_report_to_printer/tests/test_printing_job.py +++ b/base_report_to_printer/tests/test_printing_job.py @@ -1,6 +1,7 @@ # Copyright 2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from unittest import mock from odoo import fields @@ -42,17 +43,23 @@ def new_job(self, printer, vals=None): values["printer_id"] = printer.id return self.env["printing.job"].create(values) - @mock.patch("%s.cups" % model) - def test_cancel_job_error(self, cups): + def test_cancel_job_error(self): """It should catch any exception from CUPS and update status""" - cups.Connection.side_effect = Exception - printer = self.new_printer() - job = self.new_job(printer, {"job_id_cups": 2}) - job.action_cancel() - cups.Connection.side_effect = None - self.assertEqual(cups.Connection().cancelJob.call_count, 0) + with ( + mock.patch(f"{model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = Exception + printer = self.new_printer() + job = self.new_job(printer, {"job_id_cups": 2}) + job.action_cancel() + cups.Connection.side_effect = None + self.assertEqual(cups.Connection().cancelJob.call_count, 0) + + self.assertEqual(len(logs.records), 3) + self.assertEqual(logs.records[0].levelno, logging.WARNING) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_cancel_job(self, cups): """It should catch any exception from CUPS and update status""" printer = self.new_printer() diff --git a/base_report_to_printer/tests/test_printing_printer.py b/base_report_to_printer/tests/test_printing_printer.py index 8ea7d83c3a1..ddd3d7ee97c 100644 --- a/base_report_to_printer/tests/test_printing_printer.py +++ b/base_report_to_printer/tests/test_printing_printer.py @@ -1,6 +1,7 @@ # Copyright 2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging import tempfile from unittest import mock @@ -79,11 +80,11 @@ def test_print_options(self): ) self.assertTrue("InputSlot" in self.Model.print_options(report, tray="Test")) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_print_report(self, cups): """It should print a report through CUPS""" fd, file_name = tempfile.mkstemp() - with mock.patch("%s.mkstemp" % model) as mkstemp: + with mock.patch(f"{model}.mkstemp") as mkstemp: mkstemp.return_value = fd, file_name printer = self.new_record() printer.print_document(self.report, b"content to print", doc_format="pdf") @@ -91,37 +92,52 @@ def test_print_report(self, cups): printer.system_name, file_name, file_name, options={} ) - @mock.patch("%s.cups" % server_model) - def test_print_report_error(self, cups): + def test_print_report_error(self): """It should print a report through CUPS""" - cups.Connection.side_effect = Exception - fd, file_name = tempfile.mkstemp() - with mock.patch("%s.mkstemp" % model) as mkstemp: - mkstemp.return_value = fd, file_name - printer = self.new_record() - with self.assertRaises(UserError): - printer.print_document( - self.report, b"content to print", doc_format="pdf" - ) - - @mock.patch("%s.cups" % server_model) - def test_print_file(self, cups): + with ( + mock.patch(f"{model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = Exception + fd, file_name = tempfile.mkstemp() + with mock.patch(f"{model}.mkstemp") as mkstemp: + mkstemp.return_value = fd, file_name + printer = self.new_record() + with self.assertRaises(UserError): + printer.print_document( + self.report, b"content to print", doc_format="pdf" + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) + + def test_print_file(self): """It should print a file through CUPS""" - file_name = "file_name" - printer = self.new_record() - printer.print_file(file_name, "pdf") - cups.Connection().printFile.assert_called_once_with( - printer.system_name, file_name, file_name, options={} - ) + with ( + mock.patch(f"{server_model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + file_name = "file_name" + printer = self.new_record() + printer.print_file(file_name, "pdf") + cups.Connection().printFile.assert_called_once_with( + printer.system_name, file_name, file_name, options={} + ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) - @mock.patch("%s.cups" % server_model) - def test_print_file_error(self, cups): + def test_print_file_error(self): """It should print a file through CUPS""" - cups.Connection.side_effect = Exception - file_name = "file_name" - printer = self.new_record() - with self.assertRaises(UserError): - printer.print_file(file_name) + with ( + mock.patch(f"{server_model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = Exception + file_name = "file_name" + printer = self.new_record() + with self.assertRaises(UserError): + printer.print_file(file_name) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_set_default(self): """It should set a single record as default""" @@ -142,7 +158,7 @@ def test_unset_default(self): printer.unset_default() self.assertFalse(printer.default) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_cancel_all_jobs(self, cups): """It should cancel all jobs""" printer = self.new_record() @@ -151,7 +167,7 @@ def test_cancel_all_jobs(self, cups): name=printer.system_name, purge_jobs=False ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_cancel_and_purge_all_jobs(self, cups): """It should cancel all jobs""" printer = self.new_record() @@ -160,21 +176,21 @@ def test_cancel_and_purge_all_jobs(self, cups): name=printer.system_name, purge_jobs=True ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_enable_printer(self, cups): """It should enable the printer""" printer = self.new_record() printer.enable() cups.Connection().enablePrinter.assert_called_once_with(printer.system_name) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_disable_printer(self, cups): """It should disable the printer""" printer = self.new_record() printer.disable() cups.Connection().disablePrinter.assert_called_once_with(printer.system_name) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_print_test_page(self, cups): """It should print a test page""" printer = self.new_record() diff --git a/base_report_to_printer/tests/test_printing_printer_tray.py b/base_report_to_printer/tests/test_printing_printer_tray.py index c0168ff3776..687cedf4685 100644 --- a/base_report_to_printer/tests/test_printing_printer_tray.py +++ b/base_report_to_printer/tests/test_printing_printer_tray.py @@ -99,7 +99,7 @@ def mock_cups_ppd(self, cups, file_name=None, input_slots=None): } } - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_update_printers(self, cups): """ Check that the update_printers method calls _prepare_update_from_cups @@ -111,7 +111,7 @@ def test_update_printers(self, cups): self.ServerModel.update_printers() self.assertEqual(self.printer.name, "My custom name") - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups_no_ppd(self, cups): """ Check that the tray_ids field has no value when no PPD is available @@ -124,7 +124,7 @@ def test_prepare_update_from_cups_no_ppd(self, cups): vals = self.printer._prepare_update_from_cups(connection, cups_printer) self.assertFalse("tray_ids" in vals) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups_empty_ppd(self, cups): """ Check that the tray_ids field has no value when the PPD file has @@ -142,7 +142,7 @@ def test_prepare_update_from_cups_empty_ppd(self, cups): vals = self.printer._prepare_update_from_cups(connection, cups_printer) self.assertFalse("tray_ids" in vals) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") @mock.patch("os.unlink") def test_prepare_update_from_cups_unlink_error(self, os_unlink, cups): """ @@ -159,7 +159,7 @@ def test_prepare_update_from_cups_unlink_error(self, os_unlink, cups): with self.assertRaises(OSError): self.printer._prepare_update_from_cups(connection, cups_printer) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") @mock.patch("os.unlink") def test_prepare_update_from_cups_unlink_error_enoent(self, os_unlink, cups): """ @@ -181,7 +181,7 @@ def test_prepare_update_from_cups_unlink_error_enoent(self, os_unlink, cups): [(0, 0, {"name": "Auto (Default)", "system_name": "Auto"})], ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups(self, cups): """ Check the return value when adding a single tray @@ -197,7 +197,7 @@ def test_prepare_update_from_cups(self, cups): [(0, 0, {"name": "Auto (Default)", "system_name": "Auto"})], ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups_with_multiple_trays(self, cups): """ Check the return value when adding multiple trays at once @@ -216,7 +216,7 @@ def test_prepare_update_from_cups_with_multiple_trays(self, cups): ], ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups_already_known_trays(self, cups): """ Check that calling the method twice doesn't create the trays multiple @@ -236,7 +236,7 @@ def test_prepare_update_from_cups_already_known_trays(self, cups): [(0, 0, {"name": "Auto (Default)", "system_name": "Auto"})], ) - @mock.patch("%s.cups" % server_model) + @mock.patch(f"{server_model}.cups") def test_prepare_update_from_cups_unknown_trays(self, cups): """ Check that trays which are not in the PPD file are removed from Odoo diff --git a/base_report_to_printer/tests/test_printing_printer_wizard.py b/base_report_to_printer/tests/test_printing_printer_wizard.py index 11788c01e2e..f378d9b58dc 100644 --- a/base_report_to_printer/tests/test_printing_printer_wizard.py +++ b/base_report_to_printer/tests/test_printing_printer_wizard.py @@ -1,6 +1,7 @@ # Copyright 2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from unittest import mock from odoo.exceptions import UserError @@ -36,7 +37,7 @@ def _record_vals(self, sys_name="sys_name"): "uri": self.printer_vals["device-uri"], } - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_action_ok_inits_connection(self, cups): """It should initialize CUPS connection""" self.Model.action_ok() @@ -44,7 +45,7 @@ def test_action_ok_inits_connection(self, cups): host=self.server.address, port=self.server.port ) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_action_ok_gets_printers(self, cups): """It should get printers from CUPS""" cups.Connection().getPrinters.return_value = {"sys_name": self.printer_vals} @@ -52,14 +53,19 @@ def test_action_ok_gets_printers(self, cups): self.Model.action_ok() cups.Connection().getPrinters.assert_called_once_with() - @mock.patch("%s.cups" % model) - def test_action_ok_raises_warning_on_error(self, cups): + def test_action_ok_raises_warning_on_error(self): """It should raise Warning on any error""" - cups.Connection.side_effect = StopTest - with self.assertRaises(UserError): - self.Model.action_ok() + with ( + mock.patch(f"{model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = StopTest + with self.assertRaises(UserError): + self.Model.action_ok() + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_action_ok_creates_new_printer(self, cups): """It should create new printer w/ proper vals""" cups.Connection().getPrinters.return_value = {"sys_name": self.printer_vals} @@ -75,7 +81,7 @@ def test_action_ok_creates_new_printer(self, cups): self.assertEqual(val, rec_id[key]) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_action_ok_skips_existing_printer(self, cups): """It should not recreate existing printers""" cups.Connection().getPrinters.return_value = {"sys_name": self.printer_vals} diff --git a/base_report_to_printer/tests/test_printing_server.py b/base_report_to_printer/tests/test_printing_server.py index 9fb2151ffab..f9bafcd8805 100644 --- a/base_report_to_printer/tests/test_printing_server.py +++ b/base_report_to_printer/tests/test_printing_server.py @@ -1,6 +1,7 @@ # Copyright 2016 LasLabs Inc. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from unittest import mock from odoo import fields @@ -43,15 +44,20 @@ def new_job(self, printer, vals=None): values["printer_id"] = printer.id return self.env["printing.job"].create(values) - @mock.patch("%s.cups" % model) - def test_update_printers_error(self, cups): + def test_update_printers_error(self): """It should catch any exception from CUPS and update status""" - cups.Connection.side_effect = Exception - rec_id = self.new_printer() - self.Model.update_printers() - self.assertEqual("server-error", rec_id.status) + with ( + mock.patch(f"{model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = Exception + rec_id = self.new_printer() + self.Model.update_printers() + self.assertEqual("server-error", rec_id.status) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_printers_inits_cups(self, cups): """It should init CUPS connection""" self.new_printer() @@ -60,29 +66,29 @@ def test_update_printers_inits_cups(self, cups): host=self.server.address, port=self.server.port ) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_printers_gets_all_printers(self, cups): """It should get all printers from CUPS server""" self.new_printer() self.Model.update_printers() cups.Connection().getPrinters.assert_called_once_with() - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_printers_search(self, cups): """It should search all when no domain""" - with mock.patch("%s.search" % model_base) as search: + with mock.patch(f"{model_base}.search") as search: self.Model.update_printers() search.assert_called_once_with([]) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_printers_search_domain(self, cups): """It should use specific domain for search""" - with mock.patch("%s.search" % model_base) as search: + with mock.patch(f"{model_base}.search") as search: expect = [("id", ">", 0)] self.Model.update_printers(expect) search.assert_called_once_with(expect) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_printers_update_unavailable(self, cups): """It should update status when printer is unavailable""" rec_id = self.new_printer() @@ -90,7 +96,7 @@ def test_update_printers_update_unavailable(self, cups): self.Model.action_update_printers() self.assertEqual("unavailable", rec_id.status) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_archived_printers(self, cups): """It should update status even if printer is archived""" rec_id = self.new_printer() @@ -103,7 +109,7 @@ def test_update_archived_printers(self, cups): rec_id.status, ) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_jobs_cron(self, cups): """It should get all jobs from CUPS server""" self.new_printer() @@ -125,7 +131,7 @@ def test_update_jobs_cron(self, cups): ], ) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_jobs_button(self, cups): """It should get all jobs from CUPS server""" self.new_printer() @@ -147,17 +153,22 @@ def test_update_jobs_button(self, cups): ], ) - @mock.patch("%s.cups" % model) - def test_update_jobs_error(self, cups): + def test_update_jobs_error(self): """It should catch any exception from CUPS and update status""" - cups.Connection.side_effect = Exception - self.new_printer() - self.server.update_jobs() - cups.Connection.assert_called_with( - host=self.server.address, port=self.server.port - ) - - @mock.patch("%s.cups" % model) + with ( + mock.patch(f"{model}.cups") as cups, + self.assertLogs(level=logging.WARNING) as logs, + ): + cups.Connection.side_effect = Exception + self.new_printer() + self.server.update_jobs() + cups.Connection.assert_called_with( + host=self.server.address, port=self.server.port + ) + self.assertEqual(len(logs.records), 2) + self.assertEqual(logs.records[0].levelno, logging.WARNING) + + @mock.patch(f"{model}.cups") def test_update_jobs_uncompleted(self, cups): """ It should search which jobs have been completed since last update @@ -182,7 +193,7 @@ def test_update_jobs_uncompleted(self, cups): ], ) - @mock.patch("%s.cups" % model) + @mock.patch(f"{model}.cups") def test_update_jobs(self, cups): """ It should update all jobs, known or not diff --git a/base_report_to_printer/tests/test_report.py b/base_report_to_printer/tests/test_report.py index e821962d6ca..0b43c9d3e4c 100644 --- a/base_report_to_printer/tests/test_report.py +++ b/base_report_to_printer/tests/test_report.py @@ -2,6 +2,7 @@ # Copyright 2017 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import logging from unittest import mock from odoo import exceptions @@ -128,11 +129,14 @@ def test_render_qweb_pdf_not_printable(self): def test_render_qweb_pdf_printable(self): """It should print the report, only if it is printable""" - with mock.patch( - "odoo.addons.base_report_to_printer.models." - "printing_printer.PrintingPrinter." - "print_document" - ) as print_document: + with ( + mock.patch( + "odoo.addons.base_report_to_printer.models." + "printing_printer.PrintingPrinter." + "print_document" + ) as print_document, + self.assertLogs(level=logging.WARNING) as logs, + ): self.report.property_printing_action_id.action_type = "server" self.report.printing_printer_id = self.new_printer() document = self.report._render_qweb_pdf( @@ -145,14 +149,19 @@ def test_render_qweb_pdf_printable(self): doc_format="qweb-pdf", tray=False, ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_render_qweb_text_printable(self): """It should print the report, only if it is printable""" - with mock.patch( - "odoo.addons.base_report_to_printer.models." - "printing_printer.PrintingPrinter." - "print_document" - ) as print_document: + with ( + mock.patch( + "odoo.addons.base_report_to_printer.models." + "printing_printer.PrintingPrinter." + "print_document" + ) as print_document, + self.assertLogs(level=logging.WARNING) as logs, + ): self.report_text.property_printing_action_id.action_type = "server" self.report_text.printing_printer_id = self.new_printer() document = self.report_text._render_qweb_text( @@ -165,29 +174,41 @@ def test_render_qweb_text_printable(self): doc_format="qweb-text", tray=False, ) + self.assertEqual(len(logs.records), 1) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_print_document_not_printable(self): """It should print the report, regardless of the defined behaviour""" self.report.printing_printer_id = self.new_printer() - with mock.patch( - "odoo.addons.base_report_to_printer.models." - "printing_printer.PrintingPrinter." - "print_document" - ) as print_document: + with ( + mock.patch( + "odoo.addons.base_report_to_printer.models." + "printing_printer.PrintingPrinter." + "print_document" + ) as print_document, + self.assertLogs(level=logging.WARNING) as logs, + ): self.report.print_document(self.partners.ids) print_document.assert_called_once() + self.assertEqual(len(logs.records), 2) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_print_document_printable(self): """It should print the report, regardless of the defined behaviour""" self.report.property_printing_action_id.action_type = "server" self.report.printing_printer_id = self.new_printer() - with mock.patch( - "odoo.addons.base_report_to_printer.models." - "printing_printer.PrintingPrinter." - "print_document" - ) as print_document: + with ( + mock.patch( + "odoo.addons.base_report_to_printer.models." + "printing_printer.PrintingPrinter." + "print_document" + ) as print_document, + self.assertLogs(level=logging.WARNING) as logs, + ): self.report.print_document(self.partners.ids) print_document.assert_called_once() + self.assertEqual(len(logs.records), 2) + self.assertEqual(logs.records[0].levelno, logging.WARNING) def test_print_document_no_printer(self): """It should raise an error""" diff --git a/base_report_to_printer/views/printing_job.xml b/base_report_to_printer/views/printing_job.xml index 1fd513f5cc4..48647031b04 100644 --- a/base_report_to_printer/views/printing_job.xml +++ b/base_report_to_printer/views/printing_job.xml @@ -36,11 +36,11 @@ printing.job.tree (in base_report_to_printer) printing.job - + - + diff --git a/base_report_to_printer/views/printing_printer.xml b/base_report_to_printer/views/printing_printer.xml index 0c7f0f4741b..04e9eb1b66b 100644 --- a/base_report_to_printer/views/printing_printer.xml +++ b/base_report_to_printer/views/printing_printer.xml @@ -101,7 +101,7 @@ printing.printer.tree (in base_report_to_printer) printing.printer - - + @@ -135,7 +135,7 @@ Show Printers ir.actions.act_window printing.printer - tree,form + list,form printing.report.xml.action.tree (in base_report_to_printer) printing.report.xml.action - + - + diff --git a/base_report_to_printer/views/printing_server.xml b/base_report_to_printer/views/printing_server.xml index 259ec1ad176..b4ce03368c9 100644 --- a/base_report_to_printer/views/printing_server.xml +++ b/base_report_to_printer/views/printing_server.xml @@ -45,11 +45,11 @@ printing.server.tree (in base_report_to_printer) printing.server - + - + @@ -67,7 +67,7 @@ Servers ir.actions.act_window printing.server - tree,form + list,form - + - +