@@ -2,11 +2,9 @@ package e2e
22
33import (
44 "context"
5- "encoding/json"
65 "fmt"
76 "math"
87 "net/http"
9- "os"
108 "testing"
119 "time"
1210
@@ -642,283 +640,3 @@ func TestEntitlementWithLatestAggregation(t *testing.T) {
642640 }, 2 * time .Minute , time .Second )
643641 })
644642}
645-
646- func TestEntitlementStaticConfigEncoding (t * testing.T ) {
647- client := initClient (t )
648-
649- ctx , cancel := context .WithCancel (context .Background ())
650- defer cancel ()
651-
652- subject := "ent_static_config_customer"
653- customer := "ent_static_config_customer"
654- var customerID string
655- var featureId string
656- var entitlementId string
657-
658- c := CreateCustomerWithSubject (t , client , customer , subject )
659- customerID = c .Id
660-
661- t .Run ("Create Feature" , func (t * testing.T ) {
662- randKey := fmt .Sprintf ("entitlement_static_config_feature_%d" , time .Now ().Unix ())
663- resp , err := client .CreateFeatureWithResponse (ctx , api.CreateFeatureJSONRequestBody {
664- Name : "Entitlement Static Config Feature" ,
665- Key : randKey ,
666- })
667-
668- require .NoError (t , err )
669- require .Equal (t , http .StatusCreated , resp .StatusCode (), "Invalid status code [response_body=%s]" , string (resp .Body ))
670-
671- featureId = resp .JSON201 .Id
672- })
673-
674- expectedConfigJSON := `{"integrations":["github","gitlab"],"maxUsers":10}`
675- // Config needs to be a JSON-encoded string (not raw JSON object)
676- // because the API expects: {"config": "{...}"} not {"config": {...}}
677- configAsJSONString , err := json .Marshal (expectedConfigJSON )
678- require .NoError (t , err )
679-
680- t .Run ("Create Static Entitlement with Config (V1)" , func (t * testing.T ) {
681- staticEntitlement := api.EntitlementStaticCreateInputs {
682- Type : "static" ,
683- FeatureId : & featureId ,
684- Config : configAsJSONString ,
685- }
686- body := & api.CreateEntitlementJSONRequestBody {}
687- err := body .FromEntitlementStaticCreateInputs (staticEntitlement )
688- require .NoError (t , err )
689- resp , err := client .CreateEntitlementWithResponse (ctx , subject , * body )
690-
691- require .NoError (t , err )
692- require .Equal (t , http .StatusCreated , resp .StatusCode (), "Invalid status code [response_body=%s]" , string (resp .Body ))
693-
694- static , err := resp .JSON201 .AsEntitlementStatic ()
695- require .NoError (t , err )
696- entitlementId = static .Id
697-
698- // The config comes as json.RawMessage which is a JSON-encoded string
699- // Unmarshal it to get the actual JSON content
700- var configStr string
701- require .NoError (t , json .Unmarshal (static .Config , & configStr ))
702- require .JSONEq (t , expectedConfigJSON , configStr , "Config should be valid JSON, not double-encoded" )
703- })
704-
705- t .Run ("Get Entitlement by ID and Check Config (V1)" , func (t * testing.T ) {
706- resp , err := client .GetEntitlementByIdWithResponse (ctx , entitlementId )
707- require .NoError (t , err )
708- require .Equal (t , http .StatusOK , resp .StatusCode ())
709-
710- static , err := resp .JSON200 .AsEntitlementStatic ()
711- require .NoError (t , err )
712-
713- // Verify config is not double-encoded when retrieved
714- var configStr string
715- require .NoError (t , json .Unmarshal (static .Config , & configStr ))
716- require .JSONEq (t , expectedConfigJSON , configStr , "Retrieved config should match and not be double-encoded" )
717- })
718-
719- t .Run ("Get Entitlement Value and Check Config (V1)" , func (t * testing.T ) {
720- resp , err := client .GetEntitlementValueWithResponse (ctx , subject , entitlementId , nil )
721- require .NoError (t , err )
722- require .Equal (t , http .StatusOK , resp .StatusCode ())
723-
724- if resp .JSON200 .Config != nil {
725- // The config string should be valid JSON
726- require .JSONEq (t , expectedConfigJSON , * resp .JSON200 .Config , "EntitlementValue config should not be double-encoded" )
727- } else {
728- t .Fatal ("Config should not be nil in entitlement value" )
729- }
730- })
731-
732- // Test V2 API
733- t .Run ("Create Static Entitlement with Config (V2)" , func (t * testing.T ) {
734- // Create a new feature for V2 test
735- var v2FeatureId string
736- {
737- randKey := fmt .Sprintf ("entitlement_static_config_v2_feature_%d" , time .Now ().Unix ())
738- resp , err := client .CreateFeatureWithResponse (ctx , api.CreateFeatureJSONRequestBody {
739- Name : "Entitlement Static Config V2 Feature" ,
740- Key : randKey ,
741- })
742- require .NoError (t , err )
743- require .Equal (t , http .StatusCreated , resp .StatusCode ())
744- v2FeatureId = resp .JSON201 .Id
745- }
746-
747- // Create static entitlement via V2 API using V1 static create inputs
748- staticEntitlement := api.EntitlementStaticCreateInputs {
749- Type : "static" ,
750- FeatureId : & v2FeatureId ,
751- Config : configAsJSONString ,
752- }
753- var body api.CreateCustomerEntitlementV2JSONRequestBody
754- require .NoError (t , body .FromEntitlementStaticCreateInputs (staticEntitlement ))
755-
756- resp , err := client .CreateCustomerEntitlementV2WithResponse (ctx , customer , body )
757- require .NoError (t , err )
758- require .Equal (t , http .StatusCreated , resp .StatusCode (), "Invalid status code [response_body=%s]" , string (resp .Body ))
759-
760- v2Static , err := resp .JSON201 .AsEntitlementStaticV2 ()
761- require .NoError (t , err )
762-
763- // The config should be a valid JSON string, not double-encoded
764- var configStr string
765- require .NoError (t , json .Unmarshal (v2Static .Config , & configStr ))
766- require .JSONEq (t , expectedConfigJSON , configStr , "V2 Config should be valid JSON, not double-encoded" )
767- })
768-
769- // Test V3 API (Entitlement Access)
770- var v3FeatureKey string
771- t .Run ("Create Feature for V3" , func (t * testing.T ) {
772- v3FeatureKey = fmt .Sprintf ("entitlement_static_config_v3_feature_%d" , time .Now ().Unix ())
773- resp , err := client .CreateFeatureWithResponse (ctx , api.CreateFeatureJSONRequestBody {
774- Name : "Entitlement Static Config V3 Feature" ,
775- Key : v3FeatureKey ,
776- })
777- require .NoError (t , err )
778- require .Equal (t , http .StatusCreated , resp .StatusCode ())
779- })
780-
781- t .Run ("Create Static Entitlement for V3" , func (t * testing.T ) {
782- staticEntitlement := api.EntitlementStaticCreateInputs {
783- Type : "static" ,
784- FeatureKey : & v3FeatureKey ,
785- Config : configAsJSONString ,
786- }
787- body := & api.CreateEntitlementJSONRequestBody {}
788- require .NoError (t , body .FromEntitlementStaticCreateInputs (staticEntitlement ))
789- resp , err := client .CreateEntitlementWithResponse (ctx , subject , * body )
790- require .NoError (t , err )
791- require .Equal (t , http .StatusCreated , resp .StatusCode ())
792- })
793-
794- // Raw HTTP tests to verify actual format (independent of Go client)
795- baseURL := getBaseURL (t )
796- httpClient := & http.Client {}
797-
798- t .Run ("Raw HTTP: Get Entitlement by ID (V1)" , func (t * testing.T ) {
799- req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("%s/api/v1/entitlements/%s" , baseURL , entitlementId ), nil )
800- require .NoError (t , err )
801-
802- resp , err := httpClient .Do (req )
803- require .NoError (t , err )
804- defer resp .Body .Close ()
805-
806- require .Equal (t , http .StatusOK , resp .StatusCode )
807-
808- var result map [string ]interface {}
809- require .NoError (t , json .NewDecoder (resp .Body ).Decode (& result ))
810-
811- // Verify config is a string in the JSON response
812- configValue , ok := result ["config" ]
813- require .True (t , ok , "config field should exist" )
814- configStr , ok := configValue .(string )
815- require .True (t , ok , "config should be a JSON string, not an object" )
816- require .JSONEq (t , expectedConfigJSON , configStr , "Raw HTTP: config should not be double-encoded" )
817- })
818-
819- t .Run ("Raw HTTP: Get Entitlement Value (V1)" , func (t * testing.T ) {
820- req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("%s/api/v1/subjects/%s/entitlements/%s/value" , baseURL , subject , entitlementId ), nil )
821- require .NoError (t , err )
822-
823- resp , err := httpClient .Do (req )
824- require .NoError (t , err )
825- defer resp .Body .Close ()
826-
827- require .Equal (t , http .StatusOK , resp .StatusCode )
828-
829- var result map [string ]interface {}
830- require .NoError (t , json .NewDecoder (resp .Body ).Decode (& result ))
831-
832- // Verify config is a string in the JSON response
833- configValue , ok := result ["config" ]
834- require .True (t , ok , "config field should exist" )
835- configStr , ok := configValue .(string )
836- require .True (t , ok , "config should be a JSON string, not an object" )
837- require .JSONEq (t , expectedConfigJSON , configStr , "Raw HTTP: EntitlementValue config should not be double-encoded" )
838- })
839-
840- t .Run ("Raw HTTP: List Customer Entitlements (V2)" , func (t * testing.T ) {
841- req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("%s/api/v2/customers/%s/entitlements" , baseURL , customer ), nil )
842- require .NoError (t , err )
843-
844- resp , err := httpClient .Do (req )
845- require .NoError (t , err )
846- defer resp .Body .Close ()
847-
848- require .Equal (t , http .StatusOK , resp .StatusCode )
849-
850- var result map [string ]interface {}
851- require .NoError (t , json .NewDecoder (resp .Body ).Decode (& result ))
852-
853- items , ok := result ["items" ].([]interface {})
854- require .True (t , ok , "items should be an array" )
855- require .NotEmpty (t , items , "should have at least one entitlement" )
856-
857- // Find a static entitlement with config
858- var foundConfig bool
859- for _ , item := range items {
860- entitlement , ok := item .(map [string ]interface {})
861- if ! ok {
862- continue
863- }
864- if entitlement ["type" ] == "static" {
865- if configValue , ok := entitlement ["config" ]; ok {
866- configStr , ok := configValue .(string )
867- require .True (t , ok , "V2 config should be a JSON string, not an object" )
868- require .JSONEq (t , expectedConfigJSON , configStr , "Raw HTTP V2: config should not be double-encoded" )
869- foundConfig = true
870- break
871- }
872- }
873- }
874- require .True (t , foundConfig , "should find a static entitlement with config" )
875- })
876-
877- t .Run ("Raw HTTP: Check Entitlement Access (V3)" , func (t * testing.T ) {
878- req , err := http .NewRequestWithContext (ctx , "GET" , fmt .Sprintf ("%s/api/v3/openmeter/customers/%s/entitlement-access" , baseURL , customerID ), nil )
879- require .NoError (t , err )
880-
881- resp , err := httpClient .Do (req )
882- require .NoError (t , err )
883- defer resp .Body .Close ()
884-
885- require .Equal (t , http .StatusOK , resp .StatusCode , "V3 endpoint should be available" )
886-
887- var result map [string ]interface {}
888- require .NoError (t , json .NewDecoder (resp .Body ).Decode (& result ))
889-
890- data , ok := result ["data" ].([]interface {})
891- require .True (t , ok , "data should be an array" )
892- require .NotEmpty (t , data , "should have at least one access result" )
893-
894- // Find the static entitlement we created
895- var foundConfig bool
896- for _ , item := range data {
897- access , ok := item .(map [string ]interface {})
898- if ! ok {
899- continue
900- }
901- // Check if this is our v3 feature
902- if fk , ok := access ["feature_key" ].(string ); ok && fk == v3FeatureKey {
903- configValue , ok := access ["config" ]
904- require .True (t , ok , "config field should exist for static entitlement" )
905- configStr , ok := configValue .(string )
906- require .True (t , ok , "V3 config should be a JSON string, not an object" )
907- require .JSONEq (t , expectedConfigJSON , configStr , "Raw HTTP V3: config should not be double-encoded" )
908- foundConfig = true
909- break
910- }
911- }
912- require .True (t , foundConfig , "should find the v3 static entitlement with config" )
913- })
914- }
915-
916- // getBaseURL returns the base URL for raw HTTP requests
917- func getBaseURL (t * testing.T ) string {
918- t .Helper ()
919- address := os .Getenv ("OPENMETER_ADDRESS" )
920- if address == "" {
921- t .Skip ("OPENMETER_ADDRESS not set" )
922- }
923- return address
924- }
0 commit comments