github.com/google/go-github/v74@v74.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  	t.Parallel()
    19  	client, mux, _ := setup(t)
    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:     Ptr("name"),
    57  			ValueType:        "single_select",
    58  			Required:         Ptr(true),
    59  			DefaultValue:     Ptr("production"),
    60  			Description:      Ptr("Prod or dev environment"),
    61  			AllowedValues:    []string{"production", "development"},
    62  			ValuesEditableBy: Ptr("org_actors"),
    63  		},
    64  		{
    65  			PropertyName: Ptr("service"),
    66  			ValueType:    "string",
    67  		},
    68  		{
    69  			PropertyName: Ptr("team"),
    70  			ValueType:    "string",
    71  			Description:  Ptr("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  	t.Parallel()
    91  	client, mux, _ := setup(t)
    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: Ptr("name"),
   113  			ValueType:    "single_select",
   114  			Required:     Ptr(true),
   115  		},
   116  		{
   117  			PropertyName: Ptr("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: Ptr("name"),
   128  			ValueType:    "single_select",
   129  			Required:     Ptr(true),
   130  		},
   131  		{
   132  			PropertyName: Ptr("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  	t.Parallel()
   154  	client, mux, _ := setup(t)
   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:     Ptr("name"),
   180  		ValueType:        "single_select",
   181  		Required:         Ptr(true),
   182  		DefaultValue:     Ptr("production"),
   183  		Description:      Ptr("Prod or dev environment"),
   184  		AllowedValues:    []string{"production", "development"},
   185  		ValuesEditableBy: Ptr("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  	t.Parallel()
   204  	client, mux, _ := setup(t)
   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:         Ptr(true),
   226  		DefaultValue:     Ptr("production"),
   227  		Description:      Ptr("Prod or dev environment"),
   228  		AllowedValues:    []string{"production", "development"},
   229  		ValuesEditableBy: Ptr("org_actors"),
   230  	})
   231  	if err != nil {
   232  		t.Errorf("Organizations.CreateOrUpdateCustomProperty returned error: %v", err)
   233  	}
   234  
   235  	want := &CustomProperty{
   236  		PropertyName:     Ptr("name"),
   237  		ValueType:        "single_select",
   238  		Required:         Ptr(true),
   239  		DefaultValue:     Ptr("production"),
   240  		Description:      Ptr("Prod or dev environment"),
   241  		AllowedValues:    []string{"production", "development"},
   242  		ValuesEditableBy: Ptr("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  	t.Parallel()
   261  	client, mux, _ := setup(t)
   262  
   263  	mux.HandleFunc("/orgs/o/properties/schema/name", func(_ 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  	t.Parallel()
   282  	client, mux, _ := setup(t)
   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{
   287  			"page":             "1",
   288  			"per_page":         "100",
   289  			"repository_query": "repo:octocat/Hello-World",
   290  		})
   291  		fmt.Fprint(w, `[{
   292  		"repository_id": 1296269,
   293  		"repository_name": "Hello-World",
   294  		"repository_full_name": "octocat/Hello-World",
   295  		"properties": [
   296  		{
   297            "property_name": "environment",
   298            "value": "production"
   299          },
   300          {
   301            "property_name": "service",
   302            "value": "web"
   303          },
   304          {
   305            "property_name": "languages",
   306            "value": ["Go", "JavaScript"]
   307          },
   308          {
   309            "property_name": "null_property",
   310            "value": null
   311          }
   312  		]
   313          }]`)
   314  	})
   315  
   316  	ctx := context.Background()
   317  	repoPropertyValues, _, err := client.Organizations.ListCustomPropertyValues(ctx, "o", &ListCustomPropertyValuesOptions{
   318  		ListOptions: ListOptions{
   319  			Page:    1,
   320  			PerPage: 100,
   321  		},
   322  		RepositoryQuery: "repo:octocat/Hello-World",
   323  	})
   324  	if err != nil {
   325  		t.Errorf("Organizations.ListCustomPropertyValues returned error: %v", err)
   326  	}
   327  
   328  	want := []*RepoCustomPropertyValue{
   329  		{
   330  			RepositoryID:       1296269,
   331  			RepositoryName:     "Hello-World",
   332  			RepositoryFullName: "octocat/Hello-World",
   333  			Properties: []*CustomPropertyValue{
   334  				{
   335  					PropertyName: "environment",
   336  					Value:        "production",
   337  				},
   338  				{
   339  					PropertyName: "service",
   340  					Value:        "web",
   341  				},
   342  				{
   343  					PropertyName: "languages",
   344  					Value:        []string{"Go", "JavaScript"},
   345  				},
   346  				{
   347  					PropertyName: "null_property",
   348  					Value:        nil,
   349  				},
   350  			},
   351  		},
   352  	}
   353  
   354  	if !cmp.Equal(repoPropertyValues, want) {
   355  		t.Errorf("Organizations.ListCustomPropertyValues returned %+v, want %+v", repoPropertyValues, want)
   356  	}
   357  
   358  	const methodName = "ListCustomPropertyValues"
   359  
   360  	testBadOptions(t, methodName, func() (err error) {
   361  		_, _, err = client.Organizations.ListCustomPropertyValues(ctx, "\n", &ListCustomPropertyValuesOptions{})
   362  		return err
   363  	})
   364  
   365  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   366  		got, resp, err := client.Organizations.ListCustomPropertyValues(ctx, "o", nil)
   367  		if got != nil {
   368  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   369  		}
   370  		return resp, err
   371  	})
   372  }
   373  
   374  func TestCustomPropertyValue_UnmarshalJSON(t *testing.T) {
   375  	t.Parallel()
   376  	tests := map[string]struct {
   377  		data    string
   378  		want    *CustomPropertyValue
   379  		wantErr bool
   380  	}{
   381  		"Invalid JSON": {
   382  			data:    `{`,
   383  			want:    &CustomPropertyValue{},
   384  			wantErr: true,
   385  		},
   386  		"String value": {
   387  			data: `{
   388  				"property_name": "environment",
   389  				"value": "production"
   390  			}`,
   391  			want: &CustomPropertyValue{
   392  				PropertyName: "environment",
   393  				Value:        "production",
   394  			},
   395  			wantErr: false,
   396  		},
   397  		"Array of strings value": {
   398  			data: `{
   399  				"property_name": "languages",
   400  				"value": ["Go", "JavaScript"]
   401  			}`,
   402  			want: &CustomPropertyValue{
   403  				PropertyName: "languages",
   404  				Value:        []string{"Go", "JavaScript"},
   405  			},
   406  			wantErr: false,
   407  		},
   408  		"Non-string value in array": {
   409  			data: `{
   410  				"property_name": "languages",
   411  				"value": ["Go", 42]
   412  			}`,
   413  			want: &CustomPropertyValue{
   414  				PropertyName: "languages",
   415  				Value:        nil,
   416  			},
   417  			wantErr: true,
   418  		},
   419  		"Unexpected value type": {
   420  			data: `{
   421  				"property_name": "environment",
   422  				"value": {"invalid": "type"}
   423  			}`,
   424  			want: &CustomPropertyValue{
   425  				PropertyName: "environment",
   426  				Value:        nil,
   427  			},
   428  			wantErr: true,
   429  		},
   430  	}
   431  
   432  	for name, tc := range tests {
   433  		t.Run(name, func(t *testing.T) {
   434  			t.Parallel()
   435  			cpv := &CustomPropertyValue{}
   436  			err := cpv.UnmarshalJSON([]byte(tc.data))
   437  			if (err != nil) != tc.wantErr {
   438  				t.Errorf("CustomPropertyValue.UnmarshalJSON error = %v, wantErr %v", err, tc.wantErr)
   439  				return
   440  			}
   441  			if !tc.wantErr && !cmp.Equal(tc.want, cpv) {
   442  				t.Errorf("CustomPropertyValue.UnmarshalJSON expected %+v, got %+v", tc.want, cpv)
   443  			}
   444  		})
   445  	}
   446  }
   447  
   448  func TestOrganizationsService_CreateOrUpdateRepoCustomPropertyValues(t *testing.T) {
   449  	t.Parallel()
   450  	client, mux, _ := setup(t)
   451  
   452  	mux.HandleFunc("/orgs/o/properties/values", func(_ http.ResponseWriter, r *http.Request) {
   453  		testMethod(t, r, "PATCH")
   454  		testBody(t, r, `{"repository_names":["repo"],"properties":[{"property_name":"service","value":"string"}]}`+"\n")
   455  	})
   456  
   457  	ctx := context.Background()
   458  	_, err := client.Organizations.CreateOrUpdateRepoCustomPropertyValues(ctx, "o", []string{"repo"}, []*CustomPropertyValue{
   459  		{
   460  			PropertyName: "service",
   461  			Value:        Ptr("string"),
   462  		},
   463  	})
   464  	if err != nil {
   465  		t.Errorf("Organizations.CreateOrUpdateCustomPropertyValuesForRepos returned error: %v", err)
   466  	}
   467  
   468  	const methodName = "CreateOrUpdateCustomPropertyValuesForRepos"
   469  
   470  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   471  		return client.Organizations.CreateOrUpdateRepoCustomPropertyValues(ctx, "o", nil, nil)
   472  	})
   473  }