github.com/google/go-github/v74@v74.0.0/github/repos_hooks_deliveries_test.go (about)

     1  // Copyright 2021 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  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"reflect"
    14  	"testing"
    15  
    16  	"github.com/google/go-cmp/cmp"
    17  )
    18  
    19  func TestRepositoriesService_ListHookDeliveries(t *testing.T) {
    20  	t.Parallel()
    21  	client, mux, _ := setup(t)
    22  
    23  	mux.HandleFunc("/repos/o/r/hooks/1/deliveries", func(w http.ResponseWriter, r *http.Request) {
    24  		testMethod(t, r, "GET")
    25  		testFormValues(t, r, values{"cursor": "v1_12077215967"})
    26  		fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
    27  	})
    28  
    29  	opt := &ListCursorOptions{Cursor: "v1_12077215967"}
    30  
    31  	ctx := context.Background()
    32  	hooks, _, err := client.Repositories.ListHookDeliveries(ctx, "o", "r", 1, opt)
    33  	if err != nil {
    34  		t.Errorf("Repositories.ListHookDeliveries returned error: %v", err)
    35  	}
    36  
    37  	want := []*HookDelivery{{ID: Ptr(int64(1))}, {ID: Ptr(int64(2))}}
    38  	if d := cmp.Diff(hooks, want); d != "" {
    39  		t.Errorf("Repositories.ListHooks want (-), got (+):\n%s", d)
    40  	}
    41  
    42  	const methodName = "ListHookDeliveries"
    43  	testBadOptions(t, methodName, func() (err error) {
    44  		_, _, err = client.Repositories.ListHookDeliveries(ctx, "\n", "\n", -1, opt)
    45  		return err
    46  	})
    47  
    48  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    49  		got, resp, err := client.Repositories.ListHookDeliveries(ctx, "o", "r", 1, opt)
    50  		if got != nil {
    51  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    52  		}
    53  		return resp, err
    54  	})
    55  }
    56  
    57  func TestRepositoriesService_ListHookDeliveries_invalidOwner(t *testing.T) {
    58  	t.Parallel()
    59  	client, _, _ := setup(t)
    60  
    61  	ctx := context.Background()
    62  	_, _, err := client.Repositories.ListHookDeliveries(ctx, "%", "%", 1, nil)
    63  	testURLParseError(t, err)
    64  }
    65  
    66  func TestRepositoriesService_GetHookDelivery(t *testing.T) {
    67  	t.Parallel()
    68  	client, mux, _ := setup(t)
    69  
    70  	mux.HandleFunc("/repos/o/r/hooks/1/deliveries/1", func(w http.ResponseWriter, r *http.Request) {
    71  		testMethod(t, r, "GET")
    72  		fmt.Fprint(w, `{"id":1}`)
    73  	})
    74  
    75  	ctx := context.Background()
    76  	hook, _, err := client.Repositories.GetHookDelivery(ctx, "o", "r", 1, 1)
    77  	if err != nil {
    78  		t.Errorf("Repositories.GetHookDelivery returned error: %v", err)
    79  	}
    80  
    81  	want := &HookDelivery{ID: Ptr(int64(1))}
    82  	if !cmp.Equal(hook, want) {
    83  		t.Errorf("Repositories.GetHookDelivery returned %+v, want %+v", hook, want)
    84  	}
    85  
    86  	const methodName = "GetHookDelivery"
    87  	testBadOptions(t, methodName, func() (err error) {
    88  		_, _, err = client.Repositories.GetHookDelivery(ctx, "\n", "\n", -1, -1)
    89  		return err
    90  	})
    91  
    92  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    93  		got, resp, err := client.Repositories.GetHookDelivery(ctx, "o", "r", 1, 1)
    94  		if got != nil {
    95  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    96  		}
    97  		return resp, err
    98  	})
    99  }
   100  
   101  func TestRepositoriesService_GetHookDelivery_invalidOwner(t *testing.T) {
   102  	t.Parallel()
   103  	client, _, _ := setup(t)
   104  
   105  	ctx := context.Background()
   106  	_, _, err := client.Repositories.GetHookDelivery(ctx, "%", "%", 1, 1)
   107  	testURLParseError(t, err)
   108  }
   109  
   110  func TestRepositoriesService_RedeliverHookDelivery(t *testing.T) {
   111  	t.Parallel()
   112  	client, mux, _ := setup(t)
   113  
   114  	mux.HandleFunc("/repos/o/r/hooks/1/deliveries/1/attempts", func(w http.ResponseWriter, r *http.Request) {
   115  		testMethod(t, r, "POST")
   116  		fmt.Fprint(w, `{"id":1}`)
   117  	})
   118  
   119  	ctx := context.Background()
   120  	hook, _, err := client.Repositories.RedeliverHookDelivery(ctx, "o", "r", 1, 1)
   121  	if err != nil {
   122  		t.Errorf("Repositories.RedeliverHookDelivery returned error: %v", err)
   123  	}
   124  
   125  	want := &HookDelivery{ID: Ptr(int64(1))}
   126  	if !cmp.Equal(hook, want) {
   127  		t.Errorf("Repositories.RedeliverHookDelivery returned %+v, want %+v", hook, want)
   128  	}
   129  
   130  	const methodName = "RedeliverHookDelivery"
   131  	testBadOptions(t, methodName, func() (err error) {
   132  		_, _, err = client.Repositories.RedeliverHookDelivery(ctx, "\n", "\n", -1, -1)
   133  		return err
   134  	})
   135  
   136  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   137  		got, resp, err := client.Repositories.RedeliverHookDelivery(ctx, "o", "r", 1, 1)
   138  		if got != nil {
   139  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   140  		}
   141  		return resp, err
   142  	})
   143  }
   144  
   145  var hookDeliveryPayloadTypeToStruct = map[string]any{
   146  	"check_run":                      &CheckRunEvent{},
   147  	"check_suite":                    &CheckSuiteEvent{},
   148  	"code_scanning_alert":            &CodeScanningAlertEvent{},
   149  	"commit_comment":                 &CommitCommentEvent{},
   150  	"content_reference":              &ContentReferenceEvent{},
   151  	"create":                         &CreateEvent{},
   152  	"delete":                         &DeleteEvent{},
   153  	"dependabot_alert":               &DependabotAlertEvent{},
   154  	"deploy_key":                     &DeployKeyEvent{},
   155  	"deployment":                     &DeploymentEvent{},
   156  	"deployment_status":              &DeploymentStatusEvent{},
   157  	"discussion_comment":             &DiscussionCommentEvent{},
   158  	"discussion":                     &DiscussionEvent{},
   159  	"fork":                           &ForkEvent{},
   160  	"github_app_authorization":       &GitHubAppAuthorizationEvent{},
   161  	"gollum":                         &GollumEvent{},
   162  	"installation":                   &InstallationEvent{},
   163  	"installation_repositories":      &InstallationRepositoriesEvent{},
   164  	"issue_comment":                  &IssueCommentEvent{},
   165  	"issues":                         &IssuesEvent{},
   166  	"label":                          &LabelEvent{},
   167  	"marketplace_purchase":           &MarketplacePurchaseEvent{},
   168  	"member":                         &MemberEvent{},
   169  	"membership":                     &MembershipEvent{},
   170  	"meta":                           &MetaEvent{},
   171  	"milestone":                      &MilestoneEvent{},
   172  	"organization":                   &OrganizationEvent{},
   173  	"org_block":                      &OrgBlockEvent{},
   174  	"package":                        &PackageEvent{},
   175  	"page_build":                     &PageBuildEvent{},
   176  	"ping":                           &PingEvent{},
   177  	"projects_v2":                    &ProjectV2Event{},
   178  	"projects_v2_item":               &ProjectV2ItemEvent{},
   179  	"public":                         &PublicEvent{},
   180  	"pull_request":                   &PullRequestEvent{},
   181  	"pull_request_review":            &PullRequestReviewEvent{},
   182  	"pull_request_review_comment":    &PullRequestReviewCommentEvent{},
   183  	"pull_request_review_thread":     &PullRequestReviewThreadEvent{},
   184  	"pull_request_target":            &PullRequestTargetEvent{},
   185  	"push":                           &PushEvent{},
   186  	"registry_package":               &RegistryPackageEvent{},
   187  	"release":                        &ReleaseEvent{},
   188  	"repository":                     &RepositoryEvent{},
   189  	"repository_dispatch":            &RepositoryDispatchEvent{},
   190  	"repository_import":              &RepositoryImportEvent{},
   191  	"repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{},
   192  	"secret_scanning_alert":          &SecretScanningAlertEvent{},
   193  	"security_advisory":              &SecurityAdvisoryEvent{},
   194  	"security_and_analysis":          &SecurityAndAnalysisEvent{},
   195  	"star":                           &StarEvent{},
   196  	"status":                         &StatusEvent{},
   197  	"team":                           &TeamEvent{},
   198  	"team_add":                       &TeamAddEvent{},
   199  	"user":                           &UserEvent{},
   200  	"watch":                          &WatchEvent{},
   201  	"workflow_dispatch":              &WorkflowDispatchEvent{},
   202  	"workflow_job":                   &WorkflowJobEvent{},
   203  	"workflow_run":                   &WorkflowRunEvent{},
   204  }
   205  
   206  func TestHookDelivery_ParsePayload(t *testing.T) {
   207  	t.Parallel()
   208  	for evt, obj := range hookDeliveryPayloadTypeToStruct {
   209  		t.Run(evt, func(t *testing.T) {
   210  			t.Parallel()
   211  			bs, err := json.Marshal(obj)
   212  			if err != nil {
   213  				t.Fatal(err)
   214  			}
   215  
   216  			p := json.RawMessage(bs)
   217  
   218  			d := &HookDelivery{
   219  				Event: Ptr(evt),
   220  				Request: &HookRequest{
   221  					RawPayload: &p,
   222  				},
   223  			}
   224  
   225  			got, err := d.ParseRequestPayload()
   226  			if err != nil {
   227  				t.Error(err)
   228  			}
   229  
   230  			if !reflect.DeepEqual(obj, got) {
   231  				t.Errorf("want %T %v, got %T %v", obj, obj, got, got)
   232  			}
   233  		})
   234  	}
   235  }
   236  
   237  func TestHookDelivery_ParsePayload_invalidEvent(t *testing.T) {
   238  	t.Parallel()
   239  	p := json.RawMessage(nil)
   240  
   241  	d := &HookDelivery{
   242  		Event: Ptr("some_invalid_event"),
   243  		Request: &HookRequest{
   244  			RawPayload: &p,
   245  		},
   246  	}
   247  
   248  	_, err := d.ParseRequestPayload()
   249  	if err == nil || err.Error() != `unsupported event type "some_invalid_event"` {
   250  		t.Errorf("unexpected error: %v", err)
   251  	}
   252  }
   253  
   254  func TestHookDelivery_ParsePayload_invalidPayload(t *testing.T) {
   255  	t.Parallel()
   256  	p := json.RawMessage([]byte(`{"check_run":{"id":"invalid"}}`))
   257  
   258  	d := &HookDelivery{
   259  		Event: Ptr("check_run"),
   260  		Request: &HookRequest{
   261  			RawPayload: &p,
   262  		},
   263  	}
   264  
   265  	_, err := d.ParseRequestPayload()
   266  	if err == nil || err.Error() != "json: cannot unmarshal string into Go struct field CheckRun.check_run.id of type int64" {
   267  		t.Errorf("unexpected error: %v", err)
   268  	}
   269  }
   270  
   271  func TestHookRequest_Marshal(t *testing.T) {
   272  	t.Parallel()
   273  	testJSONMarshal(t, &HookRequest{}, "{}")
   274  
   275  	header := make(map[string]string)
   276  	header["key"] = "value"
   277  
   278  	jsonMsg, _ := json.Marshal(&header)
   279  
   280  	r := &HookRequest{
   281  		Headers:    header,
   282  		RawPayload: (*json.RawMessage)(&jsonMsg),
   283  	}
   284  
   285  	want := `{
   286  		"headers": {
   287  			"key": "value"
   288  		},
   289  		"payload": {
   290  			"key": "value"
   291  		}
   292  	}`
   293  
   294  	testJSONMarshal(t, r, want)
   295  }
   296  
   297  func TestHookRequest_GetHeader(t *testing.T) {
   298  	t.Parallel()
   299  
   300  	header := make(map[string]string)
   301  	header["key1"] = "value1"
   302  	header["Key+2"] = "value2"
   303  	header["kEy-3"] = "value3"
   304  	header["KEY_4"] = "value4"
   305  
   306  	r := &HookRequest{
   307  		Headers: header,
   308  	}
   309  
   310  	// Checking positive cases
   311  	testPrefixes := []string{"key", "Key", "kEy", "KEY"}
   312  	for hdrKey, hdrValue := range header {
   313  		for _, prefix := range testPrefixes {
   314  			key := prefix + hdrKey[3:]
   315  			if val := r.GetHeader(key); val != hdrValue {
   316  				t.Errorf("GetHeader(%q) is not working: %q != %q", key, val, hdrValue)
   317  			}
   318  		}
   319  	}
   320  
   321  	// Checking negative case
   322  	key := "asd"
   323  	if val := r.GetHeader(key); val != "" {
   324  		t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "")
   325  	}
   326  	key = "kay1"
   327  	if val := r.GetHeader(key); val != "" {
   328  		t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "")
   329  	}
   330  }
   331  
   332  func TestHookResponse_Marshal(t *testing.T) {
   333  	t.Parallel()
   334  	testJSONMarshal(t, &HookResponse{}, "{}")
   335  
   336  	header := make(map[string]string)
   337  	header["key"] = "value"
   338  
   339  	jsonMsg, _ := json.Marshal(&header)
   340  
   341  	r := &HookResponse{
   342  		Headers:    header,
   343  		RawPayload: (*json.RawMessage)(&jsonMsg),
   344  	}
   345  
   346  	want := `{
   347  		"headers": {
   348  			"key": "value"
   349  		},
   350  		"payload": {
   351  			"key": "value"
   352  		}
   353  	}`
   354  
   355  	testJSONMarshal(t, r, want)
   356  }
   357  
   358  func TestHookResponse_GetHeader(t *testing.T) {
   359  	t.Parallel()
   360  
   361  	header := make(map[string]string)
   362  	header["key1"] = "value1"
   363  	header["Key+2"] = "value2"
   364  	header["kEy-3"] = "value3"
   365  	header["KEY_4"] = "value4"
   366  
   367  	r := &HookResponse{
   368  		Headers: header,
   369  	}
   370  
   371  	// Checking positive cases
   372  	testPrefixes := []string{"key", "Key", "kEy", "KEY"}
   373  	for hdrKey, hdrValue := range header {
   374  		for _, prefix := range testPrefixes {
   375  			key := prefix + hdrKey[3:]
   376  			if val := r.GetHeader(key); val != hdrValue {
   377  				t.Errorf("GetHeader(%q) is not working: %q != %q", key, val, hdrValue)
   378  			}
   379  		}
   380  	}
   381  
   382  	// Checking negative case
   383  	key := "asd"
   384  	if val := r.GetHeader(key); val != "" {
   385  		t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "")
   386  	}
   387  	key = "kay1"
   388  	if val := r.GetHeader(key); val != "" {
   389  		t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "")
   390  	}
   391  }
   392  
   393  func TestHookDelivery_Marshal(t *testing.T) {
   394  	t.Parallel()
   395  	testJSONMarshal(t, &HookDelivery{}, "{}")
   396  
   397  	header := make(map[string]string)
   398  	header["key"] = "value"
   399  
   400  	jsonMsg, _ := json.Marshal(&header)
   401  
   402  	r := &HookDelivery{
   403  		ID:             Ptr(int64(1)),
   404  		GUID:           Ptr("guid"),
   405  		DeliveredAt:    &Timestamp{referenceTime},
   406  		Redelivery:     Ptr(true),
   407  		Duration:       Ptr(1.0),
   408  		Status:         Ptr("guid"),
   409  		StatusCode:     Ptr(1),
   410  		Event:          Ptr("guid"),
   411  		Action:         Ptr("guid"),
   412  		InstallationID: Ptr(int64(1)),
   413  		RepositoryID:   Ptr(int64(1)),
   414  		Request: &HookRequest{
   415  			Headers:    header,
   416  			RawPayload: (*json.RawMessage)(&jsonMsg),
   417  		},
   418  		Response: &HookResponse{
   419  			Headers:    header,
   420  			RawPayload: (*json.RawMessage)(&jsonMsg),
   421  		},
   422  	}
   423  
   424  	want := `{
   425  		"id": 1,
   426  		"guid": "guid",
   427  		"delivered_at": ` + referenceTimeStr + `,
   428  		"redelivery": true,
   429  		"duration": 1,
   430  		"status": "guid",
   431  		"status_code": 1,
   432  		"event": "guid",
   433  		"action": "guid",
   434  		"installation_id": 1,
   435  		"repository_id": 1,
   436  		"request": {
   437  			"headers": {
   438  				"key": "value"
   439  			},
   440  			"payload": {
   441  				"key": "value"
   442  			}
   443  		},
   444  		"response": {
   445  			"headers": {
   446  				"key": "value"
   447  			},
   448  			"payload": {
   449  				"key": "value"
   450  			}
   451  		}
   452  	}`
   453  
   454  	testJSONMarshal(t, r, want)
   455  }