From 777d63dff187086fd7f846de638a843c46bb23ec Mon Sep 17 00:00:00 2001 From: konrad Date: Sun, 16 Dec 2018 13:21:32 +0000 Subject: [PATCH] More unit tests (#34) --- README.md | 1 + go.sum | 1 + pkg/caldav/caldav.go | 3 +- pkg/caldav/caldav_test.go | 246 +++++++++++++++ pkg/models/fixtures/list.yml | 8 +- pkg/models/fixtures/namespaces.yml | 7 +- pkg/models/fixtures/tasks.yml | 41 +++ pkg/models/fixtures/team_list.yml | 6 + pkg/models/fixtures/team_namespaces.yml | 6 + pkg/models/fixtures/users.yml | 6 + pkg/models/fixtures/users_list.yml | 6 + pkg/models/fixtures/users_namespace.yml | 6 + pkg/models/list_read_test.go | 2 +- pkg/models/list_rights.go | 2 +- pkg/models/list_task_readall_test.go | 251 +++++++++++++++ pkg/models/list_users_readall.go | 2 +- pkg/models/list_users_rights_test.go | 99 ++++++ pkg/models/list_users_test.go | 355 +++++++++++++++++++++ pkg/models/namespace_test.go | 2 +- pkg/models/namespace_users_rights_test.go | 99 ++++++ pkg/models/namespace_users_test.go | 357 ++++++++++++++++++++++ pkg/models/team_list_test.go | 80 ++++- pkg/models/team_namespace_rights_test.go | 99 ++++++ pkg/models/team_namespace_test.go | 78 ++++- pkg/models/teams_rights_test.go | 110 +++++++ pkg/models/teams_test.go | 5 + pkg/models/user_email_confirm_test.go | 67 ++++ pkg/utils/random_string_test.go | 28 ++ pkg/utils/sha256_test.go | 55 ++++ tools.go | 1 + 30 files changed, 2019 insertions(+), 10 deletions(-) create mode 100644 pkg/caldav/caldav_test.go create mode 100644 pkg/models/fixtures/tasks.yml create mode 100644 pkg/models/fixtures/team_list.yml create mode 100644 pkg/models/fixtures/team_namespaces.yml create mode 100644 pkg/models/fixtures/users_list.yml create mode 100644 pkg/models/fixtures/users_namespace.yml create mode 100644 pkg/models/list_task_readall_test.go create mode 100644 pkg/models/list_users_rights_test.go create mode 100644 pkg/models/list_users_test.go create mode 100644 pkg/models/namespace_users_rights_test.go create mode 100644 pkg/models/namespace_users_test.go create mode 100644 pkg/models/team_namespace_rights_test.go create mode 100644 pkg/models/teams_rights_test.go create mode 100644 pkg/models/user_email_confirm_test.go create mode 100644 pkg/utils/random_string_test.go create mode 100644 pkg/utils/sha256_test.go diff --git a/README.md b/README.md index 2d0e314cf15..ed998fab69d 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![Docker Pulls](https://img.shields.io/docker/pulls/vikunja/api.svg)](https://hub.docker.com/r/vikunja/api/) [![Swagger Docs](https://img.shields.io/badge/swagger-docs-brightgreen.svg)](https://try.vikunja.io/api/v1/swagger) [![Go Report Card](https://goreportcard.com/badge/git.kolaente.de/vikunja/api)](https://goreportcard.com/report/git.kolaente.de/vikunja/api) +[![cover.run](https://cover.run/go/code.vikunja.io/api.svg?style=flat&tag=golang-1.10)](https://cover.run/go?tag=golang-1.10&repo=code.vikunja.io%2Fapi) ## Features diff --git a/go.sum b/go.sum index 4d1516f723d..cdab07c9844 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLM github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cweill/gotests v1.5.2 h1:kKqmKmS2wCV3tuLnfpbiuN8OlkosQZTpCfiqmiuNAsA= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20180901172138-1eb28afdf9b6 h1:BZGp1dbKFjqlGmxEpwkDpCWNxVwEYnUPoncIzLiHlPo= diff --git a/pkg/caldav/caldav.go b/pkg/caldav/caldav.go index cef5d775eb8..a7f11a98168 100644 --- a/pkg/caldav/caldav.go +++ b/pkg/caldav/caldav.go @@ -93,7 +93,8 @@ END:VCALENDAR` // Need a line break } func makeCalDavTimeFromUnixTime(unixtime int64) (caldavtime string) { - tm := time.Unix(unixtime, 0) + tz, _ := time.LoadLocation("UTC") + tm := time.Unix(unixtime, 0).In(tz) return tm.Format("20060102T150405") } diff --git a/pkg/caldav/caldav_test.go b/pkg/caldav/caldav_test.go new file mode 100644 index 00000000000..59badd761b7 --- /dev/null +++ b/pkg/caldav/caldav_test.go @@ -0,0 +1,246 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package caldav + +import "testing" + +func TestParseEvents(t *testing.T) { + type args struct { + config *Config + events []*Event + } + tests := []struct { + name string + args args + wantCaldavevents string + }{ + { + name: "Test caldavparsing without reminders", + args: args{ + config: &Config{ + Name: "test", + ProdID: "RandomProdID which is not random", + }, + events: []*Event{ + { + Summary: "Event #1", + Description: "Lorem Ipsum", + UID: "randommduid", + TimestampUnix: 1543626724, + StartUnix: 1543626724, + EndUnix: 1543627824, + }, + { + Summary: "Event #2", + UID: "randommduidd", + TimestampUnix: 1543726724, + StartUnix: 1543726724, + EndUnix: 1543738724, + }, + { + Summary: "Event #3 with empty uid", + UID: "20181202T0600242aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83", + TimestampUnix: 1543726824, + StartUnix: 1543726824, + EndUnix: 1543727000, + }, + }, + }, + wantCaldavevents: `BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +X-PUBLISHED-TTL:PT4H +X-WR-CALNAME:test +PRODID:-//RandomProdID which is not random//EN +BEGIN:VEVENT +UID:randommduid +SUMMARY:Event #1 +DESCRIPTION:Lorem Ipsum +DTSTAMP:20181201T011204 +DTSTART:20181201T011204 +DTEND:20181201T013024 +END:VEVENT +BEGIN:VEVENT +UID:randommduidd +SUMMARY:Event #2 +DESCRIPTION: +DTSTAMP:20181202T045844 +DTSTART:20181202T045844 +DTEND:20181202T081844 +END:VEVENT +BEGIN:VEVENT +UID:20181202T0600242aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83 +SUMMARY:Event #3 with empty uid +DESCRIPTION: +DTSTAMP:20181202T050024 +DTSTART:20181202T050024 +DTEND:20181202T050320 +END:VEVENT +END:VCALENDAR`, + }, + { + name: "Test caldavparsing with reminders", + args: args{ + config: &Config{ + Name: "test2", + ProdID: "RandomProdID which is not random", + }, + events: []*Event{ + { + Summary: "Event #1", + Description: "Lorem Ipsum", + UID: "randommduid", + TimestampUnix: 1543626724, + StartUnix: 1543626724, + EndUnix: 1543627824, + Alarms: []Alarm{ + {TimeUnix: 1543626524}, + {TimeUnix: 1543626224}, + {TimeUnix: 1543626024}, + }, + }, + { + Summary: "Event #2", + UID: "randommduidd", + TimestampUnix: 1543726724, + StartUnix: 1543726724, + EndUnix: 1543738724, + Alarms: []Alarm{ + {TimeUnix: 1543626524}, + {TimeUnix: 1543626224}, + {TimeUnix: 1543626024}, + }, + }, + { + Summary: "Event #3 with empty uid", + TimestampUnix: 1543726824, + StartUnix: 1543726824, + EndUnix: 1543727000, + Alarms: []Alarm{ + {TimeUnix: 1543626524}, + {TimeUnix: 1543626224}, + {TimeUnix: 1543626024}, + {TimeUnix: 1543826824}, + }, + }, + { + Summary: "Event #4 without any", + TimestampUnix: 1543726824, + StartUnix: 1543726824, + EndUnix: 1543727000, + }, + }, + }, + wantCaldavevents: `BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +X-PUBLISHED-TTL:PT4H +X-WR-CALNAME:test2 +PRODID:-//RandomProdID which is not random//EN +BEGIN:VEVENT +UID:randommduid +SUMMARY:Event #1 +DESCRIPTION:Lorem Ipsum +DTSTAMP:20181201T011204 +DTSTART:20181201T011204 +DTEND:20181201T013024 +BEGIN:VALARM +TRIGGER:-PT3M +ACTION:DISPLAY +DESCRIPTION:Event #1 +END:VALARM +BEGIN:VALARM +TRIGGER:-PT8M +ACTION:DISPLAY +DESCRIPTION:Event #1 +END:VALARM +BEGIN:VALARM +TRIGGER:-PT11M +ACTION:DISPLAY +DESCRIPTION:Event #1 +END:VALARM +END:VEVENT +BEGIN:VEVENT +UID:randommduidd +SUMMARY:Event #2 +DESCRIPTION: +DTSTAMP:20181202T045844 +DTSTART:20181202T045844 +DTEND:20181202T081844 +BEGIN:VALARM +TRIGGER:-PT1670M +ACTION:DISPLAY +DESCRIPTION:Event #2 +END:VALARM +BEGIN:VALARM +TRIGGER:-PT1675M +ACTION:DISPLAY +DESCRIPTION:Event #2 +END:VALARM +BEGIN:VALARM +TRIGGER:-PT1678M +ACTION:DISPLAY +DESCRIPTION:Event #2 +END:VALARM +END:VEVENT +BEGIN:VEVENT +UID:20181202T0500242aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83 +SUMMARY:Event #3 with empty uid +DESCRIPTION: +DTSTAMP:20181202T050024 +DTSTART:20181202T050024 +DTEND:20181202T050320 +BEGIN:VALARM +TRIGGER:-PT1671M +ACTION:DISPLAY +DESCRIPTION:Event #3 with empty uid +END:VALARM +BEGIN:VALARM +TRIGGER:-PT1676M +ACTION:DISPLAY +DESCRIPTION:Event #3 with empty uid +END:VALARM +BEGIN:VALARM +TRIGGER:-PT1680M +ACTION:DISPLAY +DESCRIPTION:Event #3 with empty uid +END:VALARM +BEGIN:VALARM +TRIGGER:PT1666M +ACTION:DISPLAY +DESCRIPTION:Event #3 with empty uid +END:VALARM +END:VEVENT +BEGIN:VEVENT +UID:20181202T050024ae7548ce9556df85038abe90dc674d4741a61ce74d1cf +SUMMARY:Event #4 without any +DESCRIPTION: +DTSTAMP:20181202T050024 +DTSTART:20181202T050024 +DTEND:20181202T050320 +END:VEVENT +END:VCALENDAR`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotCaldavevents := ParseEvents(tt.args.config, tt.args.events); gotCaldavevents != tt.wantCaldavevents { + t.Errorf("ParseEvents() = %v, want %v", gotCaldavevents, tt.wantCaldavevents) + } + }) + } +} diff --git a/pkg/models/fixtures/list.yml b/pkg/models/fixtures/list.yml index c151e2fc18c..27fbd05bdcd 100644 --- a/pkg/models/fixtures/list.yml +++ b/pkg/models/fixtures/list.yml @@ -15,4 +15,10 @@ title: Test3 description: Lorem Ipsum owner_id: 3 - namespace_id: 2 \ No newline at end of file + namespace_id: 2 +- + id: 4 + title: Test4 + description: Lorem Ipsum + owner_id: 3 + namespace_id: 3 \ No newline at end of file diff --git a/pkg/models/fixtures/namespaces.yml b/pkg/models/fixtures/namespaces.yml index 12c19130651..11042eacf98 100644 --- a/pkg/models/fixtures/namespaces.yml +++ b/pkg/models/fixtures/namespaces.yml @@ -7,4 +7,9 @@ id: 2 name: testnamespace2 description: Lorem Ipsum - owner_id: 2 \ No newline at end of file + owner_id: 2 +- + id: 3 + name: testnamespace3 + description: Lorem Ipsum + owner_id: 3 \ No newline at end of file diff --git a/pkg/models/fixtures/tasks.yml b/pkg/models/fixtures/tasks.yml new file mode 100644 index 00000000000..03578a5f927 --- /dev/null +++ b/pkg/models/fixtures/tasks.yml @@ -0,0 +1,41 @@ +- id: 1 + text: 'task #1' + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 +- id: 2 + text: 'task #2 done' + done: true + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 +- id: 3 + text: 'task #3 high prio' + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 + priority: 100 +- id: 4 + text: 'task #4 low prio' + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 + priority: 1 +- id: 5 + text: 'task #5 higher due date' + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 + due_date_unix: 1543636724 +- id: 6 + text: 'task #6 lower due date' + created_by_id: 1 + list_id: 1 + created: 1543626724 + updated: 1543626724 + due_date_unix: 1543616724 \ No newline at end of file diff --git a/pkg/models/fixtures/team_list.yml b/pkg/models/fixtures/team_list.yml new file mode 100644 index 00000000000..9cf742f01c9 --- /dev/null +++ b/pkg/models/fixtures/team_list.yml @@ -0,0 +1,6 @@ +- id: 1 + team_id: 1 + list_id: 3 +- id: 2 + team_id: 2 + list_id: 3 diff --git a/pkg/models/fixtures/team_namespaces.yml b/pkg/models/fixtures/team_namespaces.yml new file mode 100644 index 00000000000..413d4953442 --- /dev/null +++ b/pkg/models/fixtures/team_namespaces.yml @@ -0,0 +1,6 @@ +- id: 1 + team_id: 1 + namespace_id: 3 +- id: 2 + team_id: 2 + namespace_id: 3 diff --git a/pkg/models/fixtures/users.yml b/pkg/models/fixtures/users.yml index e278cd49fcf..46be8c21159 100644 --- a/pkg/models/fixtures/users.yml +++ b/pkg/models/fixtures/users.yml @@ -13,3 +13,9 @@ username: 'user3' password: '1234' email: 'johndoe@example.com' +- + id: 4 + username: 'user4' + password: '1234' + email: 'johndoe@example.com' + email_confirm_token: tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael \ No newline at end of file diff --git a/pkg/models/fixtures/users_list.yml b/pkg/models/fixtures/users_list.yml new file mode 100644 index 00000000000..7d56be8feb7 --- /dev/null +++ b/pkg/models/fixtures/users_list.yml @@ -0,0 +1,6 @@ +- id: 1 + user_id: 1 + list_id: 3 +- id: 2 + user_id: 2 + list_id: 3 diff --git a/pkg/models/fixtures/users_namespace.yml b/pkg/models/fixtures/users_namespace.yml new file mode 100644 index 00000000000..7212e0dbd41 --- /dev/null +++ b/pkg/models/fixtures/users_namespace.yml @@ -0,0 +1,6 @@ +- id: 1 + user_id: 1 + namespace_id: 3 +- id: 2 + user_id: 2 + namespace_id: 3 diff --git a/pkg/models/list_read_test.go b/pkg/models/list_read_test.go index c0f7b2ccd46..823ebbde142 100644 --- a/pkg/models/list_read_test.go +++ b/pkg/models/list_read_test.go @@ -40,7 +40,7 @@ func TestList_ReadAll(t *testing.T) { assert.NoError(t, err) assert.Equal(t, reflect.TypeOf(lists3).Kind(), reflect.Slice) s := reflect.ValueOf(lists3) - assert.Equal(t, s.Len(), 1) + assert.Equal(t, s.Len(), 3) // Try getting lists for a nonexistant user _, err = lists2.ReadAll("", &User{ID: 984234}, 1) diff --git a/pkg/models/list_rights.go b/pkg/models/list_rights.go index e560b147ed0..77275213700 100644 --- a/pkg/models/list_rights.go +++ b/pkg/models/list_rights.go @@ -26,7 +26,7 @@ func (l *List) IsAdmin(a web.Auth) bool { u := getUserForRights(a) // Owners are always admins - if l.Owner.ID == u.ID { + if l.OwnerID == u.ID { return true } diff --git a/pkg/models/list_task_readall_test.go b/pkg/models/list_task_readall_test.go new file mode 100644 index 00000000000..8ada5681800 --- /dev/null +++ b/pkg/models/list_task_readall_test.go @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2018 the Vikunja Authors. All rights reserved. + * Use of this source code is governed by a LPGLv3-style + * license that can be found in the LICENSE file. + */ + +package models + +import ( + "reflect" + "sort" + "testing" + + "code.vikunja.io/web" +) + +func sortTasksForTesting(by SortBy) (tasks []*ListTask) { + tasks = []*ListTask{ + { + ID: 1, + Text: "task #1", + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + }, + { + ID: 2, + Text: "task #2 done", + Done: true, + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + }, + { + ID: 3, + Text: "task #3 high prio", + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + Priority: 100, + }, + { + ID: 4, + Text: "task #4 low prio", + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + Priority: 1, + }, + { + ID: 5, + Text: "task #5 higher due date", + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + DueDateUnix: 1543636724, + }, + { + ID: 6, + Text: "task #6 lower due date", + CreatedByID: 1, + ListID: 1, + Created: 1543626724, + Updated: 1543626724, + DueDateUnix: 1543616724, + }, + } + + switch by { + case SortTasksByPriorityDesc: + sort.Slice(tasks, func(i, j int) bool { + return tasks[i].Priority > tasks[j].Priority + }) + case SortTasksByPriorityAsc: + sort.Slice(tasks, func(i, j int) bool { + return tasks[i].Priority < tasks[j].Priority + }) + case SortTasksByDueDateDesc: + sort.Slice(tasks, func(i, j int) bool { + return tasks[i].DueDateUnix > tasks[j].DueDateUnix + }) + case SortTasksByDueDateAsc: + sort.Slice(tasks, func(i, j int) bool { + return tasks[i].DueDateUnix < tasks[j].DueDateUnix + }) + } + + return +} + +func TestListTask_ReadAll(t *testing.T) { + type fields struct { + ID int64 + Text string + Description string + Done bool + DueDateUnix int64 + RemindersUnix []int64 + CreatedByID int64 + ListID int64 + RepeatAfter int64 + ParentTaskID int64 + Priority int64 + Sorting string + Subtasks []*ListTask + Created int64 + Updated int64 + CreatedBy User + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + search string + a web.Auth + page int + } + tests := []struct { + name string + fields fields + args args + want interface{} + wantErr bool + }{ + { + name: "ReadAll ListTasks normally", + fields: fields{}, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByUnsorted), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by priority (desc)", + fields: fields{ + Sorting: "priority", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByPriorityDesc), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by priority asc", + fields: fields{ + Sorting: "priorityasc", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByPriorityAsc), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by priority desc", + fields: fields{ + Sorting: "prioritydesc", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByPriorityDesc), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by due date default (desc)", + fields: fields{ + Sorting: "dueadate", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByDueDateDesc), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by due date asc", + fields: fields{ + Sorting: "duedateasc", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByDueDateAsc), + wantErr: false, + }, + { + name: "ReadAll ListTasks sorted by due date desc", + fields: fields{ + Sorting: "dueadatedesc", + }, + args: args{ + search: "", + a: &User{ID: 1}, + page: 0, + }, + want: sortTasksForTesting(SortTasksByDueDateDesc), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + lt := &ListTask{ + ID: tt.fields.ID, + Text: tt.fields.Text, + Description: tt.fields.Description, + Done: tt.fields.Done, + DueDateUnix: tt.fields.DueDateUnix, + RemindersUnix: tt.fields.RemindersUnix, + CreatedByID: tt.fields.CreatedByID, + ListID: tt.fields.ListID, + RepeatAfter: tt.fields.RepeatAfter, + ParentTaskID: tt.fields.ParentTaskID, + Priority: tt.fields.Priority, + Sorting: tt.fields.Sorting, + Subtasks: tt.fields.Subtasks, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CreatedBy: tt.fields.CreatedBy, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + got, err := lt.ReadAll(tt.args.search, tt.args.a, tt.args.page) + if (err != nil) != tt.wantErr { + t.Errorf("ListTask.ReadAll() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ListTask.ReadAll() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/models/list_users_readall.go b/pkg/models/list_users_readall.go index 6cbaa62d37b..04914ed48a7 100644 --- a/pkg/models/list_users_readall.go +++ b/pkg/models/list_users_readall.go @@ -44,7 +44,7 @@ func (ul *ListUser) ReadAll(search string, a web.Auth, page int) (interface{}, e return nil, err } if !l.CanRead(u) { - return nil, ErrNeedToHaveListReadAccess{} + return nil, ErrNeedToHaveListReadAccess{UserID: u.ID, ListID: ul.ListID} } // Get all users diff --git a/pkg/models/list_users_rights_test.go b/pkg/models/list_users_rights_test.go new file mode 100644 index 00000000000..96f3bfa1a07 --- /dev/null +++ b/pkg/models/list_users_rights_test.go @@ -0,0 +1,99 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/web" +) + +func TestListUser_CanDoSomething(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + ListID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + want map[string]bool + }{ + { + name: "CanDoSomething Normally", + fields: fields{ + ListID: 3, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true}, + }, + { + name: "CanDoSomething for a nonexistant list", + fields: fields{ + ListID: 300, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + { + name: "CanDoSomething where the user does not have the rights", + fields: fields{ + ListID: 3, + }, + args: args{ + a: &User{ID: 4}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + lu := &ListUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + if got := lu.CanCreate(tt.args.a); got != tt.want["CanCreate"] { + t.Errorf("ListUser.CanCreate() = %v, want %v", got, tt.want["CanCreate"]) + } + if got := lu.CanDelete(tt.args.a); got != tt.want["CanDelete"] { + t.Errorf("ListUser.CanDelete() = %v, want %v", got, tt.want["CanDelete"]) + } + if got := lu.CanUpdate(tt.args.a); got != tt.want["CanUpdate"] { + t.Errorf("ListUser.CanUpdate() = %v, want %v", got, tt.want["CanUpdate"]) + } + }) + } +} diff --git a/pkg/models/list_users_test.go b/pkg/models/list_users_test.go new file mode 100644 index 00000000000..f1cff13c64c --- /dev/null +++ b/pkg/models/list_users_test.go @@ -0,0 +1,355 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import ( + "reflect" + "runtime" + "testing" + + "code.vikunja.io/web" +) + +func TestListUser_Create(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + ListID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + wantErr bool + errType func(err error) bool + }{ + { + name: "ListUsers Create normally", + fields: fields{ + UserID: 1, + ListID: 2, + }, + }, + { + name: "ListUsers Create for duplicate", + fields: fields{ + UserID: 1, + ListID: 2, + }, + wantErr: true, + errType: IsErrUserAlreadyHasAccess, + }, + { + name: "ListUsers Create with invalid right", + fields: fields{ + UserID: 1, + ListID: 2, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidUserRight, + }, + { + name: "ListUsers Create with inexisting list", + fields: fields{ + UserID: 1, + ListID: 2000, + }, + wantErr: true, + errType: IsErrListDoesNotExist, + }, + { + name: "ListUsers Create with inexisting user", + fields: fields{ + UserID: 500, + ListID: 2, + }, + wantErr: true, + errType: IsErrUserDoesNotExist, + }, + { + name: "ListUsers Create with the owner as shared user", + fields: fields{ + UserID: 1, + ListID: 1, + }, + wantErr: true, + errType: IsErrUserAlreadyHasAccess, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ul := &ListUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := ul.Create(tt.args.a) + if (err != nil) != tt.wantErr { + t.Errorf("ListUser.Create() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("ListUser.Create() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} + +func TestListUser_ReadAll(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + ListID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + search string + a web.Auth + page int + } + tests := []struct { + name string + fields fields + args args + want interface{} + wantErr bool + errType func(err error) bool + }{ + { + name: "Test readall normal", + fields: fields{ + ListID: 3, + }, + args: args{ + a: &User{ID: 3}, + }, + want: []*UserWithRight{ + { + User: User{ + ID: 1, + Username: "user1", + Password: "1234", + Email: "johndoe@example.com", + }, + Right: UserRightRead, + }, + { + User: User{ + ID: 2, + Username: "user2", + Password: "1234", + Email: "johndoe@example.com", + }, + Right: UserRightRead, + }, + }, + }, + { + name: "Test ReadAll by a user who does not have access to the list", + fields: fields{ + ListID: 3, + }, + args: args{ + a: &User{ID: 4}, + }, + wantErr: true, + errType: IsErrNeedToHaveListReadAccess, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ul := &ListUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + got, err := ul.ReadAll(tt.args.search, tt.args.a, tt.args.page) + if (err != nil) != tt.wantErr { + t.Errorf("ListUser.ReadAll() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("ListUser.ReadAll() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ListUser.ReadAll() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestListUser_Update(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + ListID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Test Update Normally", + fields: fields{ + ListID: 3, + UserID: 1, + Right: UserRightAdmin, + }, + }, + { + name: "Test Update to write", + fields: fields{ + ListID: 3, + UserID: 1, + Right: UserRightWrite, + }, + }, + { + name: "Test Update to Read", + fields: fields{ + ListID: 3, + UserID: 1, + Right: UserRightRead, + }, + }, + { + name: "Test Update with invalid right", + fields: fields{ + ListID: 3, + UserID: 1, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidUserRight, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + lu := &ListUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := lu.Update() + if (err != nil) != tt.wantErr { + t.Errorf("ListUser.Update() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("ListUser.Update() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} + +func TestListUser_Delete(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + ListID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Try deleting some unexistant user", + fields: fields{ + UserID: 1000, + ListID: 2, + }, + wantErr: true, + errType: IsErrUserDoesNotExist, + }, + { + name: "Try deleting a user which does not has access but exists", + fields: fields{ + UserID: 1, + ListID: 4, + }, + wantErr: true, + errType: IsErrUserDoesNotHaveAccessToList, + }, + { + name: "Try deleting normally", + fields: fields{ + UserID: 1, + ListID: 3, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + lu := &ListUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := lu.Delete() + if (err != nil) != tt.wantErr { + t.Errorf("ListUser.Delete() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("ListUser.Delete() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} diff --git a/pkg/models/namespace_test.go b/pkg/models/namespace_test.go index a06e8413465..f224df797f6 100644 --- a/pkg/models/namespace_test.go +++ b/pkg/models/namespace_test.go @@ -105,5 +105,5 @@ func TestNamespace_Create(t *testing.T) { assert.NoError(t, err) assert.Equal(t, reflect.TypeOf(nsps).Kind(), reflect.Slice) s := reflect.ValueOf(nsps) - assert.Equal(t, 1, s.Len()) + assert.Equal(t, 3, s.Len()) } diff --git a/pkg/models/namespace_users_rights_test.go b/pkg/models/namespace_users_rights_test.go new file mode 100644 index 00000000000..8883b67a0ff --- /dev/null +++ b/pkg/models/namespace_users_rights_test.go @@ -0,0 +1,99 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/web" +) + +func TestNamespaceUser_CanDoSomething(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + NamespaceID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + want map[string]bool + }{ + { + name: "CanDoSomething Normally", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true}, + }, + { + name: "CanDoSomething for a nonexistant namespace", + fields: fields{ + NamespaceID: 300, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + { + name: "CanDoSomething where the user does not have the rights", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 4}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nu := &NamespaceUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + if got := nu.CanCreate(tt.args.a); got != tt.want["CanCreate"] { + t.Errorf("NamespaceUser.CanCreate() = %v, want %v", got, tt.want["CanCreate"]) + } + if got := nu.CanDelete(tt.args.a); got != tt.want["CanDelete"] { + t.Errorf("NamespaceUser.CanDelete() = %v, want %v", got, tt.want["CanDelete"]) + } + if got := nu.CanUpdate(tt.args.a); got != tt.want["CanUpdate"] { + t.Errorf("NamespaceUser.CanUpdate() = %v, want %v", got, tt.want["CanUpdate"]) + } + }) + } +} diff --git a/pkg/models/namespace_users_test.go b/pkg/models/namespace_users_test.go new file mode 100644 index 00000000000..16b659d88ee --- /dev/null +++ b/pkg/models/namespace_users_test.go @@ -0,0 +1,357 @@ +/* + * Vikunja is a todo-list application to facilitate your life. + * Copyright 2018 Vikunja and contributors. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package models + +import ( + "code.vikunja.io/web" + "reflect" + "runtime" + "testing" +) + +func TestNamespaceUser_Create(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + NamespaceID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + wantErr bool + errType func(err error) bool + }{ + { + name: "NamespaceUsers Create normally", + fields: fields{ + UserID: 1, + NamespaceID: 2, + }, + }, + { + name: "NamespaceUsers Create for duplicate", + fields: fields{ + UserID: 1, + NamespaceID: 2, + }, + wantErr: true, + errType: IsErrUserAlreadyHasNamespaceAccess, + }, + { + name: "NamespaceUsers Create with invalid right", + fields: fields{ + UserID: 1, + NamespaceID: 2, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidUserRight, + }, + { + name: "NamespaceUsers Create with inexisting list", + fields: fields{ + UserID: 1, + NamespaceID: 2000, + }, + wantErr: true, + errType: IsErrNamespaceDoesNotExist, + }, + { + name: "NamespaceUsers Create with inexisting user", + fields: fields{ + UserID: 500, + NamespaceID: 2, + }, + wantErr: true, + errType: IsErrUserDoesNotExist, + }, + { + name: "NamespaceUsers Create with the owner as shared user", + fields: fields{ + UserID: 1, + NamespaceID: 1, + }, + wantErr: true, + errType: IsErrUserAlreadyHasNamespaceAccess, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + un := &NamespaceUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := un.Create(tt.args.a) + if (err != nil) != tt.wantErr { + t.Errorf("NamespaceUser.Create() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("NamespaceUser.Create() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} + +func TestNamespaceUser_ReadAll(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + NamespaceID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + search string + a web.Auth + page int + } + tests := []struct { + name string + fields fields + args args + want interface{} + wantErr bool + errType func(err error) bool + }{ + { + name: "Test readall normal", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 3}, + }, + want: []*UserWithRight{ + { + User: User{ + ID: 1, + Username: "user1", + Password: "1234", + Email: "johndoe@example.com", + }, + Right: UserRightRead, + }, + { + User: User{ + ID: 2, + Username: "user2", + Password: "1234", + Email: "johndoe@example.com", + }, + Right: UserRightRead, + }, + }, + }, + { + name: "Test ReadAll by a user who does not have access to the list", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 4}, + }, + wantErr: true, + errType: IsErrNeedToHaveNamespaceReadAccess, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + un := &NamespaceUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + got, err := un.ReadAll(tt.args.search, tt.args.a, tt.args.page) + if (err != nil) != tt.wantErr { + t.Errorf("NamespaceUser.ReadAll() error = %v, wantErr %v", err, tt.wantErr) + return + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("NamespaceUser.ReadAll() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NamespaceUser.ReadAll() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNamespaceUser_Update(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + NamespaceID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Test Update Normally", + fields: fields{ + NamespaceID: 3, + UserID: 1, + Right: UserRightAdmin, + }, + }, + { + name: "Test Update to write", + fields: fields{ + NamespaceID: 3, + UserID: 1, + Right: UserRightWrite, + }, + }, + { + name: "Test Update to Read", + fields: fields{ + NamespaceID: 3, + UserID: 1, + Right: UserRightRead, + }, + }, + { + name: "Test Update with invalid right", + fields: fields{ + NamespaceID: 3, + UserID: 1, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidUserRight, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nu := &NamespaceUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := nu.Update() + if (err != nil) != tt.wantErr { + t.Errorf("NamespaceUser.Update() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("NamespaceUser.Update() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} + +func TestNamespaceUser_Delete(t *testing.T) { + type fields struct { + ID int64 + UserID int64 + NamespaceID int64 + Right UserRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Try deleting some unexistant user", + fields: fields{ + UserID: 1000, + NamespaceID: 2, + }, + wantErr: true, + errType: IsErrUserDoesNotExist, + }, + { + name: "Try deleting a user which does not has access but exists", + fields: fields{ + UserID: 1, + NamespaceID: 4, + }, + wantErr: true, + errType: IsErrUserDoesNotHaveAccessToNamespace, + }, + { + name: "Try deleting normally", + fields: fields{ + UserID: 1, + NamespaceID: 3, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + nu := &NamespaceUser{ + ID: tt.fields.ID, + UserID: tt.fields.UserID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := nu.Delete() + if (err != nil) != tt.wantErr { + t.Errorf("NamespaceUser.Delete() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("NamespaceUser.Delete() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } +} diff --git a/pkg/models/team_list_test.go b/pkg/models/team_list_test.go index 524d7b748fc..83516707a35 100644 --- a/pkg/models/team_list_test.go +++ b/pkg/models/team_list_test.go @@ -17,8 +17,10 @@ package models import ( + "code.vikunja.io/web" "github.com/stretchr/testify/assert" "reflect" + "runtime" "testing" ) @@ -85,7 +87,7 @@ func TestTeamList(t *testing.T) { // Test read all for a list where the user not has access tl6 := tl - tl6.ListID = 3 + tl6.ListID = 4 _, err = tl6.ReadAll("", &u, 1) assert.Error(t, err) assert.True(t, IsErrNeedToHaveListReadAccess(err)) @@ -104,5 +106,79 @@ func TestTeamList(t *testing.T) { err = tl4.Delete() assert.Error(t, err) assert.True(t, IsErrTeamDoesNotHaveAccessToList(err)) - +} + +func TestTeamList_Update(t *testing.T) { + type fields struct { + ID int64 + TeamID int64 + ListID int64 + Right TeamRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Test Update Normally", + fields: fields{ + ListID: 3, + TeamID: 1, + Right: TeamRightAdmin, + }, + }, + { + name: "Test Update to write", + fields: fields{ + ListID: 3, + TeamID: 1, + Right: TeamRightWrite, + }, + }, + { + name: "Test Update to Read", + fields: fields{ + ListID: 3, + TeamID: 1, + Right: TeamRightRead, + }, + }, + { + name: "Test Update with invalid right", + fields: fields{ + ListID: 3, + TeamID: 1, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidTeamRight, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tl := &TeamList{ + ID: tt.fields.ID, + TeamID: tt.fields.TeamID, + ListID: tt.fields.ListID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := tl.Update() + if (err != nil) != tt.wantErr { + t.Errorf("TeamList.Update() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("TeamList.Update() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } } diff --git a/pkg/models/team_namespace_rights_test.go b/pkg/models/team_namespace_rights_test.go new file mode 100644 index 00000000000..19c70cb6173 --- /dev/null +++ b/pkg/models/team_namespace_rights_test.go @@ -0,0 +1,99 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/web" +) + +func TestTeamNamespace_CanDoSomething(t *testing.T) { + type fields struct { + ID int64 + TeamID int64 + NamespaceID int64 + Right TeamRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + want map[string]bool + }{ + { + name: "CanDoSomething Normally", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true}, + }, + { + name: "CanDoSomething for a nonexistant namespace", + fields: fields{ + NamespaceID: 300, + }, + args: args{ + a: &User{ID: 3}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + { + name: "CanDoSomething where the user does not have the rights", + fields: fields{ + NamespaceID: 3, + }, + args: args{ + a: &User{ID: 4}, + }, + want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tn := &TeamNamespace{ + ID: tt.fields.ID, + TeamID: tt.fields.TeamID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + if got := tn.CanCreate(tt.args.a); got != tt.want["CanCreate"] { + t.Errorf("TeamNamespace.CanCreate() = %v, want %v", got, tt.want["CanCreate"]) + } + if got := tn.CanDelete(tt.args.a); got != tt.want["CanDelete"] { + t.Errorf("TeamNamespace.CanDelete() = %v, want %v", got, tt.want["CanDelete"]) + } + if got := tn.CanUpdate(tt.args.a); got != tt.want["CanUpdate"] { + t.Errorf("TeamNamespace.CanUpdate() = %v, want %v", got, tt.want["CanUpdate"]) + } + }) + } +} diff --git a/pkg/models/team_namespace_test.go b/pkg/models/team_namespace_test.go index 7575b469556..085f67b0a65 100644 --- a/pkg/models/team_namespace_test.go +++ b/pkg/models/team_namespace_test.go @@ -17,8 +17,10 @@ package models import ( + "code.vikunja.io/web" "github.com/stretchr/testify/assert" "reflect" + "runtime" "testing" ) @@ -96,5 +98,79 @@ func TestTeamNamespace(t *testing.T) { err = tn4.Delete() assert.Error(t, err) assert.True(t, IsErrTeamDoesNotHaveAccessToNamespace(err)) - +} + +func TestTeamNamespace_Update(t *testing.T) { + type fields struct { + ID int64 + TeamID int64 + NamespaceID int64 + Right TeamRight + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + tests := []struct { + name string + fields fields + wantErr bool + errType func(err error) bool + }{ + { + name: "Test Update Normally", + fields: fields{ + NamespaceID: 3, + TeamID: 1, + Right: TeamRightAdmin, + }, + }, + { + name: "Test Update to write", + fields: fields{ + NamespaceID: 3, + TeamID: 1, + Right: TeamRightWrite, + }, + }, + { + name: "Test Update to Read", + fields: fields{ + NamespaceID: 3, + TeamID: 1, + Right: TeamRightRead, + }, + }, + { + name: "Test Update with invalid right", + fields: fields{ + NamespaceID: 3, + TeamID: 1, + Right: 500, + }, + wantErr: true, + errType: IsErrInvalidTeamRight, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tl := &TeamNamespace{ + ID: tt.fields.ID, + TeamID: tt.fields.TeamID, + NamespaceID: tt.fields.NamespaceID, + Right: tt.fields.Right, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + err := tl.Update() + if (err != nil) != tt.wantErr { + t.Errorf("TeamNamespace.Update() error = %v, wantErr %v", err, tt.wantErr) + } + if (err != nil) && tt.wantErr && !tt.errType(err) { + t.Errorf("TeamNamespace.Update() Wrong error type! Error = %v, want = %v", err, runtime.FuncForPC(reflect.ValueOf(tt.errType).Pointer()).Name()) + } + }) + } } diff --git a/pkg/models/teams_rights_test.go b/pkg/models/teams_rights_test.go new file mode 100644 index 00000000000..2b25d5aebfc --- /dev/null +++ b/pkg/models/teams_rights_test.go @@ -0,0 +1,110 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/web" +) + +func TestTeam_CanDoSomething(t *testing.T) { + type fields struct { + ID int64 + Name string + Description string + CreatedByID int64 + CreatedBy User + Members []*TeamUser + Created int64 + Updated int64 + CRUDable web.CRUDable + Rights web.Rights + } + type args struct { + a web.Auth + } + tests := []struct { + name string + fields fields + args args + want map[string]bool + }{ + { + name: "CanDoSomething Normally", + fields: fields{ + ID: 1, + }, + args: args{ + a: &User{ID: 1}, + }, + want: map[string]bool{"CanCreate": true, "IsAdmin": true, "CanRead": true, "CanDelete": true, "CanUpdate": true}, + }, + { + name: "CanDoSomething for a nonexistant namespace", + fields: fields{ + ID: 300, + }, + args: args{ + a: &User{ID: 1}, + }, + want: map[string]bool{"CanCreate": true, "IsAdmin": false, "CanRead": false, "CanDelete": false, "CanUpdate": false}, + }, + { + name: "CanDoSomething where the user does not have the rights", + fields: fields{ + ID: 1, + }, + args: args{ + a: &User{ID: 4}, + }, + want: map[string]bool{"CanCreate": true, "IsAdmin": false, "CanRead": false, "CanDelete": false, "CanUpdate": false}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tm := &Team{ + ID: tt.fields.ID, + Name: tt.fields.Name, + Description: tt.fields.Description, + CreatedByID: tt.fields.CreatedByID, + CreatedBy: tt.fields.CreatedBy, + Members: tt.fields.Members, + Created: tt.fields.Created, + Updated: tt.fields.Updated, + CRUDable: tt.fields.CRUDable, + Rights: tt.fields.Rights, + } + + if got := tm.CanCreate(tt.args.a); got != tt.want["CanCreate"] { // CanCreate is currently always true + t.Errorf("Team.CanCreate() = %v, want %v", got, tt.want["CanCreate"]) + } + if got := tm.CanDelete(tt.args.a); got != tt.want["CanDelete"] { + t.Errorf("Team.CanDelete() = %v, want %v", got, tt.want["CanDelete"]) + } + if got := tm.CanUpdate(tt.args.a); got != tt.want["CanUpdate"] { + t.Errorf("Team.CanUpdate() = %v, want %v", got, tt.want["CanUpdate"]) + } + if got := tm.CanRead(tt.args.a); got != tt.want["CanRead"] { + t.Errorf("Team.CanRead() = %v, want %v", got, tt.want["CanRead"]) + } + if got := tm.IsAdmin(tt.args.a); got != tt.want["IsAdmin"] { + t.Errorf("Team.IsAdmin() = %v, want %v", got, tt.want["IsAdmin"]) + } + }) + } +} diff --git a/pkg/models/teams_test.go b/pkg/models/teams_test.go index eae5929a1ad..801505f4be8 100644 --- a/pkg/models/teams_test.go +++ b/pkg/models/teams_test.go @@ -47,6 +47,11 @@ func TestTeam_Create(t *testing.T) { assert.True(t, tm.Members[0].Admin) assert.True(t, dummyteam.CanRead(&doer)) + // Try getting a team with an ID < 0 + _, err = GetTeamByID(-1) + assert.Error(t, err) + assert.True(t, IsErrTeamDoesNotExist(err)) + // Get all teams the user is part of ts, err := tm.ReadAll("", &doer, 1) assert.NoError(t, err) diff --git a/pkg/models/user_email_confirm_test.go b/pkg/models/user_email_confirm_test.go new file mode 100644 index 00000000000..7957bbe293b --- /dev/null +++ b/pkg/models/user_email_confirm_test.go @@ -0,0 +1,67 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package models + +import "testing" + +func TestUserEmailConfirm(t *testing.T) { + type args struct { + c *EmailConfirm + } + tests := []struct { + name string + args args + wantErr bool + errType func(error) bool + }{ + { + name: "Test Empty token", + args: args{ + c: &EmailConfirm{ + Token: "", + }, + }, + wantErr: true, + errType: IsErrInvalidEmailConfirmToken, + }, + { + name: "Test invalid token", + args: args{ + c: &EmailConfirm{ + Token: "invalid", + }, + }, + wantErr: true, + errType: IsErrInvalidEmailConfirmToken, + }, + { + name: "Test valid token", + args: args{ + c: &EmailConfirm{ + Token: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UserEmailConfirm(tt.args.c); (err != nil) != tt.wantErr { + t.Errorf("UserEmailConfirm() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/utils/random_string_test.go b/pkg/utils/random_string_test.go new file mode 100644 index 00000000000..2b8b2f88479 --- /dev/null +++ b/pkg/utils/random_string_test.go @@ -0,0 +1,28 @@ +// Vikunja is a todo-list application to facilitate your life. +// Copyright 2018 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package utils + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMakeRandomString(t *testing.T) { + rand := MakeRandomString(32) + assert.NotEqual(t, rand, "loremipsuim") + assert.Equal(t, len(rand), 32) +} diff --git a/pkg/utils/sha256_test.go b/pkg/utils/sha256_test.go new file mode 100644 index 00000000000..3c780bb4197 --- /dev/null +++ b/pkg/utils/sha256_test.go @@ -0,0 +1,55 @@ +/* + * Vikunja is a todo-list application to facilitate your life. + * Copyright 2018 Vikunja and contributors. All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package utils + +import "testing" + +func TestSha256(t *testing.T) { + type args struct { + cleartext string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "Test sha256 generation", + args: args{cleartext: "vikunjarandomstringwhichisnotrandom"}, + want: "46fc0f603dd986cf7ed3e631917d43da89a8df2bdf291", + }, + { + name: "Test sha256 generation", + args: args{cleartext: "vikunjastring"}, + want: "f54d310f4d9a0bc13479dad5c5701e8d581744666b69f", + }, + { + name: "Test sha256 generation", + args: args{cleartext: "somethingsomething"}, + want: "00aef67d6df7fdee0419aa3713820e7084cbcb8b8f7c4", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Sha256(tt.args.cleartext); got != tt.want { + t.Errorf("Sha256() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/tools.go b/tools.go index 8e734ee32b8..b6fde2c39c9 100644 --- a/tools.go +++ b/tools.go @@ -22,6 +22,7 @@ package tools import ( _ "github.com/client9/misspell/cmd/misspell" + _ "github.com/cweill/gotests/..." _ "github.com/fzipp/gocyclo" _ "github.com/gordonklaus/ineffassign" _ "github.com/karalabe/xgo"