"""Tests for JSON style overlay (md2gost.styles.json / --styles).""" from __future__ import annotations import json from pathlib import Path import docx import pytest from docx.enum.text import WD_ALIGN_PARAGRAPH from md2gost.style_config import ( StyleConfigError, get_preset, resolve_style_config, style_config_from_dict, ) from md2gost.styles import apply_document_styles, apply_style_config from md2gost import page_geometry as pg TEMPLATE = Path("md2gost/Template.docx") def test_preset_unchanged_without_overlay(): cfg = resolve_style_config("mirea") assert cfg.page.left_mm == 30 assert cfg.page.right_mm == 10 h1 = cfg.styles["Heading 1"] assert h1.alignment == "left" assert h1.size_pt == 18 assert h1.all_caps is True def test_overlay_changes_margins_and_h1(tmp_path: Path): overlay = { "page": {"left_mm": 20, "right_mm": 20}, "styles": { "Heading 1": { "alignment": "center", "size_pt": 14, "left_indent_cm": 0, } }, } path = tmp_path / "custom.json" path.write_text(json.dumps(overlay), encoding="utf-8") cfg = resolve_style_config("mirea", styles_path=path) assert cfg.page.left_mm == 20 assert cfg.page.right_mm == 20 # Unspecified margins stay from preset assert cfg.page.top_mm == 20 assert cfg.page.bottom_mm == 20 assert cfg.styles["Heading 1"].alignment == "center" assert cfg.styles["Heading 1"].size_pt == 14 # Unspecified heading fields stay from preset assert cfg.styles["Heading 1"].all_caps is True assert cfg.styles["Heading 1"].bold is True def test_unknown_style_name_raises(): with pytest.raises(StyleConfigError, match="Unknown style name"): style_config_from_dict({"styles": {"Heading 9": {"size_pt": 12}}}) def test_unknown_page_key_raises(): with pytest.raises(StyleConfigError, match="Unknown page key"): style_config_from_dict({"page": {"gutter_mm": 5}}) def test_unknown_style_field_raises(): with pytest.raises(StyleConfigError, match="Unknown style field"): style_config_from_dict({"styles": {"Normal": {"color": "red"}}}) def test_cli_overlay_wins_over_near_md(tmp_path: Path): near = tmp_path / "md2gost.styles.json" near.write_text( json.dumps({"page": {"left_mm": 25}, "styles": {"Heading 1": {"size_pt": 16}}}), encoding="utf-8", ) cli = tmp_path / "cli.json" cli.write_text( json.dumps({"page": {"left_mm": 15}, "styles": {"Heading 1": {"alignment": "center"}}}), encoding="utf-8", ) cfg = resolve_style_config("mirea", md_dir=tmp_path, styles_path=cli) assert cfg.page.left_mm == 15 assert cfg.styles["Heading 1"].size_pt == 16 # from near-md, not overridden assert cfg.styles["Heading 1"].alignment == "center" # from CLI def test_apply_overlay_to_document(tmp_path: Path): overlay = style_config_from_dict({ "page": {"left_mm": 20, "right_mm": 20, "top_mm": 20, "bottom_mm": 20}, "styles": {"Heading 1": {"alignment": "center", "size_pt": 14}}, }) doc = docx.Document(str(TEMPLATE)) apply_document_styles(doc, "mirea", overlay=overlay) h1 = doc.styles["Heading 1"] assert h1.paragraph_format.alignment == WD_ALIGN_PARAGRAPH.CENTER assert abs(h1.font.size.pt - 14) < 0.01 section = doc.sections[0] assert abs(section.left_margin.mm - 20) < 0.1 assert abs(pg.MARGIN_LEFT.mm - 20) < 0.1 def test_pis_preset_h1_centered(): doc = docx.Document(str(TEMPLATE)) apply_style_config(doc, get_preset("pis_custom")) h1 = doc.styles["Heading 1"] assert h1.paragraph_format.alignment == WD_ALIGN_PARAGRAPH.CENTER assert h1.font.all_caps is True