Browse Source

Unit tests for wiki routers (#3022)

Ethan Koenig 1 year ago
parent
commit
91f3d77ceb

+ 1 - 1
models/action_test.go

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

+ 1 - 19
models/main_test.go

@@ -1,14 +1,8 @@
1 1
 package models
2 2
 
3 3
 import (
4
-	"fmt"
5
-	"os"
6
-	"path/filepath"
7 4
 	"testing"
8 5
 
9
-	"code.gitea.io/gitea/modules/setting"
10
-
11
-	_ "github.com/mattn/go-sqlite3" // for the test engine
12 6
 	"github.com/stretchr/testify/assert"
13 7
 )
14 8
 
@@ -19,17 +13,5 @@ func TestFixturesAreConsistent(t *testing.T) {
19 13
 }
20 14
 
21 15
 func TestMain(m *testing.M) {
22
-	if err := CreateTestEngine("fixtures/"); err != nil {
23
-		fmt.Printf("Error creating test engine: %v\n", err)
24
-		os.Exit(1)
25
-	}
26
-
27
-	setting.AppURL = "https://try.gitea.io/"
28
-	setting.RunUser = "runuser"
29
-	setting.SSH.Port = 3000
30
-	setting.SSH.Domain = "try.gitea.io"
31
-	setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
32
-	setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
33
-
34
-	os.Exit(m.Run())
16
+	MainTest(m, "..")
35 17
 }

+ 32 - 5
models/unit_tests.go

@@ -5,7 +5,9 @@
5 5
 package models
6 6
 
7 7
 import (
8
+	"fmt"
8 9
 	"os"
10
+	"path/filepath"
9 11
 	"testing"
10 12
 
11 13
 	"code.gitea.io/gitea/modules/setting"
@@ -13,6 +15,7 @@ import (
13 15
 	"github.com/Unknwon/com"
14 16
 	"github.com/go-xorm/core"
15 17
 	"github.com/go-xorm/xorm"
18
+	_ "github.com/mattn/go-sqlite3" // for the test engine
16 19
 	"github.com/stretchr/testify/assert"
17 20
 	"gopkg.in/testfixtures.v2"
18 21
 )
@@ -20,9 +23,30 @@ import (
20 23
 // NonexistentID an ID that will never exist
21 24
 const NonexistentID = 9223372036854775807
22 25
 
23
-// CreateTestEngine create in-memory sqlite database for unit tests
24
-// Any package that calls this must import github.com/mattn/go-sqlite3
25
-func CreateTestEngine(fixturesDir string) error {
26
+// giteaRoot a path to the gitea root
27
+var giteaRoot string
28
+
29
+// MainTest a reusable TestMain(..) function for unit tests that need to use a
30
+// test database. Creates the test database, and sets necessary settings.
31
+func MainTest(m *testing.M, pathToGiteaRoot string) {
32
+	giteaRoot = pathToGiteaRoot
33
+	fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
34
+	if err := createTestEngine(fixturesDir); err != nil {
35
+		fmt.Fprintf(os.Stderr, "Error creating test engine: %v\n", err)
36
+		os.Exit(1)
37
+	}
38
+
39
+	setting.AppURL = "https://try.gitea.io/"
40
+	setting.RunUser = "runuser"
41
+	setting.SSH.Port = 3000
42
+	setting.SSH.Domain = "try.gitea.io"
43
+	setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
44
+	setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
45
+
46
+	os.Exit(m.Run())
47
+}
48
+
49
+func createTestEngine(fixturesDir string) error {
26 50
 	var err error
27 51
 	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
28 52
 	if err != nil {
@@ -45,10 +69,13 @@ func PrepareTestDatabase() error {
45 69
 	return LoadFixtures()
46 70
 }
47 71
 
48
-func prepareTestEnv(t testing.TB) {
72
+// PrepareTestEnv prepares the environment for unit tests. Can only be called
73
+// by tests that use the above MainTest(..) function.
74
+func PrepareTestEnv(t testing.TB) {
49 75
 	assert.NoError(t, PrepareTestDatabase())
50 76
 	assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
51
-	assert.NoError(t, com.CopyDir("../integrations/gitea-repositories-meta", setting.RepoRootPath))
77
+	metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
78
+	assert.NoError(t, com.CopyDir(metaPath, setting.RepoRootPath))
52 79
 }
53 80
 
54 81
 type testCond struct {

+ 31 - 8
models/wiki_test.go

@@ -74,6 +74,14 @@ func TestWikiFilenameToName(t *testing.T) {
74 74
 		assert.NoError(t, err)
75 75
 		assert.Equal(t, test.Expected, name)
76 76
 	}
77
+	for _, badFilename := range []string{
78
+		"nofileextension",
79
+		"wrongfileextension.txt",
80
+		"badescaping%%.md",
81
+	} {
82
+		_, err := WikiFilenameToName(badFilename)
83
+		assert.Error(t, err)
84
+	}
77 85
 }
78 86
 
79 87
 func TestWikiNameToFilenameToName(t *testing.T) {
@@ -115,7 +123,7 @@ func TestRepository_WikiPath(t *testing.T) {
115 123
 }
116 124
 
117 125
 func TestRepository_HasWiki(t *testing.T) {
118
-	prepareTestEnv(t)
126
+	PrepareTestEnv(t)
119 127
 	repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
120 128
 	assert.True(t, repo1.HasWiki())
121 129
 	repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository)
@@ -123,7 +131,7 @@ func TestRepository_HasWiki(t *testing.T) {
123 131
 }
124 132
 
125 133
 func TestRepository_InitWiki(t *testing.T) {
126
-	prepareTestEnv(t)
134
+	PrepareTestEnv(t)
127 135
 	// repo1 already has a wiki
128 136
 	repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
129 137
 	assert.NoError(t, repo1.InitWiki())
@@ -135,7 +143,7 @@ func TestRepository_InitWiki(t *testing.T) {
135 143
 }
136 144
 
137 145
 func TestRepository_LocalWikiPath(t *testing.T) {
138
-	prepareTestEnv(t)
146
+	PrepareTestEnv(t)
139 147
 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
140 148
 	expected := filepath.Join(setting.AppDataPath, "tmp/local-wiki/1")
141 149
 	assert.Equal(t, expected, repo.LocalWikiPath())
@@ -150,11 +158,23 @@ func TestRepository_AddWikiPage(t *testing.T) {
150 158
 		"Another page",
151 159
 		"Here's a <tag> and a/slash",
152 160
 	} {
153
-		prepareTestEnv(t)
161
+		PrepareTestEnv(t)
154 162
 		assert.NoError(t, repo.AddWikiPage(doer, wikiName, wikiContent, commitMsg))
155 163
 		expectedPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(wikiName))
156 164
 		assert.True(t, com.IsExist(expectedPath))
157 165
 	}
166
+
167
+	// test for already-existing wiki name
168
+	PrepareTestEnv(t)
169
+	err := repo.AddWikiPage(doer, "Home", wikiContent, commitMsg)
170
+	assert.Error(t, err)
171
+	assert.True(t, IsErrWikiAlreadyExist(err))
172
+
173
+	// test for reserved wiki name
174
+	PrepareTestEnv(t)
175
+	err = repo.AddWikiPage(doer, "_edit", wikiContent, commitMsg)
176
+	assert.Error(t, err)
177
+	assert.True(t, IsErrWikiReservedName(err))
158 178
 }
159 179
 
160 180
 func TestRepository_EditWikiPage(t *testing.T) {
@@ -163,20 +183,23 @@ func TestRepository_EditWikiPage(t *testing.T) {
163 183
 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
164 184
 	doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
165 185
 	for _, newWikiName := range []string{
186
+		"Home", // same name as before
166 187
 		"New home",
167 188
 		"New/name/with/slashes",
168 189
 	} {
169
-		prepareTestEnv(t)
190
+		PrepareTestEnv(t)
170 191
 		assert.NoError(t, repo.EditWikiPage(doer, "Home", newWikiName, newWikiContent, commitMsg))
171 192
 		newPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(newWikiName))
172 193
 		assert.True(t, com.IsExist(newPath))
173
-		oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
174
-		assert.False(t, com.IsExist(oldPath))
194
+		if newWikiName != "Home" {
195
+			oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
196
+			assert.False(t, com.IsExist(oldPath))
197
+		}
175 198
 	}
176 199
 }
177 200
 
178 201
 func TestRepository_DeleteWikiPage(t *testing.T) {
179
-	prepareTestEnv(t)
202
+	PrepareTestEnv(t)
180 203
 	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
181 204
 	doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
182 205
 	assert.NoError(t, repo.DeleteWikiPage(doer, "Home"))

+ 30 - 16
modules/test/context_tests.go

@@ -9,33 +9,46 @@ import (
9 9
 	"net/url"
10 10
 	"testing"
11 11
 
12
+	"code.gitea.io/gitea/models"
12 13
 	"code.gitea.io/gitea/modules/context"
13 14
 
15
+	"github.com/go-macaron/session"
16
+	_ "github.com/mattn/go-sqlite3" // for the test engine
14 17
 	"github.com/stretchr/testify/assert"
15
-	macaron "gopkg.in/macaron.v1"
18
+	"gopkg.in/macaron.v1"
16 19
 )
17 20
 
18 21
 // MockContext mock context for unit tests
19
-func MockContext(t *testing.T) *context.Context {
20
-	var macaronContext *macaron.Context
21
-	mac := macaron.New()
22
-	mac.Get("*/", func(ctx *macaron.Context) {
23
-		macaronContext = ctx
24
-	})
25
-	req, err := http.NewRequest("GET", "star", nil)
26
-	assert.NoError(t, err)
27
-	req.Form = url.Values{}
28
-	mac.ServeHTTP(&mockResponseWriter{}, req)
29
-	assert.NotNil(t, macaronContext)
30
-	assert.EqualValues(t, req, macaronContext.Req.Request)
22
+func MockContext(t *testing.T, path string) *context.Context {
23
+	var macaronContext macaron.Context
24
+	macaronContext.ReplaceAllParams(macaron.Params{})
31 25
 	macaronContext.Locale = &mockLocale{}
26
+	requestURL, err := url.Parse(path)
27
+	assert.NoError(t, err)
28
+	macaronContext.Req = macaron.Request{Request: &http.Request{
29
+		URL:  requestURL,
30
+		Form: url.Values{},
31
+	}}
32 32
 	macaronContext.Resp = &mockResponseWriter{}
33 33
 	macaronContext.Render = &mockRender{ResponseWriter: macaronContext.Resp}
34
+	macaronContext.Data = map[string]interface{}{}
34 35
 	return &context.Context{
35
-		Context: macaronContext,
36
+		Context: &macaronContext,
37
+		Flash:   &session.Flash{},
36 38
 	}
37 39
 }
38 40
 
41
+// LoadRepo load a repo into a test context.
42
+func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
43
+	ctx.Repo = &context.Repository{}
44
+	ctx.Repo.Repository = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repoID}).(*models.Repository)
45
+}
46
+
47
+// LoadUser load a user into a test context.
48
+func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
49
+	ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User)
50
+}
51
+
39 52
 type mockLocale struct{}
40 53
 
41 54
 func (l mockLocale) Language() string {
@@ -43,7 +56,7 @@ func (l mockLocale) Language() string {
43 56
 }
44 57
 
45 58
 func (l mockLocale) Tr(s string, _ ...interface{}) string {
46
-	return "test translation"
59
+	return s
47 60
 }
48 61
 
49 62
 type mockResponseWriter struct {
@@ -91,7 +104,8 @@ func (tr *mockRender) SetResponseWriter(rw http.ResponseWriter) {
91 104
 	tr.ResponseWriter = rw
92 105
 }
93 106
 
94
-func (tr *mockRender) JSON(int, interface{}) {
107
+func (tr *mockRender) JSON(status int, _ interface{}) {
108
+	tr.Status(status)
95 109
 }
96 110
 
97 111
 func (tr *mockRender) JSONString(interface{}) (string, error) {

+ 16 - 0
routers/repo/main_test.go

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

+ 171 - 0
routers/repo/wiki_test.go

@@ -0,0 +1,171 @@
1
+// Copyright 2017 The Gitea Authors. All rights reserved.
2
+// Use of this source code is governed by a MIT-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package repo
6
+
7
+import (
8
+	"io/ioutil"
9
+	"net/http"
10
+	"path/filepath"
11
+	"testing"
12
+
13
+	"code.gitea.io/gitea/models"
14
+	"code.gitea.io/gitea/modules/auth"
15
+	"code.gitea.io/gitea/modules/test"
16
+
17
+	"github.com/Unknwon/com"
18
+	"github.com/stretchr/testify/assert"
19
+)
20
+
21
+const content = "Wiki contents for unit tests"
22
+const message = "Wiki commit message for unit tests"
23
+
24
+func wikiPath(repo *models.Repository, wikiName string) string {
25
+	return filepath.Join(repo.LocalWikiPath(), models.WikiNameToFilename(wikiName))
26
+}
27
+
28
+func wikiContent(t *testing.T, repo *models.Repository, wikiName string) string {
29
+	bytes, err := ioutil.ReadFile(wikiPath(repo, wikiName))
30
+	assert.NoError(t, err)
31
+	return string(bytes)
32
+}
33
+
34
+func assertWikiExists(t *testing.T, repo *models.Repository, wikiName string) {
35
+	assert.True(t, com.IsExist(wikiPath(repo, wikiName)))
36
+}
37
+
38
+func assertWikiNotExists(t *testing.T, repo *models.Repository, wikiName string) {
39
+	assert.False(t, com.IsExist(wikiPath(repo, wikiName)))
40
+}
41
+
42
+func assertPagesMetas(t *testing.T, expectedNames []string, metas interface{}) {
43
+	pageMetas, ok := metas.([]PageMeta)
44
+	if !assert.True(t, ok) {
45
+		return
46
+	}
47
+	if !assert.EqualValues(t, len(expectedNames), len(pageMetas)) {
48
+		return
49
+	}
50
+	for i, pageMeta := range pageMetas {
51
+		assert.EqualValues(t, expectedNames[i], pageMeta.Name)
52
+	}
53
+}
54
+
55
+func TestWiki(t *testing.T) {
56
+	models.PrepareTestEnv(t)
57
+
58
+	ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
59
+	ctx.SetParams(":page", "Home")
60
+	test.LoadRepo(t, ctx, 1)
61
+	Wiki(ctx)
62
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
63
+	assert.EqualValues(t, "Home", ctx.Data["Title"])
64
+	assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
65
+}
66
+
67
+func TestWikiPages(t *testing.T) {
68
+	models.PrepareTestEnv(t)
69
+
70
+	ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
71
+	test.LoadRepo(t, ctx, 1)
72
+	WikiPages(ctx)
73
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
74
+	assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
75
+}
76
+
77
+func TestNewWiki(t *testing.T) {
78
+	models.PrepareTestEnv(t)
79
+
80
+	ctx := test.MockContext(t, "user2/repo1/wiki/_new")
81
+	test.LoadUser(t, ctx, 2)
82
+	test.LoadRepo(t, ctx, 1)
83
+	NewWiki(ctx)
84
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
85
+	assert.EqualValues(t, ctx.Tr("repo.wiki.new_page"), ctx.Data["Title"])
86
+}
87
+
88
+func TestNewWikiPost(t *testing.T) {
89
+	for _, title := range []string{
90
+		"New page",
91
+		"&&&&",
92
+	} {
93
+		models.PrepareTestEnv(t)
94
+
95
+		ctx := test.MockContext(t, "user2/repo1/wiki/_new")
96
+		test.LoadUser(t, ctx, 2)
97
+		test.LoadRepo(t, ctx, 1)
98
+		NewWikiPost(ctx, auth.NewWikiForm{
99
+			Title:   title,
100
+			Content: content,
101
+			Message: message,
102
+		})
103
+		assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
104
+		assertWikiExists(t, ctx.Repo.Repository, title)
105
+		assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
106
+	}
107
+}
108
+
109
+func TestNewWikiPost_ReservedName(t *testing.T) {
110
+	models.PrepareTestEnv(t)
111
+
112
+	ctx := test.MockContext(t, "user2/repo1/wiki/_new")
113
+	test.LoadUser(t, ctx, 2)
114
+	test.LoadRepo(t, ctx, 1)
115
+	NewWikiPost(ctx, auth.NewWikiForm{
116
+		Title:   "_edit",
117
+		Content: content,
118
+		Message: message,
119
+	})
120
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
121
+	assert.EqualValues(t, ctx.Tr("repo.wiki.reserved_page"), ctx.Flash.ErrorMsg)
122
+	assertWikiNotExists(t, ctx.Repo.Repository, "_edit")
123
+}
124
+
125
+func TestEditWiki(t *testing.T) {
126
+	models.PrepareTestEnv(t)
127
+
128
+	ctx := test.MockContext(t, "user2/repo1/wiki/_edit/Home")
129
+	ctx.SetParams(":page", "Home")
130
+	test.LoadUser(t, ctx, 2)
131
+	test.LoadRepo(t, ctx, 1)
132
+	EditWiki(ctx)
133
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
134
+	assert.EqualValues(t, "Home", ctx.Data["Title"])
135
+	assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
136
+}
137
+
138
+func TestEditWikiPost(t *testing.T) {
139
+	for _, title := range []string{
140
+		"Home",
141
+		"New/<page>",
142
+	} {
143
+		models.PrepareTestEnv(t)
144
+		ctx := test.MockContext(t, "user2/repo1/wiki/_new/Home")
145
+		ctx.SetParams(":page", "Home")
146
+		test.LoadUser(t, ctx, 2)
147
+		test.LoadRepo(t, ctx, 1)
148
+		EditWikiPost(ctx, auth.NewWikiForm{
149
+			Title:   title,
150
+			Content: content,
151
+			Message: message,
152
+		})
153
+		assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
154
+		assertWikiExists(t, ctx.Repo.Repository, title)
155
+		assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
156
+		if title != "Home" {
157
+			assertWikiNotExists(t, ctx.Repo.Repository, "Home")
158
+		}
159
+	}
160
+}
161
+
162
+func TestDeleteWikiPagePost(t *testing.T) {
163
+	models.PrepareTestEnv(t)
164
+
165
+	ctx := test.MockContext(t, "user2/repo1/wiki/Home/delete")
166
+	test.LoadUser(t, ctx, 2)
167
+	test.LoadRepo(t, ctx, 1)
168
+	DeleteWikiPagePost(ctx)
169
+	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
170
+	assertWikiNotExists(t, ctx.Repo.Repository, "Home")
171
+}

+ 2 - 2
routers/user/home_test.go

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

+ 1 - 18
routers/user/main_test.go

@@ -5,29 +5,12 @@
5 5
 package user
6 6
 
7 7
 import (
8
-	"fmt"
9
-	"os"
10 8
 	"path/filepath"
11 9
 	"testing"
12 10
 
13 11
 	"code.gitea.io/gitea/models"
14
-	"code.gitea.io/gitea/modules/setting"
15
-
16
-	_ "github.com/mattn/go-sqlite3" // for the test engine
17 12
 )
18 13
 
19 14
 func TestMain(m *testing.M) {
20
-	if err := models.CreateTestEngine("../../models/fixtures/"); err != nil {
21
-		fmt.Printf("Error creating test engine: %v\n", err)
22
-		os.Exit(1)
23
-	}
24
-
25
-	setting.AppURL = "https://try.gitea.io/"
26
-	setting.RunUser = "runuser"
27
-	setting.SSH.Port = 3000
28
-	setting.SSH.Domain = "try.gitea.io"
29
-	setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
30
-	setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
31
-
32
-	os.Exit(m.Run())
15
+	models.MainTest(m, filepath.Join("..", ".."))
33 16
 }