-
Notifications
You must be signed in to change notification settings - Fork 86
Query language support for child iteration & area #2182
Changes from 4 commits
e06b5c6
375ee86
4fc0296
7047576
fe3528a
31b3511
0b46360
b53c8b9
d19f69f
949cb11
c43fd0a
2db9f35
09b67fd
10ae3d8
5588a87
9c02141
924ef7a
9afe79c
bdf423e
1a6bf6a
826c6cc
8450f41
4dc2094
c77e254
0c39c44
bb8f8a7
c8b23b5
33d6069
d35ccb4
a84a234
88e26d1
51ef43e
f3c1463
761d3dc
28909d0
dcbad2b
3ef0e22
387c959
0c6e586
0ed33f8
366f81b
be44bd2
80f7103
65e483a
1184566
10b021e
7e29206
d524455
1488af0
251645a
20a5d4f
3e69d32
46f2e98
b8392a4
42d62d5
3dbf8fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1030,6 +1030,219 @@ func (s *searchControllerTestSuite) TestSearchByJoinedData() { | |
}) | ||
} | ||
|
||
// TestSearchWorkItemsWithChildIterationsOption verifies the Included list of parents | ||
func (s *searchControllerTestSuite) TestSearchWorkItemsWithChildIterationsOption() { | ||
s.T().Run("iterations", func(t *testing.T) { | ||
fxt := tf.NewTestFixture(t, s.DB, | ||
tf.Iterations(3, func(fxt *tf.TestFixture, idx int) error { | ||
i := fxt.Iterations[idx] | ||
switch idx { | ||
case 0: | ||
i.Name = "Top level iteration" | ||
case 1: | ||
i.Name = "Level 1 iteration" | ||
i.MakeChildOf(*fxt.Iterations[idx-1]) | ||
case 2: | ||
i.Name = "Level 2 iteration" | ||
i.MakeChildOf(*fxt.Iterations[idx-1]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This setup is all good, but if you're searching for something easier to set up please consider using this: fxt := tf.NewTestFixture(t, s.DB,
tf.Iterations(3,
tf.SetIterationNames("Top level iteration", "Level 1 iteration", "Level 2 iteration"),
func(fxt *tf.TestFixture, idx int) error {
if idx > 0 {
fxt.Iterations[idx].MakeChildOf(*fxt.Iterations[idx-1])
}
},
),
//... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. d524455 |
||
} | ||
return nil | ||
}), | ||
|
||
tf.WorkItems(10, func(fxt *tf.TestFixture, idx int) error { | ||
switch idx { | ||
case 0, 1, 2: | ||
fxt.WorkItems[idx].Fields[workitem.SystemIteration] = fxt.Iterations[0].ID.String() | ||
case 3, 4: | ||
fxt.WorkItems[idx].Fields[workitem.SystemIteration] = fxt.Iterations[1].ID.String() | ||
case 5, 6, 7, 8: | ||
fxt.WorkItems[idx].Fields[workitem.SystemIteration] = fxt.Iterations[2].ID.String() | ||
} | ||
return nil | ||
}), | ||
) | ||
|
||
spaceIDStr := fxt.Spaces[0].ID.String() | ||
|
||
t.Run("without child iteration", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": true}`, fxt.Iterations[2].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 4) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
jarifibrahim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
t.Run("with one child iteration", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": true}`, fxt.Iterations[1].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 6) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[3].ID, | ||
fxt.WorkItems[4].ID, | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should say: "unexpected work item found" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 10b021e |
||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
jarifibrahim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
t.Run("with two child iteration", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": true}`, fxt.Iterations[0].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 9) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[0].ID, | ||
fxt.WorkItems[1].ID, | ||
fxt.WorkItems[2].ID, | ||
fxt.WorkItems[3].ID, | ||
fxt.WorkItems[4].ID, | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
jarifibrahim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
|
||
t.Run("without child iteration - implicit", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[2].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 4) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
}) | ||
t.Run("with one child iteration - implicit", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[1].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 6) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[3].ID, | ||
fxt.WorkItems[4].ID, | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
}) | ||
t.Run("with two child iteration - implicit", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[0].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 9) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[0].ID, | ||
fxt.WorkItems[1].ID, | ||
fxt.WorkItems[2].ID, | ||
fxt.WorkItems[3].ID, | ||
fxt.WorkItems[4].ID, | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
}) | ||
|
||
t.Run("without child iteration - false option", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": false}`, fxt.Iterations[2].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 4) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[5].ID, | ||
fxt.WorkItems[6].ID, | ||
fxt.WorkItems[7].ID, | ||
fxt.WorkItems[8].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
}) | ||
t.Run("with one child iteration - false option", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": false}`, fxt.Iterations[1].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 2) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[3].ID, | ||
fxt.WorkItems[4].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
}) | ||
t.Run("with two child iteration - false option", func(t *testing.T) { | ||
filter := fmt.Sprintf(`{"iteration": "%s", "child": false}`, fxt.Iterations[0].ID) | ||
_, result := test.ShowSearchOK(t, nil, nil, s.controller, &filter, nil, nil, nil, nil, &spaceIDStr) | ||
require.NotEmpty(t, result.Data) | ||
assert.Len(t, result.Data, 3) | ||
toBeFound := id.MapFromSlice(id.Slice{ | ||
fxt.WorkItems[0].ID, | ||
fxt.WorkItems[1].ID, | ||
fxt.WorkItems[2].ID, | ||
}) | ||
for _, wi := range result.Data { | ||
_, ok := toBeFound[*wi.ID] | ||
require.True(t, ok, "unknown work item found: %s", *wi.ID) | ||
delete(toBeFound, *wi.ID) | ||
} | ||
require.Empty(t, toBeFound, "failed to found all work items: %+s", toBeFound) | ||
jarifibrahim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
}) | ||
|
||
} | ||
|
||
// TestIncludedParents verifies the Included list of parents | ||
func (s *searchControllerTestSuite) TestIncludedParents() { | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package criteria | ||
|
||
// ChildExpression represents the negation operator | ||
jarifibrahim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
type ChildExpression struct { | ||
binaryExpression | ||
} | ||
|
||
// Ensure ChildExpression implements the Expression interface | ||
var _ Expression = &ChildExpression{} | ||
var _ Expression = (*ChildExpression)(nil) | ||
|
||
// Accept implements ExpressionVisitor | ||
func (t *ChildExpression) Accept(visitor ExpressionVisitor) interface{} { | ||
return visitor.Child(t) | ||
} | ||
|
||
// Child constructs a ChildExpression | ||
func Child(left Expression, right Expression) Expression { | ||
return reparent(&ChildExpression{binaryExpression{expression{}, left, right}}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,9 +275,16 @@ func parseMap(queryMap map[string]interface{}, q *Query) { | |
q.Name = key | ||
s := string(concreteVal) | ||
q.Value = &s | ||
if q.Name == "iteration" || q.Name == "area" { | ||
q.Child = true | ||
} | ||
case bool: | ||
s := concreteVal | ||
q.Negate = s | ||
if key == "negate" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this fixing? Should this maybe be moved out into its own PR? It seems like it is solving some other problem. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 366f81b |
||
q.Negate = s | ||
} else if key == "child" { | ||
q.Child = s | ||
} | ||
case nil: | ||
q.Name = key | ||
q.Value = nil | ||
|
@@ -378,6 +385,8 @@ type Query struct { | |
Children []Query | ||
// The Options represent the query options provided by the user. | ||
Options *QueryOptions | ||
// Consider child iteration/area | ||
Child bool | ||
kwk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
func isOperator(str string) bool { | ||
|
@@ -436,7 +445,11 @@ func (q Query) generateExpression() (criteria.Expression, error) { | |
if q.Substring { | ||
myexpr = append(myexpr, criteria.Substring(left, right)) | ||
} else { | ||
myexpr = append(myexpr, criteria.Equals(left, right)) | ||
if q.Child { | ||
myexpr = append(myexpr, criteria.Child(left, right)) | ||
} else { | ||
myexpr = append(myexpr, criteria.Equals(left, right)) | ||
} | ||
} | ||
} | ||
} else { | ||
|
@@ -477,7 +490,11 @@ func (q Query) generateExpression() (criteria.Expression, error) { | |
if child.Substring { | ||
myexpr = append(myexpr, criteria.Substring(left, right)) | ||
} else { | ||
myexpr = append(myexpr, criteria.Equals(left, right)) | ||
if child.Child { | ||
myexpr = append(myexpr, criteria.Child(left, right)) | ||
} else { | ||
myexpr = append(myexpr, criteria.Equals(left, right)) | ||
} | ||
} | ||
} | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please fix the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 387c959