| import os |
| |
| from markdown_it import MarkdownIt |
| import pytest |
| |
| import mdformat |
| from mdformat._util import is_md_equal |
| from mdformat.renderer import MDRenderer |
| |
| UNFORMATTED_MARKDOWN = "\n\n# A header\n\n" |
| FORMATTED_MARKDOWN = "# A header\n" |
| |
| |
| def test_fmt_file(tmp_path): |
| file_path = tmp_path / "test_markdown.md" |
| |
| # Use string argument |
| file_path.write_text(UNFORMATTED_MARKDOWN) |
| mdformat.file(str(file_path)) |
| assert file_path.read_text() == FORMATTED_MARKDOWN |
| |
| # Use pathlib.Path argument |
| file_path.write_text(UNFORMATTED_MARKDOWN) |
| mdformat.file(file_path) |
| assert file_path.read_text() == FORMATTED_MARKDOWN |
| |
| |
| def test_fmt_file__invalid_filename(): |
| with pytest.raises(ValueError) as exc_info: |
| mdformat.file("this is not a valid filepath?`=|><@{[]\\/,.%ยค#'") |
| assert "not a file" in str(exc_info.value) |
| |
| |
| def test_fmt_file__symlink(tmp_path): |
| file_path = tmp_path / "test_markdown.md" |
| file_path.write_text(UNFORMATTED_MARKDOWN) |
| symlink_path = tmp_path / "symlink.md" |
| symlink_path.symlink_to(file_path) |
| |
| with pytest.raises(ValueError) as exc_info: |
| mdformat.file(symlink_path) |
| assert "It is a symlink" in str(exc_info.value) |
| |
| |
| def test_fmt_string(): |
| assert mdformat.text(UNFORMATTED_MARKDOWN) == FORMATTED_MARKDOWN |
| |
| |
| @pytest.mark.parametrize( |
| "input_", |
| [ |
| pytest.param("\x0b"), # vertical tab only |
| pytest.param("\t##"), # no trailing newline in codeblock |
| pytest.param("a\n\n\xa0\n\nb"), # lone NBSP between two paragraphs |
| pytest.param("\xa0\n\n# heading"), # lone NBSP followed by a heading |
| pytest.param( |
| "```\na\n```\n\u2003\n# A\n" |
| ), # em space surrounded by code and header |
| ], |
| ) |
| def test_output_is_equal(input_): |
| output = mdformat.text(input_) |
| assert is_md_equal(input_, output) |
| |
| |
| @pytest.mark.parametrize( |
| "input_", |
| [ |
| pytest.param("\x1c\n\na"), |
| pytest.param(">\x0b"), |
| pytest.param("<!K"), |
| ], |
| ) |
| def test_cases_found_by_fuzzer(input_): |
| output = mdformat.text(input_) |
| assert is_md_equal(input_, output) |
| |
| |
| def test_api_options(): |
| non_numbered = """\ |
| 0. a |
| 0. b |
| 0. c |
| """ |
| numbered = """\ |
| 0. a |
| 1. b |
| 2. c |
| """ |
| assert mdformat.text(non_numbered, options={"number": True}) == numbered |
| |
| |
| def test_eol__lf(tmp_path): |
| file_path = tmp_path / "test.md" |
| file_path.write_bytes(b"Oi\r\n") |
| mdformat.file(str(file_path)) |
| assert file_path.read_bytes() == b"Oi\n" |
| |
| |
| def test_eol__crlf(tmp_path): |
| file_path = tmp_path / "test.md" |
| file_path.write_bytes(b"Oi\n") |
| mdformat.file(str(file_path), options={"end_of_line": "crlf"}) |
| assert file_path.read_bytes() == b"Oi\r\n" |
| |
| |
| def test_eol__keep_lf(tmp_path): |
| file_path = tmp_path / "test.md" |
| file_path.write_bytes(b"Oi\n") |
| mdformat.file(str(file_path), options={"end_of_line": "keep"}) |
| assert file_path.read_bytes() == b"Oi\n" |
| |
| |
| def test_eol__keep_crlf(tmp_path): |
| file_path = tmp_path / "test.md" |
| file_path.write_bytes(b"Oi\r\n") |
| mdformat.file(str(file_path), options={"end_of_line": "keep"}) |
| assert file_path.read_bytes() == b"Oi\r\n" |
| |
| |
| def test_no_timestamp_modify(tmp_path): |
| file_path = tmp_path / "test.md" |
| |
| file_path.write_bytes(b"lol\n") |
| initial_access_time = 0 |
| initial_mod_time = 0 |
| os.utime(file_path, (initial_access_time, initial_mod_time)) |
| |
| # Assert that modification time does not change when no changes are applied |
| mdformat.file(file_path) |
| assert os.path.getmtime(file_path) == initial_mod_time |
| |
| |
| def test_mdrenderer_no_finalize(tmp_path): |
| mdit = MarkdownIt() |
| mdit.options["store_labels"] = True |
| env: dict = {} |
| tokens = mdit.parse( |
| "[gl ref]: https://gitlab.com\n\nHere's a link to [GitLab][gl ref]", env |
| ) |
| unfinalized = MDRenderer().render(tokens, {}, env, finalize=False) |
| finalized = MDRenderer().render(tokens, {}, env) |
| assert finalized == unfinalized + "\n\n[gl ref]: https://gitlab.com\n" |
| |
| |
| def test_import_typing(): |
| """Try to import mdformat.renderer.typing. |
| |
| The module consists of annotation types only, so mdformat never |
| imports it at runtime. This test ensures that it still runs. |
| """ |
| import mdformat.renderer.typing # noqa: F401 |