@@ -612,3 +612,178 @@ func TestNonce(t *testing.T) {
612612 }
613613 })
614614}
615+
616+ func TestRenderAttributes (t * testing.T ) {
617+ tests := []struct {
618+ name string
619+ attributes templ.Attributes
620+ expected string
621+ }{
622+ {
623+ name : "string attributes are rendered" ,
624+ attributes : templ.Attributes {
625+ "class" : "test-class" ,
626+ "id" : "test-id" ,
627+ },
628+ expected : ` class="test-class" id="test-id"` ,
629+ },
630+ {
631+ name : "integer types are rendered as strings" ,
632+ attributes : templ.Attributes {
633+ "int" : 42 ,
634+ "int8" : int8 (8 ),
635+ "int16" : int16 (16 ),
636+ "int32" : int32 (32 ),
637+ "int64" : int64 (64 ),
638+ },
639+ expected : ` int="42" int16="16" int32="32" int64="64" int8="8"` ,
640+ },
641+ {
642+ name : "unsigned integer types are rendered as strings" ,
643+ attributes : templ.Attributes {
644+ "uint" : uint (42 ),
645+ "uint8" : uint8 (8 ),
646+ "uint16" : uint16 (16 ),
647+ "uint32" : uint32 (32 ),
648+ "uint64" : uint64 (64 ),
649+ "uintptr" : uintptr (100 ),
650+ },
651+ expected : ` uint="42" uint16="16" uint32="32" uint64="64" uint8="8" uintptr="100"` ,
652+ },
653+ {
654+ name : "float types are rendered as strings" ,
655+ attributes : templ.Attributes {
656+ "float32" : float32 (3.14 ),
657+ "float64" : float64 (2.718 ),
658+ },
659+ expected : ` float32="3.14" float64="2.718"` ,
660+ },
661+ {
662+ name : "complex types are rendered as strings" ,
663+ attributes : templ.Attributes {
664+ "complex64" : complex64 (1 + 2i ),
665+ "complex128" : complex128 (3 + 4i ),
666+ },
667+ expected : ` complex128="(3+4i)" complex64="(1+2i)"` ,
668+ },
669+ {
670+ name : "boolean attributes are rendered correctly" ,
671+ attributes : templ.Attributes {
672+ "checked" : true ,
673+ "disabled" : false ,
674+ },
675+ expected : ` checked` ,
676+ },
677+ {
678+ name : "mixed types are rendered correctly" ,
679+ attributes : templ.Attributes {
680+ "class" : "button" ,
681+ "value" : 42 ,
682+ "width" : float64 (100.5 ),
683+ "hidden" : false ,
684+ "active" : true ,
685+ },
686+ expected : ` active class="button" value="42" width="100.5"` ,
687+ },
688+ {
689+ name : "nil pointer attributes are not rendered" ,
690+ attributes : templ.Attributes {
691+ "optional" : (* string )(nil ),
692+ "visible" : (* bool )(nil ),
693+ },
694+ expected : `` ,
695+ },
696+ {
697+ name : "non-nil pointer attributes are rendered" ,
698+ attributes : templ.Attributes {
699+ "title" : ptr ("test title" ),
700+ "enabled" : ptr (true ),
701+ },
702+ expected : ` enabled title="test title"` ,
703+ },
704+ {
705+ name : "numeric pointer types are rendered as strings" ,
706+ attributes : templ.Attributes {
707+ "int-ptr" : ptr (42 ),
708+ "int8-ptr" : ptr (int8 (8 )),
709+ "int16-ptr" : ptr (int16 (16 )),
710+ "int32-ptr" : ptr (int32 (32 )),
711+ "int64-ptr" : ptr (int64 (64 )),
712+ "uint-ptr" : ptr (uint (42 )),
713+ "uint8-ptr" : ptr (uint8 (8 )),
714+ "uint16-ptr" : ptr (uint16 (16 )),
715+ "uint32-ptr" : ptr (uint32 (32 )),
716+ "uint64-ptr" : ptr (uint64 (64 )),
717+ "uintptr-ptr" : ptr (uintptr (100 )),
718+ "float32-ptr" : ptr (float32 (3.14 )),
719+ "float64-ptr" : ptr (float64 (2.718 )),
720+ "complex64-ptr" : ptr (complex64 (1 + 2i )),
721+ "complex128-ptr" : ptr (complex128 (3 + 4i )),
722+ },
723+ expected : ` complex128-ptr="(3+4i)" complex64-ptr="(1+2i)" float32-ptr="3.14" float64-ptr="2.718" int-ptr="42" int16-ptr="16" int32-ptr="32" int64-ptr="64" int8-ptr="8" uint-ptr="42" uint16-ptr="16" uint32-ptr="32" uint64-ptr="64" uint8-ptr="8" uintptr-ptr="100"` ,
724+ },
725+ {
726+ name : "nil numeric pointer attributes are not rendered" ,
727+ attributes : templ.Attributes {
728+ "int-ptr" : (* int )(nil ),
729+ "float32-ptr" : (* float32 )(nil ),
730+ "complex64-ptr" : (* complex64 )(nil ),
731+ },
732+ expected : `` ,
733+ },
734+ {
735+ name : "KeyValue[string, bool] attributes are rendered correctly" ,
736+ attributes : templ.Attributes {
737+ "data-value" : templ .KV ("test-string" , true ),
738+ "data-hidden" : templ .KV ("ignored" , false ),
739+ },
740+ expected : ` data-value="test-string"` ,
741+ },
742+ {
743+ name : "KeyValue[bool, bool] attributes are rendered correctly" ,
744+ attributes : templ.Attributes {
745+ "checked" : templ .KV (true , true ),
746+ "disabled" : templ .KV (false , true ),
747+ "hidden" : templ .KV (true , false ),
748+ },
749+ expected : ` checked` ,
750+ },
751+ {
752+ name : "function bool attributes are rendered correctly" ,
753+ attributes : templ.Attributes {
754+ "enabled" : func () bool { return true },
755+ "hidden" : func () bool { return false },
756+ },
757+ expected : ` enabled` ,
758+ },
759+ {
760+ name : "mixed KeyValue and function attributes" ,
761+ attributes : templ.Attributes {
762+ "data-name" : templ .KV ("value" , true ),
763+ "active" : templ .KV (true , true ),
764+ "dynamic" : func () bool { return true },
765+ "ignored" : templ .KV ("ignored" , false ),
766+ },
767+ expected : ` active data-name="value" dynamic` ,
768+ },
769+ }
770+ for _ , tt := range tests {
771+ t .Run (tt .name , func (t * testing.T ) {
772+ t .Parallel ()
773+ var buf bytes.Buffer
774+ err := templ .RenderAttributes (context .Background (), & buf , tt .attributes )
775+ if err != nil {
776+ t .Fatalf ("RenderAttributes failed: %v" , err )
777+ }
778+
779+ actual := buf .String ()
780+ if actual != tt .expected {
781+ t .Errorf ("expected %q, got %q" , tt .expected , actual )
782+ }
783+ })
784+ }
785+ }
786+
787+ func ptr [T any ](x T ) * T {
788+ return & x
789+ }
0 commit comments