snapshot of https://github.com/traggo/server.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
build / build (push) Failing after 3s

This commit is contained in:
upstream-mirror
2026-09-16 05:24:45 +05:00
commit cda7c1a474
272 changed files with 31973 additions and 0 deletions

38
tag/create.go Normal file
View File

@@ -0,0 +1,38 @@
package tag
import (
"context"
"fmt"
"strings"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// CreateTag creates a tag.
func (r *ResolverForTag) CreateTag(ctx context.Context, key string, color string) (*gqlmodel.TagDefinition, error) {
if strings.TrimSpace(key) == "" {
return nil, fmt.Errorf("tag must not be empty")
}
if strings.Contains(key, " ") {
return nil, fmt.Errorf("tag must not contain spaces")
}
userID := auth.GetUser(ctx).ID
definition := &model.TagDefinition{
Key: strings.ToLower(key),
Color: color,
UserID: userID,
}
if !r.DB.Where("user_id = ?", userID).Where("key = ?", strings.ToLower(key)).Find(new(model.TagDefinition)).RecordNotFound() {
return nil, fmt.Errorf("tag with key '%s' does already exist", definition.Key)
}
create := r.DB.Create(&definition)
gqlTag := &gqlmodel.TagDefinition{}
copier.Copy(gqlTag, definition)
return gqlTag, create.Error
}

101
tag/create_test.go Normal file
View File

@@ -0,0 +1,101 @@
package tag
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestGQL_CreateTag_succeeds_addsTag(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
resolver := ResolverForTag{DB: db.DB}
tag, err := resolver.CreateTag(fake.User(5), "new_tag", "#fff")
require.Nil(t, err)
expected := &gqlmodel.TagDefinition{
Key: "new_tag",
Color: "#fff",
}
require.Equal(t, expected, tag)
assertTagExist(t, db, model.TagDefinition{
Key: "new_tag",
Color: "#fff",
UserID: 5,
})
assertTagCount(t, db, 1)
}
func TestGQL_CreateTag_fails_tagAlreadyExists(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
db.Create(&model.TagDefinition{Key: "existing_tag", Color: "#fff", UserID: 5})
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "existing_tag", "#fff")
require.EqualError(t, err, "tag with key 'existing_tag' does already exist")
assertTagCount(t, db, 1)
}
func TestGQL_CreateTag_fails_tagAlreadyExists_caseInsensitive(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
db.Create(&model.TagDefinition{Key: "tag", Color: "#fff", UserID: 5})
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "Tag", "#fff")
require.EqualError(t, err, "tag with key 'tag' does already exist")
assertTagCount(t, db, 1)
}
func TestGQL_CreateTag_succeeds_existingTagForOtherUser(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(4)
db.User(5)
db.Create(&model.TagDefinition{Key: "existing_tag", Color: "#fff", UserID: 4})
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "existing_tag", "#xxx")
assert.Nil(t, err)
assertTagCount(t, db, 2)
assertTagExist(t, db, model.TagDefinition{
Key: "existing_tag",
Color: "#xxx",
UserID: 5,
})
}
func TestGQL_CreateTag_fails_empty(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "", "#fff")
require.EqualError(t, err, "tag must not be empty")
assertTagCount(t, db, 0)
}
func TestGQL_CreateTag_fails_includes_space(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "test tag", "#fff")
require.EqualError(t, err, "tag must not contain spaces")
assertTagCount(t, db, 0)
}

30
tag/get.go Normal file
View File

@@ -0,0 +1,30 @@
package tag
import (
"context"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// Tags returns all tags.
func (r *ResolverForTag) Tags(ctx context.Context) ([]*gqlmodel.TagDefinition, error) {
var tags []model.TagDefinition
userID := auth.GetUser(ctx).ID
timeSpansIdsOfUser := r.DB.Model(new(model.TimeSpan)).
Select("id").
Where(&model.TimeSpan{UserID: userID}).
SubQuery()
usages := r.DB.Select("COUNT (*)").Where("time_span_tags.time_span_id in ?", timeSpansIdsOfUser).
Where("tag_definitions.key = time_span_tags.key").
Model(new(model.TimeSpanTag)).
Group("time_span_tags.key").
SubQuery()
find := r.DB.Select("tag_definitions.*, ? as usages", usages).Where("user_id = ?", userID).Order("usages desc").Find(&tags)
result := []*gqlmodel.TagDefinition{}
copier.Copy(&result, &tags)
return result, find.Error
}

36
tag/get_test.go Normal file
View File

@@ -0,0 +1,36 @@
package tag
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestGQL_Tags(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
right := db.User(2)
left.NewTagDefinition("my tag")
left.NewTagDefinition("my tag 2")
left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z").Tag("my tag", "value")
left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z").Tag("my tag", "value").Tag("my tag 2", "v")
left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z").Tag("my tag", "value").Tag("my tag 2", "v")
right.NewTagDefinition("my tag")
right.NewTagDefinition("my tag 2")
right.NewTagDefinition("my tag 5")
right.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z").Tag("my tag", "value").Tag("my tag 2", "v")
resolver := ResolverForTag{DB: db.DB}
tags, err := resolver.Tags(fake.User(left.User.ID))
require.Nil(t, err)
expected := []*gqlmodel.TagDefinition{
{Key: "my tag", Usages: 3},
{Key: "my tag 2", Usages: 2},
}
require.Equal(t, expected, tags)
}

60
tag/remove.go Normal file
View File

@@ -0,0 +1,60 @@
package tag
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// RemoveTag removes a tag.
func (r *ResolverForTag) RemoveTag(ctx context.Context, key string) (*gqlmodel.TagDefinition, error) {
tag := model.TagDefinition{}
userID := auth.GetUser(ctx).ID
if r.DB.Where(&model.TagDefinition{UserID: userID, Key: key}).Find(&tag).RecordNotFound() {
return nil, fmt.Errorf("tag with key '%s' does not exist", key)
}
usedInEntries := []model.DashboardEntry{}
if err := r.DB.
Joins("INNER JOIN dashboards ON dashboard_entries.dashboard_id = dashboards.id").
Where("dashboards.user_id = ?", userID).
Where("keys LIKE ? OR keys LIKE ? OR keys LIKE ?", "%"+key, "%"+key+"%", key+"%").
Find(&usedInEntries).Error; err != nil {
return nil, err
}
if len(usedInEntries) > 0 {
dashboard := &model.Dashboard{ID: usedInEntries[0].DashboardID}
r.DB.Find(dashboard)
return nil, fmt.Errorf("tag '%s' is used in dashboard '%s' entry '%s', remove this reference before deleting the tag", key, dashboard.Name, usedInEntries[0].Title)
}
tx := r.DB.Begin()
if err := tx.Where(model.TagDefinition{Key: key, UserID: userID}).
Delete(new(model.TagDefinition)).Error; err != nil {
tx.Rollback()
return nil, err
}
timeSpansIdsOfUser := tx.Model(new(model.TimeSpan)).
Select("id").
Where(&model.TimeSpan{UserID: userID}).
SubQuery()
if err := tx.
Where("time_span_id in ?", timeSpansIdsOfUser).
Where(&model.TimeSpanTag{Key: key}).
Delete(new(model.TimeSpanTag)).Error; err != nil {
tx.Rollback()
return nil, err
}
remove := tx.Commit()
gqlTag := &gqlmodel.TagDefinition{}
copier.Copy(gqlTag, &tag)
return gqlTag, remove.Error
}

106
tag/remove_test.go Normal file
View File

@@ -0,0 +1,106 @@
package tag
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestGQL_RemoveTag_succeeds_removesTag(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(3)
user.NewTagDefinition("existing")
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(3), "existing")
require.Nil(t, err)
user.AssertHasTagDefinition("existing", false)
}
func TestRemove_referencedInDashboardEntry(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
left.NewTagDefinition("coolio")
dashboard := left.Dashboard("yeah")
dashboard.Entry("entry")
entry := dashboard.Dashboard.Entries[0]
entry.Keys = "abc,coolio,chicken"
db.Save(&entry)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(left.User.ID), "coolio")
require.EqualError(t, err, "tag 'coolio' is used in dashboard 'yeah' entry 'entry', remove this reference before deleting the tag")
}
func TestGQL_RemoveTag_succeeds_removesTimespans(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(3)
right := db.User(4)
left.NewTagDefinition("tag")
right.NewTagDefinition("tag")
leftTs := left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
leftTs.Tag("tag", "def")
rightTs := right.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
rightTs.Tag("tag", "def")
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(left.User.ID), "tag")
require.Nil(t, err)
assertTagCount(t, db, 1)
left.AssertHasTagDefinition("tag", false)
right.AssertHasTagDefinition("tag", true)
leftTs.AssertExists(true).AssertHasTag("tag", "def", false)
rightTs.AssertExists(true).AssertHasTag("tag", "def", true)
}
func TestGQL_RemoveTag_fails_notExistingTag(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(3)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(3), "not existing")
require.EqualError(t, err, "tag with key 'not existing' does not exist")
}
func TestGQL_RemoveTag_fails_notPermission(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(3).NewTagDefinition("existing")
db.User(5)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(5), "existing")
require.EqualError(t, err, "tag with key 'existing' does not exist")
}
func TestRemove_crossUserIsolation(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
userA := db.User(5)
userB := db.User(2)
userA.NewTagDefinition("project")
userB.NewTagDefinition("project")
dashboardB := userB.Dashboard("secretDashboard")
dashboardB.Entry("secretEntry")
entryB := dashboardB.Dashboard.Entries[0]
entryB.Keys = "project,secret"
db.Save(&entryB)
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.RemoveTag(fake.User(userA.User.ID), "project")
require.NoError(t, err, "removing user's own tag should succeed even if another user has a dashboard entry with that tag")
userA.AssertHasTagDefinition("project", false)
userB.AssertHasTagDefinition("project", true)
}

19
tag/suggest.go Normal file
View File

@@ -0,0 +1,19 @@
package tag
import (
"context"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// SuggestTag suggests a tag.
func (r *ResolverForTag) SuggestTag(ctx context.Context, query string) ([]*gqlmodel.TagDefinition, error) {
var suggestions []model.TagDefinition
find := r.DB.Where("user_id = ?", auth.GetUser(ctx).ID).Where("Key LIKE ?", query+"%").Find(&suggestions)
var result []*gqlmodel.TagDefinition
copier.Copy(&result, &suggestions)
return result, find.Error
}

47
tag/suggest_test.go Normal file
View File

@@ -0,0 +1,47 @@
package tag
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestGQL_SuggestTag_matchesTags(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(1)
db.User(2)
resolver := ResolverForTag{DB: db.DB}
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "project2", Color: "#fff", UserID: 2})
db.Create(&model.TagDefinition{Key: "priority", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", UserID: 1})
tags, err := resolver.SuggestTag(fake.User(1), "pr")
require.Nil(t, err)
expected := []*gqlmodel.TagDefinition{
{Key: "project", Color: "#fff"},
{Key: "priority", Color: "#fff"},
}
require.Equal(t, expected, tags)
}
func TestGQL_SuggestTag_noMatchingTags(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(1)
resolver := ResolverForTag{DB: db.DB}
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", UserID: 1})
tags, err := resolver.SuggestTag(fake.User(1), "fire")
require.Nil(t, err)
expected := []*gqlmodel.TagDefinition{}
require.Equal(t, expected, tags)
}

8
tag/tagresolver.go Normal file
View File

@@ -0,0 +1,8 @@
package tag
import "github.com/jinzhu/gorm"
// ResolverForTag resolves tag specific things.
type ResolverForTag struct {
DB *gorm.DB
}

86
tag/update.go Normal file
View File

@@ -0,0 +1,86 @@
package tag
import (
"context"
"fmt"
"strings"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// UpdateTag updates a tag.
func (r *ResolverForTag) UpdateTag(ctx context.Context, key string, newKey *string, color string) (*gqlmodel.TagDefinition, error) {
tag := model.TagDefinition{}
userID := auth.GetUser(ctx).ID
if r.DB.Where(&model.TagDefinition{UserID: userID, Key: key}).Find(&tag).RecordNotFound() {
return nil, fmt.Errorf("tag with key '%s' does not exist", key)
}
tx := r.DB.Begin()
newValue := model.TagDefinition{
Key: strings.ToLower(key),
Color: color,
UserID: userID,
}
if newKey != nil && *newKey != key {
if strings.Contains(*newKey, " ") {
tx.Rollback()
return nil, fmt.Errorf("tag must not contain spaces")
}
*newKey = strings.ToLower(*newKey)
newValue.Key = *newKey
timeSpansIdsOfUser := tx.Model(new(model.TimeSpan)).
Select("id").
Where(&model.TimeSpan{UserID: userID}).
SubQuery()
if err := tx.
Model(new(model.TimeSpanTag)).
Where("time_span_id in ?", timeSpansIdsOfUser).
Where(&model.TimeSpanTag{Key: key}).
Updates(&model.TimeSpanTag{Key: *newKey}).Error; err != nil {
tx.Rollback()
return nil, err
}
usedInEntries := []model.DashboardEntry{}
if err := tx.
Joins("INNER JOIN dashboards ON dashboard_entries.dashboard_id = dashboards.id").
Where("dashboards.user_id = ?", userID).
Where("keys LIKE ? OR keys LIKE ? OR keys LIKE ?", "%"+key, "%"+key+"%", key+"%").
Find(&usedInEntries).Error; err != nil {
tx.Rollback()
return nil, err
}
for _, entry := range usedInEntries {
tags := strings.Split(entry.Keys, ",")
for index, tagInEntry := range tags {
if tagInEntry == key {
tags[index] = *newKey
}
}
entry.Keys = strings.Join(tags, ",")
if err := tx.Save(&entry).Error; err != nil {
tx.Rollback()
return nil, err
}
}
}
if err := tx.Model(new(model.TagDefinition)).Where(&model.TagDefinition{UserID: userID, Key: key}).Updates(&newValue).Error; err != nil {
tx.Rollback()
return nil, err
}
update := tx.Commit()
gqlTag := &gqlmodel.TagDefinition{}
copier.Copy(gqlTag, &newValue)
return gqlTag, update.Error
}

158
tag/update_test.go Normal file
View File

@@ -0,0 +1,158 @@
package tag
import (
"testing"
"github.com/magiconair/properties/assert"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestUpdate_withKey(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
right := db.User(2)
left.NewTagDefinition("coolio")
right.NewTagDefinition("coolio")
leftTs := left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
leftTs.Tag("coolio", "mama")
rightTs := right.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
rightTs.Tag("coolio", "mama")
resolver := ResolverForTag{DB: db.DB}
newTagName := "mega"
tag, err := resolver.UpdateTag(fake.User(left.User.ID), "coolio", &newTagName, "#abc")
require.NoError(t, err)
require.Equal(t, &gqlmodel.TagDefinition{
Color: "#abc",
Key: "mega",
}, tag)
left.AssertHasTagDefinition("coolio", false).AssertHasTagDefinition("mega", true)
right.AssertHasTagDefinition("coolio", true).AssertHasTagDefinition("mega", false)
leftTs.AssertHasTag("mega", "mama", true).AssertHasTag("coolio", "mama", false)
rightTs.AssertHasTag("coolio", "mama", true).AssertHasTag("mega", "mama", false)
}
func TestUpdate_lowercases(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(5)
user.NewTagDefinition("coolio")
ts := user.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
ts.Tag("coolio", "mama")
resolver := ResolverForTag{DB: db.DB}
newTagName := "Mega"
tag, err := resolver.UpdateTag(fake.User(user.User.ID), "coolio", &newTagName, "#abc")
require.NoError(t, err)
require.Equal(t, &gqlmodel.TagDefinition{
Color: "#abc",
Key: "mega",
}, tag)
user.AssertHasTagDefinition("coolio", false).AssertHasTagDefinition("mega", true)
ts.AssertHasTag("mega", "mama", true).AssertHasTag("coolio", "mama", false)
}
func TestUpdate_disallow_space(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(5)
user.NewTagDefinition("coolio")
resolver := ResolverForTag{DB: db.DB}
newTagName := "the coolio"
_, err := resolver.UpdateTag(fake.User(user.User.ID), "coolio", &newTagName, "#abc")
require.EqualError(t, err, "tag must not contain spaces")
}
func TestUpdate_withoutKey(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
right := db.User(2)
left.NewTagDefinition("coolio")
right.NewTagDefinition("coolio")
leftTs := left.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
leftTs.Tag("coolio", "mama")
rightTs := right.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
rightTs.Tag("coolio", "mama")
resolver := ResolverForTag{DB: db.DB}
tag, err := resolver.UpdateTag(fake.User(left.User.ID), "coolio", nil, "#abc")
require.NoError(t, err)
assert.Equal(t, &gqlmodel.TagDefinition{
Color: "#abc",
Key: "coolio",
}, tag)
}
func TestUpdate_dashboardEntryKey(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
left.NewTagDefinition("coolio")
dashboard := left.Dashboard("yeah")
dashboard.Entry("entry")
entry := dashboard.Dashboard.Entries[0]
entry.Keys = "abc,coolio,chicken"
db.Save(&entry)
newTag := "yes"
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.UpdateTag(fake.User(left.User.ID), "coolio", &newTag, "#abc")
require.NoError(t, err)
db.Find(&entry)
require.Equal(t, "abc,yes,chicken", entry.Keys)
}
func TestUpdate_noPermissions(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
left := db.User(5)
right := db.User(2)
right.NewTagDefinition("coolio")
rightTs := right.TimeSpan("2009-06-30T18:30:00Z", "2009-06-30T18:40:00Z")
rightTs.Tag("coolio", "mama")
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.UpdateTag(fake.User(left.User.ID), "coolio", nil, "#abc")
require.EqualError(t, err, "tag with key 'coolio' does not exist")
right.AssertHasTagDefinition("coolio", true)
}
func TestUpdate_dashboardEntryKey_crossUserIsolation(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
userA := db.User(5)
userB := db.User(2)
userA.NewTagDefinition("project")
userB.NewTagDefinition("project")
dashboardA := userA.Dashboard("dashboardA")
dashboardA.Entry("entryA")
entryA := dashboardA.Dashboard.Entries[0]
entryA.Keys = "project,task1"
db.Save(&entryA)
dashboardB := userB.Dashboard("dashboardB")
dashboardB.Entry("entryB")
entryB := dashboardB.Dashboard.Entries[0]
entryB.Keys = "project,task2"
db.Save(&entryB)
newTag := "newproject"
resolver := ResolverForTag{DB: db.DB}
_, err := resolver.UpdateTag(fake.User(userA.User.ID), "project", &newTag, "#abc")
require.NoError(t, err)
db.Find(&entryA)
require.Equal(t, "newproject,task1", entryA.Keys, "user A's entry should be updated")
db.Find(&entryB)
require.Equal(t, "project,task2", entryB.Keys, "user B's entry should NOT be modified")
}

23
tag/utils_test.go Normal file
View File

@@ -0,0 +1,23 @@
package tag
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
)
func assertTagExist(t *testing.T, db *test.Database, expected model.TagDefinition) {
foundUser := new(model.TagDefinition)
find := db.Where("key = ?", expected.Key).Find(foundUser)
require.Nil(t, find.Error)
require.NotNil(t, foundUser)
require.Equal(t, expected, *foundUser)
}
func assertTagCount(t *testing.T, db *test.Database, expected int) {
count := new(int)
db.Model(new(model.TagDefinition)).Count(count)
require.Equal(t, expected, *count)
}