github.com/openfga/go-sdk@v0.3.5/client/client_test.go (about)

     1  /**
     2   * Go SDK for OpenFGA
     3   *
     4   * API version: 0.1
     5   * Website: https://openfga.dev
     6   * Documentation: https://openfga.dev/docs
     7   * Support: https://discord.gg/8naAwJfWN6
     8   * License: [Apache-2.0](https://github.com/openfga/go-sdk/blob/main/LICENSE)
     9   *
    10   * NOTE: This file was auto generated by OpenAPI Generator (https://openapi-generator.tech). DO NOT EDIT.
    11   */
    12  
    13  package client_test
    14  
    15  import (
    16  	"context"
    17  	"encoding/json"
    18  	"fmt"
    19  	"net/http"
    20  	"testing"
    21  
    22  	"github.com/jarcoal/httpmock"
    23  	"github.com/openfga/go-sdk"
    24  	. "github.com/openfga/go-sdk/client"
    25  )
    26  
    27  type TestDefinition struct {
    28  	Name           string
    29  	JsonResponse   string
    30  	ResponseStatus int
    31  	Method         string
    32  	RequestPath    string
    33  }
    34  
    35  func TestOpenFgaClient(t *testing.T) {
    36  	fgaClient, err := NewSdkClient(&ClientConfiguration{
    37  		ApiUrl:  "https://api.fga.example",
    38  		StoreId: "01GXSB9YR785C4FYS3C0RTG7B2",
    39  	})
    40  	if err != nil {
    41  		t.Fatalf("%v", err)
    42  	}
    43  
    44  	t.Run("Allow client to have no store ID specified", func(t *testing.T) {
    45  		_, err := NewSdkClient(&ClientConfiguration{
    46  			ApiHost: "api.fga.example",
    47  		})
    48  		if err != nil {
    49  			t.Fatalf("Expect no error when store id is not specified but got %v", err)
    50  		}
    51  	})
    52  
    53  	t.Run("Allow client to have ApiUrl specified", func(t *testing.T) {
    54  		_, err := NewSdkClient(&ClientConfiguration{
    55  			ApiUrl: "https://api.fga.example",
    56  		})
    57  		if err != nil {
    58  			t.Fatalf("Expect no error when api url is specified but got %v", err)
    59  		}
    60  	})
    61  
    62  	t.Run("Ensure that ApiUrl is well formed", func(t *testing.T) {
    63  		urls := []string{
    64  			"api.fga.example",
    65  			"https//api.fga.example",
    66  			"https://api.fga.example:notavalidport",
    67  			"https://https://api.fga.example",
    68  			"notavalidscheme://api.fga.example",
    69  		}
    70  		for _, uri := range urls {
    71  			_, err := NewSdkClient(&ClientConfiguration{
    72  				ApiUrl: uri,
    73  			})
    74  			if err == nil {
    75  				t.Fatalf("Expected an error for invalid uri (%s) but got nil", uri)
    76  			}
    77  
    78  			expectedErrorString := fmt.Sprintf("Configuration.ApiUrl (%s) does not form a valid uri", uri)
    79  			if err.Error() != expectedErrorString {
    80  				t.Fatalf("Expected error (%s) but got (%s)", expectedErrorString, err.Error())
    81  			}
    82  		}
    83  	})
    84  
    85  	t.Run("Allow client to have empty store ID specified", func(t *testing.T) {
    86  		_, err := NewSdkClient(&ClientConfiguration{
    87  			ApiHost: "api.fga.example",
    88  			StoreId: "",
    89  		})
    90  		if err != nil {
    91  			t.Fatalf("Expect no error when store id is empty but has %v", err)
    92  		}
    93  	})
    94  
    95  	t.Run("Validate store ID when specified", func(t *testing.T) {
    96  		_, err := NewSdkClient(&ClientConfiguration{
    97  			ApiHost: "api.fga.example",
    98  			StoreId: "error",
    99  		})
   100  		if err == nil {
   101  			t.Fatalf("Expect invalid store ID to result in error but there is none")
   102  		}
   103  	})
   104  
   105  	t.Run("Validate auth model ID when specified", func(t *testing.T) {
   106  		_, err := NewSdkClient(&ClientConfiguration{
   107  			ApiHost:              "api.fga.example",
   108  			StoreId:              "01GXSB9YR785C4FYS3C0RTG7B2",
   109  			AuthorizationModelId: "BadAuthID",
   110  		})
   111  		if err == nil {
   112  			t.Fatalf("Expect invalid auth mode ID to result in error but there is none")
   113  		}
   114  	})
   115  
   116  	t.Run("Allow auth model ID to be empty when specified", func(t *testing.T) {
   117  		_, err := NewSdkClient(&ClientConfiguration{
   118  			ApiHost:              "api.fga.example",
   119  			StoreId:              "01GXSB9YR785C4FYS3C0RTG7B2",
   120  			AuthorizationModelId: "",
   121  		})
   122  		if err != nil {
   123  			t.Fatalf("Expect no error when auth model id is empty but has %v", err)
   124  		}
   125  	})
   126  
   127  	t.Run("Allow specifying an ApiUrl with a port and a base path", func(t *testing.T) {
   128  		_, err := NewSdkClient(&ClientConfiguration{
   129  			ApiUrl:  "https://api.fga.example:8080/fga",
   130  			StoreId: "01GXSB9YR785C4FYS3C0RTG7B2",
   131  		})
   132  		if err != nil {
   133  			t.Fatalf("Expect no error when auth model id is empty but has %v", err)
   134  		}
   135  
   136  		test := TestDefinition{
   137  			Name:           "ListStores",
   138  			JsonResponse:   `{"stores":[]}`,
   139  			ResponseStatus: http.StatusOK,
   140  			Method:         http.MethodGet,
   141  		}
   142  
   143  		var expectedResponse openfga.ListStoresResponse
   144  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   145  			t.Fatalf("%v", err)
   146  		}
   147  
   148  		httpmock.Activate()
   149  		defer httpmock.DeactivateAndReset()
   150  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores", fgaClient.GetConfig().ApiUrl),
   151  			func(req *http.Request) (*http.Response, error) {
   152  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   153  				if err != nil {
   154  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   155  				}
   156  				return resp, nil
   157  			},
   158  		)
   159  
   160  		got, err := fgaClient.ListStores(context.Background()).Execute()
   161  		if err != nil {
   162  			t.Fatalf("%v", err)
   163  		}
   164  		if len(got.Stores) != 0 {
   165  			t.Fatalf("expected stores of length 0, got %v", len(got.Stores))
   166  		}
   167  	})
   168  
   169  	/* Stores */
   170  	t.Run("ListStores", func(t *testing.T) {
   171  		test := TestDefinition{
   172  			Name:           "ListStores",
   173  			JsonResponse:   `{"stores":[{"id":"01GXSA8YR785C4FYS3C0RTG7B1","name":"Test Store","created_at":"2023-01-01T23:23:23.000000000Z","updated_at":"2023-01-01T23:23:23.000000000Z"}]}`,
   174  			ResponseStatus: http.StatusOK,
   175  			Method:         http.MethodGet,
   176  		}
   177  
   178  		var expectedResponse openfga.ListStoresResponse
   179  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   180  			t.Fatalf("%v", err)
   181  		}
   182  
   183  		httpmock.Activate()
   184  		defer httpmock.DeactivateAndReset()
   185  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores", fgaClient.GetConfig().ApiUrl),
   186  			func(req *http.Request) (*http.Response, error) {
   187  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   188  				if err != nil {
   189  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   190  				}
   191  				return resp, nil
   192  			},
   193  		)
   194  
   195  		options := ClientListStoresOptions{
   196  			PageSize:          openfga.PtrInt32(10),
   197  			ContinuationToken: openfga.PtrString("..."),
   198  		}
   199  		got, err := fgaClient.ListStores(context.Background()).Options(options).Execute()
   200  		if err != nil {
   201  			t.Fatalf("%v", err)
   202  		}
   203  
   204  		if len(got.Stores) != 1 {
   205  			t.Fatalf("%v", err)
   206  		}
   207  
   208  		if got.Stores[0].Id != expectedResponse.Stores[0].Id {
   209  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got.Stores[0].Id, expectedResponse.Stores[0].Id)
   210  		}
   211  		// ListStores without options should work
   212  		_, err = fgaClient.ListStores(context.Background()).Execute()
   213  		if err != nil {
   214  			t.Fatalf("%v", err)
   215  		}
   216  	})
   217  
   218  	t.Run("CreateStore", func(t *testing.T) {
   219  		test := TestDefinition{
   220  			Name:           "CreateStore",
   221  			JsonResponse:   `{"id":"01GXSA8YR785C4FYS3C0RTG7B1","name":"Test Store","created_at":"2023-01-01T23:23:23.000000000Z","updated_at":"2023-01-01T23:23:23.000000000Z"}`,
   222  			ResponseStatus: http.StatusOK,
   223  			Method:         http.MethodPost,
   224  		}
   225  		requestBody := ClientCreateStoreRequest{
   226  			Name: "Test Store",
   227  		}
   228  
   229  		var expectedResponse openfga.CreateStoreResponse
   230  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   231  			t.Fatalf("%v", err)
   232  		}
   233  
   234  		httpmock.Activate()
   235  		defer httpmock.DeactivateAndReset()
   236  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores", fgaClient.GetConfig().ApiUrl),
   237  			func(req *http.Request) (*http.Response, error) {
   238  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   239  				if err != nil {
   240  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   241  				}
   242  				return resp, nil
   243  			},
   244  		)
   245  		got, err := fgaClient.CreateStore(context.Background()).Body(requestBody).Execute()
   246  		if err != nil {
   247  			t.Fatalf("%v", err)
   248  		}
   249  
   250  		_, err = got.MarshalJSON()
   251  		if err != nil {
   252  			t.Fatalf("%v", err)
   253  		}
   254  		if got.Name != expectedResponse.Name {
   255  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got.Name, expectedResponse.Name)
   256  		}
   257  		// CreateStore without options should work
   258  		_, err = fgaClient.CreateStore(context.Background()).Body(requestBody).Execute()
   259  		if err != nil {
   260  			t.Fatalf("%v", err)
   261  		}
   262  	})
   263  
   264  	t.Run("GetStore", func(t *testing.T) {
   265  		test := TestDefinition{
   266  			Name:           "GetStore",
   267  			JsonResponse:   `{"id":"01GXSA8YR785C4FYS3C0RTG7B1","name":"Test Store","created_at":"2023-01-01T23:23:23.000000000Z","updated_at":"2023-01-01T23:23:23.000000000Z"}`,
   268  			ResponseStatus: http.StatusOK,
   269  			Method:         http.MethodGet,
   270  		}
   271  
   272  		var expectedResponse openfga.GetStoreResponse
   273  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   274  			t.Fatalf("%v", err)
   275  		}
   276  
   277  		httpmock.Activate()
   278  		defer httpmock.DeactivateAndReset()
   279  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId),
   280  			func(req *http.Request) (*http.Response, error) {
   281  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   282  				if err != nil {
   283  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   284  				}
   285  				return resp, nil
   286  			},
   287  		)
   288  
   289  		got, err := fgaClient.GetStore(context.Background()).Execute()
   290  		if err != nil {
   291  			t.Fatalf("%v", err)
   292  		}
   293  
   294  		if got.Id != expectedResponse.Id {
   295  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got.Id, expectedResponse.Id)
   296  		}
   297  		// GetStore without options should work
   298  		_, err = fgaClient.GetStore(context.Background()).Execute()
   299  		if err != nil {
   300  			t.Fatalf("%v", err)
   301  		}
   302  	})
   303  
   304  	t.Run("GetStoreAfterSettingStoreId", func(t *testing.T) {
   305  		test := TestDefinition{
   306  			Name:           "GetStoreAfterSettingStoreId",
   307  			JsonResponse:   `{"id":"01GXSA8YR785C4FYS3C0RTG7B1","name":"Test Store","created_at":"2023-01-01T23:23:23.000000000Z","updated_at":"2023-01-01T23:23:23.000000000Z"}`,
   308  			ResponseStatus: http.StatusOK,
   309  			Method:         http.MethodPost,
   310  		}
   311  
   312  		requestBody := ClientCreateStoreRequest{
   313  			Name: "Test Store",
   314  		}
   315  
   316  		var expectedResponse openfga.CreateStoreResponse
   317  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   318  			t.Fatalf("%v", err)
   319  		}
   320  
   321  		httpmock.Activate()
   322  		defer httpmock.DeactivateAndReset()
   323  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores", fgaClient.GetConfig().ApiUrl),
   324  			func(req *http.Request) (*http.Response, error) {
   325  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   326  				if err != nil {
   327  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   328  				}
   329  				return resp, nil
   330  			},
   331  		)
   332  
   333  		got1, err1 := fgaClient.CreateStore(context.Background()).Body(requestBody).Execute()
   334  		if err1 != nil {
   335  			t.Fatalf("%v", err1)
   336  		}
   337  
   338  		_, err = got1.MarshalJSON()
   339  		if err != nil {
   340  			t.Fatalf("%v", err)
   341  		}
   342  		if got1.Name != expectedResponse.Name {
   343  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got1.Name, expectedResponse.Name)
   344  		}
   345  
   346  		storeId := got1.Id
   347  		fgaClient.SetStoreId(storeId)
   348  
   349  		httpmock.Activate()
   350  		defer httpmock.DeactivateAndReset()
   351  		httpmock.RegisterResponder(http.MethodGet, fmt.Sprintf("%s/stores/%s", fgaClient.GetConfig().ApiUrl, storeId),
   352  			func(req *http.Request) (*http.Response, error) {
   353  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   354  				if err != nil {
   355  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   356  				}
   357  				return resp, nil
   358  			},
   359  		)
   360  
   361  		got2, err2 := fgaClient.GetStore(context.Background()).Execute()
   362  		if err2 != nil {
   363  			t.Fatalf("%v", err2)
   364  		}
   365  
   366  		if got2.Id != storeId {
   367  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got2.Id, storeId)
   368  		}
   369  	})
   370  
   371  	t.Run("DeleteStore", func(t *testing.T) {
   372  		test := TestDefinition{
   373  			Name:           "DeleteStore",
   374  			JsonResponse:   ``,
   375  			ResponseStatus: http.StatusNoContent,
   376  			Method:         http.MethodDelete,
   377  		}
   378  
   379  		httpmock.Activate()
   380  		defer httpmock.DeactivateAndReset()
   381  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId),
   382  			func(req *http.Request) (*http.Response, error) {
   383  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, "{}")
   384  				if err != nil {
   385  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   386  				}
   387  				return resp, nil
   388  			},
   389  		)
   390  		_, err := fgaClient.DeleteStore(context.Background()).Execute()
   391  		if err != nil {
   392  			t.Fatalf("%v", err)
   393  		}
   394  		// DeleteStore without options should work
   395  		_, err = fgaClient.DeleteStore(context.Background()).Execute()
   396  		if err != nil {
   397  			t.Fatalf("%v", err)
   398  		}
   399  	})
   400  
   401  	/* Authorization Models */
   402  	t.Run("ReadAuthorizationModels", func(t *testing.T) {
   403  		test := TestDefinition{
   404  			Name:           "ReadAuthorizationModels",
   405  			JsonResponse:   `{"authorization_models":[{"id":"01GXSA8YR785C4FYS3C0RTG7B1","schema_version":"1.1","type_definitions":[]}]}`,
   406  			ResponseStatus: http.StatusOK,
   407  			Method:         http.MethodGet,
   408  			RequestPath:    "authorization-models",
   409  		}
   410  
   411  		var expectedResponse openfga.ReadAuthorizationModelsResponse
   412  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   413  			t.Fatalf("%v", err)
   414  		}
   415  
   416  		httpmock.Activate()
   417  		defer httpmock.DeactivateAndReset()
   418  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   419  			func(req *http.Request) (*http.Response, error) {
   420  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   421  				if err != nil {
   422  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   423  				}
   424  				return resp, nil
   425  			},
   426  		)
   427  
   428  		options := ClientReadAuthorizationModelsOptions{
   429  			PageSize:          openfga.PtrInt32(10),
   430  			ContinuationToken: openfga.PtrString("..."),
   431  		}
   432  		got, err := fgaClient.ReadAuthorizationModels(context.Background()).Options(options).Execute()
   433  		if err != nil {
   434  			t.Fatalf("%v", err)
   435  		}
   436  
   437  		if len(got.AuthorizationModels) != 1 {
   438  			t.Fatalf("%v", err)
   439  		}
   440  
   441  		if got.AuthorizationModels[0].Id != expectedResponse.AuthorizationModels[0].Id {
   442  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, got.AuthorizationModels[0].Id, expectedResponse.AuthorizationModels[0].Id)
   443  		}
   444  		// ReadAuthorizationModels without options should work
   445  		_, err = fgaClient.ReadAuthorizationModels(context.Background()).Execute()
   446  		if err != nil {
   447  			t.Fatalf("%v", err)
   448  		}
   449  	})
   450  
   451  	t.Run("WriteAuthorizationModel", func(t *testing.T) {
   452  		test := TestDefinition{
   453  			Name:           "WriteAuthorizationModel",
   454  			JsonResponse:   `{"authorization_model_id":"01GXSA8YR785C4FYS3C0RTG7B1"}`,
   455  			ResponseStatus: http.StatusOK,
   456  			Method:         http.MethodPost,
   457  			RequestPath:    "authorization-models",
   458  		}
   459  		requestBody := ClientWriteAuthorizationModelRequest{
   460  			SchemaVersion: "1.1",
   461  			TypeDefinitions: []openfga.TypeDefinition{
   462  				{Type: "user", Relations: &map[string]openfga.Userset{}},
   463  				{
   464  					Type: "document",
   465  					Relations: &map[string]openfga.Userset{
   466  						"writer": {
   467  							This: &map[string]interface{}{},
   468  						},
   469  						"viewer": {Union: &openfga.Usersets{
   470  							Child: []openfga.Userset{
   471  								{This: &map[string]interface{}{}},
   472  								{ComputedUserset: &openfga.ObjectRelation{
   473  									Object:   openfga.PtrString(""),
   474  									Relation: openfga.PtrString("writer"),
   475  								}},
   476  							},
   477  						}},
   478  					},
   479  					Metadata: &openfga.Metadata{
   480  						Relations: &map[string]openfga.RelationMetadata{
   481  							"writer": {
   482  								DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   483  									{Type: "user"},
   484  								},
   485  							},
   486  							"viewer": {
   487  								DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   488  									{Type: "user"},
   489  								},
   490  							},
   491  						},
   492  					},
   493  				}},
   494  		}
   495  
   496  		var expectedResponse openfga.WriteAuthorizationModelResponse
   497  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   498  			t.Fatalf("%v", err)
   499  		}
   500  
   501  		httpmock.Activate()
   502  		defer httpmock.DeactivateAndReset()
   503  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   504  			func(req *http.Request) (*http.Response, error) {
   505  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   506  				if err != nil {
   507  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   508  				}
   509  				return resp, nil
   510  			},
   511  		)
   512  		options := ClientWriteAuthorizationModelOptions{}
   513  		got, err := fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Options(options).Execute()
   514  		if err != nil {
   515  			t.Fatalf("%v", err)
   516  		}
   517  
   518  		_, err = got.MarshalJSON()
   519  		if err != nil {
   520  			t.Fatalf("%v", err)
   521  		}
   522  
   523  		if got.GetAuthorizationModelId() != expectedResponse.GetAuthorizationModelId() {
   524  			t.Fatalf("OpenFgaClient.%v() / AuthorizationModelId = %v, want %v", test.Name, got.GetAuthorizationModelId(), expectedResponse.GetAuthorizationModelId())
   525  		}
   526  
   527  		// WriteAuthorizationModel without options should work
   528  		_, err = fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Execute()
   529  		if err != nil {
   530  			t.Fatalf("%v", err)
   531  		}
   532  	})
   533  
   534  	t.Run("WriteAuthorizationModelWithCondition", func(t *testing.T) {
   535  		test := TestDefinition{
   536  			Name:           "WriteAuthorizationModelWithCondition",
   537  			JsonResponse:   `{"authorization_model_id":"01GXSA8YR785C4FYS3C0RTG7B1"}`,
   538  			ResponseStatus: http.StatusOK,
   539  			Method:         http.MethodPost,
   540  			RequestPath:    "authorization-models",
   541  		}
   542  		requestBody := ClientWriteAuthorizationModelRequest{
   543  			SchemaVersion: "1.1",
   544  			TypeDefinitions: []openfga.TypeDefinition{
   545  				{
   546  					Type:      "user",
   547  					Relations: &map[string]openfga.Userset{},
   548  				},
   549  				{
   550  					Type: "document",
   551  					Relations: &map[string]openfga.Userset{
   552  						"writer": {This: &map[string]interface{}{}},
   553  						"viewer": {Union: &openfga.Usersets{
   554  							Child: []openfga.Userset{
   555  								{This: &map[string]interface{}{}},
   556  								{ComputedUserset: &openfga.ObjectRelation{
   557  									Object:   openfga.PtrString(""),
   558  									Relation: openfga.PtrString("writer"),
   559  								}},
   560  							},
   561  						}},
   562  					},
   563  					Metadata: &openfga.Metadata{
   564  						Relations: &map[string]openfga.RelationMetadata{
   565  							"writer": {
   566  								DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   567  									{Type: "user"},
   568  									{Type: "user", Condition: openfga.PtrString("ViewCountLessThan200")},
   569  								},
   570  							},
   571  							"viewer": {
   572  								DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   573  									{Type: "user"},
   574  								},
   575  							},
   576  						},
   577  					},
   578  				},
   579  			},
   580  			Conditions: &map[string]openfga.Condition{
   581  				"ViewCountLessThan200": {
   582  					Name:       "ViewCountLessThan200",
   583  					Expression: "ViewCount < 200",
   584  					Parameters: &map[string]openfga.ConditionParamTypeRef{
   585  						"ViewCount": {
   586  							TypeName: openfga.INT,
   587  						},
   588  						"Type": {
   589  							TypeName: openfga.STRING,
   590  						},
   591  						"Name": {
   592  							TypeName: openfga.STRING,
   593  						},
   594  					},
   595  				},
   596  			},
   597  		}
   598  
   599  		var expectedResponse openfga.WriteAuthorizationModelResponse
   600  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   601  			t.Fatalf("%v", err)
   602  		}
   603  
   604  		httpmock.Activate()
   605  		defer httpmock.DeactivateAndReset()
   606  		httpmock.RegisterMatcherResponder(
   607  			test.Method,
   608  			fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   609  			httpmock.BodyContainsString(`"ViewCountLessThan200"`),
   610  			func(req *http.Request) (*http.Response, error) {
   611  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   612  				if err != nil {
   613  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   614  				}
   615  				return resp, nil
   616  			},
   617  		)
   618  		options := ClientWriteAuthorizationModelOptions{}
   619  		got, err := fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Options(options).Execute()
   620  		if err != nil {
   621  			t.Fatalf("%v", err)
   622  		}
   623  
   624  		_, err = got.MarshalJSON()
   625  		if err != nil {
   626  			t.Fatalf("%v", err)
   627  		}
   628  
   629  		if got.GetAuthorizationModelId() != expectedResponse.GetAuthorizationModelId() {
   630  			t.Fatalf("OpenFgaClient.%v() / AuthorizationModelId = %v, want %v", test.Name, got.GetAuthorizationModelId(), expectedResponse.GetAuthorizationModelId())
   631  		}
   632  
   633  		// WriteAuthorizationModel without options should work
   634  		_, err = fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Execute()
   635  		if err != nil {
   636  			t.Fatalf("%v", err)
   637  		}
   638  	})
   639  
   640  	t.Run("WriteAuthorizationModelWithCondition2", func(t *testing.T) {
   641  		test := TestDefinition{
   642  			Name:           "WriteAuthorizationModelWithCondition2",
   643  			JsonResponse:   `{"authorization_model_id":"01GXSA8YR785C4FYS3C0RTG7B1"}`,
   644  			ResponseStatus: http.StatusOK,
   645  			Method:         http.MethodPost,
   646  			RequestPath:    "authorization-models",
   647  		}
   648  
   649  		schemaVersion := "1.1"
   650  		typeDefs := []openfga.TypeDefinition{
   651  			{
   652  				Type:      "user",
   653  				Relations: &map[string]openfga.Userset{},
   654  			},
   655  			{
   656  				Type: "document",
   657  				Relations: &map[string]openfga.Userset{
   658  					"writer": {This: &map[string]interface{}{}},
   659  					"viewer": {Union: &openfga.Usersets{
   660  						Child: []openfga.Userset{
   661  							{This: &map[string]interface{}{}},
   662  							{ComputedUserset: &openfga.ObjectRelation{
   663  								Object:   openfga.PtrString(""),
   664  								Relation: openfga.PtrString("writer"),
   665  							}},
   666  						},
   667  					}},
   668  				},
   669  				Metadata: &openfga.Metadata{
   670  					Relations: &map[string]openfga.RelationMetadata{
   671  						"writer": {
   672  							DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   673  								{Type: "user"},
   674  								{Type: "user", Condition: openfga.PtrString("ViewCountLessThan200")},
   675  							},
   676  						},
   677  						"viewer": {
   678  							DirectlyRelatedUserTypes: &[]openfga.RelationReference{
   679  								{Type: "user"},
   680  							},
   681  						},
   682  					},
   683  				},
   684  			},
   685  		}
   686  		conditions := map[string]openfga.Condition{
   687  			"ViewCountLessThan200": {
   688  				Name:       "ViewCountLessThan200",
   689  				Expression: "ViewCount < 200",
   690  				Parameters: &map[string]openfga.ConditionParamTypeRef{
   691  					"ViewCount": {
   692  						TypeName: openfga.INT,
   693  					},
   694  					"Type": {
   695  						TypeName: openfga.STRING,
   696  					},
   697  					"Name": {
   698  						TypeName: openfga.STRING,
   699  					},
   700  				},
   701  			},
   702  		}
   703  		requestBody := ClientWriteAuthorizationModelRequest{
   704  			SchemaVersion:   schemaVersion,
   705  			TypeDefinitions: typeDefs,
   706  			Conditions:      &conditions,
   707  		}
   708  
   709  		var expectedResponse openfga.WriteAuthorizationModelResponse
   710  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   711  			t.Fatalf("%v", err)
   712  		}
   713  
   714  		httpmock.Activate()
   715  		defer httpmock.DeactivateAndReset()
   716  		httpmock.RegisterMatcherResponder(
   717  			test.Method,
   718  			fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   719  			httpmock.BodyContainsString(`"ViewCountLessThan200"`),
   720  			func(req *http.Request) (*http.Response, error) {
   721  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   722  				if err != nil {
   723  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   724  				}
   725  				return resp, nil
   726  			},
   727  		)
   728  		options := ClientWriteAuthorizationModelOptions{}
   729  		got, err := fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Options(options).Execute()
   730  		if err != nil {
   731  			t.Fatalf("%v", err)
   732  		}
   733  
   734  		_, err = got.MarshalJSON()
   735  		if err != nil {
   736  			t.Fatalf("%v", err)
   737  		}
   738  
   739  		if got.GetAuthorizationModelId() != expectedResponse.GetAuthorizationModelId() {
   740  			t.Fatalf("OpenFgaClient.%v() / AuthorizationModelId = %v, want %v", test.Name, got.GetAuthorizationModelId(), expectedResponse.GetAuthorizationModelId())
   741  		}
   742  
   743  		// WriteAuthorizationModel without options should work
   744  		_, err = fgaClient.WriteAuthorizationModel(context.Background()).Body(requestBody).Execute()
   745  		if err != nil {
   746  			t.Fatalf("%v", err)
   747  		}
   748  	})
   749  
   750  	t.Run("ReadAuthorizationModel", func(t *testing.T) {
   751  		test := TestDefinition{
   752  			Name:           "ReadAuthorizationModel",
   753  			JsonResponse:   `{"authorization_model":{"id":"01GXSA8YR785C4FYS3C0RTG7B1","schema_version":"1.1","type_definitions":[{"type":"github-repo", "relations":{"viewer":{"this":{}}}}]}}`,
   754  			ResponseStatus: http.StatusOK,
   755  			Method:         http.MethodGet,
   756  			RequestPath:    "authorization-models",
   757  		}
   758  
   759  		var expectedResponse openfga.ReadAuthorizationModelResponse
   760  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   761  			t.Fatalf("%v", err)
   762  		}
   763  		modelId := expectedResponse.AuthorizationModel.Id
   764  
   765  		httpmock.Activate()
   766  		defer httpmock.DeactivateAndReset()
   767  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath, modelId),
   768  			func(req *http.Request) (*http.Response, error) {
   769  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   770  				if err != nil {
   771  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   772  				}
   773  				return resp, nil
   774  			},
   775  		)
   776  		options := ClientReadAuthorizationModelOptions{
   777  			AuthorizationModelId: openfga.PtrString(modelId),
   778  		}
   779  		got, err := fgaClient.ReadAuthorizationModel(context.Background()).Options(options).Execute()
   780  		if err != nil {
   781  			t.Fatalf("%v", err)
   782  		}
   783  
   784  		responseJson, err := got.MarshalJSON()
   785  		if err != nil {
   786  			t.Fatalf("%v", err)
   787  		}
   788  
   789  		if got.AuthorizationModel.Id != modelId {
   790  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
   791  		}
   792  		// ReadAuthorizationModel without options should not work
   793  		_, err = fgaClient.ReadAuthorizationModel(context.Background()).Execute()
   794  		expectedError := "Required parameter AuthorizationModelId was not provided"
   795  		if err == nil || err.Error() != expectedError {
   796  			t.Fatalf("Expected error:%v, got: %v", expectedError, err)
   797  		}
   798  		// ReadAuthorizationModel with options of empty string should not work
   799  		badOptions := ClientReadAuthorizationModelOptions{
   800  			AuthorizationModelId: openfga.PtrString(""),
   801  		}
   802  		_, err = fgaClient.ReadAuthorizationModel(context.Background()).Options(badOptions).Execute()
   803  		if err == nil || err.Error() != expectedError {
   804  			t.Fatalf("Expected error:%v, got: %v", expectedError, err)
   805  		}
   806  	})
   807  
   808  	t.Run("ReadLatestAuthorizationModel", func(t *testing.T) {
   809  		test := TestDefinition{
   810  			Name:           "ReadAuthorizationModels",
   811  			JsonResponse:   `{"authorization_models":[{"id":"01GXSA8YR785C4FYS3C0RTG7B1","schema_version":"1.1","type_definitions":[{"type":"github-repo", "relations":{"viewer":{"this":{}}}}]}]}`,
   812  			ResponseStatus: http.StatusOK,
   813  			Method:         http.MethodGet,
   814  			RequestPath:    "authorization-models",
   815  		}
   816  
   817  		var expectedResponse openfga.ReadAuthorizationModelsResponse
   818  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   819  			t.Fatalf("%v", err)
   820  		}
   821  		modelId := expectedResponse.AuthorizationModels[0].Id
   822  
   823  		httpmock.Activate()
   824  		defer httpmock.DeactivateAndReset()
   825  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   826  			func(req *http.Request) (*http.Response, error) {
   827  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   828  				if err != nil {
   829  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   830  				}
   831  				return resp, nil
   832  			},
   833  		)
   834  		options := ClientReadLatestAuthorizationModelOptions{}
   835  		got, err := fgaClient.ReadLatestAuthorizationModel(context.Background()).Options(options).Execute()
   836  		if err != nil {
   837  			t.Fatalf("%v", err)
   838  		}
   839  
   840  		responseJson, err := got.MarshalJSON()
   841  		if err != nil {
   842  			t.Fatalf("%v", err)
   843  		}
   844  
   845  		if got.AuthorizationModel.GetId() != modelId {
   846  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
   847  		}
   848  		// ReadLatestAuthorizationModel without options should work
   849  		_, err = fgaClient.ReadLatestAuthorizationModel(context.Background()).Execute()
   850  		if err != nil {
   851  			t.Fatalf("%v", err)
   852  		}
   853  	})
   854  
   855  	/* Relationship Tuples */
   856  	t.Run("ReadChanges", func(t *testing.T) {
   857  		test := TestDefinition{
   858  			Name:           "ReadChanges",
   859  			JsonResponse:   `{"changes":[{"tuple_key":{"user":"user:81684243-9356-4421-8fbf-a4f8d36aa31b","relation":"viewer","object":"document:roadmap"},"operation":"TUPLE_OPERATION_WRITE","timestamp": "2000-01-01T00:00:00Z"}],"continuation_token":"eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ=="}`,
   860  			ResponseStatus: http.StatusOK,
   861  			Method:         http.MethodGet,
   862  			RequestPath:    "changes",
   863  		}
   864  
   865  		var expectedResponse openfga.ReadChangesResponse
   866  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   867  			t.Fatalf("%v", err)
   868  		}
   869  
   870  		httpmock.Activate()
   871  		defer httpmock.DeactivateAndReset()
   872  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   873  			func(req *http.Request) (*http.Response, error) {
   874  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   875  				if err != nil {
   876  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   877  				}
   878  				return resp, nil
   879  			},
   880  		)
   881  		body := ClientReadChangesRequest{
   882  			Type: "document",
   883  		}
   884  		options := ClientReadChangesOptions{ContinuationToken: openfga.PtrString("eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ=="), PageSize: openfga.PtrInt32(25)}
   885  		got, err := fgaClient.ReadChanges(context.Background()).Body(body).Options(options).Execute()
   886  		if err != nil {
   887  			t.Fatalf("%v", err)
   888  		}
   889  
   890  		responseJson, err := got.MarshalJSON()
   891  		if err != nil {
   892  			t.Fatalf("%v", err)
   893  		}
   894  
   895  		if len(got.Changes) != len(expectedResponse.Changes) {
   896  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
   897  		}
   898  		// ReadChanges without options should work
   899  		_, err = fgaClient.ReadChanges(context.Background()).Body(body).Execute()
   900  		if err != nil {
   901  			t.Fatalf("%v", err)
   902  		}
   903  	})
   904  
   905  	t.Run("Read", func(t *testing.T) {
   906  		test := TestDefinition{
   907  			Name:           "Read",
   908  			JsonResponse:   `{"tuples":[{"key":{"user":"user:81684243-9356-4421-8fbf-a4f8d36aa31b","relation":"viewer","object":"document:roadmap"},"timestamp": "2000-01-01T00:00:00Z"}]}`,
   909  			ResponseStatus: http.StatusOK,
   910  			Method:         http.MethodPost,
   911  			RequestPath:    "read",
   912  		}
   913  
   914  		requestBody := ClientReadRequest{
   915  			User:     openfga.PtrString("user:81684243-9356-4421-8fbf-a4f8d36aa31b"),
   916  			Relation: openfga.PtrString("viewer"),
   917  			Object:   openfga.PtrString("document:roadmap"),
   918  		}
   919  
   920  		var expectedResponse openfga.ReadResponse
   921  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   922  			t.Fatalf("%v", err)
   923  		}
   924  
   925  		httpmock.Activate()
   926  		defer httpmock.DeactivateAndReset()
   927  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   928  			func(req *http.Request) (*http.Response, error) {
   929  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   930  				if err != nil {
   931  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   932  				}
   933  				return resp, nil
   934  			},
   935  		)
   936  
   937  		options := ClientReadOptions{
   938  			PageSize:          openfga.PtrInt32(10),
   939  			ContinuationToken: openfga.PtrString("eyJwayI6IkxBVEVTVF9OU0NPTkZJR19hdXRoMHN0b3JlIiwic2siOiIxem1qbXF3MWZLZExTcUoyN01MdTdqTjh0cWgifQ=="),
   940  		}
   941  		got, err := fgaClient.Read(context.Background()).Body(requestBody).Options(options).Execute()
   942  		if err != nil {
   943  			t.Fatalf("%v", err)
   944  		}
   945  
   946  		responseJson, err := got.MarshalJSON()
   947  		if err != nil {
   948  			t.Fatalf("%v", err)
   949  		}
   950  
   951  		if len(got.Tuples) != len(expectedResponse.Tuples) {
   952  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
   953  		}
   954  		// Read without options should work
   955  		_, err = fgaClient.Read(context.Background()).Body(requestBody).Execute()
   956  		if err != nil {
   957  			t.Fatalf("%v", err)
   958  		}
   959  	})
   960  
   961  	t.Run("Write", func(t *testing.T) {
   962  		test := TestDefinition{
   963  			Name:           "Write",
   964  			JsonResponse:   `{}`,
   965  			ResponseStatus: http.StatusOK,
   966  			Method:         http.MethodPost,
   967  			RequestPath:    "write",
   968  		}
   969  		requestBody := ClientWriteRequest{
   970  			Writes: []ClientTupleKey{{
   971  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
   972  				Relation: "viewer",
   973  				Object:   "document:roadmap",
   974  			}},
   975  			Deletes: []ClientTupleKeyWithoutCondition{},
   976  		}
   977  		options := ClientWriteOptions{
   978  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
   979  		}
   980  
   981  		var expectedResponse map[string]interface{}
   982  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
   983  			t.Fatalf("%v", err)
   984  		}
   985  
   986  		httpmock.Activate()
   987  		defer httpmock.DeactivateAndReset()
   988  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
   989  			func(req *http.Request) (*http.Response, error) {
   990  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
   991  				if err != nil {
   992  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
   993  				}
   994  				return resp, nil
   995  			},
   996  		)
   997  		data, err := fgaClient.Write(context.Background()).Body(requestBody).Options(options).Execute()
   998  		if err != nil {
   999  			t.Fatalf("%v", err)
  1000  		}
  1001  
  1002  		if len(data.Writes) != 1 {
  1003  			t.Fatalf("OpenFgaClient.%v() - expected %v Writes, got %v", test.Name, 1, len(data.Writes))
  1004  		}
  1005  
  1006  		if len(data.Deletes) != 0 {
  1007  			t.Fatalf("OpenFgaClient.%v() - expected %v Deletes, got %v", test.Name, 0, len(data.Deletes))
  1008  		}
  1009  
  1010  		for index := 0; index < len(data.Writes); index++ {
  1011  			response := data.Writes[index]
  1012  			if response.Error != nil {
  1013  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1014  			}
  1015  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1016  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1017  			}
  1018  
  1019  			_, err := response.MarshalJSON()
  1020  			if err != nil {
  1021  				t.Fatalf("%v", err)
  1022  			}
  1023  		}
  1024  
  1025  		for index := 0; index < len(data.Deletes); index++ {
  1026  			response := data.Deletes[index]
  1027  			if response.Error != nil {
  1028  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1029  			}
  1030  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1031  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1032  			}
  1033  
  1034  			_, err := response.MarshalJSON()
  1035  			if err != nil {
  1036  				t.Fatalf("%v", err)
  1037  			}
  1038  		}
  1039  		// Write without options should work
  1040  		_, err = fgaClient.Write(context.Background()).Body(requestBody).Execute()
  1041  		if err != nil {
  1042  			t.Fatalf("%v", err)
  1043  		}
  1044  	})
  1045  
  1046  	t.Run("Write with invalid auth model id", func(t *testing.T) {
  1047  		test := TestDefinition{
  1048  			Name:           "Write",
  1049  			JsonResponse:   `{}`,
  1050  			ResponseStatus: http.StatusOK,
  1051  			Method:         http.MethodPost,
  1052  			RequestPath:    "write",
  1053  		}
  1054  		requestBody := ClientWriteRequest{
  1055  			Writes: []ClientTupleKey{{
  1056  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1057  				Relation: "viewer",
  1058  				Object:   "document:roadmap",
  1059  			}},
  1060  		}
  1061  		options := ClientWriteOptions{
  1062  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1063  		}
  1064  
  1065  		var expectedResponse map[string]interface{}
  1066  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1067  			t.Fatalf("%v", err)
  1068  		}
  1069  
  1070  		_, err := fgaClient.Write(context.Background()).Body(requestBody).Options(options).Execute()
  1071  		if err == nil {
  1072  			t.Fatalf("Expect error due to invalid auth model ID but there is none")
  1073  		}
  1074  	})
  1075  
  1076  	t.Run("WriteNonTransaction", func(t *testing.T) {
  1077  		test := TestDefinition{
  1078  			Name:           "Write",
  1079  			JsonResponse:   `{}`,
  1080  			ResponseStatus: http.StatusOK,
  1081  			Method:         http.MethodPost,
  1082  			RequestPath:    "write",
  1083  		}
  1084  		requestBody := ClientWriteRequest{
  1085  			Writes: []ClientTupleKey{{
  1086  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1087  				Relation: "viewer",
  1088  				Object:   "document:roadmap",
  1089  			}, {
  1090  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1091  				Relation: "viewer",
  1092  				Object:   "document:budget",
  1093  			}},
  1094  			Deletes: []ClientTupleKeyWithoutCondition{{
  1095  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1096  				Relation: "viewer",
  1097  				Object:   "document:planning",
  1098  			}},
  1099  		}
  1100  		const authModelId = "01GAHCE4YVKPQEKZQHT2R89MQV"
  1101  		options := ClientWriteOptions{
  1102  			AuthorizationModelId: openfga.PtrString(authModelId),
  1103  			Transaction: &TransactionOptions{
  1104  				Disable:             true,
  1105  				MaxParallelRequests: 5,
  1106  				MaxPerChunk:         1,
  1107  			},
  1108  		}
  1109  
  1110  		var expectedResponse map[string]interface{}
  1111  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1112  			t.Fatalf("%v", err)
  1113  		}
  1114  
  1115  		httpmock.Activate()
  1116  		defer httpmock.DeactivateAndReset()
  1117  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1118  			func(req *http.Request) (*http.Response, error) {
  1119  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1120  				if err != nil {
  1121  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1122  				}
  1123  				return resp, nil
  1124  			},
  1125  		)
  1126  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, authModelId),
  1127  			func(req *http.Request) (*http.Response, error) {
  1128  				return httpmock.NewStringResponse(http.StatusOK, ""), nil
  1129  			},
  1130  		)
  1131  		data, err := fgaClient.Write(context.Background()).Body(requestBody).Options(options).Execute()
  1132  		if err != nil {
  1133  			t.Fatalf("%v", err)
  1134  		}
  1135  
  1136  		if len(data.Writes) != 2 {
  1137  			t.Fatalf("OpenFgaClient.%v() - expected %v Writes, got %v", test.Name, 2, len(data.Writes))
  1138  		}
  1139  
  1140  		if len(data.Deletes) != 1 {
  1141  			t.Fatalf("OpenFgaClient.%v() - expected %v Deletes, got %v", test.Name, 1, len(data.Deletes))
  1142  		}
  1143  
  1144  		for index := 0; index < len(data.Writes); index++ {
  1145  			response := data.Writes[index]
  1146  			if response.Error != nil {
  1147  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1148  			}
  1149  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1150  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1151  			}
  1152  
  1153  			_, err := response.MarshalJSON()
  1154  			if err != nil {
  1155  				t.Fatalf("%v", err)
  1156  			}
  1157  		}
  1158  
  1159  		for index := 0; index < len(data.Deletes); index++ {
  1160  			response := data.Deletes[index]
  1161  			if response.Error != nil {
  1162  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1163  			}
  1164  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1165  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1166  			}
  1167  
  1168  			_, err := response.MarshalJSON()
  1169  			if err != nil {
  1170  				t.Fatalf("%v", err)
  1171  			}
  1172  		}
  1173  	})
  1174  
  1175  	t.Run("WriteTuples", func(t *testing.T) {
  1176  		test := TestDefinition{
  1177  			Name:           "Write",
  1178  			JsonResponse:   `{}`,
  1179  			ResponseStatus: http.StatusOK,
  1180  			Method:         http.MethodPost,
  1181  			RequestPath:    "write",
  1182  		}
  1183  		requestBody := []ClientTupleKey{{
  1184  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1185  			Relation: "viewer",
  1186  			Object:   "document:roadmap",
  1187  		}}
  1188  		options := ClientWriteOptions{
  1189  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1190  		}
  1191  
  1192  		var expectedResponse map[string]interface{}
  1193  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1194  			t.Fatalf("%v", err)
  1195  		}
  1196  
  1197  		httpmock.Activate()
  1198  		defer httpmock.DeactivateAndReset()
  1199  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1200  			func(req *http.Request) (*http.Response, error) {
  1201  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1202  				if err != nil {
  1203  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1204  				}
  1205  				return resp, nil
  1206  			},
  1207  		)
  1208  		data, err := fgaClient.WriteTuples(context.Background()).Body(requestBody).Options(options).Execute()
  1209  		if err != nil {
  1210  			t.Fatalf("%v", err)
  1211  		}
  1212  
  1213  		if len(data.Writes) != 1 {
  1214  			t.Fatalf("OpenFgaClient.%v() - expected %v Writes, got %v", test.Name, 1, len(data.Writes))
  1215  		}
  1216  
  1217  		if len(data.Deletes) != 0 {
  1218  			t.Fatalf("OpenFgaClient.%v() - expected %v Deletes, got %v", test.Name, 0, len(data.Deletes))
  1219  		}
  1220  
  1221  		for index := 0; index < len(data.Writes); index++ {
  1222  			response := data.Writes[index]
  1223  			if response.Error != nil {
  1224  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1225  			}
  1226  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1227  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1228  			}
  1229  
  1230  			_, err := response.MarshalJSON()
  1231  			if err != nil {
  1232  				t.Fatalf("%v", err)
  1233  			}
  1234  		}
  1235  
  1236  		for index := 0; index < len(data.Deletes); index++ {
  1237  			response := data.Deletes[index]
  1238  			if response.Error != nil {
  1239  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1240  			}
  1241  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1242  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1243  			}
  1244  
  1245  			_, err := response.MarshalJSON()
  1246  			if err != nil {
  1247  				t.Fatalf("%v", err)
  1248  			}
  1249  		}
  1250  		// WriteTuples without options should work
  1251  		_, err = fgaClient.WriteTuples(context.Background()).Body(requestBody).Execute()
  1252  		if err != nil {
  1253  			t.Fatalf("%v", err)
  1254  		}
  1255  	})
  1256  
  1257  	t.Run("DeleteTuples", func(t *testing.T) {
  1258  		test := TestDefinition{
  1259  			Name:           "Write",
  1260  			JsonResponse:   `{}`,
  1261  			ResponseStatus: http.StatusOK,
  1262  			Method:         http.MethodPost,
  1263  			RequestPath:    "write",
  1264  		}
  1265  
  1266  		requestBody := []ClientTupleKeyWithoutCondition{{
  1267  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1268  			Relation: "viewer",
  1269  			Object:   "document:roadmap",
  1270  		}}
  1271  		options := ClientWriteOptions{
  1272  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1273  		}
  1274  
  1275  		var expectedResponse map[string]interface{}
  1276  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1277  			t.Fatalf("%v", err)
  1278  		}
  1279  
  1280  		httpmock.Activate()
  1281  		defer httpmock.DeactivateAndReset()
  1282  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1283  			func(req *http.Request) (*http.Response, error) {
  1284  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1285  				if err != nil {
  1286  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1287  				}
  1288  				return resp, nil
  1289  			},
  1290  		)
  1291  		data, err := fgaClient.DeleteTuples(context.Background()).Body(requestBody).Options(options).Execute()
  1292  		if err != nil {
  1293  			t.Fatalf("%v", err)
  1294  		}
  1295  
  1296  		if len(data.Writes) != 0 {
  1297  			t.Fatalf("OpenFgaClient.%v() - expected no Writes, got %v", test.Name, len(data.Writes))
  1298  		}
  1299  
  1300  		if len(data.Deletes) != 1 {
  1301  			t.Fatalf("OpenFgaClient.%v() - expected no Deletes, got %v", test.Name, len(data.Deletes))
  1302  		}
  1303  
  1304  		for index := 0; index < len(data.Writes); index++ {
  1305  			response := data.Writes[index]
  1306  			if response.Error != nil {
  1307  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1308  			}
  1309  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1310  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1311  			}
  1312  
  1313  			_, err := response.MarshalJSON()
  1314  			if err != nil {
  1315  				t.Fatalf("%v", err)
  1316  			}
  1317  		}
  1318  
  1319  		for index := 0; index < len(data.Deletes); index++ {
  1320  			response := data.Deletes[index]
  1321  			if response.Error != nil {
  1322  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1323  			}
  1324  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1325  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1326  			}
  1327  
  1328  			_, err := response.MarshalJSON()
  1329  			if err != nil {
  1330  				t.Fatalf("%v", err)
  1331  			}
  1332  		}
  1333  		// DeleteTuples without options should work
  1334  		_, err = fgaClient.DeleteTuples(context.Background()).Body(requestBody).Execute()
  1335  		if err != nil {
  1336  			t.Fatalf("%v", err)
  1337  		}
  1338  	})
  1339  
  1340  	/* Relationship Queries */
  1341  	t.Run("Check", func(t *testing.T) {
  1342  		test := TestDefinition{
  1343  			Name:           "Check",
  1344  			JsonResponse:   `{"allowed":true, "resolution":""}`,
  1345  			ResponseStatus: http.StatusOK,
  1346  			Method:         http.MethodPost,
  1347  			RequestPath:    "check",
  1348  		}
  1349  		requestBody := ClientCheckRequest{
  1350  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1351  			Relation: "viewer",
  1352  			Object:   "document:roadmap",
  1353  			ContextualTuples: []ClientContextualTupleKey{{
  1354  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1355  				Relation: "editor",
  1356  				Object:   "document:roadmap",
  1357  			}},
  1358  		}
  1359  
  1360  		options := ClientCheckOptions{
  1361  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1362  		}
  1363  
  1364  		var expectedResponse openfga.CheckResponse
  1365  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1366  			t.Fatalf("%v", err)
  1367  		}
  1368  
  1369  		httpmock.Activate()
  1370  		defer httpmock.DeactivateAndReset()
  1371  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1372  			func(req *http.Request) (*http.Response, error) {
  1373  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1374  				if err != nil {
  1375  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1376  				}
  1377  				return resp, nil
  1378  			},
  1379  		)
  1380  		got, err := fgaClient.Check(context.Background()).Body(requestBody).Options(options).Execute()
  1381  		if err != nil {
  1382  			t.Fatalf("%v", err)
  1383  		}
  1384  
  1385  		responseJson, err := got.MarshalJSON()
  1386  		if err != nil {
  1387  			t.Fatalf("%v", err)
  1388  		}
  1389  
  1390  		if got.GetAllowed() != *expectedResponse.Allowed {
  1391  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
  1392  		}
  1393  		// Check without options should work
  1394  		_, err = fgaClient.Check(context.Background()).Body(requestBody).Execute()
  1395  		if err != nil {
  1396  			t.Fatalf("%v", err)
  1397  		}
  1398  
  1399  		// check with invalid auth model id should result in error
  1400  		badOptions := ClientCheckOptions{
  1401  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1402  		}
  1403  		_, err = fgaClient.Check(context.Background()).Body(requestBody).Options(badOptions).Execute()
  1404  		if err == nil {
  1405  			t.Fatalf("Expect error with bad auth model id but there is none")
  1406  		}
  1407  
  1408  	})
  1409  
  1410  	t.Run("BatchCheck", func(t *testing.T) {
  1411  		test := TestDefinition{
  1412  			Name:           "Check",
  1413  			JsonResponse:   `{"allowed":true, "resolution":""}`,
  1414  			ResponseStatus: http.StatusOK,
  1415  			Method:         http.MethodPost,
  1416  			RequestPath:    "check",
  1417  		}
  1418  		requestBody := ClientBatchCheckBody{{
  1419  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1420  			Relation: "viewer",
  1421  			Object:   "document:roadmap",
  1422  			ContextualTuples: []ClientContextualTupleKey{{
  1423  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1424  				Relation: "editor",
  1425  				Object:   "document:roadmap",
  1426  			}},
  1427  		}, {
  1428  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1429  			Relation: "admin",
  1430  			Object:   "document:roadmap",
  1431  			ContextualTuples: []ClientContextualTupleKey{{
  1432  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1433  				Relation: "editor",
  1434  				Object:   "document:roadmap",
  1435  			}},
  1436  		}, {
  1437  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1438  			Relation: "creator",
  1439  			Object:   "document:roadmap",
  1440  		}, {
  1441  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1442  			Relation: "deleter",
  1443  			Object:   "document:roadmap",
  1444  		}}
  1445  
  1446  		const authModelId = "01GAHCE4YVKPQEKZQHT2R89MQV"
  1447  
  1448  		options := ClientBatchCheckOptions{
  1449  			AuthorizationModelId: openfga.PtrString(authModelId),
  1450  			MaxParallelRequests:  openfga.PtrInt32(5),
  1451  		}
  1452  
  1453  		var expectedResponse openfga.CheckResponse
  1454  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1455  			t.Fatalf("%v", err)
  1456  		}
  1457  
  1458  		httpmock.Activate()
  1459  		defer httpmock.DeactivateAndReset()
  1460  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1461  			func(req *http.Request) (*http.Response, error) {
  1462  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1463  				if err != nil {
  1464  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1465  				}
  1466  				return resp, nil
  1467  			},
  1468  		)
  1469  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId),
  1470  			func(req *http.Request) (*http.Response, error) {
  1471  				return httpmock.NewStringResponse(http.StatusOK, ""), nil
  1472  			},
  1473  		)
  1474  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, authModelId),
  1475  			func(req *http.Request) (*http.Response, error) {
  1476  				return httpmock.NewStringResponse(http.StatusOK, ""), nil
  1477  			},
  1478  		)
  1479  		got, err := fgaClient.BatchCheck(context.Background()).Body(requestBody).Options(options).Execute()
  1480  		if err != nil {
  1481  			t.Fatalf("%v", err)
  1482  		}
  1483  
  1484  		if httpmock.GetTotalCallCount() != 5 {
  1485  			t.Fatalf("OpenFgaClient.%v() - wanted %v calls to /check + 1 call to validate auth model, got %v", test.Name, 4, httpmock.GetTotalCallCount())
  1486  		}
  1487  
  1488  		if len(*got) != len(requestBody) {
  1489  			t.Fatalf("OpenFgaClient.%v() - Response Length = %v, want %v", test.Name, len(*got), len(requestBody))
  1490  		}
  1491  
  1492  		for index := 0; index < len(*got); index++ {
  1493  			response := (*got)[index]
  1494  			if response.Error != nil {
  1495  				t.Fatalf("OpenFgaClient.%v()|%d/ %v", test.Name, index, response.Error)
  1496  			}
  1497  			if response.HttpResponse.StatusCode != test.ResponseStatus {
  1498  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, response.HttpResponse.StatusCode, test.ResponseStatus)
  1499  			}
  1500  
  1501  			responseJson, err := response.MarshalJSON()
  1502  			if err != nil {
  1503  				t.Fatalf("%v", err)
  1504  			}
  1505  
  1506  			if *response.Allowed != *expectedResponse.Allowed {
  1507  				t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
  1508  			}
  1509  		}
  1510  		// BatchCheck without options should work
  1511  		_, err = fgaClient.BatchCheck(context.Background()).Body(requestBody).Execute()
  1512  		if err != nil {
  1513  			t.Fatalf("%v", err)
  1514  		}
  1515  		// BatchCheck with invalid auth model ID should fail
  1516  		badOptions := ClientBatchCheckOptions{
  1517  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1518  			MaxParallelRequests:  openfga.PtrInt32(5),
  1519  		}
  1520  		_, err = fgaClient.BatchCheck(context.Background()).Body(requestBody).Options(badOptions).Execute()
  1521  		if err == nil {
  1522  			t.Fatalf("Expect error with invalid auth model id but there is none")
  1523  		}
  1524  
  1525  	})
  1526  
  1527  	t.Run("BatchCheckConnectionProblem", func(t *testing.T) {
  1528  		test := TestDefinition{
  1529  			Name:           "Check",
  1530  			JsonResponse:   `{"allowed":true, "resolution":""}`,
  1531  			ResponseStatus: http.StatusOK,
  1532  			Method:         http.MethodPost,
  1533  			RequestPath:    "check",
  1534  		}
  1535  		requestBody := ClientBatchCheckBody{{
  1536  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1537  			Relation: "viewer",
  1538  			Object:   "document:roadmap",
  1539  			ContextualTuples: []ClientContextualTupleKey{{
  1540  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1541  				Relation: "editor",
  1542  				Object:   "document:roadmap",
  1543  			}},
  1544  		}, {
  1545  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1546  			Relation: "admin",
  1547  			Object:   "document:roadmap",
  1548  			ContextualTuples: []ClientContextualTupleKey{{
  1549  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1550  				Relation: "editor",
  1551  				Object:   "document:roadmap",
  1552  			}},
  1553  		}, {
  1554  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1555  			Relation: "creator",
  1556  			Object:   "document:roadmap",
  1557  		}, {
  1558  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1559  			Relation: "deleter",
  1560  			Object:   "document:roadmap",
  1561  		}}
  1562  
  1563  		const authModelId = "01GAHCE4YVKPQEKZQHT2R89MQV"
  1564  
  1565  		options := ClientBatchCheckOptions{
  1566  			AuthorizationModelId: openfga.PtrString(authModelId),
  1567  			MaxParallelRequests:  openfga.PtrInt32(5),
  1568  		}
  1569  
  1570  		var expectedResponse openfga.CheckResponse
  1571  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1572  			t.Fatalf("%v", err)
  1573  		}
  1574  
  1575  		httpmock.Activate()
  1576  		defer httpmock.DeactivateAndReset()
  1577  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1578  			func(req *http.Request) (*http.Response, error) {
  1579  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1580  				if err != nil {
  1581  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1582  				}
  1583  				return resp, nil
  1584  			},
  1585  		)
  1586  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId),
  1587  			func(req *http.Request) (*http.Response, error) {
  1588  				return httpmock.NewStringResponse(http.StatusUnauthorized, ""), nil
  1589  			},
  1590  		)
  1591  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, authModelId),
  1592  			func(req *http.Request) (*http.Response, error) {
  1593  				return httpmock.NewStringResponse(http.StatusUnauthorized, ""), nil
  1594  			},
  1595  		)
  1596  		_, err := fgaClient.BatchCheck(context.Background()).Body(requestBody).Options(options).Execute()
  1597  		if err == nil {
  1598  			t.Fatalf("Expect error but there is none")
  1599  		}
  1600  
  1601  	})
  1602  
  1603  	t.Run("Expand", func(t *testing.T) {
  1604  		test := TestDefinition{
  1605  			Name:           "Expand",
  1606  			JsonResponse:   `{"tree":{"root":{"name":"document:roadmap#viewer","union":{"nodes":[{"name": "document:roadmap#viewer","leaf":{"users":{"users":["user:81684243-9356-4421-8fbf-a4f8d36aa31b"]}}}]}}}}`,
  1607  			ResponseStatus: http.StatusOK,
  1608  			Method:         http.MethodPost,
  1609  			RequestPath:    "expand",
  1610  		}
  1611  
  1612  		requestBody := ClientExpandRequest{
  1613  			Relation: "viewer",
  1614  			Object:   "document:roadmap",
  1615  		}
  1616  		options := ClientExpandOptions{
  1617  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1618  		}
  1619  
  1620  		var expectedResponse openfga.ExpandResponse
  1621  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1622  			t.Fatalf("%v", err)
  1623  		}
  1624  
  1625  		httpmock.Activate()
  1626  		defer httpmock.DeactivateAndReset()
  1627  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1628  			func(req *http.Request) (*http.Response, error) {
  1629  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1630  				if err != nil {
  1631  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1632  				}
  1633  				return resp, nil
  1634  			},
  1635  		)
  1636  		got, err := fgaClient.Expand(context.Background()).Body(requestBody).Options(options).Execute()
  1637  		if err != nil {
  1638  			t.Fatalf("%v", err)
  1639  		}
  1640  
  1641  		_, err = got.MarshalJSON()
  1642  		if err != nil {
  1643  			t.Fatalf("%v", err)
  1644  		}
  1645  		// Expand without options should work
  1646  		_, err = fgaClient.Expand(context.Background()).Body(requestBody).Execute()
  1647  		if err != nil {
  1648  			t.Fatalf("%v", err)
  1649  		}
  1650  		// Invalid auth model ID should result in error
  1651  		badOptions := ClientExpandOptions{
  1652  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1653  		}
  1654  		_, err = fgaClient.Expand(context.Background()).Body(requestBody).Options(badOptions).Execute()
  1655  		if err == nil {
  1656  			t.Fatalf("Expect error for invalid auth model id but there is none")
  1657  		}
  1658  	})
  1659  
  1660  	t.Run("ListObjects", func(t *testing.T) {
  1661  		test := TestDefinition{
  1662  			Name:           "ListObjects",
  1663  			JsonResponse:   `{"objects":["document:roadmap"]}`,
  1664  			ResponseStatus: http.StatusOK,
  1665  			Method:         http.MethodPost,
  1666  			RequestPath:    "list-objects",
  1667  		}
  1668  
  1669  		requestBody := ClientListObjectsRequest{
  1670  			User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1671  			Relation: "can_read",
  1672  			Type:     "document",
  1673  			ContextualTuples: []ClientContextualTupleKey{{
  1674  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1675  				Relation: "editor",
  1676  				Object:   "folder:product",
  1677  			}, {
  1678  				User:     "folder:product",
  1679  				Relation: "parent",
  1680  				Object:   "document:roadmap",
  1681  			}},
  1682  		}
  1683  		options := ClientListObjectsOptions{
  1684  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1685  		}
  1686  
  1687  		var expectedResponse openfga.ListObjectsResponse
  1688  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1689  			t.Fatalf("%v", err)
  1690  		}
  1691  
  1692  		httpmock.Activate()
  1693  		defer httpmock.DeactivateAndReset()
  1694  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1695  			func(req *http.Request) (*http.Response, error) {
  1696  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1697  				if err != nil {
  1698  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1699  				}
  1700  				return resp, nil
  1701  			},
  1702  		)
  1703  		got, err := fgaClient.ListObjects(context.Background()).
  1704  			Body(requestBody).
  1705  			Options(options).
  1706  			Execute()
  1707  		if err != nil {
  1708  			t.Fatalf("%v", err)
  1709  		}
  1710  
  1711  		responseJson, err := got.MarshalJSON()
  1712  		if err != nil {
  1713  			t.Fatalf("%v", err)
  1714  		}
  1715  
  1716  		if len(got.Objects) != len(expectedResponse.Objects) || (got.Objects)[0] != (expectedResponse.Objects)[0] {
  1717  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
  1718  		}
  1719  		// ListObjects without options should work
  1720  		_, err = fgaClient.ListObjects(context.Background()).Body(requestBody).Execute()
  1721  		if err != nil {
  1722  			t.Fatalf("%v", err)
  1723  		}
  1724  		// Invalid auth model id should result in error
  1725  		badOptions := ClientListObjectsOptions{
  1726  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1727  		}
  1728  		_, err = fgaClient.ListObjects(context.Background()).
  1729  			Body(requestBody).
  1730  			Options(badOptions).
  1731  			Execute()
  1732  		if err == nil {
  1733  			t.Fatalf("Expect error with invalid auth model id but there is none")
  1734  		}
  1735  	})
  1736  
  1737  	t.Run("ListRelations", func(t *testing.T) {
  1738  		test := TestDefinition{
  1739  			Name:           "ListRelations",
  1740  			JsonResponse:   `{"allowed":true, "resolution":""}`,
  1741  			ResponseStatus: http.StatusOK,
  1742  			Method:         http.MethodPost,
  1743  			RequestPath:    "check",
  1744  		}
  1745  
  1746  		requestBody := ClientListRelationsRequest{
  1747  			User:      "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1748  			Object:    "document:roadmap",
  1749  			Relations: []string{"can_view", "can_edit", "can_delete", "can_rename"},
  1750  			ContextualTuples: []ClientContextualTupleKey{{
  1751  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1752  				Relation: "editor",
  1753  				Object:   "document:roadmap",
  1754  			}},
  1755  		}
  1756  		const authModelId = "01GAHCE4YVKPQEKZQHT2R89MQV"
  1757  		options := ClientListRelationsOptions{
  1758  			AuthorizationModelId: openfga.PtrString(authModelId),
  1759  		}
  1760  
  1761  		var expectedResponse openfga.CheckResponse
  1762  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1763  			t.Fatalf("%v", err)
  1764  		}
  1765  
  1766  		httpmock.Activate()
  1767  		defer httpmock.DeactivateAndReset()
  1768  		httpmock.RegisterMatcherResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1769  			httpmock.BodyContainsString(`"relation":"can_delete"`),
  1770  			func(req *http.Request) (*http.Response, error) {
  1771  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, openfga.CheckResponse{Allowed: openfga.PtrBool(false)})
  1772  				if err != nil {
  1773  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1774  				}
  1775  				return resp, nil
  1776  			},
  1777  		)
  1778  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath),
  1779  			func(req *http.Request) (*http.Response, error) {
  1780  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1781  				if err != nil {
  1782  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1783  				}
  1784  				return resp, nil
  1785  			},
  1786  		)
  1787  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId),
  1788  			func(req *http.Request) (*http.Response, error) {
  1789  				return httpmock.NewStringResponse(http.StatusOK, ""), nil
  1790  			},
  1791  		)
  1792  		httpmock.RegisterResponder("GET", fmt.Sprintf("%s/stores/%s/authorization-models/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, authModelId),
  1793  			func(req *http.Request) (*http.Response, error) {
  1794  				return httpmock.NewStringResponse(http.StatusOK, ""), nil
  1795  			},
  1796  		)
  1797  
  1798  		got, err := fgaClient.ListRelations(context.Background()).
  1799  			Body(requestBody).
  1800  			Options(options).
  1801  			Execute()
  1802  		if err != nil {
  1803  			t.Fatalf("%v", err)
  1804  		}
  1805  
  1806  		if httpmock.GetTotalCallCount() != 5 {
  1807  			t.Fatalf("OpenFgaClient.%v() - wanted %v calls to /check + 1 call to validate auth model, got %v", test.Name, 4, httpmock.GetTotalCallCount())
  1808  		}
  1809  
  1810  		_, err = got.MarshalJSON()
  1811  		if err != nil {
  1812  			t.Fatalf("%v", err)
  1813  		}
  1814  
  1815  		if len(got.Relations) != 3 {
  1816  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, len(got.Relations), 3)
  1817  		}
  1818  		// ListRelations without options should work
  1819  		_, err = fgaClient.ListRelations(context.Background()).Body(requestBody).Execute()
  1820  		if err != nil {
  1821  			t.Fatalf("%v", err)
  1822  		}
  1823  		// Invalid auth model ID should result in error
  1824  		badOptions := ClientListRelationsOptions{
  1825  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1826  		}
  1827  		_, err = fgaClient.ListRelations(context.Background()).
  1828  			Body(requestBody).
  1829  			Options(badOptions).
  1830  			Execute()
  1831  		if err == nil {
  1832  			t.Fatalf("Expect error with invalid auth model id but there is none")
  1833  		}
  1834  
  1835  	})
  1836  
  1837  	t.Run("ListRelationsNoRelationsProvided", func(t *testing.T) {
  1838  		test := TestDefinition{
  1839  			Name:           "ListRelations",
  1840  			JsonResponse:   ``,
  1841  			ResponseStatus: http.StatusOK,
  1842  			Method:         http.MethodPost,
  1843  			RequestPath:    "check",
  1844  		}
  1845  
  1846  		requestBody := ClientListRelationsRequest{
  1847  			User:      "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1848  			Object:    "document:roadmap",
  1849  			Relations: []string{},
  1850  			ContextualTuples: []ClientContextualTupleKey{{
  1851  				User:     "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1852  				Relation: "editor",
  1853  				Object:   "document:roadmap",
  1854  			}},
  1855  		}
  1856  		options := ClientListRelationsOptions{
  1857  			AuthorizationModelId: openfga.PtrString("01GAHCE4YVKPQEKZQHT2R89MQV"),
  1858  		}
  1859  
  1860  		httpmock.Activate()
  1861  		defer httpmock.DeactivateAndReset()
  1862  		_, err := fgaClient.ListRelations(context.Background()).
  1863  			Body(requestBody).
  1864  			Options(options).
  1865  			Execute()
  1866  
  1867  		if err == nil {
  1868  			t.Fatalf("OpenFgaClient.%v() - expected an error but received none", test.Name)
  1869  		}
  1870  	})
  1871  
  1872  	/* Assertions */
  1873  	t.Run("ReadAssertions", func(t *testing.T) {
  1874  		modelId := "01GAHCE4YVKPQEKZQHT2R89MQV"
  1875  		test := TestDefinition{
  1876  			Name:           "ReadAssertions",
  1877  			JsonResponse:   fmt.Sprintf(`{"assertions":[{"tuple_key":{"user":"user:anna","relation":"can_view","object":"document:roadmap"},"expectation":true}],"authorization_model_id":"%s"}`, modelId),
  1878  			ResponseStatus: http.StatusOK,
  1879  			Method:         http.MethodGet,
  1880  			RequestPath:    "assertions",
  1881  		}
  1882  
  1883  		options := ClientReadAssertionsOptions{
  1884  			AuthorizationModelId: openfga.PtrString(modelId),
  1885  		}
  1886  
  1887  		var expectedResponse openfga.ReadAssertionsResponse
  1888  		if err := json.Unmarshal([]byte(test.JsonResponse), &expectedResponse); err != nil {
  1889  			t.Fatalf("%v", err)
  1890  		}
  1891  
  1892  		httpmock.Activate()
  1893  		defer httpmock.DeactivateAndReset()
  1894  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath, modelId),
  1895  			func(req *http.Request) (*http.Response, error) {
  1896  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, expectedResponse)
  1897  				if err != nil {
  1898  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1899  				}
  1900  				return resp, nil
  1901  			},
  1902  		)
  1903  		got, err := fgaClient.ReadAssertions(context.Background()).
  1904  			Options(options).
  1905  			Execute()
  1906  		if err != nil {
  1907  			t.Fatalf("%v", err)
  1908  		}
  1909  
  1910  		responseJson, err := got.MarshalJSON()
  1911  		if err != nil {
  1912  			t.Fatalf("%v", err)
  1913  		}
  1914  
  1915  		if len(*got.Assertions) != len(*expectedResponse.Assertions) || (*got.Assertions)[0].Expectation != (*expectedResponse.Assertions)[0].Expectation {
  1916  			t.Fatalf("OpenFgaClient.%v() = %v, want %v", test.Name, string(responseJson), test.JsonResponse)
  1917  		}
  1918  		// ReadAssertions without options should work
  1919  		_, err = fgaClient.ReadAssertions(context.Background()).Execute()
  1920  		expectedError := "Required parameter AuthorizationModelId was not provided"
  1921  		if err == nil || err.Error() != expectedError {
  1922  			t.Fatalf("Expected error:%v, got: %v", expectedError, err)
  1923  		}
  1924  
  1925  		// Invalid auth model id should result in error
  1926  		badOptions := ClientReadAssertionsOptions{
  1927  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1928  		}
  1929  		_, err = fgaClient.ReadAssertions(context.Background()).
  1930  			Options(badOptions).
  1931  			Execute()
  1932  		if err == nil {
  1933  			t.Fatalf("Invalid auth model ID should result in error")
  1934  		}
  1935  	})
  1936  
  1937  	t.Run("WriteAssertions", func(t *testing.T) {
  1938  		modelId := "01GAHCE4YVKPQEKZQHT2R89MQV"
  1939  		test := TestDefinition{
  1940  			Name:           "WriteAssertions",
  1941  			JsonResponse:   "",
  1942  			ResponseStatus: http.StatusNoContent,
  1943  			Method:         http.MethodPut,
  1944  			RequestPath:    "assertions",
  1945  		}
  1946  
  1947  		requestBody := ClientWriteAssertionsRequest{
  1948  			{
  1949  				User:        "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
  1950  				Relation:    "can_view",
  1951  				Object:      "document:roadmap",
  1952  				Expectation: true,
  1953  			},
  1954  		}
  1955  		options := ClientWriteAssertionsOptions{
  1956  			AuthorizationModelId: openfga.PtrString(modelId),
  1957  		}
  1958  
  1959  		httpmock.Activate()
  1960  		defer httpmock.DeactivateAndReset()
  1961  		httpmock.RegisterResponder(test.Method, fmt.Sprintf("%s/stores/%s/%s/%s", fgaClient.GetConfig().ApiUrl, fgaClient.GetConfig().StoreId, test.RequestPath, modelId),
  1962  			func(req *http.Request) (*http.Response, error) {
  1963  				resp, err := httpmock.NewJsonResponse(test.ResponseStatus, "")
  1964  				if err != nil {
  1965  					return httpmock.NewStringResponse(http.StatusInternalServerError, ""), nil
  1966  				}
  1967  				return resp, nil
  1968  			},
  1969  		)
  1970  		_, err := fgaClient.WriteAssertions(context.Background()).
  1971  			Body(requestBody).
  1972  			Options(options).
  1973  			Execute()
  1974  		if err != nil {
  1975  			t.Fatalf("%v", err)
  1976  		}
  1977  		// WriteAssertions without options should work
  1978  		_, err = fgaClient.WriteAssertions(context.Background()).Body(requestBody).Execute()
  1979  		expectedError := "Required parameter AuthorizationModelId was not provided"
  1980  		if err == nil || err.Error() != expectedError {
  1981  			t.Fatalf("Expected error:%v, got: %v", expectedError, err)
  1982  		}
  1983  		badOptions := ClientWriteAssertionsOptions{
  1984  			AuthorizationModelId: openfga.PtrString("INVALID"),
  1985  		}
  1986  		_, err = fgaClient.WriteAssertions(context.Background()).
  1987  			Body(requestBody).
  1988  			Options(badOptions).
  1989  			Execute()
  1990  		if err == nil {
  1991  			t.Fatalf("Invalid auth model id should result in error but there is none")
  1992  		}
  1993  	})
  1994  }