From 7f7e92586f7a51c38a3ec4f06917f2f3025625b9 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 1 Dec 2019 13:12:35 +0100 Subject: [PATCH] Only use one handler to get tasks --- pkg/integrations/link_sharing_test.go | 27 +++- pkg/integrations/task_collection_test.go | 153 ++++++++++++++++++++++- pkg/integrations/task_test.go | 144 --------------------- pkg/models/task_collection.go | 17 +++ pkg/models/task_readall_test.go | 27 +--- pkg/models/tasks.go | 25 ---- pkg/routes/routes.go | 16 +-- 7 files changed, 200 insertions(+), 209 deletions(-) diff --git a/pkg/integrations/link_sharing_test.go b/pkg/integrations/link_sharing_test.go index 59d4b67d4..227df3594 100644 --- a/pkg/integrations/link_sharing_test.go +++ b/pkg/integrations/link_sharing_test.go @@ -409,6 +409,27 @@ func TestLinkSharing(t *testing.T) { }) t.Run("Tasks", func(t *testing.T) { + testHandlerTaskReadOnlyCollection := webHandlerTest{ + linkShare: linkshareRead, + strFunc: func() handler.CObject { + return &models.TaskCollection{} + }, + t: t, + } + testHandlerTaskWriteCollection := webHandlerTest{ + linkShare: linkShareWrite, + strFunc: func() handler.CObject { + return &models.TaskCollection{} + }, + t: t, + } + testHandlerTaskAdminCollection := webHandlerTest{ + linkShare: linkShareAdmin, + strFunc: func() handler.CObject { + return &models.TaskCollection{} + }, + t: t, + } testHandlerTaskReadOnly := webHandlerTest{ linkShare: linkshareRead, strFunc: func() handler.CObject { @@ -432,7 +453,7 @@ func TestLinkSharing(t *testing.T) { } t.Run("ReadAll", func(t *testing.T) { t.Run("Shared readonly", func(t *testing.T) { - rec, err := testHandlerTaskReadOnly.testReadAllWithLinkShare(nil, nil) + rec, err := testHandlerTaskReadOnlyCollection.testReadAllWithLinkShare(nil, nil) assert.NoError(t, err) assert.Contains(t, rec.Body.String(), `task #1`) assert.Contains(t, rec.Body.String(), `task #2`) @@ -450,7 +471,7 @@ func TestLinkSharing(t *testing.T) { assert.NotContains(t, rec.Body.String(), `task #14`) }) t.Run("Shared write", func(t *testing.T) { - rec, err := testHandlerTaskWrite.testReadAllWithLinkShare(nil, nil) + rec, err := testHandlerTaskWriteCollection.testReadAllWithLinkShare(nil, nil) assert.NoError(t, err) assert.NotContains(t, rec.Body.String(), `task #2`) assert.NotContains(t, rec.Body.String(), `task #3`) @@ -467,7 +488,7 @@ func TestLinkSharing(t *testing.T) { assert.NotContains(t, rec.Body.String(), `task #14`) }) t.Run("Shared admin", func(t *testing.T) { - rec, err := testHandlerTaskAdmin.testReadAllWithLinkShare(nil, nil) + rec, err := testHandlerTaskAdminCollection.testReadAllWithLinkShare(nil, nil) assert.NoError(t, err) assert.NotContains(t, rec.Body.String(), `task #2`) assert.NotContains(t, rec.Body.String(), `task #4`) diff --git a/pkg/integrations/task_collection_test.go b/pkg/integrations/task_collection_test.go index 06eebd493..586556617 100644 --- a/pkg/integrations/task_collection_test.go +++ b/pkg/integrations/task_collection_test.go @@ -33,11 +33,12 @@ func TestTaskCollection(t *testing.T) { }, t: t, } - // Only run specific nested tests: - // ^TestTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$ - t.Run("ReadAll", func(t *testing.T) { + t.Run("ReadAll on list", func(t *testing.T) { + + urlParams := map[string]string{"list": "1"} + t.Run("Normal", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(nil, map[string]string{"list": "1"}) + rec, err := testHandler.testReadAllWithUser(nil, urlParams) assert.NoError(t, err) // Not using assert.Equal to avoid having the tests break every time we add new fixtures assert.Contains(t, rec.Body.String(), `task #1`) @@ -70,6 +71,150 @@ func TestTaskCollection(t *testing.T) { assert.Contains(t, rec.Body.String(), `task #28`) assert.NotContains(t, rec.Body.String(), `task #32`) }) + t.Run("Search", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"s": []string{"task #6"}}, urlParams) + assert.NoError(t, err) + assert.NotContains(t, rec.Body.String(), `task #1`) + assert.NotContains(t, rec.Body.String(), `task #2`) + assert.NotContains(t, rec.Body.String(), `task #3`) + assert.NotContains(t, rec.Body.String(), `task #4`) + assert.NotContains(t, rec.Body.String(), `task #5`) + assert.Contains(t, rec.Body.String(), `task #6`) + assert.NotContains(t, rec.Body.String(), `task #7`) + assert.NotContains(t, rec.Body.String(), `task #8`) + assert.NotContains(t, rec.Body.String(), `task #9`) + assert.NotContains(t, rec.Body.String(), `task #10`) + assert.NotContains(t, rec.Body.String(), `task #11`) + assert.NotContains(t, rec.Body.String(), `task #12`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + }) + t.Run("Sort Order", func(t *testing.T) { + // should equal priority desc + t.Run("by priority", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"priority"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`) + }) + t.Run("by priority desc", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"prioritydesc"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`) + }) + t.Run("by priority asc", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"priorityasc"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`) + }) + // should equal duedate desc + t.Run("by duedate", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedate"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) + }) + t.Run("by duedate desc", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedatedesc"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) + }) + t.Run("by duedate asc", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedateasc"}}, urlParams) + assert.NoError(t, err) + assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`) + }) + t.Run("invalid parameter", func(t *testing.T) { + // Invalid parameter should not sort at all + rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"loremipsum"}}, urlParams) + assert.NoError(t, err) + assert.NotContains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":1`) + assert.NotContains(t, rec.Body.String(), `{"id":4,"text":"task #4 low prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}}]`) + assert.NotContains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"dueDate":1543636724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) + assert.NotContains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"dueDate":1543616724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"dueDate":1543636724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}}]`) + }) + }) + t.Run("Date range", func(t *testing.T) { + t.Run("start and end date", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"startdate": []string{"1540000000"}, "enddate": []string{"1544700001"}}, urlParams) + assert.NoError(t, err) + assert.NotContains(t, rec.Body.String(), `task #1`) + assert.NotContains(t, rec.Body.String(), `task #2`) + assert.NotContains(t, rec.Body.String(), `task #3`) + assert.NotContains(t, rec.Body.String(), `task #4`) + assert.Contains(t, rec.Body.String(), `task #5`) + assert.Contains(t, rec.Body.String(), `task #6`) + assert.Contains(t, rec.Body.String(), `task #7`) + assert.Contains(t, rec.Body.String(), `task #8`) + assert.Contains(t, rec.Body.String(), `task #9`) + assert.NotContains(t, rec.Body.String(), `task #10`) + assert.NotContains(t, rec.Body.String(), `task #11`) + assert.NotContains(t, rec.Body.String(), `task #12`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + }) + t.Run("start date only", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"startdate": []string{"1540000000"}}, urlParams) + assert.NoError(t, err) + assert.NotContains(t, rec.Body.String(), `task #1`) + assert.NotContains(t, rec.Body.String(), `task #2`) + assert.NotContains(t, rec.Body.String(), `task #3`) + assert.NotContains(t, rec.Body.String(), `task #4`) + assert.Contains(t, rec.Body.String(), `task #5`) + assert.Contains(t, rec.Body.String(), `task #6`) + assert.Contains(t, rec.Body.String(), `task #7`) + assert.Contains(t, rec.Body.String(), `task #8`) + assert.Contains(t, rec.Body.String(), `task #9`) + assert.NotContains(t, rec.Body.String(), `task #10`) + assert.NotContains(t, rec.Body.String(), `task #11`) + assert.NotContains(t, rec.Body.String(), `task #12`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + }) + t.Run("end date only", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(url.Values{"enddate": []string{"1544700001"}}, urlParams) + assert.NoError(t, err) + // If no start date but an end date is specified, this should be null + // since we don't have any tasks in the fixtures with an end date > + // the current date. + assert.Equal(t, "null\n", rec.Body.String()) + }) + }) + }) + + t.Run("ReadAll for all tasks", func(t *testing.T) { + t.Run("Normal", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser(nil, nil) + assert.NoError(t, err) + // Not using assert.Equal to avoid having the tests break every time we add new fixtures + assert.Contains(t, rec.Body.String(), `task #1`) + assert.Contains(t, rec.Body.String(), `task #2`) + assert.Contains(t, rec.Body.String(), `task #3`) + assert.Contains(t, rec.Body.String(), `task #4`) + assert.Contains(t, rec.Body.String(), `task #5`) + assert.Contains(t, rec.Body.String(), `task #6`) + assert.Contains(t, rec.Body.String(), `task #7`) + assert.Contains(t, rec.Body.String(), `task #8`) + assert.Contains(t, rec.Body.String(), `task #9`) + assert.Contains(t, rec.Body.String(), `task #10`) + assert.Contains(t, rec.Body.String(), `task #11`) + assert.Contains(t, rec.Body.String(), `task #12`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + assert.Contains(t, rec.Body.String(), `task #15`) // Shared via team readonly + assert.Contains(t, rec.Body.String(), `task #16`) // Shared via team write + assert.Contains(t, rec.Body.String(), `task #17`) // Shared via team admin + assert.Contains(t, rec.Body.String(), `task #18`) // Shared via user readonly + assert.Contains(t, rec.Body.String(), `task #19`) // Shared via user write + assert.Contains(t, rec.Body.String(), `task #20`) // Shared via user admin + assert.Contains(t, rec.Body.String(), `task #21`) // Shared via namespace team readonly + assert.Contains(t, rec.Body.String(), `task #22`) // Shared via namespace team write + assert.Contains(t, rec.Body.String(), `task #23`) // Shared via namespace team admin + assert.Contains(t, rec.Body.String(), `task #24`) // Shared via namespace user readonly + assert.Contains(t, rec.Body.String(), `task #25`) // Shared via namespace user write + assert.Contains(t, rec.Body.String(), `task #26`) // Shared via namespace user admin + // TODO: Add some cases where the user has access to the list, somhow shared + }) t.Run("Search", func(t *testing.T) { rec, err := testHandler.testReadAllWithUser(url.Values{"s": []string{"task #6"}}, nil) assert.NoError(t, err) diff --git a/pkg/integrations/task_test.go b/pkg/integrations/task_test.go index b7ccb8a34..c522455fb 100644 --- a/pkg/integrations/task_test.go +++ b/pkg/integrations/task_test.go @@ -21,7 +21,6 @@ import ( "code.vikunja.io/web/handler" "github.com/labstack/echo/v4" "github.com/stretchr/testify/assert" - "net/url" "testing" ) @@ -35,149 +34,6 @@ func TestTask(t *testing.T) { } // Only run specific nested tests: // ^TestTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$ - t.Run("ReadAll", func(t *testing.T) { - t.Run("Normal", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(nil, nil) - assert.NoError(t, err) - // Not using assert.Equal to avoid having the tests break every time we add new fixtures - assert.Contains(t, rec.Body.String(), `task #1`) - assert.Contains(t, rec.Body.String(), `task #2`) - assert.Contains(t, rec.Body.String(), `task #3`) - assert.Contains(t, rec.Body.String(), `task #4`) - assert.Contains(t, rec.Body.String(), `task #5`) - assert.Contains(t, rec.Body.String(), `task #6`) - assert.Contains(t, rec.Body.String(), `task #7`) - assert.Contains(t, rec.Body.String(), `task #8`) - assert.Contains(t, rec.Body.String(), `task #9`) - assert.Contains(t, rec.Body.String(), `task #10`) - assert.Contains(t, rec.Body.String(), `task #11`) - assert.Contains(t, rec.Body.String(), `task #12`) - assert.NotContains(t, rec.Body.String(), `task #13`) - assert.NotContains(t, rec.Body.String(), `task #14`) - assert.NotContains(t, rec.Body.String(), `task #13`) - assert.NotContains(t, rec.Body.String(), `task #14`) - assert.Contains(t, rec.Body.String(), `task #15`) // Shared via team readonly - assert.Contains(t, rec.Body.String(), `task #16`) // Shared via team write - assert.Contains(t, rec.Body.String(), `task #17`) // Shared via team admin - assert.Contains(t, rec.Body.String(), `task #18`) // Shared via user readonly - assert.Contains(t, rec.Body.String(), `task #19`) // Shared via user write - assert.Contains(t, rec.Body.String(), `task #20`) // Shared via user admin - assert.Contains(t, rec.Body.String(), `task #21`) // Shared via namespace team readonly - assert.Contains(t, rec.Body.String(), `task #22`) // Shared via namespace team write - assert.Contains(t, rec.Body.String(), `task #23`) // Shared via namespace team admin - assert.Contains(t, rec.Body.String(), `task #24`) // Shared via namespace user readonly - assert.Contains(t, rec.Body.String(), `task #25`) // Shared via namespace user write - assert.Contains(t, rec.Body.String(), `task #26`) // Shared via namespace user admin - // TODO: Add some cases where the user has access to the list, somhow shared - }) - t.Run("Search", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"s": []string{"task #6"}}, nil) - assert.NoError(t, err) - assert.NotContains(t, rec.Body.String(), `task #1`) - assert.NotContains(t, rec.Body.String(), `task #2`) - assert.NotContains(t, rec.Body.String(), `task #3`) - assert.NotContains(t, rec.Body.String(), `task #4`) - assert.NotContains(t, rec.Body.String(), `task #5`) - assert.Contains(t, rec.Body.String(), `task #6`) - assert.NotContains(t, rec.Body.String(), `task #7`) - assert.NotContains(t, rec.Body.String(), `task #8`) - assert.NotContains(t, rec.Body.String(), `task #9`) - assert.NotContains(t, rec.Body.String(), `task #10`) - assert.NotContains(t, rec.Body.String(), `task #11`) - assert.NotContains(t, rec.Body.String(), `task #12`) - assert.NotContains(t, rec.Body.String(), `task #13`) - assert.NotContains(t, rec.Body.String(), `task #14`) - }) - t.Run("Sort Order", func(t *testing.T) { - // should equal priority desc - t.Run("by priority", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"priority"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`) - }) - t.Run("by priority desc", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"prioritydesc"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,`) - }) - t.Run("by priority asc", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"priorityasc"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `{"id":33,"text":"task #33 with percent done","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0.5,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`) - }) - // should equal duedate desc - t.Run("by duedate", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedate"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) - }) - t.Run("by duedate desc", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedatedesc"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) - }) - t.Run("by duedate asc", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"duedateasc"}}, nil) - assert.NoError(t, err) - assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","percentDone":0,"related_tasks":{},"attachments":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`) - }) - t.Run("invalid parameter", func(t *testing.T) { - // Invalid parameter should not sort at all - rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"loremipsum"}}, nil) - assert.NoError(t, err) - assert.NotContains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":1`) - assert.NotContains(t, rec.Body.String(), `{"id":4,"text":"task #4 low prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"dueDate":0,"reminderDates":null,"repeatAfter":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}}]`) - assert.NotContains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"dueDate":1543636724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`) - assert.NotContains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"dueDate":1543616724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"dueDate":1543636724,"reminderDates":null,"repeatAfter":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":0,"username":"","email":"","created":0,"updated":0}}]`) - }) - }) - t.Run("Date range", func(t *testing.T) { - t.Run("start and end date", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"startdate": []string{"1540000000"}, "enddate": []string{"1544700001"}}, nil) - assert.NoError(t, err) - assert.NotContains(t, rec.Body.String(), `task #1`) - assert.NotContains(t, rec.Body.String(), `task #2`) - assert.NotContains(t, rec.Body.String(), `task #3`) - assert.NotContains(t, rec.Body.String(), `task #4`) - assert.Contains(t, rec.Body.String(), `task #5`) - assert.Contains(t, rec.Body.String(), `task #6`) - assert.Contains(t, rec.Body.String(), `task #7`) - assert.Contains(t, rec.Body.String(), `task #8`) - assert.Contains(t, rec.Body.String(), `task #9`) - assert.NotContains(t, rec.Body.String(), `task #10`) - assert.NotContains(t, rec.Body.String(), `task #11`) - assert.NotContains(t, rec.Body.String(), `task #12`) - assert.NotContains(t, rec.Body.String(), `task #13`) - assert.NotContains(t, rec.Body.String(), `task #14`) - }) - t.Run("start date only", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"startdate": []string{"1540000000"}}, nil) - assert.NoError(t, err) - assert.NotContains(t, rec.Body.String(), `task #1`) - assert.NotContains(t, rec.Body.String(), `task #2`) - assert.NotContains(t, rec.Body.String(), `task #3`) - assert.NotContains(t, rec.Body.String(), `task #4`) - assert.Contains(t, rec.Body.String(), `task #5`) - assert.Contains(t, rec.Body.String(), `task #6`) - assert.Contains(t, rec.Body.String(), `task #7`) - assert.Contains(t, rec.Body.String(), `task #8`) - assert.Contains(t, rec.Body.String(), `task #9`) - assert.NotContains(t, rec.Body.String(), `task #10`) - assert.NotContains(t, rec.Body.String(), `task #11`) - assert.NotContains(t, rec.Body.String(), `task #12`) - assert.NotContains(t, rec.Body.String(), `task #13`) - assert.NotContains(t, rec.Body.String(), `task #14`) - }) - t.Run("end date only", func(t *testing.T) { - rec, err := testHandler.testReadAllWithUser(url.Values{"enddate": []string{"1544700001"}}, nil) - assert.NoError(t, err) - // If no start date but an end date is specified, this should be null - // since we don't have any tasks in the fixtures with an end date > - // the current date. - assert.Equal(t, "null\n", rec.Body.String()) - }) - }) - }) t.Run("Update", func(t *testing.T) { t.Run("Update task items", func(t *testing.T) { t.Run("Text", func(t *testing.T) { diff --git a/pkg/models/task_collection.go b/pkg/models/task_collection.go index db79f953a..4707388f0 100644 --- a/pkg/models/task_collection.go +++ b/pkg/models/task_collection.go @@ -34,6 +34,23 @@ type TaskCollection struct { web.Rights `xorm:"-" json:"-"` } +// ReadAll gets all tasks for a user +// @Summary Get tasks +// @Description Returns all tasks on any list the user has access to. +// @tags task +// @Accept json +// @Produce json +// @Param page query int false "The page number. Used for pagination. If not provided, the first page of results is returned." +// @Param per_page query int false "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page." +// @Param s query string false "Search tasks by task text." +// @Param sort query string false "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc." +// @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time." +// @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time." +// @Security JWTKeyAuth +// @Success 200 {array} models.Task "The tasks" +// @Failure 500 {object} models.Message "Internal error" +// @Router /tasks/all [get] + // ReadAll gets all tasks for a collection // @Summary Get tasks on a list // @Description Returns all tasks for the current list. diff --git a/pkg/models/task_readall_test.go b/pkg/models/task_readall_test.go index 47e8ce1c5..7b27fa13a 100644 --- a/pkg/models/task_readall_test.go +++ b/pkg/models/task_readall_test.go @@ -471,22 +471,11 @@ func TestTask_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 - Priority int64 Sorting string StartDateSortUnix int64 EndDateSortUnix int64 - Created int64 - Updated int64 - CreatedBy *User + Lists []*List CRUDable web.CRUDable Rights web.Rights } @@ -708,23 +697,11 @@ func TestTask_ReadAll(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - lt := &Task{ - 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, + lt := &TaskCollection{ ListID: tt.fields.ListID, - RepeatAfter: tt.fields.RepeatAfter, - Priority: tt.fields.Priority, Sorting: tt.fields.Sorting, StartDateSortUnix: tt.fields.StartDateSortUnix, EndDateSortUnix: tt.fields.EndDateSortUnix, - Created: tt.fields.Created, - Updated: tt.fields.Updated, - CreatedBy: tt.fields.CreatedBy, CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 2dc6ee0ff..9ee72473f 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -117,31 +117,6 @@ const ( SortTasksByPriorityDesc ) -// ReadAll gets all tasks for a user -// @Summary Get tasks -// @Description Returns all tasks on any list the user has access to. -// @tags task -// @Accept json -// @Produce json -// @Param page query int false "The page number. Used for pagination. If not provided, the first page of results is returned." -// @Param per_page query int false "The maximum number of items per page. Note this parameter is limited by the configured maximum of items per page." -// @Param s query string false "Search tasks by task text." -// @Param sort query string false "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, duedate, duedatedesc, duedateasc." -// @Param startdate query int false "The start date parameter to filter by. Expects a unix timestamp. If no end date, but a start date is specified, the end date is set to the current time." -// @Param enddate query int false "The end date parameter to filter by. Expects a unix timestamp. If no start date, but an end date is specified, the start date is set to the current time." -// @Security JWTKeyAuth -// @Success 200 {array} models.Task "The tasks" -// @Failure 500 {object} models.Message "Internal error" -// @Router /tasks/all [get] -func (t *Task) ReadAll(a web.Auth, search string, page int, perPage int) (result interface{}, resultCount int, totalItems int64, err error) { - tc := &TaskCollection{ - Sorting: t.Sorting, - StartDateSortUnix: t.StartDateSortUnix, - EndDateSortUnix: t.EndDateSortUnix, - } - return tc.ReadAll(a, search, page, perPage) -} - type taskOptions struct { search string sortby SortBy diff --git a/pkg/routes/routes.go b/pkg/routes/routes.go index 2cef8f2ee..3eaea560f 100644 --- a/pkg/routes/routes.go +++ b/pkg/routes/routes.go @@ -215,6 +215,13 @@ func registerAPIRoutes(a *echo.Group) { a.DELETE("/lists/:list/shares/:share", listSharingHandler.DeleteWeb) } + taskCollectionHandler := &handler.WebHandler{ + EmptyStruct: func() handler.CObject { + return &models.TaskCollection{} + }, + } + a.GET("/lists/:list/tasks", taskCollectionHandler.ReadAllWeb) + taskHandler := &handler.WebHandler{ EmptyStruct: func() handler.CObject { return &models.Task{} @@ -222,17 +229,10 @@ func registerAPIRoutes(a *echo.Group) { } a.PUT("/lists/:list", taskHandler.CreateWeb) a.GET("/tasks/:listtask", taskHandler.ReadOneWeb) - a.GET("/tasks/all", taskHandler.ReadAllWeb) + a.GET("/tasks/all", taskCollectionHandler.ReadAllWeb) a.DELETE("/tasks/:listtask", taskHandler.DeleteWeb) a.POST("/tasks/:listtask", taskHandler.UpdateWeb) - taskCollectionHandler := &handler.WebHandler{ - EmptyStruct: func() handler.CObject { - return &models.TaskCollection{} - }, - } - a.GET("/lists/:list/tasks", taskCollectionHandler.ReadAllWeb) - bulkTaskHandler := &handler.WebHandler{ EmptyStruct: func() handler.CObject { return &models.BulkTask{}