def test_pattern_properties() -> None: soup = generate_case("pattern_properties") pattern_label = soup.find_all("span", class_=["badge-info"]) pattern_label_text = [ex.text for ex in pattern_label] assert pattern_label_text == ["Pattern Property"] pattern_content = soup.find_all("span", class_="pattern-value") pattern_content_text = [ ex.findChildren()[0].text for ex in pattern_content ] assert pattern_content_text == ["$[a-c][0-9]^"] tests.html_schema_doc_asserts.assert_property_names( soup, ["firstName", "lastName", "paperSize", "rating", "review"]) tests.html_schema_doc_asserts.assert_descriptions( soup, [ "The person's first name.", "The person's last name.", "Review of a paper size.", "Numerical rating for paper size.", "Narrative review of the paper size.", ], )
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_pattern_properties_html_id() -> None: """Test the HTML IDs generated for patterns under patternProperties""" soup = generate_case("pattern_properties_html_id") pattern_label = soup.find_all("span", class_=["badge-info"]) pattern_label_text = [ex.text for ex in pattern_label] assert pattern_label_text == ["Pattern Property"] * 4 pattern_content = soup.find_all("span", class_="pattern-value") pattern_content_text = [ ex.findChildren()[0].text for ex in pattern_content ] assert pattern_content_text == [".$", ".*", "..", "^."] tests.html_schema_doc_asserts.assert_property_names( soup, ["not_a_pattern", "Title 4", "Title 1", "Title 2", "Title 3"]) tests.html_schema_doc_asserts.assert_descriptions( soup, ["Description 4", "Description 1", "Description 2", "Description 3"], ) property_divs = soup.find_all("div", class_="property-definition-div") property_divs_id = [div.attrs["id"] for div in property_divs] assert property_divs_id == [ "not_a_pattern", "not_a_pattern_pattern1", "pattern1", "pattern2", "pattern3" ]
def test_references_url_two_levels() -> None: """Test rendering a schema with references as URL""" soup = generate_case("references_url_two_levels") tests.html_schema_doc_asserts.assert_descriptions( soup, ["Testing $ref of a remote $ref"] + ["a filled string"] * 2)
def test_combining_one_of(): """Test rendering of oneOf schema attribute in tabs""" soup = generate_case("combining_oneOf") tests.html_schema_doc_asserts.assert_one_of_options(soup, 4) tests.html_schema_doc_asserts.assert_types(soup, ["object"] * 5) tests.html_schema_doc_asserts.assert_required(soup, [True])
def test_description_from_ref() -> None: """Test that having a description next to a $ref in an object uses that description and not the one from the referenced object """ soup = generate_case("description_from_ref") tests.html_schema_doc_asserts.assert_descriptions(soup, ["a filled string"] * 2)
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_combining_one_of(): """Test rendering of oneOf schema attribute in tabs""" soup = generate_case("combining_oneOf") tests.html_schema_doc_asserts.assert_one_of_options_names(soup, ["diskDevice", "diskUUID", "nfs", "tmpfs"]) tests.html_schema_doc_asserts.assert_types(soup, ["object"] * 5) tests.html_schema_doc_asserts.assert_required(soup, [True])
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_deprecated_in_description() -> None: """Test finding whether a property is deprecated from its description""" soup = generate_case("deprecated", find_deprecated=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_top_level_combining() -> None: """Test rendering a schema with a combining property at the top level""" soup = generate_case("top_level_combining") tests.html_schema_doc_asserts.assert_title(soup, "Combining at top level") tests.html_schema_doc_asserts.assert_descriptions(soup, ["For the combine"]) tests.html_schema_doc_asserts.assert_types(soup, ["object"] * 4)
def test_multiple_types() -> None: """Test rendering a schema with type being an array.""" soup = generate_case("multiple_types") tests.html_schema_doc_asserts.assert_types( soup, ["object", "string", "string or null", "integer or number", "integer, string, number or null"] )
def test_top_level_array() -> None: """Test rendering a schema with an array instead of an object at the top level""" soup = generate_case("top_level_array") tests.html_schema_doc_asserts.assert_title(soup, "Array at top level") tests.html_schema_doc_asserts.assert_descriptions( soup, ["Sometimes there are no properties", "A string"])
def test_conditional_subschema() -> None: soup = generate_case("conditional_subschema") tests.html_schema_doc_asserts.assert_types(soup, [ "object", "object", "const", "object", "object", "object", "object", "string", "enum (of string)" ])
def test_references() -> None: """Test rendering a schema with references""" soup = generate_case("references") tests.html_schema_doc_asserts.assert_property_names( soup, [ "a_gift", "anchor_with_slash", "propertyA", "anchor_no_slash", "anchor_nested_reference", "same_file_anchor_with_slash", "same_file_anchor_no_slash", "same_file_nested_reference", "other_file_anchor", "with_wrap", "other_file_dot_anchor", "other_file_dot_dot_anchor", "other_file_only", "not_a_string", "multi_hierarchy_reference", "propertyA", ], ) tests.html_schema_doc_asserts.assert_descriptions( soup, [ "Testing $ref", "A gift, or is it?", "Description for object_def/items/propertyA", "Description for array_def", "Description for string_def", "The delivery is a gift, no prices displayed", "The delivery is a gift, no prices displayed", "The delivery is a gift, no prices displayed", "Test schema with a not", "Contents of propertyA in final.json", ], ) tests.html_schema_doc_asserts.assert_types( soup, [ "object", # root "string", # a_gift "object", # anchor_with_slash "string", # anchor_with_slash -> propertyA "array of string", # anchor_no_slash "string", # anchor_no_slash items "string", # anchor_nested_reference "string", # same_file_anchor_with_slash "object", # other_file_anchor "boolean", # with_wrap "object", # other_file_only "string", # not_a_string, not "object", # multi_hierarchy_reference "string", # multi_hierarchy_reference -> propertyA ], )
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_array_advanced(): """Test rendering a schema that uses minItems, maxItems, and uniqueItems for arrays""" soup = generate_case("array_advanced") tests.html_schema_doc_asserts.assert_descriptions(soup, ["A little food fun", "5 to 8 fruits that you like"]) tests.html_schema_doc_asserts.assert_property_names(soup, ["fruits", "vegetables"]) tests.html_schema_doc_asserts.assert_const(soup, ["eggplant"]) tests.html_schema_doc_asserts.assert_required(soup, [False] * 2)
def test_single_element_allOf() -> None: """Test loading schema that has a single-element allOf property""" soup = generate_case("single_element_allOf") tests.html_schema_doc_asserts.assert_title(soup, "Schema containing a single-element allOf") tests.html_schema_doc_asserts.assert_descriptions( soup, ["Schema containing a single-element allOf", "My string definition"] )
def test_combining_not(): """Test rendering of the not schema attribute""" soup = generate_case("combining_not") definitions = soup.find_all(class_="property-definition-div") assert len(definitions) == 1 assert definitions[0].text.lstrip().startswith("Must not be:")
def test_references_url_yaml() -> None: """Test rendering a schema with references as URL pointing to a YAML file""" soup = generate_case("references_url_yaml") tests.html_schema_doc_asserts.assert_property_names(soup, ["address", "street_address", "city", "state"]) tests.html_schema_doc_asserts.assert_descriptions(soup, ["Testing $ref with URL with YAML destination"]) tests.html_schema_doc_asserts.assert_types(soup, ["object", "object", "string", "string", "string"])
def test_circular_reference() -> None: """Test that generating a schema that has circular references does not crash""" soup = generate_case("circular") tests.html_schema_doc_asserts.assert_types(soup, ["object", "object", "string"]) tests.html_schema_doc_asserts.assert_property_names(soup, ["person", "a1"]) tests.html_schema_doc_asserts.assert_descriptions(soup, ["Description from b"]) tests.html_schema_doc_asserts.assert_default_values(soup, ['"Default from c"'])
def test_references_url() -> None: """Test rendering a schema with references as URL""" soup = generate_case("references_url") tests.html_schema_doc_asserts.assert_property_names(soup, ["firstName"]) tests.html_schema_doc_asserts.assert_descriptions(soup, ["Testing $ref with URL", "The person's first name."]) tests.html_schema_doc_asserts.assert_types(soup, ["object", "string"])
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_combining_not(): """Test rendering of the not schema attribute""" soup = generate_case("combining_not") not_value = soup.find_all(class_="not-value") assert len(not_value) == 1 assert not_value[0].text.lstrip().startswith("Must not be:")
def test_description_with_ref() -> None: """Test that having a description next to a $ref in an object uses that description and not the one from the referenced object """ soup = generate_case("description_with_ref") tests.html_schema_doc_asserts.assert_descriptions( soup, ["We should see this", "inner description", "We should see this too"])
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 test_prefix_items() -> None: soup = generate_case("prefixItems") tests.html_schema_doc_asserts.assert_types(soup, [ "object", "array", "number", "string", "enum (of string)", "enum (of string)" ]) tests.html_schema_doc_asserts.assert_descriptions(soup, ["followed by a string"])
def test_schema_with_keywords_as_properties() -> None: """Test rendering a schema in which properties are named the same as JSON schema keywords""" soup = generate_case("with_keywords") keywords = [ "default", "examples", "if", "then", "else", "anyOf", "allOf", "not", "properties", "patternProperties" ] tests.html_schema_doc_asserts.assert_property_names(soup, keywords) tests.html_schema_doc_asserts.assert_descriptions(soup, keywords)
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_html_in_patterns() -> None: soup = generate_case("html_in_patterns") code_blocks = soup.find_all("code") assert list(block.text for block in code_blocks) == [ "^(<<variable:([-+/*0-9A-Za-z_]+)>>|<<auto>>)$", "$[a-c][0-9]^<a>", ] tests.html_schema_doc_asserts.assert_property_names(soup, ["$[a-c][0-9]^<a>"])