From 97cda935afecbef5716c8fbeebe4ce93eb148288 Mon Sep 17 00:00:00 2001 From: "Schinckel, Matthew" Date: Fri, 24 May 2024 12:17:58 +0930 Subject: [PATCH] Collect coverage data when rendering widgets. Resolves #94 --- django_coverage_plugin/plugin.py | 14 ++++++++++++-- tests/plugin_test.py | 7 +++++-- tests/test_source.py | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/django_coverage_plugin/plugin.py b/django_coverage_plugin/plugin.py index 158ee9a..f282e6b 100644 --- a/django_coverage_plugin/plugin.py +++ b/django_coverage_plugin/plugin.py @@ -104,10 +104,20 @@ def check_debug(): # change over versions. def filename_for_frame(frame): try: - return frame.f_locals["self"].origin.name - except (KeyError, AttributeError): + self = frame.f_locals["self"] + except KeyError: return None + try: + return self.origin.name + except AttributeError: + pass + + try: + return self[0].origin.name + except (IndexError, AttributeError): + pass + def position_for_node(node): try: diff --git a/tests/plugin_test.py b/tests/plugin_test.py index cc90be8..13d7adb 100644 --- a/tests/plugin_test.py +++ b/tests/plugin_test.py @@ -87,13 +87,14 @@ def make_template(self, text, name=None): return os.path.abspath(self.make_file(template_path, text)) def run_django_coverage( - self, name=None, text=None, context=None, options=None, using=None + self, name=None, text=None, context=None, options=None, using=None, widget=None ): """Run a template under coverage. The data context is `context` if provided, else {}. If `text` is provided, make a string template to run. Otherwise, - if `name` is provided, run that template, otherwise use the last + if `name` is provided, run that template, otherwise, + if `widget` is provided, render the widget, otherwise use the last template made by `make_template`. If `options` is provided, they are kwargs for the Coverage @@ -118,6 +119,8 @@ def run_django_coverage( elif text is not None: tem = Template(text) use_real_context = True + elif widget is not None: + tem = widget else: tem = get_template(name or self.template_file) diff --git a/tests/test_source.py b/tests/test_source.py index 6313504..2d972ef 100644 --- a/tests/test_source.py +++ b/tests/test_source.py @@ -177,3 +177,28 @@ def test_custom_html_report_isnt_measured(self): # Run coverage again with an HTML report on disk. text = self.run_django_coverage(name="main.html") self.assert_measured_files("main.html") + + def test_widget_template_coverage_captured(self): + from django import forms + + class Widget(forms.Widget): + template_name = 'widget.html' + + def render(self, context): + """ + We need to replace the normal Widget.render (which accepts a name, value and attrs) + with something that just accepts a context, like a normal Template.render would. + We also need to replace the `renderer`, as the hooks for the testing only work + based on the TemplatesSetting. + """ + return self._render( + self.template_name, + context, + renderer=forms.renderers.TemplatesSetting(), + ) + + self.make_template(name='widget.html', text="Hello") + text = self.run_django_coverage(widget=Widget()) + self.assertEqual(text, 'Hello') + + self.assert_measured_files('widget.html')