github.com/google/go-github/v64@v64.0.0/github/orgs_properties_test.go (about)

     1  // Copyright 2023 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"net/http"
    12  	"testing"
    13  
    14  	"github.com/google/go-cmp/cmp"
    15  )
    16  
    17  func TestOrganizationsService_GetAllCustomProperties(t *testing.T) {
    18  	client, mux, _, teardown := setup()
    19  	defer teardown()
    20  
    21  	mux.HandleFunc("/orgs/o/properties/schema", func(w http.ResponseWriter, r *http.Request) {
    22  		testMethod(t, r, "GET")
    23  		fmt.Fprint(w, `[
    24  		{
    25            "property_name": "name",
    26            "value_type": "single_select",
    27            "required": true,
    28            "default_value": "production",
    29            "description": "Prod or dev environment",
    30            "allowed_values":[
    31              "production",
    32              "development"
    33            ],
    34            "values_editable_by": "org_actors"
    35          },
    36          {
    37            "property_name": "service",
    38            "value_type": "string"
    39          },
    40          {
    41            "property_name": "team",
    42            "value_type": "string",
    43            "description": "Team owning the repository"
    44          }
    45          ]`)
    46  	})
    47  
    48  	ctx := context.Background()
    49  	properties, _, err := client.Organizations.GetAllCustomProperties(ctx, "o")
    50  	if err != nil {
    51  		t.Errorf("Organizations.GetAllCustomProperties returned error: %v", err)
    52  	}
    53  
    54  	want := []*CustomProperty{
    55  		{
    56  			PropertyName:     String("name"),
    57  			ValueType:        "single_select",
    58  			Required:         Bool(true),
    59  			DefaultValue:     String("production"),
    60  			Description:      String("Prod or dev environment"),
    61  			AllowedValues:    []string{"production", "development"},
    62  			ValuesEditableBy: String("org_actors"),
    63  		},
    64  		{
    65  			PropertyName: String("service"),
    66  			ValueType:    "string",
    67  		},
    68  		{
    69  			PropertyName: String("team"),
    70  			ValueType:    "string",
    71  			Description:  String("Team owning the repository"),
    72  		},
    73  	}
    74  	if !cmp.Equal(properties, want) {
    75  		t.Errorf("Organizations.GetAllCustomProperties returned %+v, want %+v", properties, want)
    76  	}
    77  
    78  	const methodName = "GetAllCustomProperties"
    79  
    80  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    81  		got, resp, err := client.Organizations.GetAllCustomProperties(ctx, "o")
    82  		if got != nil {
    83  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    84  		}
    85  		return resp, err
    86  	})
    87  }
    88  
    89  func TestOrganizationsService_CreateOrUpdateCustomProperties(t *testing.T) {
    90  	client, mux, _, teardown := setup()
    91  	defer teardown()
    92  
    93  	mux.HandleFunc("/orgs/o/properties/schema", func(w http.ResponseWriter, r *http.Request) {
    94  		testMethod(t, r, "PATCH")
    95  		testBody(t, r, `{"properties":[{"property_name":"name","value_type":"single_select","required":true},{"property_name":"service","value_type":"string"}]}`+"\n")
    96  		fmt.Fprint(w, `[
    97  		{
    98            "property_name": "name",
    99            "value_type": "single_select",
   100            "required": true
   101          },
   102          {
   103            "property_name": "service",
   104            "value_type": "string"
   105          }
   106          ]`)
   107  	})
   108  
   109  	ctx := context.Background()
   110  	properties, _, err := client.Organizations.CreateOrUpdateCustomProperties(ctx, "o", []*CustomProperty{
   111  		{
   112  			PropertyName: String("name"),
   113  			ValueType:    "single_select",
   114  			Required:     Bool(true),
   115  		},
   116  		{
   117  			PropertyName: String("service"),
   118  			ValueType:    "string",
   119  		},
   120  	})
   121  	if err != nil {
   122  		t.Errorf("Organizations.CreateOrUpdateCustomProperties returned error: %v", err)
   123  	}
   124  
   125  	want := []*CustomProperty{
   126  		{
   127  			PropertyName: String("name"),
   128  			ValueType:    "single_select",
   129  			Required:     Bool(true),
   130  		},
   131  		{
   132  			PropertyName: String("service"),
   133  			ValueType:    "string",
   134  		},
   135  	}
   136  
   137  	if !cmp.Equal(properties, want) {
   138  		t.Errorf("Organizations.CreateOrUpdateCustomProperties returned %+v, want %+v", properties, want)
   139  	}
   140  
   141  	const methodName = "CreateOrUpdateCustomProperties"
   142  
   143  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   144  		got, resp, err := client.Organizations.CreateOrUpdateCustomProperties(ctx, "o", nil)
   145  		if got != nil {
   146  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   147  		}
   148  		return resp, err
   149  	})
   150  }
   151  
   152  func TestOrganizationsService_GetCustomProperty(t *testing.T) {
   153  	client, mux, _, teardown := setup()
   154  	defer teardown()
   155  
   156  	mux.HandleFunc("/orgs/o/properties/schema/name", func(w http.ResponseWriter, r *http.Request) {
   157  		testMethod(t, r, "GET")
   158  		fmt.Fprint(w, `{
   159  		"property_name": "name",
   160  		"value_type": "single_select",
   161  		"required": true,
   162  		"default_value": "production",
   163  		"description": "Prod or dev environment",
   164  		"allowed_values":[
   165  		  "production",
   166  		  "development"
   167  		],
   168  		"values_editable_by": "org_actors"
   169  	  }`)
   170  	})
   171  
   172  	ctx := context.Background()
   173  	property, _, err := client.Organizations.GetCustomProperty(ctx, "o", "name")
   174  	if err != nil {
   175  		t.Errorf("Organizations.GetCustomProperty returned error: %v", err)
   176  	}
   177  
   178  	want := &CustomProperty{
   179  		PropertyName:     String("name"),
   180  		ValueType:        "single_select",
   181  		Required:         Bool(true),
   182  		DefaultValue:     String("production"),
   183  		Description:      String("Prod or dev environment"),
   184  		AllowedValues:    []string{"production", "development"},
   185  		ValuesEditableBy: String("org_actors"),
   186  	}
   187  	if !cmp.Equal(property, want) {
   188  		t.Errorf("Organizations.GetCustomProperty returned %+v, want %+v", property, want)
   189  	}
   190  
   191  	const methodName = "GetCustomProperty"
   192  
   193  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   194  		got, resp, err := client.Organizations.GetCustomProperty(ctx, "o", "name")
   195  		if got != nil {
   196  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   197  		}
   198  		return resp, err
   199  	})
   200  }
   201  
   202  func TestOrganizationsService_CreateOrUpdateCustomProperty(t *testing.T) {
   203  	client, mux, _, teardown := setup()
   204  	defer teardown()
   205  
   206  	mux.HandleFunc("/orgs/o/properties/schema/name", func(w http.ResponseWriter, r *http.Request) {
   207  		testMethod(t, r, "PUT")
   208  		fmt.Fprint(w, `{
   209  		"property_name": "name",
   210  		"value_type": "single_select",
   211  		"required": true,
   212  		"default_value": "production",
   213  		"description": "Prod or dev environment",
   214  		"allowed_values":[
   215  		  "production",
   216  		  "development"
   217  		],
   218  		"values_editable_by": "org_actors"
   219  	  }`)
   220  	})
   221  
   222  	ctx := context.Background()
   223  	property, _, err := client.Organizations.CreateOrUpdateCustomProperty(ctx, "o", "name", &CustomProperty{
   224  		ValueType:        "single_select",
   225  		Required:         Bool(true),
   226  		DefaultValue:     String("production"),
   227  		Description:      String("Prod or dev environment"),
   228  		AllowedValues:    []string{"production", "development"},
   229  		ValuesEditableBy: String("org_actors"),
   230  	})
   231  	if err != nil {
   232  		t.Errorf("Organizations.CreateOrUpdateCustomProperty returned error: %v", err)
   233  	}
   234  
   235  	want := &CustomProperty{
   236  		PropertyName:     String("name"),
   237  		ValueType:        "single_select",
   238  		Required:         Bool(true),
   239  		DefaultValue:     String("production"),
   240  		Description:      String("Prod or dev environment"),
   241  		AllowedValues:    []string{"production", "development"},
   242  		ValuesEditableBy: String("org_actors"),
   243  	}
   244  	if !cmp.Equal(property, want) {
   245  		t.Errorf("Organizations.CreateOrUpdateCustomProperty returned %+v, want %+v", property, want)
   246  	}
   247  
   248  	const methodName = "CreateOrUpdateCustomProperty"
   249  
   250  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   251  		got, resp, err := client.Organizations.CreateOrUpdateCustomProperty(ctx, "o", "name", nil)
   252  		if got != nil {
   253  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   254  		}
   255  		return resp, err
   256  	})
   257  }
   258  
   259  func TestOrganizationsService_RemoveCustomProperty(t *testing.T) {
   260  	client, mux, _, teardown := setup()
   261  	defer teardown()
   262  
   263  	mux.HandleFunc("/orgs/o/properties/schema/name", func(w http.ResponseWriter, r *http.Request) {
   264  		testMethod(t, r, "DELETE")
   265  	})
   266  
   267  	ctx := context.Background()
   268  	_, err := client.Organizations.RemoveCustomProperty(ctx, "o", "name")
   269  	if err != nil {
   270  		t.Errorf("Organizations.RemoveCustomProperty returned error: %v", err)
   271  	}
   272  
   273  	const methodName = "RemoveCustomProperty"
   274  
   275  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   276  		return client.Organizations.RemoveCustomProperty(ctx, "0", "name")
   277  	})
   278  }
   279  
   280  func TestOrganizationsService_ListCustomPropertyValues(t *testing.T) {
   281  	client, mux, _, teardown := setup()
   282  	defer teardown()
   283  
   284  	mux.HandleFunc("/orgs/o/properties/values", func(w http.ResponseWriter, r *http.Request) {
   285  		testMethod(t, r, "GET")
   286  		testFormValues(t, r, values{"page": "1", "per_page": "100"})
   287  		fmt.Fprint(w, `[{
   288  		"repository_id": 1296269,
   289  		"repository_name": "Hello-World",
   290  		"repository_full_name": "octocat/Hello-World",
   291  		"properties": [
   292  		{
   293            "property_name": "environment",
   294            "value": "production"
   295          },
   296          {
   297            "property_name": "service",
   298            "value": "web"
   299          },
   300          {
   301            "property_name": "languages",
   302            "value": ["Go", "JavaScript"]
   303          },
   304          {
   305            "property_name": "null_property",
   306            "value": null
   307          }
   308  		]
   309          }]`)
   310  	})
   311  
   312  	ctx := context.Background()
   313  	repoPropertyValues, _, err := client.Organizations.ListCustomPropertyValues(ctx, "o", &ListOptions{
   314  		Page:    1,
   315  		PerPage: 100,
   316  	})
   317  	if err != nil {
   318  		t.Errorf("Organizations.ListCustomPropertyValues returned error: %v", err)
   319  	}
   320  
   321  	want := []*RepoCustomPropertyValue{
   322  		{
   323  			RepositoryID:       1296269,
   324  			RepositoryName:     "Hello-World",
   325  			RepositoryFullName: "octocat/Hello-World",
   326  			Properties: []*CustomPropertyValue{
   327  				{
   328  					PropertyName: "environment",
   329  					Value:        "production",
   330  				},
   331  				{
   332  					PropertyName: "service",
   333  					Value:        "web",
   334  				},
   335  				{
   336  					PropertyName: "languages",
   337  					Value:        []string{"Go", "JavaScript"},
   338  				},
   339  				{
   340  					PropertyName: "null_property",
   341  					Value:        nil,
   342  				},
   343  			},
   344  		},
   345  	}
   346  
   347  	if !cmp.Equal(repoPropertyValues, want) {
   348  		t.Errorf("Organizations.ListCustomPropertyValues returned %+v, want %+v", repoPropertyValues, want)
   349  	}
   350  
   351  	const methodName = "ListCustomPropertyValues"
   352  
   353  	testBadOptions(t, methodName, func() (err error) {
   354  		_, _, err = client.Organizations.ListCustomPropertyValues(ctx, "\n", &ListOptions{})
   355  		return err
   356  	})
   357  
   358  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   359  		got, resp, err := client.Organizations.ListCustomPropertyValues(ctx, "o", nil)
   360  		if got != nil {
   361  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   362  		}
   363  		return resp, err
   364  	})
   365  }
   366  
   367  func TestCustomPropertyValue_UnmarshalJSON(t *testing.T) {
   368  	tests := map[string]struct {
   369  		data    string
   370  		want    *CustomPropertyValue
   371  		wantErr bool
   372  	}{
   373  		"Invalid JSON": {
   374  			data:    `{`,
   375  			want:    &CustomPropertyValue{},
   376  			wantErr: true,
   377  		},
   378  		"String value": {
   379  			data: `{
   380  				"property_name": "environment",
   381  				"value": "production"
   382  			}`,
   383  			want: &CustomPropertyValue{
   384  				PropertyName: "environment",
   385  				Value:        "production",
   386  			},
   387  			wantErr: false,
   388  		},
   389  		"Array of strings value": {
   390  			data: `{
   391  				"property_name": "languages",
   392  				"value": ["Go", "JavaScript"]
   393  			}`,
   394  			want: &CustomPropertyValue{
   395  				PropertyName: "languages",
   396  				Value:        []string{"Go", "JavaScript"},
   397  			},
   398  			wantErr: false,
   399  		},
   400  		"Non-string value in array": {
   401  			data: `{
   402  				"property_name": "languages",
   403  				"value": ["Go", 42]
   404  			}`,
   405  			want: &CustomPropertyValue{
   406  				PropertyName: "languages",
   407  				Value:        nil,
   408  			},
   409  			wantErr: true,
   410  		},
   411  		"Unexpected value type": {
   412  			data: `{
   413  				"property_name": "environment",
   414  				"value": {"invalid": "type"}
   415  			}`,
   416  			want: &CustomPropertyValue{
   417  				PropertyName: "environment",
   418  				Value:        nil,
   419  			},
   420  			wantErr: true,
   421  		},
   422  	}
   423  
   424  	for name, tc := range tests {
   425  		t.Run(name, func(t *testing.T) {
   426  			cpv := &CustomPropertyValue{}
   427  			err := cpv.UnmarshalJSON([]byte(tc.data))
   428  			if (err != nil) != tc.wantErr {
   429  				t.Errorf("CustomPropertyValue.UnmarshalJSON error = %v, wantErr %v", err, tc.wantErr)
   430  				return
   431  			}
   432  			if !tc.wantErr && !cmp.Equal(tc.want, cpv) {
   433  				t.Errorf("CustomPropertyValue.UnmarshalJSON expected %+v, got %+v", tc.want, cpv)
   434  			}
   435  		})
   436  	}
   437  }
   438  
   439  func TestOrganizationsService_CreateOrUpdateRepoCustomPropertyValues(t *testing.T) {
   440  	client, mux, _, teardown := setup()
   441  	defer teardown()
   442  
   443  	mux.HandleFunc("/orgs/o/properties/values", func(w http.ResponseWriter, r *http.Request) {
   444  		testMethod(t, r, "PATCH")
   445  		testBody(t, r, `{"repository_names":["repo"],"properties":[{"property_name":"service","value":"string"}]}`+"\n")
   446  	})
   447  
   448  	ctx := context.Background()
   449  	_, err := client.Organizations.CreateOrUpdateRepoCustomPropertyValues(ctx, "o", []string{"repo"}, []*CustomPropertyValue{
   450  		{
   451  			PropertyName: "service",
   452  			Value:        String("string"),
   453  		},
   454  	})
   455  	if err != nil {
   456  		t.Errorf("Organizations.CreateOrUpdateCustomPropertyValuesForRepos returned error: %v", err)
   457  	}
   458  
   459  	const methodName = "CreateOrUpdateCustomPropertyValuesForRepos"
   460  
   461  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   462  		return client.Organizations.CreateOrUpdateRepoCustomPropertyValues(ctx, "o", nil, nil)
   463  	})
   464  }