code.gitea.io/gitea@v1.22.3/routers/web/repo/wiki_test.go (about)

     1  // Copyright 2017 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"io"
     8  	"net/http"
     9  	"net/url"
    10  	"testing"
    11  
    12  	"code.gitea.io/gitea/models/db"
    13  	repo_model "code.gitea.io/gitea/models/repo"
    14  	"code.gitea.io/gitea/models/unittest"
    15  	"code.gitea.io/gitea/modules/git"
    16  	"code.gitea.io/gitea/modules/gitrepo"
    17  	"code.gitea.io/gitea/modules/web"
    18  	"code.gitea.io/gitea/services/contexttest"
    19  	"code.gitea.io/gitea/services/forms"
    20  	wiki_service "code.gitea.io/gitea/services/wiki"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  const (
    26  	content = "Wiki contents for unit tests"
    27  	message = "Wiki commit message for unit tests"
    28  )
    29  
    30  func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry {
    31  	wikiRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
    32  	assert.NoError(t, err)
    33  	defer wikiRepo.Close()
    34  	commit, err := wikiRepo.GetBranchCommit("master")
    35  	assert.NoError(t, err)
    36  	entries, err := commit.ListEntries()
    37  	assert.NoError(t, err)
    38  	for _, entry := range entries {
    39  		if entry.Name() == wiki_service.WebPathToGitPath(wikiName) {
    40  			return entry
    41  		}
    42  	}
    43  	return nil
    44  }
    45  
    46  func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) string {
    47  	entry := wikiEntry(t, repo, wikiName)
    48  	if !assert.NotNil(t, entry) {
    49  		return ""
    50  	}
    51  	reader, err := entry.Blob().DataAsync()
    52  	assert.NoError(t, err)
    53  	defer reader.Close()
    54  	bytes, err := io.ReadAll(reader)
    55  	assert.NoError(t, err)
    56  	return string(bytes)
    57  }
    58  
    59  func assertWikiExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) {
    60  	assert.NotNil(t, wikiEntry(t, repo, wikiName))
    61  }
    62  
    63  func assertWikiNotExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) {
    64  	assert.Nil(t, wikiEntry(t, repo, wikiName))
    65  }
    66  
    67  func assertPagesMetas(t *testing.T, expectedNames []string, metas any) {
    68  	pageMetas, ok := metas.([]PageMeta)
    69  	if !assert.True(t, ok) {
    70  		return
    71  	}
    72  	if !assert.Len(t, pageMetas, len(expectedNames)) {
    73  		return
    74  	}
    75  	for i, pageMeta := range pageMetas {
    76  		assert.EqualValues(t, expectedNames[i], pageMeta.Name)
    77  	}
    78  }
    79  
    80  func TestWiki(t *testing.T) {
    81  	unittest.PrepareTestEnv(t)
    82  
    83  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki")
    84  	ctx.SetParams("*", "Home")
    85  	contexttest.LoadRepo(t, ctx, 1)
    86  	Wiki(ctx)
    87  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
    88  	assert.EqualValues(t, "Home", ctx.Data["Title"])
    89  	assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"])
    90  
    91  	ctx, _ = contexttest.MockContext(t, "user2/repo1/jpeg.jpg")
    92  	ctx.SetParams("*", "jpeg.jpg")
    93  	contexttest.LoadRepo(t, ctx, 1)
    94  	Wiki(ctx)
    95  	assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
    96  	assert.Equal(t, "/user2/repo1/wiki/raw/jpeg.jpg", ctx.Resp.Header().Get("Location"))
    97  }
    98  
    99  func TestWikiPages(t *testing.T) {
   100  	unittest.PrepareTestEnv(t)
   101  
   102  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/?action=_pages")
   103  	contexttest.LoadRepo(t, ctx, 1)
   104  	WikiPages(ctx)
   105  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
   106  	assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name", "Unescaped File"}, ctx.Data["Pages"])
   107  }
   108  
   109  func TestNewWiki(t *testing.T) {
   110  	unittest.PrepareTestEnv(t)
   111  
   112  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/?action=_new")
   113  	contexttest.LoadUser(t, ctx, 2)
   114  	contexttest.LoadRepo(t, ctx, 1)
   115  	NewWiki(ctx)
   116  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
   117  	assert.EqualValues(t, ctx.Tr("repo.wiki.new_page"), ctx.Data["Title"])
   118  }
   119  
   120  func TestNewWikiPost(t *testing.T) {
   121  	for _, title := range []string{
   122  		"New page",
   123  		"&&&&",
   124  	} {
   125  		unittest.PrepareTestEnv(t)
   126  
   127  		ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/?action=_new")
   128  		contexttest.LoadUser(t, ctx, 2)
   129  		contexttest.LoadRepo(t, ctx, 1)
   130  		web.SetForm(ctx, &forms.NewWikiForm{
   131  			Title:   title,
   132  			Content: content,
   133  			Message: message,
   134  		})
   135  		NewWikiPost(ctx)
   136  		assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
   137  		assertWikiExists(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title))
   138  		assert.Equal(t, wikiContent(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title)), content)
   139  	}
   140  }
   141  
   142  func TestNewWikiPost_ReservedName(t *testing.T) {
   143  	unittest.PrepareTestEnv(t)
   144  
   145  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/?action=_new")
   146  	contexttest.LoadUser(t, ctx, 2)
   147  	contexttest.LoadRepo(t, ctx, 1)
   148  	web.SetForm(ctx, &forms.NewWikiForm{
   149  		Title:   "_edit",
   150  		Content: content,
   151  		Message: message,
   152  	})
   153  	NewWikiPost(ctx)
   154  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
   155  	assert.EqualValues(t, ctx.Tr("repo.wiki.reserved_page", "_edit"), ctx.Flash.ErrorMsg)
   156  	assertWikiNotExists(t, ctx.Repo.Repository, "_edit")
   157  }
   158  
   159  func TestEditWiki(t *testing.T) {
   160  	unittest.PrepareTestEnv(t)
   161  
   162  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/Home?action=_edit")
   163  	ctx.SetParams("*", "Home")
   164  	contexttest.LoadUser(t, ctx, 2)
   165  	contexttest.LoadRepo(t, ctx, 1)
   166  	EditWiki(ctx)
   167  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
   168  	assert.EqualValues(t, "Home", ctx.Data["Title"])
   169  	assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
   170  
   171  	ctx, _ = contexttest.MockContext(t, "user2/repo1/wiki/jpeg.jpg?action=_edit")
   172  	ctx.SetParams("*", "jpeg.jpg")
   173  	contexttest.LoadUser(t, ctx, 2)
   174  	contexttest.LoadRepo(t, ctx, 1)
   175  	EditWiki(ctx)
   176  	assert.EqualValues(t, http.StatusForbidden, ctx.Resp.Status())
   177  }
   178  
   179  func TestEditWikiPost(t *testing.T) {
   180  	for _, title := range []string{
   181  		"Home",
   182  		"New/<page>",
   183  	} {
   184  		unittest.PrepareTestEnv(t)
   185  		ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/Home?action=_new")
   186  		ctx.SetParams("*", "Home")
   187  		contexttest.LoadUser(t, ctx, 2)
   188  		contexttest.LoadRepo(t, ctx, 1)
   189  		web.SetForm(ctx, &forms.NewWikiForm{
   190  			Title:   title,
   191  			Content: content,
   192  			Message: message,
   193  		})
   194  		EditWikiPost(ctx)
   195  		assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
   196  		assertWikiExists(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title))
   197  		assert.Equal(t, wikiContent(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title)), content)
   198  		if title != "Home" {
   199  			assertWikiNotExists(t, ctx.Repo.Repository, "Home")
   200  		}
   201  	}
   202  }
   203  
   204  func TestDeleteWikiPagePost(t *testing.T) {
   205  	unittest.PrepareTestEnv(t)
   206  
   207  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/Home?action=_delete")
   208  	contexttest.LoadUser(t, ctx, 2)
   209  	contexttest.LoadRepo(t, ctx, 1)
   210  	DeleteWikiPagePost(ctx)
   211  	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
   212  	assertWikiNotExists(t, ctx.Repo.Repository, "Home")
   213  }
   214  
   215  func TestWikiRaw(t *testing.T) {
   216  	for filepath, filetype := range map[string]string{
   217  		"jpeg.jpg":                      "image/jpeg",
   218  		"images/jpeg.jpg":               "image/jpeg",
   219  		"files/Non-Renderable-File.zip": "application/octet-stream",
   220  		"Page With Spaced Name":         "text/plain; charset=utf-8",
   221  		"Page-With-Spaced-Name":         "text/plain; charset=utf-8",
   222  		"Page With Spaced Name.md":      "", // there is no "Page With Spaced Name.md" in repo
   223  		"Page-With-Spaced-Name.md":      "text/plain; charset=utf-8",
   224  	} {
   225  		unittest.PrepareTestEnv(t)
   226  
   227  		ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki/raw/"+url.PathEscape(filepath))
   228  		ctx.SetParams("*", filepath)
   229  		contexttest.LoadUser(t, ctx, 2)
   230  		contexttest.LoadRepo(t, ctx, 1)
   231  		WikiRaw(ctx)
   232  		if filetype == "" {
   233  			assert.EqualValues(t, http.StatusNotFound, ctx.Resp.Status(), "filepath: %s", filepath)
   234  		} else {
   235  			assert.EqualValues(t, http.StatusOK, ctx.Resp.Status(), "filepath: %s", filepath)
   236  			assert.EqualValues(t, filetype, ctx.Resp.Header().Get("Content-Type"), "filepath: %s", filepath)
   237  		}
   238  	}
   239  }
   240  
   241  func TestDefaultWikiBranch(t *testing.T) {
   242  	unittest.PrepareTestEnv(t)
   243  
   244  	// repo with no wiki
   245  	repoWithNoWiki := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
   246  	assert.False(t, repoWithNoWiki.HasWiki())
   247  	assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repoWithNoWiki, "main"))
   248  
   249  	// repo with wiki
   250  	assert.NoError(t, repo_model.UpdateRepositoryCols(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"}))
   251  
   252  	ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki")
   253  	ctx.SetParams("*", "Home")
   254  	contexttest.LoadRepo(t, ctx, 1)
   255  	assert.Equal(t, "wrong-branch", ctx.Repo.Repository.DefaultWikiBranch)
   256  	Wiki(ctx) // after the visiting, the out-of-sync database record will update the branch name to "master"
   257  	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   258  	assert.Equal(t, "master", ctx.Repo.Repository.DefaultWikiBranch)
   259  
   260  	// invalid branch name should fail
   261  	assert.Error(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "the bad name"))
   262  	repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   263  	assert.Equal(t, "master", repo.DefaultWikiBranch)
   264  
   265  	// the same branch name, should succeed (actually a no-op)
   266  	assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "master"))
   267  	repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   268  	assert.Equal(t, "master", repo.DefaultWikiBranch)
   269  
   270  	// change to another name
   271  	assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repo, "main"))
   272  	repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
   273  	assert.Equal(t, "main", repo.DefaultWikiBranch)
   274  }