def test_override_template_md_options() -> None: """Test init GenerationConfiguration with default values""" # add new new_property key config = GenerationConfiguration(template_md_options={ "new_property": True, }) assert config.template_md_options == { "new_property": True, "badge_as_image": False, "show_heading_numbers": True, "show_array_restrictions": True, } # override badge_as_image key config = GenerationConfiguration( deprecated_from_description=True, template_name="md", template_md_options={"badge_as_image": "test"}) assert config.template_md_options["badge_as_image"] == "test" # override badge_as_image key config = GenerationConfiguration( deprecated_from_description=True, template_name="md", template_md_options={"badge_as_image": True}) assert config.template_md_options["badge_as_image"] == True
def schema(output_file, output_format, data_type, url, database): print_messages = _log.isEnabledFor(logging.ERROR) if output_file: stream = output_file else: stream = sys.stdout schema_data = edb_schemas[data_type] if output_format == "json": json.dump(schema_data, stream, indent=2) else: if output_format == "markdown": tmpl = "md" elif output_format == "html": tmpl = "flat" elif output_format == "html-js": tmpl = "js" config = GenerationConfiguration(template_name=tmpl) with tempfile.TemporaryDirectory() as tmpdir_name: schema_path = pathlib.Path(tmpdir_name) / "schema.json" with schema_path.open("w+", encoding="utf-8") as schema_file: json.dump(schema_data, schema_file) schema_file.seek(0) schema_gen.generate_from_file_object(schema_file, stream, config=config)
def test_with_yaml_examples() -> None: soup = generate_case("with_examples", GenerationConfiguration(examples_as_yaml=True)) examples_label = soup.find_all("div", class_=["badge", "badge-secondary"]) examples_label_text = [ex.text for ex in examples_label] assert examples_label_text == [ "Examples:", "Example:", "Example:", "Example:" ] examples_content = soup.find_all("div", class_="examples") examples_content_text = [ ex.findChildren()[0].text for ex in examples_content ] assert examples_content_text == [ "Guido\n...\n", "BDFL\n...\n", "Van Rossum\n...\n", "64\n...\n", "birthplace: Haarlem, Netherlands\nfavorite_emoji: 🐍\n" "motto: Beautiful is better than ugly.\\nExplicit is better than implicit.\\nSimple is\n" " better than complex.\\nComplex is better than complicated.\\nFlat is better than nested.\\nSparse\n" " is better than dense.\\nReadability counts.\\nSpecial cases aren't special enough\n" " to break the rules.\\nAlthough practicality beats purity.\\nErrors should never pass\n" " silently.\\nUnless explicitly silenced.\\nIn the face of ambiguity, refuse the temptation\n" " to guess.\\nThere should be one-- and preferably only one --obvious way to do it.\\nAlthough\n" " that way may not be obvious at first unless you're Dutch.\\nNow is better than never.\\nAlthough\n" " never is often better than *right* now.\\nIf the implementation is hard to explain,\n" " it's a bad idea.\\nIf the implementation is easy to explain, it may be a good idea.\\nNamespaces\n" " are one honking great idea -- let's do more of those!\n", ]
def test_deprecated_not_in_description() -> None: """Test that the deprecated badge does not get added if the option to get deprecated from description is disabled""" soup = generate_case( "deprecated", GenerationConfiguration(deprecated_from_description=False)) tests.html_schema_doc_asserts.assert_deprecated(soup, [False] * 3)
def test_override_markdown_options() -> None: """Test init GenerationConfiguration with default values""" # override break-on-newline key config = GenerationConfiguration(markdown_options={ "break-on-newline": False, }) assert config.markdown_options == { "break-on-newline": False, "fenced-code-blocks": { "cssclass": "highlight jumbotron" }, "tables": None, } # override fenced-code-blocks key config = GenerationConfiguration(markdown_options={ "fenced-code-blocks": { "cssclass": "test" }, }) assert config.markdown_options == { "break-on-newline": True, "fenced-code-blocks": { "cssclass": "test" }, "tables": None, } # override tables key config = GenerationConfiguration(markdown_options={"tables": ["test"]}) assert config.markdown_options == { "break-on-newline": True, "fenced-code-blocks": { "cssclass": "highlight jumbotron" }, "tables": ["test"], } # add a new key config = GenerationConfiguration(markdown_options={"newKey": "test"}) assert config.markdown_options == { "break-on-newline": True, "fenced-code-blocks": { "cssclass": "highlight jumbotron" }, "tables": None, "newKey": "test", }
def test_description_markdown_with_default_options() -> None: """Override default options""" soup = generate_case("description_markdown", GenerationConfiguration()) assert ( str(soup.find("span", class_="description")) == '<span class="description"><p>DOC<br/> * List 1<br/> * List 2</p> </span>' )
def test_description_with_ref_link_to_reused_ref() -> None: """Same as "test_description_with_ref", but do not allow reusing references.""" soup = generate_case("description_with_ref", GenerationConfiguration(link_to_reused_ref=False)) tests.html_schema_doc_asserts.assert_descriptions(soup, [ "We should see this", "inner description", "We should see this too", "inner description" ])
def test_deprecated_in_description() -> None: """Test finding whether a property is deprecated from its description""" soup = generate_case( "deprecated", GenerationConfiguration(deprecated_from_description=True)) tests.html_schema_doc_asserts.assert_property_names( soup, ["deprecated1", "deprecated2", "not_deprecated"]) tests.html_schema_doc_asserts.assert_deprecated(soup, [True, True, False])
def test_default_values() -> None: """Test init GenerationConfiguration with default values""" config = GenerationConfiguration() assert config.markdown_options == { "break-on-newline": True, "fenced-code-blocks": { "cssclass": "highlight jumbotron" }, "tables": None, } assert config.template_md_options["badge_as_image"] == False
def test_recursive_array() -> None: """Test a schema having a recursive definition pointing to array items""" soup = generate_case("recursive_array", GenerationConfiguration(link_to_reused_ref=True)) assert_descriptions(soup, [ "A list of people", "A human being", "The children they had", "A human being" ]) assert_ref_link(soup, "#person_items", "Same definition as person")
def test_long_description(collapse: bool) -> None: soup = generate_case( "long_description", GenerationConfiguration(collapse_long_descriptions=collapse)) read_more = soup.find("a", href="#collapseDescription_it_s_hard_to_explain") if collapse: assert read_more else: assert not read_more
def test_generate_from_schema_config_object(tmp_path: Path, caplog: LogCaptureFixture) -> None: config = GenerationConfiguration(minify=False, default_from_description=True, copy_css=False, copy_js=False) caplog.set_level(logging.INFO) generate_from_schema(get_test_case_path("basic"), config=config) _assert_deprecation_message(caplog, False) assert_css_and_js_not_copied(tmp_path)
def test_recursive(link_to_reused_ref: bool) -> None: """Test a schema having a recursive definition. Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError """ soup = generate_case( "recursive", GenerationConfiguration(link_to_reused_ref=link_to_reused_ref)) assert_descriptions( soup, ["A human being", "The children they had", "A human being"]) assert_ref_link(soup, "#person", "Same definition as person")
def test_description_markdown_with_custom_options() -> None: """Same as "test_description_markdown_with_default_options" but with option to render list""" soup = generate_case( "description_markdown", GenerationConfiguration(markdown_options={ "cuddled-lists": True, }), ) assert ( str(soup.find("span", class_="description")) == """<span class="description"><p>DOC </p> <ul> <li>List 1</li> <li>List 2</li> </ul> </span>""" )
def test_defaults_with_merge(link_to_reused_ref: bool) -> None: """Test default values being displayed correctly when they come from a common ref""" soup = generate_case( "defaults", GenerationConfiguration(link_to_reused_ref=link_to_reused_ref)) tests.html_schema_doc_asserts.assert_types(soup, ["object", "object", "object"]) tests.html_schema_doc_asserts.assert_descriptions( soup, ["Description of a", "A common description"]) tests.html_schema_doc_asserts.assert_property_names(soup, ["a", "b"]) tests.html_schema_doc_asserts.assert_default_values( soup, ['"Default from a"', '"Default from b"'])
def test_with_special_chars() -> None: soup = generate_case( "with_special_chars", GenerationConfiguration(deprecated_from_description=False)) tests.html_schema_doc_asserts.assert_property_names( soup, ["prénom", "nomDeFamille", "âge", "0 de quoi d'autre"]) buttons = soup.find_all("button", attrs={"aria-controls": True}) expected_targets = [ "#pr_nom", "#nomDeFamille", "#a_ge", "#a0_de_quoi_d_autre" ] for i, expected_target in enumerate(expected_targets): assert buttons[i].attrs["data-target"] == expected_target
def generate_docs(schemaName: str, format: str): template_name = "js" if format == "html" else "md_nested" file_name = "html" if format == "html" else "md" outdir = Path(f"output") outdir.mkdir(parents=True, exist_ok=True) doc = outdir.joinpath(f"{schemaName}.{file_name}") schema_file = Path(f"schema/{schemaName}.schema.json") config = GenerationConfiguration( template_name=template_name, show_toc=True, link_to_reused_ref=False, collapse_long_descriptions=False, ) generate_from_filename(schema_file, doc, config=config) print(f"Created {doc}...")
def test_generate_no_file_output(tmp_path: Path, monkeypatch: MonkeyPatch) -> None: """Test generating and getting output as a str instead of writing to file""" monkeypatch.chdir(tmp_path) test_case_name = "basic" test_case_file_name = f"{test_case_name}.json" test_case_path = get_test_case_path("basic") schemas = get_schemas_to_render(test_case_path, None, "md") template_renderer = MagicMock(TemplateRenderer) template_renderer.render.return_value = "" template_renderer.config = GenerationConfiguration() generated = generate_schemas_doc(schemas, template_renderer) assert list(generated.keys()) == [test_case_file_name] # Ensure no file is written to current working directory assert len(list(tmp_path.glob("**"))) == 1 # glob("**") returns itself
def test_recursive_parent_in_definition(link_to_reused_ref: bool) -> None: """Test a schema having a recursive definition. Moreover, the ref is linked to an attribute in a definition that has not been seen in the tree before Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError """ soup = generate_case( "recursive_parent_in_definition", GenerationConfiguration(link_to_reused_ref=link_to_reused_ref)) assert_descriptions( soup, [ "Relationships between this person and others", "A human being", "Relationships between this person and others", "A human being", ], ) assert_ref_link(soup, "#relationships_mother", "Same definition as mother")
def test_generate_multiple_path_inputs(tmp_path: Path) -> None: """Test generating using the all-purpose "generate" method with multiple Path inputs""" test_case1 = "basic" test_case2 = "with_default" test_case_path1 = get_test_case_path(test_case1) test_case_path2 = get_test_case_path(test_case2) result_path = tmp_path / "test_generate" result_path.mkdir() schemas = get_schemas_to_render_from_cli_arguments(test_case_path1, result_path, "md") schemas += get_schemas_to_render_from_cli_arguments( test_case_path2, result_path, "md") template_renderer = MagicMock(TemplateRenderer) template_renderer.render.return_value = "" template_renderer.config = GenerationConfiguration() generated = generate_schemas_doc(schemas, template_renderer) assert generated is not None
def test_recursive_two_files(link_to_reused_ref: bool) -> None: """Test rendering a schema with a recursive definition with the same name, but in another file""" soup = generate_case( "recursive_two_files", GenerationConfiguration(link_to_reused_ref=link_to_reused_ref)) assert_descriptions( soup, [ "A human being", "The children they had", "Person definition from second file. Not the same!", "Person definition from second file. Not the same!", ], ) if link_to_reused_ref: assert_ref_link(soup, "#person_siblings", "Same definition as siblings") else: assert not get_ref_link(soup, "#person_siblings")
def test_recursive_full_schema(link_to_reused_ref: bool) -> None: """Test a schema having a recursive definition. Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError """ soup = generate_case( "recursive_full_schema", GenerationConfiguration(link_to_reused_ref=link_to_reused_ref)) assert_descriptions( soup, [ "Display the issue.", "Code property", "RecursiveArray property", "Display the issue.", "DecoratedRecursiveArray property", "Display the issue.", ], ) assert_ref_link(soup, "#root", "Same definition as Bug")
import sys from json_schema_for_humans.generate import generate_from_filename from json_schema_for_humans.generation_configuration import GenerationConfiguration config = GenerationConfiguration(copy_css=True, expand_buttons=True, minify=False, link_to_reused_ref=False, footer_show_time=False) schema = sys.argv[1] source_dir = sys.argv[2] output_dir = sys.argv[3] schema_path = source_dir + "/" + schema + ".json" output_path = output_dir + "/" + schema + ".html" generate_from_filename(schema_path, output_path, config=config)
dir_name: str config: GenerationConfiguration md_example_template: str CONFIGURATIONS: List[ExampleConfiguration] = [ { "title": "JS template", "dir_name": "examples_js_default", "config": GenerationConfiguration( minify=False, template_name="js", deprecated_from_description=True, expand_buttons=True, footer_show_time=False, ), "md_example_template": MD_EXAMPLE_JS_TEMPLATE, }, { "title": "Flat template", "dir_name": "examples_flat_default", "config": GenerationConfiguration( minify=False, template_name="flat",
import os from typing import List import pytest from dataclasses import dataclass from pathlib import Path from json_schema_for_humans.generation_configuration import GenerationConfiguration from tests.md_utils_asserts import MdUtilsAsserts current_dir = os.path.abspath(os.path.dirname(__file__)) parent_dir = os.path.abspath(os.path.dirname(current_dir)) examples_dir = os.path.join(parent_dir, "docs", "examples") config_badge = GenerationConfiguration( template_name="md", template_md_options={"badge_as_image": True}, deprecated_from_description=True) config_no_badge = GenerationConfiguration( template_name="md", template_md_options={"badge_as_image": False}, deprecated_from_description=True) @dataclass class TestCase: name: str config: GenerationConfiguration __test__ = False
def test_basic() -> None: intermediate = build_intermediate_representation( get_test_case_path("basic"), GenerationConfiguration()) assert intermediate
parent_dir = os.path.abspath(os.path.dirname(current_dir)) sys.path.insert(0, parent_dir) from json_schema_for_humans.generate import generate_from_filename from json_schema_for_humans.generation_configuration import GenerationConfiguration template_names = ["js", "flat", "md", "md_nested"] template_extension = "html" if len(sys.argv) >= 2: template_names = [sys.argv[1]] examples_dir = os.path.join(current_dir, "examples") json_examples_dir = os.path.join(examples_dir, "cases") config_md = GenerationConfiguration(template_name="md", deprecated_from_description=True) EXAMPLES_HEADER_TEMPLATE = """ # {title} <!-- {{docsify-ignore-all}} --> <!-- select:start --> <!-- select-menu-labels: Schema --> Here you can browse various example schemas and their rendition with several templates. """ CONFIGURATION_HEADER_TEMPLATE = """ # {title} <!-- {{docsify-ignore-all}} --> <!-- select:start -->
def test_references() -> None: intermediate = build_intermediate_representation( get_test_case_path("references"), GenerationConfiguration()) assert intermediate