code.gitea.io/gitea@v1.22.3/tests/integration/repo_commits_test.go (about)

     1  // Copyright 2017 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package integration
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"path"
    11  	"sync"
    12  	"testing"
    13  
    14  	auth_model "code.gitea.io/gitea/models/auth"
    15  	"code.gitea.io/gitea/modules/json"
    16  	"code.gitea.io/gitea/modules/setting"
    17  	api "code.gitea.io/gitea/modules/structs"
    18  	"code.gitea.io/gitea/tests"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestRepoCommits(t *testing.T) {
    24  	defer tests.PrepareTestEnv(t)()
    25  
    26  	session := loginUser(t, "user2")
    27  
    28  	// Request repository commits page
    29  	req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
    30  	resp := session.MakeRequest(t, req, http.StatusOK)
    31  
    32  	doc := NewHTMLParser(t, resp.Body)
    33  	commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Attr("href")
    34  	assert.True(t, exists)
    35  	assert.NotEmpty(t, commitURL)
    36  }
    37  
    38  func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
    39  	defer tests.PrepareTestEnv(t)()
    40  
    41  	session := loginUser(t, "user2")
    42  
    43  	// Request repository commits page
    44  	req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
    45  	resp := session.MakeRequest(t, req, http.StatusOK)
    46  
    47  	doc := NewHTMLParser(t, resp.Body)
    48  	// Get first commit URL
    49  	commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Attr("href")
    50  	assert.True(t, exists)
    51  	assert.NotEmpty(t, commitURL)
    52  
    53  	// Call API to add status for commit
    54  	ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
    55  	t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
    56  		State:       api.CommitStatusState(state),
    57  		TargetURL:   "http://test.ci/",
    58  		Description: "",
    59  		Context:     "testci",
    60  	}))
    61  
    62  	req = NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
    63  	resp = session.MakeRequest(t, req, http.StatusOK)
    64  
    65  	doc = NewHTMLParser(t, resp.Body)
    66  	// Check if commit status is displayed in message column (.tippy-target to ignore the tippy trigger)
    67  	sel := doc.doc.Find("#commits-table tbody tr td.message .tippy-target .commit-status")
    68  	assert.Equal(t, 1, sel.Length())
    69  	for _, class := range classes {
    70  		assert.True(t, sel.HasClass(class))
    71  	}
    72  
    73  	// By SHA
    74  	req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)+"/statuses")
    75  	reqOne := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)+"/status")
    76  	testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
    77  
    78  	// By short SHA
    79  	req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)[:10]+"/statuses")
    80  	reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)[:10]+"/status")
    81  	testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
    82  
    83  	// By Ref
    84  	req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/statuses")
    85  	reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/status")
    86  	testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
    87  	req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/v1.1/statuses")
    88  	reqOne = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/v1.1/status")
    89  	testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), session.MakeRequest(t, reqOne, http.StatusOK), state)
    90  }
    91  
    92  func testRepoCommitsWithStatus(t *testing.T, resp, respOne *httptest.ResponseRecorder, state string) {
    93  	var statuses []*api.CommitStatus
    94  	assert.NoError(t, json.Unmarshal(resp.Body.Bytes(), &statuses))
    95  	var status api.CombinedStatus
    96  	assert.NoError(t, json.Unmarshal(respOne.Body.Bytes(), &status))
    97  	assert.NotNil(t, status)
    98  
    99  	if assert.Len(t, statuses, 1) {
   100  		assert.Equal(t, api.CommitStatusState(state), statuses[0].State)
   101  		assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/statuses/65f1bf27bc3bf70f64657658635e66094edbcb4d", statuses[0].URL)
   102  		assert.Equal(t, "http://test.ci/", statuses[0].TargetURL)
   103  		assert.Equal(t, "", statuses[0].Description)
   104  		assert.Equal(t, "testci", statuses[0].Context)
   105  
   106  		assert.Len(t, status.Statuses, 1)
   107  		assert.Equal(t, statuses[0], status.Statuses[0])
   108  		assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.SHA)
   109  	}
   110  }
   111  
   112  func TestRepoCommitsWithStatusPending(t *testing.T) {
   113  	doTestRepoCommitWithStatus(t, "pending", "octicon-dot-fill", "yellow")
   114  }
   115  
   116  func TestRepoCommitsWithStatusSuccess(t *testing.T) {
   117  	doTestRepoCommitWithStatus(t, "success", "octicon-check", "green")
   118  }
   119  
   120  func TestRepoCommitsWithStatusError(t *testing.T) {
   121  	doTestRepoCommitWithStatus(t, "error", "gitea-exclamation", "red")
   122  }
   123  
   124  func TestRepoCommitsWithStatusFailure(t *testing.T) {
   125  	doTestRepoCommitWithStatus(t, "failure", "octicon-x", "red")
   126  }
   127  
   128  func TestRepoCommitsWithStatusWarning(t *testing.T) {
   129  	doTestRepoCommitWithStatus(t, "warning", "gitea-exclamation", "yellow")
   130  }
   131  
   132  func TestRepoCommitsStatusParallel(t *testing.T) {
   133  	defer tests.PrepareTestEnv(t)()
   134  
   135  	session := loginUser(t, "user2")
   136  
   137  	// Request repository commits page
   138  	req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
   139  	resp := session.MakeRequest(t, req, http.StatusOK)
   140  
   141  	doc := NewHTMLParser(t, resp.Body)
   142  	// Get first commit URL
   143  	commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Attr("href")
   144  	assert.True(t, exists)
   145  	assert.NotEmpty(t, commitURL)
   146  
   147  	var wg sync.WaitGroup
   148  	for i := 0; i < 10; i++ {
   149  		wg.Add(1)
   150  		go func(parentT *testing.T, i int) {
   151  			parentT.Run(fmt.Sprintf("ParallelCreateStatus_%d", i), func(t *testing.T) {
   152  				ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
   153  				runBody := doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
   154  					State:       api.CommitStatusPending,
   155  					TargetURL:   "http://test.ci/",
   156  					Description: "",
   157  					Context:     "testci",
   158  				})
   159  				runBody(t)
   160  				wg.Done()
   161  			})
   162  		}(t, i)
   163  	}
   164  	wg.Wait()
   165  }
   166  
   167  func TestRepoCommitsStatusMultiple(t *testing.T) {
   168  	defer tests.PrepareTestEnv(t)()
   169  
   170  	session := loginUser(t, "user2")
   171  
   172  	// Request repository commits page
   173  	req := NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
   174  	resp := session.MakeRequest(t, req, http.StatusOK)
   175  
   176  	doc := NewHTMLParser(t, resp.Body)
   177  	// Get first commit URL
   178  	commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Attr("href")
   179  	assert.True(t, exists)
   180  	assert.NotEmpty(t, commitURL)
   181  
   182  	// Call API to add status for commit
   183  	ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository)
   184  	t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
   185  		State:       api.CommitStatusSuccess,
   186  		TargetURL:   "http://test.ci/",
   187  		Description: "",
   188  		Context:     "testci",
   189  	}))
   190  
   191  	t.Run("CreateStatus", doAPICreateCommitStatus(ctx, path.Base(commitURL), api.CreateStatusOption{
   192  		State:       api.CommitStatusSuccess,
   193  		TargetURL:   "http://test.ci/",
   194  		Description: "",
   195  		Context:     "other_context",
   196  	}))
   197  
   198  	req = NewRequest(t, "GET", "/user2/repo1/commits/branch/master")
   199  	resp = session.MakeRequest(t, req, http.StatusOK)
   200  
   201  	doc = NewHTMLParser(t, resp.Body)
   202  	// Check that the data-tippy="commit-statuses" (for trigger) and commit-status (svg) are present
   203  	sel := doc.doc.Find("#commits-table tbody tr td.message [data-tippy=\"commit-statuses\"] .commit-status")
   204  	assert.Equal(t, 1, sel.Length())
   205  }