code.gitea.io/gitea@v1.22.3/services/contexttest/context_tests.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 // Package contexttest provides utilities for testing Web/API contexts with models. 5 package contexttest 6 7 import ( 8 gocontext "context" 9 "io" 10 "maps" 11 "net/http" 12 "net/http/httptest" 13 "net/url" 14 "strings" 15 "testing" 16 "time" 17 18 access_model "code.gitea.io/gitea/models/perm/access" 19 repo_model "code.gitea.io/gitea/models/repo" 20 "code.gitea.io/gitea/models/unittest" 21 user_model "code.gitea.io/gitea/models/user" 22 "code.gitea.io/gitea/modules/cache" 23 "code.gitea.io/gitea/modules/gitrepo" 24 "code.gitea.io/gitea/modules/session" 25 "code.gitea.io/gitea/modules/templates" 26 "code.gitea.io/gitea/modules/translation" 27 "code.gitea.io/gitea/modules/web/middleware" 28 "code.gitea.io/gitea/services/context" 29 30 "github.com/go-chi/chi/v5" 31 "github.com/stretchr/testify/assert" 32 ) 33 34 func mockRequest(t *testing.T, reqPath string) *http.Request { 35 method, path, found := strings.Cut(reqPath, " ") 36 if !found { 37 method = "GET" 38 path = reqPath 39 } 40 requestURL, err := url.Parse(path) 41 assert.NoError(t, err) 42 req := &http.Request{Method: method, Host: requestURL.Host, URL: requestURL, Form: maps.Clone(requestURL.Query()), Header: http.Header{}} 43 req = req.WithContext(middleware.WithContextData(req.Context())) 44 return req 45 } 46 47 type MockContextOption struct { 48 Render context.Render 49 SessionStore *session.MockStore 50 } 51 52 // MockContext mock context for unit tests 53 func MockContext(t *testing.T, reqPath string, opts ...MockContextOption) (*context.Context, *httptest.ResponseRecorder) { 54 var opt MockContextOption 55 if len(opts) > 0 { 56 opt = opts[0] 57 } 58 if opt.Render == nil { 59 opt.Render = &MockRender{} 60 } 61 resp := httptest.NewRecorder() 62 req := mockRequest(t, reqPath) 63 base, baseCleanUp := context.NewBaseContext(resp, req) 64 _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later 65 base.Data = middleware.GetContextData(req.Context()) 66 base.Locale = &translation.MockLocale{} 67 68 chiCtx := chi.NewRouteContext() 69 ctx := context.NewWebContext(base, opt.Render, nil) 70 ctx.AppendContextValue(context.WebContextKey, ctx) 71 ctx.AppendContextValue(chi.RouteCtxKey, chiCtx) 72 if opt.SessionStore != nil { 73 ctx.AppendContextValue(session.MockStoreContextKey, opt.SessionStore) 74 ctx.Session = opt.SessionStore 75 } 76 ctx.Cache = cache.GetCache() 77 ctx.PageData = map[string]any{} 78 ctx.Data["PageStartTime"] = time.Now() 79 return ctx, resp 80 } 81 82 // MockAPIContext mock context for unit tests 83 func MockAPIContext(t *testing.T, reqPath string) (*context.APIContext, *httptest.ResponseRecorder) { 84 resp := httptest.NewRecorder() 85 req := mockRequest(t, reqPath) 86 base, baseCleanUp := context.NewBaseContext(resp, req) 87 base.Data = middleware.GetContextData(req.Context()) 88 base.Locale = &translation.MockLocale{} 89 ctx := &context.APIContext{Base: base} 90 _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later 91 92 chiCtx := chi.NewRouteContext() 93 ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx) 94 return ctx, resp 95 } 96 97 func MockPrivateContext(t *testing.T, reqPath string) (*context.PrivateContext, *httptest.ResponseRecorder) { 98 resp := httptest.NewRecorder() 99 req := mockRequest(t, reqPath) 100 base, baseCleanUp := context.NewBaseContext(resp, req) 101 base.Data = middleware.GetContextData(req.Context()) 102 base.Locale = &translation.MockLocale{} 103 ctx := &context.PrivateContext{Base: base} 104 _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later 105 chiCtx := chi.NewRouteContext() 106 ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx) 107 return ctx, resp 108 } 109 110 // LoadRepo load a repo into a test context. 111 func LoadRepo(t *testing.T, ctx gocontext.Context, repoID int64) { 112 var doer *user_model.User 113 repo := &context.Repository{} 114 switch ctx := ctx.(type) { 115 case *context.Context: 116 ctx.Repo = repo 117 doer = ctx.Doer 118 case *context.APIContext: 119 ctx.Repo = repo 120 doer = ctx.Doer 121 default: 122 assert.FailNow(t, "context is not *context.Context or *context.APIContext") 123 } 124 125 repo.Repository = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) 126 var err error 127 repo.Owner, err = user_model.GetUserByID(ctx, repo.Repository.OwnerID) 128 assert.NoError(t, err) 129 repo.RepoLink = repo.Repository.Link() 130 repo.Permission, err = access_model.GetUserRepoPermission(ctx, repo.Repository, doer) 131 assert.NoError(t, err) 132 } 133 134 // LoadRepoCommit loads a repo's commit into a test context. 135 func LoadRepoCommit(t *testing.T, ctx gocontext.Context) { 136 var repo *context.Repository 137 switch ctx := ctx.(type) { 138 case *context.Context: 139 repo = ctx.Repo 140 case *context.APIContext: 141 repo = ctx.Repo 142 default: 143 assert.FailNow(t, "context is not *context.Context or *context.APIContext") 144 } 145 146 gitRepo, err := gitrepo.OpenRepository(ctx, repo.Repository) 147 assert.NoError(t, err) 148 defer gitRepo.Close() 149 branch, err := gitRepo.GetHEADBranch() 150 assert.NoError(t, err) 151 assert.NotNil(t, branch) 152 if branch != nil { 153 repo.Commit, err = gitRepo.GetBranchCommit(branch.Name) 154 assert.NoError(t, err) 155 } 156 } 157 158 // LoadUser load a user into a test context 159 func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) { 160 doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) 161 switch ctx := ctx.(type) { 162 case *context.Context: 163 ctx.Doer = doer 164 case *context.APIContext: 165 ctx.Doer = doer 166 default: 167 assert.FailNow(t, "context is not *context.Context or *context.APIContext") 168 } 169 } 170 171 // LoadGitRepo load a git repo into a test context. Requires that ctx.Repo has 172 // already been populated. 173 func LoadGitRepo(t *testing.T, ctx *context.Context) { 174 assert.NoError(t, ctx.Repo.Repository.LoadOwner(ctx)) 175 var err error 176 ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) 177 assert.NoError(t, err) 178 } 179 180 type MockRender struct{} 181 182 func (tr *MockRender) TemplateLookup(tmpl string, _ gocontext.Context) (templates.TemplateExecutor, error) { 183 return nil, nil 184 } 185 186 func (tr *MockRender) HTML(w io.Writer, status int, _ string, _ any, _ gocontext.Context) error { 187 if resp, ok := w.(http.ResponseWriter); ok { 188 resp.WriteHeader(status) 189 } 190 return nil 191 }