@@ -785,6 +785,138 @@ func (c CustomError) Error() string {
785785 return c .msg
786786}
787787
788+ func TestAs (t * testing.T ) {
789+ t .Run ("As returns TrogonError when error matches" , func (t * testing.T ) {
790+ template := trogonerror .NewErrorTemplate ("shopify.inventory" , "INSUFFICIENT_INVENTORY" ,
791+ trogonerror .TemplateWithCode (trogonerror .CodeFailedPrecondition ))
792+
793+ originalErr := template .NewError (
794+ trogonerror .WithMetadataValue (trogonerror .VisibilityPublic , "productId" , "gid://shopify/Product/1234567890" ))
795+
796+ trogonErr , ok := trogonerror .As (originalErr , template )
797+ assert .True (t , ok )
798+ assert .NotNil (t , trogonErr )
799+ assert .Equal (t , "shopify.inventory" , trogonErr .Domain ())
800+ assert .Equal (t , "INSUFFICIENT_INVENTORY" , trogonErr .Reason ())
801+ assert .Equal (t , "gid://shopify/Product/1234567890" , trogonErr .Metadata ()["productId" ].Value ())
802+
803+ })
804+
805+ t .Run ("As returns false when error doesn't match" , func (t * testing.T ) {
806+ template1 := trogonerror .NewErrorTemplate ("shopify.inventory" , "INSUFFICIENT_INVENTORY" )
807+ template2 := trogonerror .NewErrorTemplate ("shopify.users" , "NOT_FOUND" )
808+
809+ err1 := template1 .NewError ()
810+
811+ trogonErr , ok := trogonerror .As (err1 , template2 )
812+ assert .False (t , ok )
813+ assert .Nil (t , trogonErr )
814+ })
815+
816+ t .Run ("As returns false for non-TrogonError" , func (t * testing.T ) {
817+ template := trogonerror .NewErrorTemplate ("shopify.inventory" , "INSUFFICIENT_INVENTORY" )
818+ regularErr := errors .New ("regular error" )
819+
820+ trogonErr , ok := trogonerror .As (regularErr , template )
821+ assert .False (t , ok )
822+ assert .Nil (t , trogonErr )
823+ })
824+
825+ t .Run ("As works with WithChanges pattern" , func (t * testing.T ) {
826+ template := trogonerror .NewErrorTemplate ("shopify.inventory" , "INSUFFICIENT_INVENTORY" ,
827+ trogonerror .TemplateWithCode (trogonerror .CodeResourceExhausted ))
828+
829+ originalErr := template .NewError (
830+ trogonerror .WithMetadataValue (trogonerror .VisibilityPublic , "productId" , "gid://shopify/Product/1234567890" ))
831+
832+ trogonErr , ok := trogonerror .As (originalErr , template )
833+ assert .True (t , ok )
834+ assert .NotNil (t , trogonErr )
835+
836+ modifiedErr := trogonErr .WithChanges (
837+ trogonerror .WithChangeMetadataValue (trogonerror .VisibilityPublic , "main_order_id" , "order_123" ),
838+ trogonerror .WithChangeMetadataValue (trogonerror .VisibilityPublic , "listing_count" , "5" ),
839+ )
840+
841+ assert .Equal (t , "order_123" , modifiedErr .Metadata ()["main_order_id" ].Value ())
842+ assert .Equal (t , "5" , modifiedErr .Metadata ()["listing_count" ].Value ())
843+ assert .Equal (t , "gid://shopify/Product/1234567890" , modifiedErr .Metadata ()["productId" ].Value ()) // Original preserved
844+ })
845+
846+ t .Run ("As works with TrogonError directly" , func (t * testing.T ) {
847+ originalErr := trogonerror .NewError ("shopify.inventory" , "INSUFFICIENT_INVENTORY" ,
848+ trogonerror .WithCode (trogonerror .CodeFailedPrecondition ),
849+ trogonerror .WithMetadataValue (trogonerror .VisibilityPublic , "productId" , "gid://shopify/Product/1234567890" ))
850+
851+ // Test with TrogonError as target (not template)
852+ trogonErr , ok := trogonerror .As (originalErr , originalErr )
853+ assert .True (t , ok )
854+ assert .NotNil (t , trogonErr )
855+ assert .Equal (t , "shopify.inventory" , trogonErr .Domain ())
856+ assert .Equal (t , "INSUFFICIENT_INVENTORY" , trogonErr .Reason ())
857+ })
858+
859+ t .Run ("As works with wrapped TrogonError" , func (t * testing.T ) {
860+ template := trogonerror .NewErrorTemplate ("shopify.inventory" , "INSUFFICIENT_INVENTORY" )
861+
862+ originalErr := template .NewError (
863+ trogonerror .WithMetadataValue (trogonerror .VisibilityPublic , "productId" , "gid://shopify/Product/1234567890" ))
864+
865+ // Wrap the TrogonError with fmt.Errorf (this was the problematic scenario)
866+ wrappedErr := fmt .Errorf ("context: %w" , originalErr )
867+
868+ // Test the As function with the wrapped error
869+ trogonErr , ok := trogonerror .As (wrappedErr , template )
870+ assert .True (t , ok , "As should return true for wrapped TrogonError" )
871+ assert .NotNil (t , trogonErr , "As should return non-nil TrogonError" )
872+
873+ // Verify the extracted error has the correct properties
874+ assert .Equal (t , "shopify.inventory" , trogonErr .Domain ())
875+ assert .Equal (t , "INSUFFICIENT_INVENTORY" , trogonErr .Reason ())
876+ assert .Equal (t , "gid://shopify/Product/1234567890" , trogonErr .Metadata ()["productId" ].Value ())
877+ })
878+
879+ }
880+
881+ func TestInternalMethods (t * testing.T ) {
882+ t .Run ("TrogonError.is method delegates to Is" , func (t * testing.T ) {
883+ err1 := trogonerror .NewError ("shopify.session" , "SESSION_EXPIRED" )
884+ err2 := trogonerror .NewError ("shopify.session" , "SESSION_EXPIRED" )
885+ err3 := trogonerror .NewError ("shopify.session" , "SESSION_INVALID" )
886+
887+ // Test the internal is method by using it in the As function
888+ // This indirectly tests the is method since As calls target.is(err)
889+ trogonErr , ok := trogonerror .As (err2 , err1 )
890+ assert .True (t , ok )
891+ assert .NotNil (t , trogonErr )
892+
893+ trogonErr2 , ok2 := trogonerror .As (err3 , err1 )
894+ assert .False (t , ok2 )
895+ assert .Nil (t , trogonErr2 )
896+ })
897+
898+ t .Run ("ErrorTemplate.is method delegates to Is" , func (t * testing.T ) {
899+ template := trogonerror .NewErrorTemplate ("shopify.session" , "SESSION_EXPIRED" )
900+ err1 := template .NewError ()
901+ err2 := trogonerror .NewError ("shopify.session" , "SESSION_EXPIRED" )
902+ err3 := trogonerror .NewError ("shopify.session" , "SESSION_INVALID" )
903+
904+ // Test the internal is method by using it in the As function
905+ // This indirectly tests the is method since As calls target.is(err)
906+ trogonErr , ok := trogonerror .As (err1 , template )
907+ assert .True (t , ok )
908+ assert .NotNil (t , trogonErr )
909+
910+ trogonErr2 , ok2 := trogonerror .As (err2 , template )
911+ assert .True (t , ok2 )
912+ assert .NotNil (t , trogonErr2 )
913+
914+ trogonErr3 , ok3 := trogonerror .As (err3 , template )
915+ assert .False (t , ok3 )
916+ assert .Nil (t , trogonErr3 )
917+ })
918+ }
919+
788920func TestErrorTemplate (t * testing.T ) {
789921 t .Run ("NewErrorTemplate creates template with defaults" , func (t * testing.T ) {
790922 template := trogonerror .NewErrorTemplate ("shopify.session" , "SESSION_EXPIRED" )
0 commit comments