"""Regression tests for the bug where translated Excel chart references kept pointing at the original (now-renamed) sheet name, causing the chart to render as zero/empty series after translation. This is a real bug: see e.g. test_excel.xlsx where the chart references 'Sales 2024'!$D$2:$D$61 but the sheet is renamed to "Chiffre d'affaires par produit" — the chart then shows 0 for every data point. """ import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from lxml import etree from translators.excel_translator import ExcelTranslator NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart" def _build_chart_xml(series_refs): """Helper: build a chart XML with the given strings.""" sers = "\n".join( f"{ref}" f"{ref}" f"{ref}" for ref in series_refs ) return f""" {sers} """ def test_quoted_sheet_name_with_apostrophe_in_new_name(): r = ExcelTranslator._rewrite_sheet_ref( "'Sales 2024'!$D$2:$D$61", {"Sales 2024": "Chiffre d'affaires par produit"}, ) assert r == "'Chiffre d''affaires par produit'!$D$2:$D$61", f"got: {r!r}" def test_unquoted_sheet_name_simple(): r = ExcelTranslator._rewrite_sheet_ref( "Sheet1!$A$1", {"Sheet1": "Feuille1"}, ) assert r == "Feuille1!$A$1", f"got: {r!r}" def test_new_name_with_space_gets_quoted(): r = ExcelTranslator._rewrite_sheet_ref( "Sheet1!$A$1", {"Sheet1": "Ma Feuille"}, ) assert r == "'Ma Feuille'!$A$1", f"got: {r!r}" def test_name_not_in_mapping_unchanged(): r = ExcelTranslator._rewrite_sheet_ref( "Other!$A$1", {"Sheet1": "Feuille1"}, ) assert r == "Other!$A$1", f"got: {r!r}" def test_empty_mapping_is_noop(): r = ExcelTranslator._rewrite_sheet_ref("Sheet1!$A$1", {}) assert r == "Sheet1!$A$1", f"got: {r!r}" def test_no_bang_is_noop(): r = ExcelTranslator._rewrite_sheet_ref("just_a_label", {"x": "y"}) assert r == "just_a_label", f"got: {r!r}" def test_real_chart_xml_all_refs_rewritten(): chart_xml = etree.fromstring(_build_chart_xml(["Sheet1!$B$1"])) n = ExcelTranslator._rewrite_sheet_refs_in_chart(chart_xml, {"Sheet1": "Ma Feuille"}) assert n == 3, f"expected 3 rewrites, got {n}" refs = [f.text for f in chart_xml.iter(f"{{{NS_C}}}f")] assert refs == [ "'Ma Feuille'!$B$1", "'Ma Feuille'!$B$1", "'Ma Feuille'!$B$1", ], f"got: {refs}" def test_real_chart_xml_apostrophe_escaped_in_new_name(): chart_xml = etree.fromstring(_build_chart_xml(["Sheet1!$B$1"])) n = ExcelTranslator._rewrite_sheet_refs_in_chart( chart_xml, {"Sheet1": "Chiffre d'affaires"} ) assert n == 3 refs = [f.text for f in chart_xml.iter(f"{{{NS_C}}}f")] assert all(r == "'Chiffre d''affaires'!$B$1" for r in refs), f"got: {refs}" def test_partial_mapping_leaves_other_refs_intact(): """When only one sheet is renamed, refs to other sheets must stay.""" chart_xml = etree.fromstring( _build_chart_xml(["Sheet1!$A$1", "Sheet2!$B$1"]) ) n = ExcelTranslator._rewrite_sheet_refs_in_chart( chart_xml, {"Sheet1": "Feuille1"} ) # 3 refs to Sheet1 (one series) are rewritten; 3 refs to Sheet2 stay. assert n == 3, f"expected 3 rewrites, got {n}" refs = [f.text for f in chart_xml.iter(f"{{{NS_C}}}f")] assert "Feuille1!$A$1" in refs assert "Sheet2!$B$1" in refs def test_multiple_series_renamed(): """When several sheets are renamed, refs to any of them get updated.""" chart_xml = etree.fromstring( _build_chart_xml(["Sheet1!$A$1", "Sheet2!$B$1", "Sheet3!$C$1"]) ) n = ExcelTranslator._rewrite_sheet_refs_in_chart( chart_xml, {"Sheet1": "F1", "Sheet2": "F2", "Sheet3": "F3"}, ) assert n == 9, f"expected 9 rewrites (3 series x 3 refs each), got {n}" if __name__ == "__main__": test_quoted_sheet_name_with_apostrophe_in_new_name() test_unquoted_sheet_name_simple() test_new_name_with_space_gets_quoted() test_name_not_in_mapping_unchanged() test_empty_mapping_is_noop() test_no_bang_is_noop() test_real_chart_xml_all_refs_rewritten() test_real_chart_xml_apostrophe_escaped_in_new_name() test_partial_mapping_leaves_other_refs_intact() test_multiple_series_renamed() print("All chart sheet-ref rewrite tests passed.")