Unit tests for wiki routers (#3022)

This commit is contained in:
Ethan Koenig 2017-11-30 07:52:15 -08:00 committed by Lauris BH
parent 82e8486f13
commit 91f3d77ceb
9 changed files with 285 additions and 69 deletions

View File

@ -297,7 +297,7 @@ func TestCommitRepoAction(t *testing.T) {
} }
for _, s := range samples { for _, s := range samples {
prepareTestEnv(t) PrepareTestEnv(t)
user := AssertExistsAndLoadBean(t, &User{ID: s.userID}).(*User) user := AssertExistsAndLoadBean(t, &User{ID: s.userID}).(*User)
repo := AssertExistsAndLoadBean(t, &Repository{ID: s.repositoryID, OwnerID: user.ID}).(*Repository) repo := AssertExistsAndLoadBean(t, &Repository{ID: s.repositoryID, OwnerID: user.ID}).(*Repository)

View File

@ -1,14 +1,8 @@
package models package models
import ( import (
"fmt"
"os"
"path/filepath"
"testing" "testing"
"code.gitea.io/gitea/modules/setting"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -19,17 +13,5 @@ func TestFixturesAreConsistent(t *testing.T) {
} }
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
if err := CreateTestEngine("fixtures/"); err != nil { MainTest(m, "..")
fmt.Printf("Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
} }

View File

@ -5,7 +5,9 @@
package models package models
import ( import (
"fmt"
"os" "os"
"path/filepath"
"testing" "testing"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -13,6 +15,7 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/core" "github.com/go-xorm/core"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"gopkg.in/testfixtures.v2" "gopkg.in/testfixtures.v2"
) )
@ -20,9 +23,30 @@ import (
// NonexistentID an ID that will never exist // NonexistentID an ID that will never exist
const NonexistentID = 9223372036854775807 const NonexistentID = 9223372036854775807
// CreateTestEngine create in-memory sqlite database for unit tests // giteaRoot a path to the gitea root
// Any package that calls this must import github.com/mattn/go-sqlite3 var giteaRoot string
func CreateTestEngine(fixturesDir string) error {
// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGiteaRoot string) {
giteaRoot = pathToGiteaRoot
fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
if err := createTestEngine(fixturesDir); err != nil {
fmt.Fprintf(os.Stderr, "Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
}
func createTestEngine(fixturesDir string) error {
var err error var err error
x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared") x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
if err != nil { if err != nil {
@ -45,10 +69,13 @@ func PrepareTestDatabase() error {
return LoadFixtures() return LoadFixtures()
} }
func prepareTestEnv(t testing.TB) { // PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
assert.NoError(t, PrepareTestDatabase()) assert.NoError(t, PrepareTestDatabase())
assert.NoError(t, os.RemoveAll(setting.RepoRootPath)) assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
assert.NoError(t, com.CopyDir("../integrations/gitea-repositories-meta", setting.RepoRootPath)) metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
assert.NoError(t, com.CopyDir(metaPath, setting.RepoRootPath))
} }
type testCond struct { type testCond struct {

View File

@ -74,6 +74,14 @@ func TestWikiFilenameToName(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, test.Expected, name) assert.Equal(t, test.Expected, name)
} }
for _, badFilename := range []string{
"nofileextension",
"wrongfileextension.txt",
"badescaping%%.md",
} {
_, err := WikiFilenameToName(badFilename)
assert.Error(t, err)
}
} }
func TestWikiNameToFilenameToName(t *testing.T) { func TestWikiNameToFilenameToName(t *testing.T) {
@ -115,7 +123,7 @@ func TestRepository_WikiPath(t *testing.T) {
} }
func TestRepository_HasWiki(t *testing.T) { func TestRepository_HasWiki(t *testing.T) {
prepareTestEnv(t) PrepareTestEnv(t)
repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
assert.True(t, repo1.HasWiki()) assert.True(t, repo1.HasWiki())
repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository) repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository)
@ -123,7 +131,7 @@ func TestRepository_HasWiki(t *testing.T) {
} }
func TestRepository_InitWiki(t *testing.T) { func TestRepository_InitWiki(t *testing.T) {
prepareTestEnv(t) PrepareTestEnv(t)
// repo1 already has a wiki // repo1 already has a wiki
repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
assert.NoError(t, repo1.InitWiki()) assert.NoError(t, repo1.InitWiki())
@ -135,7 +143,7 @@ func TestRepository_InitWiki(t *testing.T) {
} }
func TestRepository_LocalWikiPath(t *testing.T) { func TestRepository_LocalWikiPath(t *testing.T) {
prepareTestEnv(t) PrepareTestEnv(t)
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
expected := filepath.Join(setting.AppDataPath, "tmp/local-wiki/1") expected := filepath.Join(setting.AppDataPath, "tmp/local-wiki/1")
assert.Equal(t, expected, repo.LocalWikiPath()) assert.Equal(t, expected, repo.LocalWikiPath())
@ -150,11 +158,23 @@ func TestRepository_AddWikiPage(t *testing.T) {
"Another page", "Another page",
"Here's a <tag> and a/slash", "Here's a <tag> and a/slash",
} { } {
prepareTestEnv(t) PrepareTestEnv(t)
assert.NoError(t, repo.AddWikiPage(doer, wikiName, wikiContent, commitMsg)) assert.NoError(t, repo.AddWikiPage(doer, wikiName, wikiContent, commitMsg))
expectedPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(wikiName)) expectedPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(wikiName))
assert.True(t, com.IsExist(expectedPath)) assert.True(t, com.IsExist(expectedPath))
} }
// test for already-existing wiki name
PrepareTestEnv(t)
err := repo.AddWikiPage(doer, "Home", wikiContent, commitMsg)
assert.Error(t, err)
assert.True(t, IsErrWikiAlreadyExist(err))
// test for reserved wiki name
PrepareTestEnv(t)
err = repo.AddWikiPage(doer, "_edit", wikiContent, commitMsg)
assert.Error(t, err)
assert.True(t, IsErrWikiReservedName(err))
} }
func TestRepository_EditWikiPage(t *testing.T) { func TestRepository_EditWikiPage(t *testing.T) {
@ -163,20 +183,23 @@ func TestRepository_EditWikiPage(t *testing.T) {
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
for _, newWikiName := range []string{ for _, newWikiName := range []string{
"Home", // same name as before
"New home", "New home",
"New/name/with/slashes", "New/name/with/slashes",
} { } {
prepareTestEnv(t) PrepareTestEnv(t)
assert.NoError(t, repo.EditWikiPage(doer, "Home", newWikiName, newWikiContent, commitMsg)) assert.NoError(t, repo.EditWikiPage(doer, "Home", newWikiName, newWikiContent, commitMsg))
newPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(newWikiName)) newPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(newWikiName))
assert.True(t, com.IsExist(newPath)) assert.True(t, com.IsExist(newPath))
oldPath := path.Join(repo.LocalWikiPath(), "Home.md") if newWikiName != "Home" {
assert.False(t, com.IsExist(oldPath)) oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
assert.False(t, com.IsExist(oldPath))
}
} }
} }
func TestRepository_DeleteWikiPage(t *testing.T) { func TestRepository_DeleteWikiPage(t *testing.T) {
prepareTestEnv(t) PrepareTestEnv(t)
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User) doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
assert.NoError(t, repo.DeleteWikiPage(doer, "Home")) assert.NoError(t, repo.DeleteWikiPage(doer, "Home"))

View File

@ -9,33 +9,46 @@ import (
"net/url" "net/url"
"testing" "testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"github.com/go-macaron/session"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
macaron "gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
) )
// MockContext mock context for unit tests // MockContext mock context for unit tests
func MockContext(t *testing.T) *context.Context { func MockContext(t *testing.T, path string) *context.Context {
var macaronContext *macaron.Context var macaronContext macaron.Context
mac := macaron.New() macaronContext.ReplaceAllParams(macaron.Params{})
mac.Get("*/", func(ctx *macaron.Context) {
macaronContext = ctx
})
req, err := http.NewRequest("GET", "star", nil)
assert.NoError(t, err)
req.Form = url.Values{}
mac.ServeHTTP(&mockResponseWriter{}, req)
assert.NotNil(t, macaronContext)
assert.EqualValues(t, req, macaronContext.Req.Request)
macaronContext.Locale = &mockLocale{} macaronContext.Locale = &mockLocale{}
requestURL, err := url.Parse(path)
assert.NoError(t, err)
macaronContext.Req = macaron.Request{Request: &http.Request{
URL: requestURL,
Form: url.Values{},
}}
macaronContext.Resp = &mockResponseWriter{} macaronContext.Resp = &mockResponseWriter{}
macaronContext.Render = &mockRender{ResponseWriter: macaronContext.Resp} macaronContext.Render = &mockRender{ResponseWriter: macaronContext.Resp}
macaronContext.Data = map[string]interface{}{}
return &context.Context{ return &context.Context{
Context: macaronContext, Context: &macaronContext,
Flash: &session.Flash{},
} }
} }
// LoadRepo load a repo into a test context.
func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
ctx.Repo = &context.Repository{}
ctx.Repo.Repository = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repoID}).(*models.Repository)
}
// LoadUser load a user into a test context.
func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User)
}
type mockLocale struct{} type mockLocale struct{}
func (l mockLocale) Language() string { func (l mockLocale) Language() string {
@ -43,7 +56,7 @@ func (l mockLocale) Language() string {
} }
func (l mockLocale) Tr(s string, _ ...interface{}) string { func (l mockLocale) Tr(s string, _ ...interface{}) string {
return "test translation" return s
} }
type mockResponseWriter struct { type mockResponseWriter struct {
@ -91,7 +104,8 @@ func (tr *mockRender) SetResponseWriter(rw http.ResponseWriter) {
tr.ResponseWriter = rw tr.ResponseWriter = rw
} }
func (tr *mockRender) JSON(int, interface{}) { func (tr *mockRender) JSON(status int, _ interface{}) {
tr.Status(status)
} }
func (tr *mockRender) JSONString(interface{}) (string, error) { func (tr *mockRender) JSONString(interface{}) (string, error) {

16
routers/repo/main_test.go Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"path/filepath"
"testing"
"code.gitea.io/gitea/models"
)
func TestMain(m *testing.M) {
models.MainTest(m, filepath.Join("..", ".."))
}

171
routers/repo/wiki_test.go Normal file
View File

@ -0,0 +1,171 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"io/ioutil"
"net/http"
"path/filepath"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/test"
"github.com/Unknwon/com"
"github.com/stretchr/testify/assert"
)
const content = "Wiki contents for unit tests"
const message = "Wiki commit message for unit tests"
func wikiPath(repo *models.Repository, wikiName string) string {
return filepath.Join(repo.LocalWikiPath(), models.WikiNameToFilename(wikiName))
}
func wikiContent(t *testing.T, repo *models.Repository, wikiName string) string {
bytes, err := ioutil.ReadFile(wikiPath(repo, wikiName))
assert.NoError(t, err)
return string(bytes)
}
func assertWikiExists(t *testing.T, repo *models.Repository, wikiName string) {
assert.True(t, com.IsExist(wikiPath(repo, wikiName)))
}
func assertWikiNotExists(t *testing.T, repo *models.Repository, wikiName string) {
assert.False(t, com.IsExist(wikiPath(repo, wikiName)))
}
func assertPagesMetas(t *testing.T, expectedNames []string, metas interface{}) {
pageMetas, ok := metas.([]PageMeta)
if !assert.True(t, ok) {
return
}
if !assert.EqualValues(t, len(expectedNames), len(pageMetas)) {
return
}
for i, pageMeta := range pageMetas {
assert.EqualValues(t, expectedNames[i], pageMeta.Name)
}
}
func TestWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
ctx.SetParams(":page", "Home")
test.LoadRepo(t, ctx, 1)
Wiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, "Home", ctx.Data["Title"])
assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
}
func TestWikiPages(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
test.LoadRepo(t, ctx, 1)
WikiPages(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
}
func TestNewWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, ctx.Tr("repo.wiki.new_page"), ctx.Data["Title"])
}
func TestNewWikiPost(t *testing.T) {
for _, title := range []string{
"New page",
"&&&&",
} {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWikiPost(ctx, auth.NewWikiForm{
Title: title,
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
assertWikiExists(t, ctx.Repo.Repository, title)
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
}
}
func TestNewWikiPost_ReservedName(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWikiPost(ctx, auth.NewWikiForm{
Title: "_edit",
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, ctx.Tr("repo.wiki.reserved_page"), ctx.Flash.ErrorMsg)
assertWikiNotExists(t, ctx.Repo.Repository, "_edit")
}
func TestEditWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_edit/Home")
ctx.SetParams(":page", "Home")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
EditWiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, "Home", ctx.Data["Title"])
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
}
func TestEditWikiPost(t *testing.T) {
for _, title := range []string{
"Home",
"New/<page>",
} {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new/Home")
ctx.SetParams(":page", "Home")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
EditWikiPost(ctx, auth.NewWikiForm{
Title: title,
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
assertWikiExists(t, ctx.Repo.Repository, title)
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
if title != "Home" {
assertWikiNotExists(t, ctx.Repo.Repository, "Home")
}
}
}
func TestDeleteWikiPagePost(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/Home/delete")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
DeleteWikiPagePost(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assertWikiNotExists(t, ctx.Repo.Repository, "Home")
}

View File

@ -19,8 +19,8 @@ func TestIssues(t *testing.T) {
setting.UI.IssuePagingNum = 1 setting.UI.IssuePagingNum = 1
assert.NoError(t, models.LoadFixtures()) assert.NoError(t, models.LoadFixtures())
ctx := test.MockContext(t) ctx := test.MockContext(t, "issues")
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) test.LoadUser(t, ctx, 2)
ctx.SetParams(":type", "issues") ctx.SetParams(":type", "issues")
ctx.Req.Form.Set("state", "closed") ctx.Req.Form.Set("state", "closed")
Issues(ctx) Issues(ctx)

View File

@ -5,29 +5,12 @@
package user package user
import ( import (
"fmt"
"os"
"path/filepath" "path/filepath"
"testing" "testing"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/setting"
_ "github.com/mattn/go-sqlite3" // for the test engine
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
if err := models.CreateTestEngine("../../models/fixtures/"); err != nil { models.MainTest(m, filepath.Join("..", ".."))
fmt.Printf("Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
} }