Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

Query language support for child iteration & area #2182

Merged
merged 56 commits into from
Oct 3, 2018
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e06b5c6
Query language support for child iteration & area
baijum Jul 25, 2018
375ee86
remove comment
baijum Jul 25, 2018
4fc0296
more test cases
baijum Jul 26, 2018
7047576
child is true by default for area
baijum Jul 26, 2018
fe3528a
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Jul 30, 2018
31b3511
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Jul 31, 2018
0b46360
update query include parent iter
baijum Aug 1, 2018
b53c8b9
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 1, 2018
d19f69f
fix query
baijum Aug 2, 2018
949cb11
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 2, 2018
c43fd0a
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 2, 2018
2db9f35
avoid unwanted select
baijum Aug 2, 2018
09b67fd
do not override child enablement
baijum Aug 2, 2018
10ae3d8
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 2, 2018
5588a87
YAGNI
baijum Aug 3, 2018
9c02141
better description
baijum Aug 3, 2018
924ef7a
no return value
baijum Aug 3, 2018
9afe79c
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 3, 2018
bdf423e
test child expression
baijum Aug 3, 2018
1a6bf6a
Use value based syntax to fetch
baijum Aug 14, 2018
826c6cc
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Aug 14, 2018
8450f41
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 10, 2018
4dc2094
New SQL query based on
baijum Sep 10, 2018
c77e254
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 10, 2018
0c39c44
Update query based on new path representation
baijum Sep 10, 2018
bb8f8a7
Fix tests
baijum Sep 10, 2018
c8b23b5
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 11, 2018
33d6069
Set false option explicitly
baijum Sep 11, 2018
d35ccb4
typo
baijum Sep 11, 2018
a84a234
Revert "Set false option explicitly"
baijum Sep 11, 2018
88e26d1
better test description
baijum Sep 11, 2018
51ef43e
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 11, 2018
f3c1463
typo
baijum Sep 11, 2018
761d3dc
Use apropriate table alias
baijum Sep 11, 2018
28909d0
better comment
baijum Sep 11, 2018
dcbad2b
Avoid unnecessary helper function
baijum Sep 11, 2018
3ef0e22
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 11, 2018
387c959
fix comment
baijum Sep 11, 2018
0c6e586
Merge branch 'master' into wi-2450
baijum Sep 11, 2018
0ed33f8
Fix key used for joins map
baijum Sep 11, 2018
366f81b
remove unrelated changes
baijum Sep 13, 2018
be44bd2
remove ambiguous comment
baijum Sep 13, 2018
80f7103
use space id, better comment, better message
baijum Sep 14, 2018
65e483a
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 18, 2018
1184566
child: true is no more supported
baijum Sep 18, 2018
10b021e
better word
baijum Sep 18, 2018
7e29206
test a error case
baijum Sep 18, 2018
d524455
use compact syntax
baijum Sep 21, 2018
1488af0
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Sep 21, 2018
251645a
Merge branch 'master' into wi-2450
baijum Sep 21, 2018
20a5d4f
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Oct 1, 2018
3e69d32
Use attribute instead of value based syntax
baijum Oct 1, 2018
46f2e98
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Oct 1, 2018
b8392a4
Merge remote-tracking branch 'upstream/master' into wi-2450
baijum Oct 3, 2018
42d62d5
dont' override already set value
baijum Oct 3, 2018
3dbf8fe
test against default
baijum Oct 3, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions controller/search_blackbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,175 @@ func (s *searchControllerTestSuite) TestSearchByJoinedData() {
})
}

// TestSearchWorkItemsWithChildIterationsOption verifies the child work item search for iteration
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])
Copy link
Collaborator

Choose a reason for hiding this comment

The 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])
      }
    },
  ),
  //...

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 find all work items: %+s", toBeFound)
})
t.Run("with one child iteration", 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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should say: "unexpected work item found"

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 find all work items: %+s", toBeFound)
})
t.Run("with two child iteration", 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 find all work items: %+s", toBeFound)
})

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 find all work items: %+s", toBeFound)
})
t.Run("without child iteration - no /** suffix", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[2].ID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to provide 'child:false' option here as the test says 'false option'. Otherwise how would this test be diffferent from the one above it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 33d6069

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reverted the commit, because it's no more relying on false option rather we use a /** suffix to get children. I will update the test description.

_, 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 find all work items: %+s", toBeFound)
})
t.Run("with one child iteration - no /** suffix", 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, 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 find all work items: %+s", toBeFound)
})
t.Run("with two child iteration - no /** suffix", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a test for
{"iteration": "%s/**", "child":true} just to make sure nothing breaks when both the options are set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "child" attribute is not recognized by the parser, and it won't make any difference. So, I am not sure we need to test it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. It looks like this line https://github.com/fabric8-services/fabric8-wit/pull/2182/files#diff-acc8d3974d80a8260ecd28803a0b064aR278 would set child:true if both the options are set.
Adding a test would've been better, but it's fine if we don't add it 👍

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, 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() {

Expand Down
20 changes: 20 additions & 0 deletions criteria/expression_child.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package criteria

// ChildExpression represents the child operator
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}})
}
1 change: 1 addition & 0 deletions criteria/expression_visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ type ExpressionVisitor interface {
Parameter(v *ParameterExpression) interface{}
Literal(c *LiteralExpression) interface{}
Not(e *NotExpression) interface{}
Child(e *ChildExpression) interface{}
IsNull(e *IsNullExpression) interface{}
}
4 changes: 4 additions & 0 deletions criteria/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ func (i *postOrderIterator) Not(exp *NotExpression) interface{} {
return i.binary(exp)
}

func (i *postOrderIterator) Child(exp *ChildExpression) interface{} {
return i.binary(exp)
}

func (i *postOrderIterator) IsNull(exp *IsNullExpression) interface{} {
return i.visit(exp)
}
Expand Down
25 changes: 22 additions & 3 deletions search/search_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,18 @@ func parseMap(queryMap map[string]interface{}, q *Query) {
q.Name = key
s := string(concreteVal)
q.Value = &s
if q.Name == "iteration" || q.Name == "area" {
if strings.HasSuffix(s, "/**") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you choose this suffix to be appended and not have a different compare function alongside Equal, Not? This /** suffix will not work when you want to search for work items in an iteration when the iteration is given by name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not getting the last of part. When this is not going to work?

Copy link
Collaborator

@kwk kwk Sep 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try to rephrase my question...

How can I query for an iteration or area by name and expect the children of the given iteration/area to be found?

You're checking for q.Name if it is "area" or "iteration" and if I remember correctly, those are the ID columns, aren't they? If I understand the logic correctly, your code will not be triggered when you query for iteration.name or area.name. That is why I ask about a different comparator (e.g. @>) so you could potentially right any of these queries:

iteration @> 2e0698d8-753e-4cef-bb7c-f027634824a2
area @> 2e0698d8-753e-4cef-bb7c-f027634824a2
iteration.name @> foo
area.name @> foo

I think we can only allow for /** if we prohibit that this string is ever used inside an iteration/area name, don't you think? Also, to me the the / looks like it is supposed to be used only when you're querying for an iteration path as in iteration.path = /foo/bar and even then we must prohibit usage of /** inside of iteration/area names. Those measures are not taken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is only considering ID column to lookup for child iteration/area. Since IDs are UUIDs, there won't be any /** character anywhere in the value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did get that and that is why I'm so concerned.

But then you would have to learn a new syntax when you want to allow searching for an iteration/area that is given by any other field. I don't see the real value in this other than a quick fix with problems down the line. I mean the /** doesn't even work for paths of an iteration where it seems to make the most sense (/foo/bar/**) because nobody is holding you back from naming your iteration **.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If path & name requires similar syntax, we can do it in a separate PR.

Copy link
Collaborator

@kwk kwk Sep 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is exactly my point, path, resolved_path, name, number, start date, ... they probably require different suffixes because of the domain and allowed vocabulary. And as a user I probably should not care by what field I query (e.g. name, path, id, number) the syntax should remain the same everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, what should I do with this PR? Avoid using /** altogether and use "child":true attribute?
Please suggest.

q.Child = true
ns := s[0 : len(s)-3]
q.Value = &ns
}
}
case bool:
s := concreteVal
q.Negate = s
if key == "negate" {
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 366f81b

q.Negate = s
}
case nil:
q.Name = key
q.Value = nil
Expand Down Expand Up @@ -378,6 +387,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 {
Expand Down Expand Up @@ -436,7 +447,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 {
Expand Down Expand Up @@ -477,7 +492,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 {
Expand Down
76 changes: 76 additions & 0 deletions search/search_repository_blackbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,82 @@ func (s *searchRepositoryBlackboxTest) getTestFixture() *tf.TestFixture {
)
}

func (s *searchRepositoryBlackboxTest) TestSearchWithChildIterationWorkItems() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a test for child:true and another one for /** with child:false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "child" attribute is not recognized by the parser, and it won't make any difference. So, I am not sure we need to test it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it is very unclear at this point if you have to specify child:true in order to get work items from child iterations or if it is enough if you ask for <ITERATION-ID>/**. Why do we have both of these notations anyway and why is nothing of this defined in the PR description? Please update that with a lot more details.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no support for "child": true. The only supported format is ID/**.

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])
}
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
}),
)
t.Run("without child iteration", func(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test name is confusion. You're searching for work items in iteration "Level 2 iteration" which has no children but the search itself does ask for children if I'm not mistaken.

filter := fmt.Sprintf(`{"$AND": [{"iteration": "%s/**"}, {"space": "%s"}]}`, fxt.Iterations[2].ID, fxt.Spaces[0].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 4, count)
})

t.Run("with one child iteration", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s/**"}`, fxt.Iterations[1].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 6, count)
})
t.Run("with two child iteration", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s/**"}`, fxt.Iterations[0].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 9, count)
})
t.Run("without child iteration - no /** suffix", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[2].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 4, count)
})
t.Run("with one child iteration - no /** suffix", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[1].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 2, count)
})
t.Run("with two child iteration - no /** suffix", func(t *testing.T) {
filter := fmt.Sprintf(`{"iteration": "%s"}`, fxt.Iterations[0].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 3, count)
})
t.Run("with two child iteration and space", func(t *testing.T) {
filter := fmt.Sprintf(`{"$AND": [{"iteration": "%s/**"},{"space": "%s"}]}`, fxt.Iterations[0].ID, fxt.Spaces[0].ID)
_, count, _, _, err := s.searchRepo.Filter(context.Background(), filter, nil, nil, nil)
require.NoError(t, err)
assert.Equal(t, 9, count)
})
})
}

func (s *searchRepositoryBlackboxTest) TestSearchWithJoin() {
s.T().Run("join iterations", func(t *testing.T) {
fxt := tf.NewTestFixture(t, s.DB,
Expand Down
Loading