From b980a0abca1f47b3d69f0d1fd260121eb904ef08 Mon Sep 17 00:00:00 2001
From: David Szotten <davidszotten@gmail.com>
Date: Fri, 20 Dec 2019 16:03:09 +0000
Subject: [PATCH] fix context reporting for relative_files

fix reporting of contexts when `relative_files = True`

fixes #900
---
 coverage/html.py       |  2 +-
 coverage/jsonreport.py |  5 ++-
 tests/test_html.py     | 17 +++++++++
 tests/test_json.py     | 81 +++++++++++++++++++++++-------------------
 4 files changed, 65 insertions(+), 40 deletions(-)

diff --git a/coverage/html.py b/coverage/html.py
index 4aa018e3f..596e11435 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -95,7 +95,7 @@ def data_for_file(self, fr, analysis):
             arcs_executed = analysis.arcs_executed()
 
         if self.config.show_contexts:
-            contexts_by_lineno = analysis.data.contexts_by_lineno(fr.filename)
+            contexts_by_lineno = analysis.data.contexts_by_lineno(analysis.filename)
 
         lines = []
 
diff --git a/coverage/jsonreport.py b/coverage/jsonreport.py
index e44cbf089..0c3f313d9 100644
--- a/coverage/jsonreport.py
+++ b/coverage/jsonreport.py
@@ -43,7 +43,6 @@ def report(self, morfs, outfile=None):
         for file_reporter, analysis in get_analysis_to_report(self.coverage, morfs):
             measured_files[file_reporter.relative_filename()] = self.report_one_file(
                 coverage_data,
-                file_reporter,
                 analysis
             )
 
@@ -71,7 +70,7 @@ def report(self, morfs, outfile=None):
 
         return self.total.n_statements and self.total.pc_covered
 
-    def report_one_file(self, coverage_data, file_reporter, analysis):
+    def report_one_file(self, coverage_data, analysis):
         """Extract the relevant report data for a single file"""
         nums = analysis.numbers
         self.total += nums
@@ -90,7 +89,7 @@ def report_one_file(self, coverage_data, file_reporter, analysis):
         }
         if self.config.json_show_contexts:
             reported_file['contexts'] = analysis.data.contexts_by_lineno(
-                file_reporter.filename
+                analysis.filename,
             )
         if coverage_data.has_arcs():
             reported_file['summary'].update({
diff --git a/tests/test_html.py b/tests/test_html.py
index 6c4c706c0..b543fa08e 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -1127,3 +1127,20 @@ def test_no_contexts_warns_no_contexts(self):
         self.start_import_stop(cov, "two_tests")
         with self.assert_warnings(cov, ["No contexts were measured"]):
             cov.html_report()
+
+    def test_dynamic_contexts_relative_files(self):
+        self.make_file("two_tests.py", self.SOURCE)
+        self.make_file("config", "[run]\nrelative_files = True")
+        cov = coverage.Coverage(source=["."], config_file="config")
+        cov.set_option("run:dynamic_context", "test_function")
+        cov.set_option("html:show_contexts", True)
+        mod = self.start_import_stop(cov, "two_tests")
+        d = self.html_data_from_cov(cov, mod)
+        context_labels = [self.EMPTY, 'two_tests.test_one', 'two_tests.test_two']
+        expected_lines = [self.OUTER_LINES, self.TEST_ONE_LINES, self.TEST_TWO_LINES]
+        for label, expected in zip(context_labels, expected_lines):
+            actual = [
+                ld.number for ld in d.lines
+                if label == ld.contexts_label or label in (ld.contexts or ())
+            ]
+            assert sorted(expected) == sorted(actual)
diff --git a/tests/test_json.py b/tests/test_json.py
index 1ae5764ee..64de92929 100644
--- a/tests/test_json.py
+++ b/tests/test_json.py
@@ -103,42 +103,51 @@ def test_simple_line_coverage(self):
         self._assert_expected_json_report(cov, expected_result)
 
     def test_context(self):
-        cov = coverage.Coverage(context="cool_test")
-        cov.config.json_show_contexts = True
-        expected_result = {
-            'meta': {
-                "version": coverage.__version__,
-                "branch_coverage": False,
-                "show_contexts": True,
-            },
-            'files': {
-                'a.py': {
-                    'executed_lines': [1, 2],
-                    'missing_lines': [3],
-                    'excluded_lines': [],
-                    "contexts": {
-                        "1": [
-                            "cool_test"
-                        ],
-                        "2": [
-                            "cool_test"
-                        ]
-                    },
-                    'summary': {
-                        'excluded_lines': 0,
-                        'missing_lines': 1,
-                        'covered_lines': 2,
-                        'num_statements': 3,
-                        'percent_covered': 66.66666666666667
+        for relative_files in [False, True]:
+            config_file = os.path.join(self.temp_dir, "config")
+            with open(config_file, 'w') as handle:
+                handle.write(
+                    "[run]\nrelative_files = {}".format(relative_files)
+                )
+            cov = coverage.Coverage(
+                context="cool_test",
+                config_file=config_file
+            )
+            cov.config.json_show_contexts = True
+            expected_result = {
+                'meta': {
+                    "version": coverage.__version__,
+                    "branch_coverage": False,
+                    "show_contexts": True,
+                },
+                'files': {
+                    'a.py': {
+                        'executed_lines': [1, 2],
+                        'missing_lines': [3],
+                        'excluded_lines': [],
+                        "contexts": {
+                            "1": [
+                                "cool_test"
+                            ],
+                            "2": [
+                                "cool_test"
+                            ]
+                        },
+                        'summary': {
+                            'excluded_lines': 0,
+                            'missing_lines': 1,
+                            'covered_lines': 2,
+                            'num_statements': 3,
+                            'percent_covered': 66.66666666666667
+                        }
                     }
+                },
+                'totals': {
+                    'excluded_lines': 0,
+                    'missing_lines': 1,
+                    'covered_lines': 2,
+                    'num_statements': 3,
+                    'percent_covered': 66.66666666666667
                 }
-            },
-            'totals': {
-                'excluded_lines': 0,
-                'missing_lines': 1,
-                'covered_lines': 2,
-                'num_statements': 3,
-                'percent_covered': 66.66666666666667
             }
-        }
-        self._assert_expected_json_report(cov, expected_result)
+            self._assert_expected_json_report(cov, expected_result)