Browse Source

Unit tests for repo watching (#963)

Ethan Koenig 3 years ago
parent
commit
be48b32e63
4 changed files with 202 additions and 103 deletions
  1. 1 0
      models/fixtures/repository.yml
  2. 0 103
      models/repo.go
  3. 103 0
      models/repo_watch.go
  4. 98 0
      models/repo_watch_test.go

+ 1 - 0
models/fixtures/repository.yml

@@ -33,6 +33,7 @@
33 33
   num_closed_issues: 0
34 34
   num_pulls: 0
35 35
   num_closed_pulls: 0
36
+  num_watches: 0
36 37
 
37 38
 -
38 39
   id: 4

+ 0 - 103
models/repo.go

@@ -2256,109 +2256,6 @@ func (repos MirrorRepositoryList) LoadAttributes() error {
2256 2256
 	return repos.loadAttributes(x)
2257 2257
 }
2258 2258
 
2259
-//  __      __         __         .__
2260
-// /  \    /  \_____ _/  |_  ____ |  |__
2261
-// \   \/\/   /\__  \\   __\/ ___\|  |  \
2262
-//  \        /  / __ \|  | \  \___|   Y  \
2263
-//   \__/\  /  (____  /__|  \___  >___|  /
2264
-//        \/        \/          \/     \/
2265
-
2266
-// Watch is connection request for receiving repository notification.
2267
-type Watch struct {
2268
-	ID     int64 `xorm:"pk autoincr"`
2269
-	UserID int64 `xorm:"UNIQUE(watch)"`
2270
-	RepoID int64 `xorm:"UNIQUE(watch)"`
2271
-}
2272
-
2273
-func isWatching(e Engine, userID, repoID int64) bool {
2274
-	has, _ := e.Get(&Watch{0, userID, repoID})
2275
-	return has
2276
-}
2277
-
2278
-// IsWatching checks if user has watched given repository.
2279
-func IsWatching(userID, repoID int64) bool {
2280
-	return isWatching(x, userID, repoID)
2281
-}
2282
-
2283
-func watchRepo(e Engine, userID, repoID int64, watch bool) (err error) {
2284
-	if watch {
2285
-		if isWatching(e, userID, repoID) {
2286
-			return nil
2287
-		}
2288
-		if _, err = e.Insert(&Watch{RepoID: repoID, UserID: userID}); err != nil {
2289
-			return err
2290
-		}
2291
-		_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoID)
2292
-	} else {
2293
-		if !isWatching(e, userID, repoID) {
2294
-			return nil
2295
-		}
2296
-		if _, err = e.Delete(&Watch{0, userID, repoID}); err != nil {
2297
-			return err
2298
-		}
2299
-		_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoID)
2300
-	}
2301
-	return err
2302
-}
2303
-
2304
-// WatchRepo watch or unwatch repository.
2305
-func WatchRepo(userID, repoID int64, watch bool) (err error) {
2306
-	return watchRepo(x, userID, repoID, watch)
2307
-}
2308
-
2309
-func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
2310
-	watches := make([]*Watch, 0, 10)
2311
-	return watches, e.Find(&watches, &Watch{RepoID: repoID})
2312
-}
2313
-
2314
-// GetWatchers returns all watchers of given repository.
2315
-func GetWatchers(repoID int64) ([]*Watch, error) {
2316
-	return getWatchers(x, repoID)
2317
-}
2318
-
2319
-// GetWatchers returns range of users watching given repository.
2320
-func (repo *Repository) GetWatchers(page int) ([]*User, error) {
2321
-	users := make([]*User, 0, ItemsPerPage)
2322
-	sess := x.Where("watch.repo_id=?", repo.ID).
2323
-		Join("LEFT", "watch", "`user`.id=`watch`.user_id")
2324
-	if page > 0 {
2325
-		sess = sess.Limit(ItemsPerPage, (page-1)*ItemsPerPage)
2326
-	}
2327
-	return users, sess.Find(&users)
2328
-}
2329
-
2330
-func notifyWatchers(e Engine, act *Action) error {
2331
-	// Add feeds for user self and all watchers.
2332
-	watches, err := getWatchers(e, act.RepoID)
2333
-	if err != nil {
2334
-		return fmt.Errorf("get watchers: %v", err)
2335
-	}
2336
-
2337
-	// Add feed for actioner.
2338
-	act.UserID = act.ActUserID
2339
-	if _, err = e.InsertOne(act); err != nil {
2340
-		return fmt.Errorf("insert new actioner: %v", err)
2341
-	}
2342
-
2343
-	for i := range watches {
2344
-		if act.ActUserID == watches[i].UserID {
2345
-			continue
2346
-		}
2347
-
2348
-		act.ID = 0
2349
-		act.UserID = watches[i].UserID
2350
-		if _, err = e.InsertOne(act); err != nil {
2351
-			return fmt.Errorf("insert new action: %v", err)
2352
-		}
2353
-	}
2354
-	return nil
2355
-}
2356
-
2357
-// NotifyWatchers creates batch of actions for every watcher.
2358
-func NotifyWatchers(act *Action) error {
2359
-	return notifyWatchers(x, act)
2360
-}
2361
-
2362 2259
 // ___________           __
2363 2260
 // \_   _____/__________|  | __
2364 2261
 //  |    __)/  _ \_  __ \  |/ /

+ 103 - 0
models/repo_watch.go

@@ -0,0 +1,103 @@
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 models
6
+
7
+import "fmt"
8
+
9
+// Watch is connection request for receiving repository notification.
10
+type Watch struct {
11
+	ID     int64 `xorm:"pk autoincr"`
12
+	UserID int64 `xorm:"UNIQUE(watch)"`
13
+	RepoID int64 `xorm:"UNIQUE(watch)"`
14
+}
15
+
16
+func isWatching(e Engine, userID, repoID int64) bool {
17
+	has, _ := e.Get(&Watch{UserID: userID, RepoID: repoID})
18
+	return has
19
+}
20
+
21
+// IsWatching checks if user has watched given repository.
22
+func IsWatching(userID, repoID int64) bool {
23
+	return isWatching(x, userID, repoID)
24
+}
25
+
26
+func watchRepo(e Engine, userID, repoID int64, watch bool) (err error) {
27
+	if watch {
28
+		if isWatching(e, userID, repoID) {
29
+			return nil
30
+		}
31
+		if _, err = e.Insert(&Watch{RepoID: repoID, UserID: userID}); err != nil {
32
+			return err
33
+		}
34
+		_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoID)
35
+	} else {
36
+		if !isWatching(e, userID, repoID) {
37
+			return nil
38
+		}
39
+		if _, err = e.Delete(&Watch{0, userID, repoID}); err != nil {
40
+			return err
41
+		}
42
+		_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoID)
43
+	}
44
+	return err
45
+}
46
+
47
+// WatchRepo watch or unwatch repository.
48
+func WatchRepo(userID, repoID int64, watch bool) (err error) {
49
+	return watchRepo(x, userID, repoID, watch)
50
+}
51
+
52
+func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
53
+	watches := make([]*Watch, 0, 10)
54
+	return watches, e.Find(&watches, &Watch{RepoID: repoID})
55
+}
56
+
57
+// GetWatchers returns all watchers of given repository.
58
+func GetWatchers(repoID int64) ([]*Watch, error) {
59
+	return getWatchers(x, repoID)
60
+}
61
+
62
+// GetWatchers returns range of users watching given repository.
63
+func (repo *Repository) GetWatchers(page int) ([]*User, error) {
64
+	users := make([]*User, 0, ItemsPerPage)
65
+	sess := x.Where("watch.repo_id=?", repo.ID).
66
+		Join("LEFT", "watch", "`user`.id=`watch`.user_id")
67
+	if page > 0 {
68
+		sess = sess.Limit(ItemsPerPage, (page-1)*ItemsPerPage)
69
+	}
70
+	return users, sess.Find(&users)
71
+}
72
+
73
+func notifyWatchers(e Engine, act *Action) error {
74
+	// Add feeds for user self and all watchers.
75
+	watches, err := getWatchers(e, act.RepoID)
76
+	if err != nil {
77
+		return fmt.Errorf("get watchers: %v", err)
78
+	}
79
+
80
+	// Add feed for actioner.
81
+	act.UserID = act.ActUserID
82
+	if _, err = e.InsertOne(act); err != nil {
83
+		return fmt.Errorf("insert new actioner: %v", err)
84
+	}
85
+
86
+	for i := range watches {
87
+		if act.ActUserID == watches[i].UserID {
88
+			continue
89
+		}
90
+
91
+		act.ID = 0
92
+		act.UserID = watches[i].UserID
93
+		if _, err = e.InsertOne(act); err != nil {
94
+			return fmt.Errorf("insert new action: %v", err)
95
+		}
96
+	}
97
+	return nil
98
+}
99
+
100
+// NotifyWatchers creates batch of actions for every watcher.
101
+func NotifyWatchers(act *Action) error {
102
+	return notifyWatchers(x, act)
103
+}

+ 98 - 0
models/repo_watch_test.go

@@ -0,0 +1,98 @@
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 models
6
+
7
+import (
8
+	"testing"
9
+
10
+	"github.com/stretchr/testify/assert"
11
+)
12
+
13
+func TestIsWatching(t *testing.T) {
14
+	assert.NoError(t, PrepareTestDatabase())
15
+
16
+	assert.True(t, IsWatching(1, 1))
17
+	assert.True(t, IsWatching(4, 1))
18
+
19
+	assert.False(t, IsWatching(1, 5))
20
+	assert.False(t, IsWatching(NonexistentID, NonexistentID))
21
+}
22
+
23
+func TestWatchRepo(t *testing.T) {
24
+	assert.NoError(t, PrepareTestDatabase())
25
+	const repoID = 3
26
+	const userID = 2
27
+
28
+	assert.NoError(t, WatchRepo(userID, repoID, true))
29
+	AssertExistsAndLoadBean(t, &Watch{RepoID: repoID, UserID: userID})
30
+	CheckConsistencyFor(t, &Repository{ID: repoID})
31
+
32
+	assert.NoError(t, WatchRepo(userID, repoID, false))
33
+	AssertNotExistsBean(t, &Watch{RepoID: repoID, UserID: userID})
34
+	CheckConsistencyFor(t, &Repository{ID: repoID})
35
+}
36
+
37
+func TestGetWatchers(t *testing.T) {
38
+	assert.NoError(t, PrepareTestDatabase())
39
+
40
+	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
41
+	watches, err := GetWatchers(repo.ID)
42
+	assert.NoError(t, err)
43
+	assert.Len(t, watches, repo.NumWatches)
44
+	for _, watch := range watches {
45
+		assert.EqualValues(t, repo.ID, watch.RepoID)
46
+	}
47
+
48
+	watches, err = GetWatchers(NonexistentID)
49
+	assert.NoError(t, err)
50
+	assert.Len(t, watches, 0)
51
+}
52
+
53
+func TestRepository_GetWatchers(t *testing.T) {
54
+	assert.NoError(t, PrepareTestDatabase())
55
+
56
+	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
57
+	watchers, err := repo.GetWatchers(1)
58
+	assert.NoError(t, err)
59
+	assert.Len(t, watchers, repo.NumWatches)
60
+	for _, watcher := range watchers {
61
+		AssertExistsAndLoadBean(t, &Watch{UserID: watcher.ID, RepoID: repo.ID})
62
+	}
63
+
64
+	repo = AssertExistsAndLoadBean(t, &Repository{ID: 10}).(*Repository)
65
+	watchers, err = repo.GetWatchers(1)
66
+	assert.NoError(t, err)
67
+	assert.Len(t, watchers, 0)
68
+}
69
+
70
+func TestNotifyWatchers(t *testing.T) {
71
+	assert.NoError(t, PrepareTestDatabase())
72
+
73
+	action := &Action{
74
+		ActUserID: 8,
75
+		RepoID:    1,
76
+		OpType:    ActionStarRepo,
77
+	}
78
+	assert.NoError(t, NotifyWatchers(action))
79
+
80
+	AssertExistsAndLoadBean(t, &Action{
81
+		ActUserID: action.ActUserID,
82
+		UserID:    1,
83
+		RepoID:    action.RepoID,
84
+		OpType:    action.OpType,
85
+	})
86
+	AssertExistsAndLoadBean(t, &Action{
87
+		ActUserID: action.ActUserID,
88
+		UserID:    4,
89
+		RepoID:    action.RepoID,
90
+		OpType:    action.OpType,
91
+	})
92
+	AssertExistsAndLoadBean(t, &Action{
93
+		ActUserID: action.ActUserID,
94
+		UserID:    8,
95
+		RepoID:    action.RepoID,
96
+		OpType:    action.OpType,
97
+	})
98
+}