diff options
Diffstat (limited to 'tests/test_component.py')
-rw-r--r-- | tests/test_component.py | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/tests/test_component.py b/tests/test_component.py new file mode 100644 index 0000000..9961b21 --- /dev/null +++ b/tests/test_component.py @@ -0,0 +1,315 @@ +import pytest + +from jinjax import Component, DuplicateDefDeclaration, InvalidArgument + + +def test_load_args(): + com = Component( + name="Test.jinja", + source='{#def message, lorem=4, ipsum="bar" -#}\n', + ) + assert com.required == ["message"] + assert com.optional == { + "lorem": 4, + "ipsum": "bar", + } + + +def test_expression_args(): + com = Component( + name="Test.jinja", + source="{#def expr=1 + 2 + 3, a=1 -#}\n", + ) + assert com.required == [] + assert com.optional == { + "expr": 6, + "a": 1, + } + + +def test_dict_args(): + com = Component( + name="Test.jinja", + source="{#def expr={'a': 'b', 'c': 'd'} -#}\n", + ) + assert com.optional == { + "expr": {"a": "b", "c": "d"}, + } + + com = Component( + name="Test.jinja", + source='{#def a=1, expr={"a": "b", "c": "d"} -#}\n', + ) + assert com.optional == { + "a": 1, + "expr": {"a": "b", "c": "d"}, + } + + +def test_lowercase_booleans(): + com = Component( + name="Test.jinja", + source="{#def a=false, b=true -#}\n", + ) + assert com.optional == { + "a": False, + "b": True, + } + + +def test_no_args(): + com = Component( + name="Test.jinja", + source="\n", + ) + assert com.required == [] + assert com.optional == {} + + +def test_fails_when_invalid_name(): + with pytest.raises(InvalidArgument): + source = "{#def 000abc -#}\n" + co = Component(name="", source=source) + print(co.required, co.optional) + + +def test_fails_when_missing_comma_between_args(): + with pytest.raises(InvalidArgument): + source = "{#def lorem ipsum -#}\n" + co = Component(name="", source=source) + print(co.required, co.optional) + + +def test_fails_when_missing_quotes_arround_default_value(): + with pytest.raises(InvalidArgument): + source = "{#def lorem=ipsum -#}\n" + co = Component(name="", source=source) + print(co.required, co.optional) + + +def test_fails_when_prop_is_expression(): + with pytest.raises(InvalidArgument): + source = "{#def a-b -#}\n" + co = Component(name="", source=source) + print(co.required, co.optional) + + +def test_fails_when_extra_comma_between_args(): + with pytest.raises(InvalidArgument): + source = "{#def a, , b -#}\n" + co = Component(name="", source=source) + print(co.required, co.optional) + + +def test_comma_in_default_value(): + com = Component( + name="Test.jinja", + source="{#def a='lorem, ipsum' -#}\n", + ) + assert com.optional == {"a": "lorem, ipsum"} + + +def test_load_assets(): + com = Component( + name="Test.jinja", + url_prefix="/static/", + source=""" + {#css a.css, "b.css", c.css -#} + {#js a.js, b.js, c.js -#} + """, + ) + assert com.css == ["/static/a.css", "/static/b.css", "/static/c.css"] + assert com.js == ["/static/a.js", "/static/b.js", "/static/c.js"] + + +def test_no_comma_in_assets_list_is_your_problem(): + com = Component( + name="Test.jinja", + source="{#js a.js b.js c.js -#}\n", + url_prefix="/static/" + ) + assert com.js == ["/static/a.js b.js c.js"] + + +def test_load_metadata_in_any_order(): + com = Component( + name="Test.jinja", + source=""" + {#css a.css #} + {#def lorem, ipsum=4 #} + {#js a.js #} + """, + ) + assert com.required == ["lorem"] + assert com.optional == {"ipsum": 4} + assert com.css == ["a.css"] + assert com.js == ["a.js"] + + +def test_ignore_metadata_if_not_first(): + com = Component( + name="Test.jinja", + source=""" + I am content + {#css a.css #} + {#def lorem, ipsum=4 #} + {#js a.js #} + """, + ) + assert com.required == [] + assert com.optional == {} + assert com.css == [] + assert com.js == [] + + +def test_fail_with_more_than_one_args_declaration(): + with pytest.raises(DuplicateDefDeclaration): + Component( + name="Test.jinja", + source=""" + {#def lorem, ipsum=4 #} + {#def a, b, c, ipsum="nope" #} + """, + ) + + +def test_merge_repeated_css_or_js_declarations(): + com = Component( + name="Test.jinja", + source=""" + {#css a.css #} + {#def lorem, ipsum=4 #} + {#css b.css #} + {#js a.js #} + {#js b.js #} + """, + ) + assert com.required == ["lorem"] + assert com.optional == {"ipsum": 4} + assert com.css == ["a.css", "b.css"] + assert com.js == ["a.js", "b.js"] + + +def test_linejump_in_args_decl(): + com = Component( + name="Test.jinja", + source='{#def\n message,\n lorem=4,\n ipsum="bar"\n#}\n', + ) + assert com.required == ["message"] + assert com.optional == { + "lorem": 4, + "ipsum": "bar", + } + + +def test_global_assets(): + com = Component( + name="Test.jinja", + source=""" + {#css a.css, /static/shared/b.css, http://example.com/cdn.css #} + {#js "http://example.com/cdn.js", a.js, /static/shared/b.js #} + """, + ) + assert com.css == ["a.css", "/static/shared/b.css", "http://example.com/cdn.css"] + assert com.js == ["http://example.com/cdn.js", "a.js", "/static/shared/b.js"] + + +def test_types_in_args_decl(): + com = Component( + name="Test.jinja", + source="""{# def + ring_class: str = "ring-1 ring-black", + rounded_class: str = "rounded-2xl md:rounded-3xl", + + image: str | None = None, + + title: str = "", + p_class: str = "px-5 md:px-6 py-5 md:py-6", + gap_class: str = "gap-4", + content_class: str = "", + + layer_class: str | None = None, + layer_height: int = 4, +#}""" + ) + assert com.required == [] + print(com.optional) + assert com.optional == { + "ring_class": "ring-1 ring-black", + "rounded_class": "rounded-2xl md:rounded-3xl", + "image": None, + "title": "", + "p_class": "px-5 md:px-6 py-5 md:py-6", + "gap_class": "gap-4", + "content_class": "", + "layer_class": None, + "layer_height": 4, + } + + +def test_comments_in_args_decl(): + com = Component( + name="Test.jinja", + source="""{# def + # + # Card style + ring_class: str = "ring-1 ring-black", + rounded_class: str = "rounded-2xl md:rounded-3xl", + # + # Image + image: str | None = None, + # + # Content + title: str = "", + p_class: str = "px-5 md:px-6 py-5 md:py-6", + gap_class: str = "gap-4", + content_class: str = "", + # + # Decorative layer + layer_class: str | None = None, + layer_height: int = 4, +#}""" + ) + assert com.required == [] + print(com.optional) + assert com.optional == { + "ring_class": "ring-1 ring-black", + "rounded_class": "rounded-2xl md:rounded-3xl", + "image": None, + "title": "", + "p_class": "px-5 md:px-6 py-5 md:py-6", + "gap_class": "gap-4", + "content_class": "", + "layer_class": None, + "layer_height": 4, + } + + +def test_comment_after_args_decl(): + com = Component( + name="Test.jinja", + source=""" +{# def + arg, +#} + +{# + Some comment. +#} +Hi +""".strip()) + assert com.required == ["arg"] + assert com.optional == {} + + +def test_fake_decl(): + com = Component( + name="Test.jinja", + source=""" +{# definitely not an args decl! #} +{# def arg #} +{# jsadfghkl are letters #} +{# csssssss #} +""".strip()) + assert com.required == ["arg"] + assert com.optional == {} |