github.com/go-playground/webhooks/v6@v6.3.0/gitlab/gitlab_test.go (about)

     1  package gitlab
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"log"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"os"
    10  	"reflect"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  // NOTES:
    17  // - Run "go test" to run tests
    18  // - Run "gocov test | gocov report" to report on test converage by file
    19  // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
    20  //
    21  // or
    22  //
    23  // -- may be a good idea to change to output path to somewherelike /tmp
    24  // go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
    25  //
    26  
    27  const (
    28  	path = "/webhooks"
    29  )
    30  
    31  var hook *Webhook
    32  
    33  func TestMain(m *testing.M) {
    34  
    35  	// setup
    36  	var err error
    37  	hook, err = New(Options.Secret("sampleToken!"))
    38  	if err != nil {
    39  		log.Fatal(err)
    40  	}
    41  	os.Exit(m.Run())
    42  
    43  	// teardown
    44  }
    45  
    46  func newServer(handler http.HandlerFunc) *httptest.Server {
    47  	mux := http.NewServeMux()
    48  	mux.HandleFunc(path, handler)
    49  	return httptest.NewServer(mux)
    50  }
    51  
    52  func TestBadRequests(t *testing.T) {
    53  	assert := require.New(t)
    54  	tests := []struct {
    55  		name    string
    56  		event   Event
    57  		payload io.Reader
    58  		headers http.Header
    59  	}{
    60  		{
    61  			name:    "BadNoEventHeader",
    62  			event:   PushEvents,
    63  			payload: bytes.NewBuffer([]byte("{}")),
    64  			headers: http.Header{},
    65  		},
    66  		{
    67  			name:    "UnsubscribedEvent",
    68  			event:   PushEvents,
    69  			payload: bytes.NewBuffer([]byte("{}")),
    70  			headers: http.Header{
    71  				"X-Gitlab-Event": []string{"noneexistant_event"},
    72  			},
    73  		},
    74  		{
    75  			name:    "BadBody",
    76  			event:   PushEvents,
    77  			payload: bytes.NewBuffer([]byte("")),
    78  			headers: http.Header{
    79  				"X-Gitlab-Event": []string{"Push Hook"},
    80  				"X-Gitlab-Token": []string{"sampleToken!"},
    81  			},
    82  		},
    83  		{
    84  			name:    "TokenMismatch",
    85  			event:   PushEvents,
    86  			payload: bytes.NewBuffer([]byte("{}")),
    87  			headers: http.Header{
    88  				"X-Gitlab-Event": []string{"Push Hook"},
    89  				"X-Gitlab-Token": []string{"badsampleToken!!"},
    90  			},
    91  		},
    92  	}
    93  
    94  	for _, tt := range tests {
    95  		tc := tt
    96  		client := &http.Client{}
    97  		t.Run(tt.name, func(t *testing.T) {
    98  			t.Parallel()
    99  			var parseError error
   100  			server := newServer(func(w http.ResponseWriter, r *http.Request) {
   101  				_, parseError = hook.Parse(r, tc.event)
   102  			})
   103  			defer server.Close()
   104  			req, err := http.NewRequest(http.MethodPost, server.URL+path, tc.payload)
   105  			assert.NoError(err)
   106  			req.Header = tc.headers
   107  			req.Header.Set("Content-Type", "application/json")
   108  
   109  			resp, err := client.Do(req)
   110  			assert.NoError(err)
   111  			assert.Equal(http.StatusOK, resp.StatusCode)
   112  			assert.Error(parseError)
   113  		})
   114  	}
   115  }
   116  
   117  func TestWebhooks(t *testing.T) {
   118  	assert := require.New(t)
   119  	tests := []struct {
   120  		name     string
   121  		event    Event
   122  		typ      interface{}
   123  		filename string
   124  		headers  http.Header
   125  	}{
   126  		{
   127  			name:     "PushEvent",
   128  			event:    PushEvents,
   129  			typ:      PushEventPayload{},
   130  			filename: "../testdata/gitlab/push-event.json",
   131  			headers: http.Header{
   132  				"X-Gitlab-Event": []string{"Push Hook"},
   133  			},
   134  		},
   135  		{
   136  			name:     "TagEvent",
   137  			event:    TagEvents,
   138  			typ:      TagEventPayload{},
   139  			filename: "../testdata/gitlab/tag-event.json",
   140  			headers: http.Header{
   141  				"X-Gitlab-Event": []string{"Tag Push Hook"},
   142  			},
   143  		},
   144  		{
   145  			name:     "IssueEvent",
   146  			event:    IssuesEvents,
   147  			typ:      IssueEventPayload{},
   148  			filename: "../testdata/gitlab/issue-event.json",
   149  			headers: http.Header{
   150  				"X-Gitlab-Event": []string{"Issue Hook"},
   151  			},
   152  		},
   153  		{
   154  			name:     "ConfidentialIssueEvent",
   155  			event:    ConfidentialIssuesEvents,
   156  			typ:      ConfidentialIssueEventPayload{},
   157  			filename: "../testdata/gitlab/confidential-issue-event.json",
   158  			headers: http.Header{
   159  				"X-Gitlab-Event": []string{"Confidential Issue Hook"},
   160  			},
   161  		},
   162  		{
   163  			name:     "CommentCommitEvent",
   164  			event:    CommentEvents,
   165  			typ:      CommentEventPayload{},
   166  			filename: "../testdata/gitlab/comment-commit-event.json",
   167  			headers: http.Header{
   168  				"X-Gitlab-Event": []string{"Note Hook"},
   169  			},
   170  		},
   171  		{
   172  			name:     "ConfidentialCommentCommitEvent",
   173  			event:    ConfidentialCommentEvents,
   174  			typ:      ConfidentialCommentEventPayload{},
   175  			filename: "../testdata/gitlab/confidential-comment-event.json",
   176  			headers: http.Header{
   177  				"X-Gitlab-Event": []string{"Confidential Note Hook"},
   178  			},
   179  		},
   180  		{
   181  			name:     "CommentMergeRequestEvent",
   182  			event:    CommentEvents,
   183  			typ:      CommentEventPayload{},
   184  			filename: "../testdata/gitlab/comment-merge-request-event.json",
   185  			headers: http.Header{
   186  				"X-Gitlab-Event": []string{"Note Hook"},
   187  			},
   188  		},
   189  		{
   190  			name:     "CommentIssueEvent",
   191  			event:    CommentEvents,
   192  			typ:      CommentEventPayload{},
   193  			filename: "../testdata/gitlab/comment-issue-event.json",
   194  			headers: http.Header{
   195  				"X-Gitlab-Event": []string{"Note Hook"},
   196  			},
   197  		},
   198  		{
   199  			name:     "CommentSnippetEvent",
   200  			event:    CommentEvents,
   201  			typ:      CommentEventPayload{},
   202  			filename: "../testdata/gitlab/comment-snippet-event.json",
   203  			headers: http.Header{
   204  				"X-Gitlab-Event": []string{"Note Hook"},
   205  			},
   206  		},
   207  		{
   208  			name:     "MergeRequestEvent",
   209  			event:    MergeRequestEvents,
   210  			typ:      MergeRequestEventPayload{},
   211  			filename: "../testdata/gitlab/merge-request-event.json",
   212  			headers: http.Header{
   213  				"X-Gitlab-Event": []string{"Merge Request Hook"},
   214  			},
   215  		},
   216  		{
   217  			name:     "WikipageEvent",
   218  			event:    WikiPageEvents,
   219  			typ:      WikiPageEventPayload{},
   220  			filename: "../testdata/gitlab/wikipage-event.json",
   221  			headers: http.Header{
   222  				"X-Gitlab-Event": []string{"Wiki Page Hook"},
   223  			},
   224  		},
   225  		{
   226  			name:     "PipelineEvent",
   227  			event:    PipelineEvents,
   228  			typ:      PipelineEventPayload{},
   229  			filename: "../testdata/gitlab/pipeline-event.json",
   230  			headers: http.Header{
   231  				"X-Gitlab-Event": []string{"Pipeline Hook"},
   232  			},
   233  		},
   234  		{
   235  			name:     "BuildEvent",
   236  			event:    BuildEvents,
   237  			typ:      BuildEventPayload{},
   238  			filename: "../testdata/gitlab/build-event.json",
   239  			headers: http.Header{
   240  				"X-Gitlab-Event": []string{"Build Hook"},
   241  			},
   242  		},
   243  		{
   244  			name:     "DeploymentEvent",
   245  			event:    DeploymentEvents,
   246  			typ:      DeploymentEventPayload{},
   247  			filename: "../testdata/gitlab/deployment-event.json",
   248  			headers: http.Header{
   249  				"X-Gitlab-Event": []string{"Deployment Hook"},
   250  			},
   251  		},
   252  	}
   253  
   254  	for _, tt := range tests {
   255  		tc := tt
   256  		client := &http.Client{}
   257  		t.Run(tt.name, func(t *testing.T) {
   258  			t.Parallel()
   259  			payload, err := os.Open(tc.filename)
   260  			assert.NoError(err)
   261  			defer func() {
   262  				_ = payload.Close()
   263  			}()
   264  
   265  			var parseError error
   266  			var results interface{}
   267  			server := newServer(func(w http.ResponseWriter, r *http.Request) {
   268  				results, parseError = hook.Parse(r, tc.event)
   269  			})
   270  			defer server.Close()
   271  			req, err := http.NewRequest(http.MethodPost, server.URL+path, payload)
   272  			assert.NoError(err)
   273  			req.Header = tc.headers
   274  			req.Header.Set("Content-Type", "application/json")
   275  			req.Header.Set("X-Gitlab-Token", "sampleToken!")
   276  
   277  			resp, err := client.Do(req)
   278  			assert.NoError(err)
   279  			assert.Equal(http.StatusOK, resp.StatusCode)
   280  			assert.NoError(parseError)
   281  			assert.Equal(reflect.TypeOf(tc.typ), reflect.TypeOf(results))
   282  		})
   283  	}
   284  }
   285  
   286  func TestJobHooks(t *testing.T) {
   287  	assert := require.New(t)
   288  	tests := []struct {
   289  		name     string
   290  		events   []Event
   291  		typ      interface{}
   292  		filename string
   293  		headers  http.Header
   294  	}{
   295  		{
   296  			name:     "JobEvent",
   297  			events:   []Event{JobEvents, BuildEvents},
   298  			typ:      BuildEventPayload{},
   299  			filename: "../testdata/gitlab/build-event.json",
   300  			headers: http.Header{
   301  				"X-Gitlab-Event": []string{"Job Hook"},
   302  			},
   303  		},
   304  	}
   305  
   306  	for _, tt := range tests {
   307  		tc := tt
   308  		client := &http.Client{}
   309  		t.Run(tt.name, func(t *testing.T) {
   310  			t.Parallel()
   311  			payload, err := os.Open(tc.filename)
   312  			assert.NoError(err)
   313  			defer func() {
   314  				_ = payload.Close()
   315  			}()
   316  
   317  			var parseError error
   318  			var results interface{}
   319  			server := newServer(func(w http.ResponseWriter, r *http.Request) {
   320  				results, parseError = hook.Parse(r, tc.events...)
   321  			})
   322  			defer server.Close()
   323  			req, err := http.NewRequest(http.MethodPost, server.URL+path, payload)
   324  			assert.NoError(err)
   325  			req.Header = tc.headers
   326  			req.Header.Set("Content-Type", "application/json")
   327  			req.Header.Set("X-Gitlab-Token", "sampleToken!")
   328  
   329  			resp, err := client.Do(req)
   330  			assert.NoError(err)
   331  			assert.Equal(http.StatusOK, resp.StatusCode)
   332  			assert.NoError(parseError)
   333  			assert.Equal(reflect.TypeOf(tc.typ), reflect.TypeOf(results))
   334  		})
   335  	}
   336  }
   337  
   338  func TestSystemHooks(t *testing.T) {
   339  	assert := require.New(t)
   340  	tests := []struct {
   341  		name     string
   342  		event    Event
   343  		typ      interface{}
   344  		filename string
   345  	}{
   346  		{
   347  			name:     "PushEvent",
   348  			event:    PushEvents,
   349  			typ:      PushEventPayload{},
   350  			filename: "../testdata/gitlab/system-push-event.json",
   351  		},
   352  		{
   353  			name:     "TagEvent",
   354  			event:    TagEvents,
   355  			typ:      TagEventPayload{},
   356  			filename: "../testdata/gitlab/system-tag-event.json",
   357  		},
   358  		{
   359  			name:     "MergeRequestEvent",
   360  			event:    MergeRequestEvents,
   361  			typ:      MergeRequestEventPayload{},
   362  			filename: "../testdata/gitlab/system-merge-request-event.json",
   363  		},
   364  		{
   365  			name:     "ProjectCreatedEvent",
   366  			event:    SystemHookEvents,
   367  			typ:      ProjectCreatedEventPayload{},
   368  			filename: "../testdata/gitlab/system-project-created.json",
   369  		},
   370  		{
   371  			name:     "ProjectDestroyedEvent",
   372  			event:    SystemHookEvents,
   373  			typ:      ProjectDestroyedEventPayload{},
   374  			filename: "../testdata/gitlab/system-project-destroyed.json",
   375  		},
   376  		{
   377  			name:     "ProjectRenamedEvent",
   378  			event:    SystemHookEvents,
   379  			typ:      ProjectRenamedEventPayload{},
   380  			filename: "../testdata/gitlab/system-project-renamed.json",
   381  		},
   382  		{
   383  			name:     "ProjectTransferredEvent",
   384  			event:    SystemHookEvents,
   385  			typ:      ProjectTransferredEventPayload{},
   386  			filename: "../testdata/gitlab/system-project-transferred.json",
   387  		},
   388  		{
   389  			name:     "ProjectUpdatedEvent",
   390  			event:    SystemHookEvents,
   391  			typ:      ProjectUpdatedEventPayload{},
   392  			filename: "../testdata/gitlab/system-project-updated.json",
   393  		},
   394  		{
   395  			name:     "TeamMemberAddedEvent",
   396  			event:    SystemHookEvents,
   397  			typ:      TeamMemberAddedEventPayload{},
   398  			filename: "../testdata/gitlab/system-team-member-added.json",
   399  		},
   400  		{
   401  			name:     "TeamMemberRemovedEvent",
   402  			event:    SystemHookEvents,
   403  			typ:      TeamMemberRemovedEventPayload{},
   404  			filename: "../testdata/gitlab/system-team-member-removed.json",
   405  		},
   406  		{
   407  			name:     "TeamMemberUpdatedEvent",
   408  			event:    SystemHookEvents,
   409  			typ:      TeamMemberUpdatedEventPayload{},
   410  			filename: "../testdata/gitlab/system-team-member-updated.json",
   411  		},
   412  		{
   413  			name:     "UserCreatedEvent",
   414  			event:    SystemHookEvents,
   415  			typ:      UserCreatedEventPayload{},
   416  			filename: "../testdata/gitlab/system-user-created.json",
   417  		},
   418  		{
   419  			name:     "UserRemovedEvent",
   420  			event:    SystemHookEvents,
   421  			typ:      UserRemovedEventPayload{},
   422  			filename: "../testdata/gitlab/system-user-removed.json",
   423  		},
   424  		{
   425  			name:     "UserFailedLoginEvent",
   426  			event:    SystemHookEvents,
   427  			typ:      UserFailedLoginEventPayload{},
   428  			filename: "../testdata/gitlab/system-user-failed-login.json",
   429  		},
   430  		{
   431  			name:     "UserRenamedEvent",
   432  			event:    SystemHookEvents,
   433  			typ:      UserRenamedEventPayload{},
   434  			filename: "../testdata/gitlab/system-user-renamed.json",
   435  		},
   436  		{
   437  			name:     "KeyAddedEvent",
   438  			event:    SystemHookEvents,
   439  			typ:      KeyAddedEventPayload{},
   440  			filename: "../testdata/gitlab/system-key-added.json",
   441  		},
   442  		{
   443  			name:     "KeyRemovedEvent",
   444  			event:    SystemHookEvents,
   445  			typ:      KeyRemovedEventPayload{},
   446  			filename: "../testdata/gitlab/system-key-removed.json",
   447  		},
   448  		{
   449  			name:     "GroupCreatedEvent",
   450  			event:    SystemHookEvents,
   451  			typ:      GroupCreatedEventPayload{},
   452  			filename: "../testdata/gitlab/system-group-created.json",
   453  		},
   454  		{
   455  			name:     "GroupRemovedEvent",
   456  			event:    SystemHookEvents,
   457  			typ:      GroupRemovedEventPayload{},
   458  			filename: "../testdata/gitlab/system-group-removed.json",
   459  		},
   460  		{
   461  			name:     "GroupRenamedEvent",
   462  			event:    SystemHookEvents,
   463  			typ:      GroupRenamedEventPayload{},
   464  			filename: "../testdata/gitlab/system-group-renamed.json",
   465  		},
   466  		{
   467  			name:     "GroupMemberAddedEvent",
   468  			event:    SystemHookEvents,
   469  			typ:      GroupMemberAddedEventPayload{},
   470  			filename: "../testdata/gitlab/system-group-member-added.json",
   471  		},
   472  		{
   473  			name:     "GroupMemberRemovedEvent",
   474  			event:    SystemHookEvents,
   475  			typ:      GroupMemberRemovedEventPayload{},
   476  			filename: "../testdata/gitlab/system-group-member-removed.json",
   477  		},
   478  		{
   479  			name:     "GroupMemberUpdatedEvent",
   480  			event:    SystemHookEvents,
   481  			typ:      GroupMemberUpdatedEventPayload{},
   482  			filename: "../testdata/gitlab/system-group-member-updated.json",
   483  		},
   484  	}
   485  	for _, tt := range tests {
   486  		tc := tt
   487  		client := &http.Client{}
   488  		t.Run(tt.name, func(t *testing.T) {
   489  			t.Parallel()
   490  			payload, err := os.Open(tc.filename)
   491  			assert.NoError(err)
   492  			defer func() {
   493  				_ = payload.Close()
   494  			}()
   495  
   496  			var parseError error
   497  			var results interface{}
   498  			server := newServer(func(w http.ResponseWriter, r *http.Request) {
   499  				results, parseError = hook.Parse(r, SystemHookEvents, tc.event)
   500  			})
   501  			defer server.Close()
   502  			req, err := http.NewRequest(http.MethodPost, server.URL+path, payload)
   503  			assert.NoError(err)
   504  			req.Header.Set("Content-Type", "application/json")
   505  			req.Header.Set("X-Gitlab-Token", "sampleToken!")
   506  			req.Header.Set("X-Gitlab-Event", "System Hook")
   507  
   508  			resp, err := client.Do(req)
   509  			assert.NoError(err)
   510  			assert.Equal(http.StatusOK, resp.StatusCode)
   511  			assert.NoError(parseError)
   512  			assert.Equal(reflect.TypeOf(tc.typ), reflect.TypeOf(results))
   513  		})
   514  	}
   515  }