1
0

Task Position (#412)

Fix misspell

Fix sorting tasks with null values

Fix sorting by priority for postgres

Merge branch 'master' into feature/position

Add community link

Update golang.org/x/crypto commit hash to 44a6062 (#429)

Update golang.org/x/crypto commit hash to 44a6062

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/429

Update module lib/pq to v1.4.0 (#428)

Update module lib/pq to v1.4.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/428

Fix updating position

Add ordering tasks in buckets by position

Make task sort by string

Merge branch 'master' into feature/position

Update golang.org/x/crypto commit hash to 3c4aac8 (#419)

Update golang.org/x/crypto commit hash to 3c4aac8

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/419

Merge branch 'master' into feature/position

Fix moving tasks back into the empty (ID: 0) bucket

Add adding a default position when creating new tasks

Update golang.org/x/crypto commit hash to a76a400 (#411)

Update golang.org/x/crypto commit hash to a76a400

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/411

Remove unused code

Fix tests

Add migration for position attribute

Add position attribute

Co-authored-by: kolaente <k@knt.li>
Co-authored-by: renovate <renovatebot@kolaente.de>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/412
This commit is contained in:
konrad
2020-04-24 15:23:03 +00:00
parent 86bdd1e386
commit e433289832
8 changed files with 163 additions and 978 deletions

View File

@ -17,10 +17,7 @@
package models
import (
"github.com/mohae/deepcopy"
"github.com/stretchr/testify/assert"
"math/rand"
"reflect"
"testing"
)
@ -62,11 +59,12 @@ func TestSortParamValidation(t *testing.T) {
taskPropertyUID,
taskPropertyCreated,
taskPropertyUpdated,
taskPropertyPosition,
} {
t.Run(test, func(t *testing.T) {
s := &sortParam{
orderBy: orderAscending,
sortBy: sortProperty(test),
sortBy: test,
}
err := s.validate()
assert.NoError(t, err)
@ -92,774 +90,3 @@ func TestSortParamValidation(t *testing.T) {
assert.True(t, IsErrInvalidTaskField(err))
})
}
var (
task1 = &Task{
ID: 1,
Text: "aaa",
Description: "Lorem Ipsum",
Done: true,
DoneAt: 1543626000,
ListID: 1,
UID: "JywtBPCESImlyKugvaZWrxmXAFAWXFISMeXYImEh",
Created: 1543626724,
Updated: 1543626724,
}
task2 = &Task{
ID: 2,
Text: "bbb",
Description: "Arem Ipsum",
Done: true,
DoneAt: 1543626724,
CreatedByID: 1,
ListID: 2,
PercentDone: 0.3,
StartDate: 1543626724,
Created: 1553626724,
Updated: 1553626724,
}
task3 = &Task{
ID: 3,
Text: "ccc",
DueDate: 1583626724,
Priority: 100,
ListID: 3,
HexColor: "000000",
PercentDone: 0.1,
Updated: 1555555555,
}
task4 = &Task{
ID: 4,
Text: "ddd",
Priority: 1,
StartDate: 1643626724,
ListID: 1,
}
task5 = &Task{
ID: 5,
Text: "eef",
Priority: 50,
UID: "shggzCHQWLhGNMNsOGOCOjcVkInOYjTAnORqTkdL",
DueDate: 1543636724,
Updated: 1565555555,
}
task6 = &Task{
ID: 6,
Text: "eef",
DueDate: 1543616724,
RepeatAfter: 6400,
CreatedByID: 2,
HexColor: "ffffff",
}
task7 = &Task{
ID: 7,
Text: "mmmn",
Description: "Zoremis",
StartDate: 1544600000,
EndDate: 1584600000,
UID: "tyzCZuLMSKhwclJOsDyDcUdyVAPBDOPHNTBOLTcW",
}
task8 = &Task{
ID: 8,
Text: "b123",
EndDate: 1544700000,
}
task9 = &Task{
ID: 9,
Done: true,
DoneAt: 1573626724,
Text: "a123",
RepeatAfter: 86000,
StartDate: 1544600000,
EndDate: 1544700000,
}
task10 = &Task{
ID: 10,
Text: "zzz",
Priority: 10,
PercentDone: 1,
}
)
type taskSortTestCase struct {
name string
wantAsc []*Task
wantDesc []*Task
sortProperty string
}
var taskSortTestCases = []taskSortTestCase{
{
name: "id",
sortProperty: taskPropertyID,
wantAsc: []*Task{
task1,
task2,
task3,
task4,
task5,
task6,
task7,
task8,
task9,
task10,
},
wantDesc: []*Task{
task10,
task9,
task8,
task7,
task6,
task5,
task4,
task3,
task2,
task1,
},
},
{
name: "text",
sortProperty: taskPropertyText,
wantAsc: []*Task{
task9,
task1,
task8,
task2,
task3,
task4,
task5,
task6,
task7,
task10,
},
wantDesc: []*Task{
task10,
task7,
task5,
task6,
task4,
task3,
task2,
task8,
task1,
task9,
},
},
{
name: "description",
sortProperty: taskPropertyDescription,
wantAsc: []*Task{
task3,
task4,
task5,
task6,
task8,
task9,
task10,
task2,
task1,
task7,
},
wantDesc: []*Task{
task7,
task1,
task2,
task3,
task4,
task5,
task6,
task8,
task9,
task10,
},
},
{
name: "done",
sortProperty: taskPropertyDone,
wantAsc: []*Task{
// These are not
task3,
task4,
task5,
task6,
task7,
task8,
task10,
// These are done
task1,
task2,
task9,
},
wantDesc: []*Task{
// These are done
task1,
task2,
task9,
// These are not
task3,
task4,
task5,
task6,
task7,
task8,
task10,
},
},
{
name: "done at",
sortProperty: taskPropertyDoneAtUnix,
wantAsc: []*Task{
task3,
task4,
task5,
task6,
task7,
task8,
task10,
task1,
task2,
task9,
},
wantDesc: []*Task{
task9,
task2,
task1,
task3,
task4,
task5,
task6,
task7,
task8,
task10,
},
},
{
name: "due date",
sortProperty: taskPropertyDueDateUnix,
wantAsc: []*Task{
task1,
task2,
task4,
task7,
task8,
task9,
task10,
task6,
task5,
task3,
},
wantDesc: []*Task{
task3,
task5,
task6,
task1,
task2,
task4,
task7,
task8,
task9,
task10,
},
},
{
name: "created by id",
sortProperty: taskPropertyCreatedByID,
wantAsc: []*Task{
task1,
task3,
task4,
task5,
task7,
task8,
task9,
task10,
task2,
task6,
},
wantDesc: []*Task{
task6,
task2,
task1,
task3,
task4,
task5,
task7,
task8,
task9,
task10,
},
},
{
name: "list id",
sortProperty: taskPropertyListID,
wantAsc: []*Task{
task5,
task6,
task7,
task8,
task9,
task10,
task1,
task4,
task2,
task3,
},
wantDesc: []*Task{
task3,
task2,
task1,
task4,
task5,
task6,
task7,
task8,
task9,
task10,
},
},
{
name: "repeat after",
sortProperty: taskPropertyRepeatAfter,
wantAsc: []*Task{
task1,
task2,
task3,
task4,
task5,
task7,
task8,
task10,
task6,
task9,
},
wantDesc: []*Task{
task9,
task6,
task1,
task2,
task3,
task4,
task5,
task7,
task8,
task10,
},
},
{
name: "priority",
sortProperty: taskPropertyPriority,
wantAsc: []*Task{
task1,
task2,
task6,
task7,
task8,
task9,
task4,
task10,
task5,
task3,
},
wantDesc: []*Task{
task3,
task5,
task10,
task4,
task1,
task2,
task6,
task7,
task8,
task9,
},
},
{
name: "start date",
sortProperty: taskPropertyStartDateUnix,
wantAsc: []*Task{
task1,
task3,
task5,
task6,
task8,
task10,
task2,
task7,
task9,
task4,
},
wantDesc: []*Task{
task4,
task7,
task9,
task2,
task1,
task3,
task5,
task6,
task8,
task10,
},
},
{
name: "end date",
sortProperty: taskPropertyEndDateUnix,
wantAsc: []*Task{
task1,
task2,
task3,
task4,
task5,
task6,
task10,
task8,
task9,
task7,
},
wantDesc: []*Task{
task7,
task8,
task9,
task1,
task2,
task3,
task4,
task5,
task6,
task10,
},
},
{
name: "hex color",
sortProperty: taskPropertyHexColor,
wantAsc: []*Task{
task1,
task2,
task4,
task5,
task7,
task8,
task9,
task10,
task3,
task6,
},
wantDesc: []*Task{
task6,
task3,
task1,
task2,
task4,
task5,
task7,
task8,
task9,
task10,
},
},
{
name: "percent done",
sortProperty: taskPropertyPercentDone,
wantAsc: []*Task{
task1,
task4,
task5,
task6,
task7,
task8,
task9,
task3,
task2,
task10,
},
wantDesc: []*Task{
task10,
task2,
task3,
task1,
task4,
task5,
task6,
task7,
task8,
task9,
},
},
{
name: "uid",
sortProperty: taskPropertyUID,
wantAsc: []*Task{
task2,
task3,
task4,
task6,
task8,
task9,
task10,
task1,
task5,
task7,
},
wantDesc: []*Task{
task7,
task5,
task1,
task2,
task3,
task4,
task6,
task8,
task9,
task10,
},
},
{
name: "created",
sortProperty: taskPropertyCreated,
wantAsc: []*Task{
task3,
task4,
task5,
task6,
task7,
task8,
task9,
task10,
task1,
task2,
},
wantDesc: []*Task{
task2,
task1,
task3,
task4,
task5,
task6,
task7,
task8,
task9,
task10,
},
},
{
name: "updated",
sortProperty: taskPropertyUpdated,
wantAsc: []*Task{
task4,
task6,
task7,
task8,
task9,
task10,
task1,
task2,
task3,
task5,
},
wantDesc: []*Task{
task5,
task3,
task2,
task1,
task4,
task6,
task7,
task8,
task9,
task10,
},
},
}
func TestTaskSort(t *testing.T) {
assertTestSliceMatch := func(t *testing.T, got, want []*Task) {
if !reflect.DeepEqual(got, want) {
t.Error("Slices do not match in order")
t.Error("Got\t| Want")
for in, task := range got {
fail := ""
if task.ID != want[in].ID {
fail = "wrong"
}
t.Errorf("\t%d\t| %d \t%s", task.ID, want[in].ID, fail)
}
}
}
for _, testCase := range taskSortTestCases {
t.Run(testCase.name, func(t *testing.T) {
t.Run("asc default", func(t *testing.T) {
by := []*sortParam{
{
sortBy: sortProperty(testCase.sortProperty),
},
}
got := deepcopy.Copy(testCase.wantAsc).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, by)
assertTestSliceMatch(t, got, testCase.wantAsc)
})
t.Run("asc", func(t *testing.T) {
by := []*sortParam{
{
sortBy: sortProperty(testCase.sortProperty),
orderBy: orderAscending,
},
}
got := deepcopy.Copy(testCase.wantAsc).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, by)
assertTestSliceMatch(t, got, testCase.wantAsc)
})
t.Run("desc", func(t *testing.T) {
by := []*sortParam{
{
sortBy: sortProperty(testCase.sortProperty),
orderBy: orderDescending,
},
}
got := deepcopy.Copy(testCase.wantDesc).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, by)
assertTestSliceMatch(t, got, testCase.wantDesc)
})
})
}
// Other cases
t.Run("Order by Done Ascending and ID Descending", func(t *testing.T) {
want := []*Task{
// Not done
task10,
task8,
task7,
task6,
task5,
task4,
task3,
// Done
task9,
task2,
task1,
}
sortParams := []*sortParam{
{
sortBy: sortProperty(taskPropertyDone),
orderBy: orderAscending,
},
{
sortBy: sortProperty(taskPropertyID),
orderBy: orderDescending,
},
}
got := deepcopy.Copy(want).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, sortParams)
assertTestSliceMatch(t, got, want)
})
t.Run("Order by Done Ascending and Text Descending", func(t *testing.T) {
want := []*Task{
// Not done
task10,
task7,
task5,
task6,
task4,
task3,
task8,
// Done
task2,
task1,
task9,
}
sortParams := []*sortParam{
{
sortBy: sortProperty(taskPropertyDone),
orderBy: orderAscending,
},
{
sortBy: sortProperty(taskPropertyText),
orderBy: orderDescending,
},
}
got := deepcopy.Copy(want).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, sortParams)
assertTestSliceMatch(t, got, want)
})
t.Run("Order by Done Descending and Text Ascending", func(t *testing.T) {
want := []*Task{
// Done
task9,
task1,
task2,
// Not done
task8,
task3,
task4,
task5,
task6,
task7,
task10,
}
sortParams := []*sortParam{
{
sortBy: sortProperty(taskPropertyDone),
orderBy: orderDescending,
},
{
sortBy: sortProperty(taskPropertyText),
orderBy: orderAscending,
},
}
got := deepcopy.Copy(want).([]*Task)
// Destroy wanted order to obtain some slice we can sort
rand.Shuffle(len(got), func(i, j int) {
got[i], got[j] = got[j], got[i]
})
sortTasks(got, sortParams)
assertTestSliceMatch(t, got, want)
})
}