mirror of
https://github.com/mattermost/focalboard.git
synced 2025-01-26 18:48:15 +02:00
Search boards by prop (#4291)
* SearchBoardsForUser API with property name search.
This commit is contained in:
parent
2a5c033fa5
commit
b63542fb63
@ -114,6 +114,11 @@ func (a *API) handleSearchBoards(w http.ResponseWriter, r *http.Request) {
|
|||||||
// description: The search term. Must have at least one character
|
// description: The search term. Must have at least one character
|
||||||
// required: true
|
// required: true
|
||||||
// type: string
|
// type: string
|
||||||
|
// - name: field
|
||||||
|
// in: query
|
||||||
|
// description: The field to search on for search term. Can be `title`, `property_name`. Defaults to `title`
|
||||||
|
// required: false
|
||||||
|
// type: string
|
||||||
// security:
|
// security:
|
||||||
// - BearerAuth: []
|
// - BearerAuth: []
|
||||||
// responses:
|
// responses:
|
||||||
@ -128,8 +133,18 @@ func (a *API) handleSearchBoards(w http.ResponseWriter, r *http.Request) {
|
|||||||
// schema:
|
// schema:
|
||||||
// "$ref": "#/definitions/ErrorResponse"
|
// "$ref": "#/definitions/ErrorResponse"
|
||||||
|
|
||||||
|
var err error
|
||||||
teamID := mux.Vars(r)["teamID"]
|
teamID := mux.Vars(r)["teamID"]
|
||||||
term := r.URL.Query().Get("q")
|
term := r.URL.Query().Get("q")
|
||||||
|
searchFieldText := r.URL.Query().Get("field")
|
||||||
|
searchField := model.BoardSearchFieldTitle
|
||||||
|
if searchFieldText != "" {
|
||||||
|
searchField, err = model.BoardSearchFieldFromString(searchFieldText)
|
||||||
|
if err != nil {
|
||||||
|
a.errorResponse(w, r, model.NewErrBadRequest(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
userID := getUserID(r)
|
userID := getUserID(r)
|
||||||
|
|
||||||
if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) {
|
if !a.permissions.HasPermissionToTeam(userID, teamID, model.PermissionViewTeam) {
|
||||||
@ -153,7 +168,7 @@ func (a *API) handleSearchBoards(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// retrieve boards list
|
// retrieve boards list
|
||||||
boards, err := a.app.SearchBoardsForUser(term, userID, !isGuest)
|
boards, err := a.app.SearchBoardsForUser(term, searchField, userID, !isGuest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.errorResponse(w, r, err)
|
a.errorResponse(w, r, err)
|
||||||
return
|
return
|
||||||
@ -312,7 +327,7 @@ func (a *API) handleSearchAllBoards(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// retrieve boards list
|
// retrieve boards list
|
||||||
boards, err := a.app.SearchBoardsForUser(term, userID, !isGuest)
|
boards, err := a.app.SearchBoardsForUser(term, model.BoardSearchFieldTitle, userID, !isGuest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.errorResponse(w, r, err)
|
a.errorResponse(w, r, err)
|
||||||
return
|
return
|
||||||
|
@ -637,8 +637,8 @@ func (a *App) DeleteBoardMember(boardID, userID string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SearchBoardsForUser(term, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
func (a *App) SearchBoardsForUser(term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
||||||
return a.store.SearchBoardsForUser(term, userID, includePublicBoards)
|
return a.store.SearchBoardsForUser(term, searchField, userID, includePublicBoards)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error) {
|
func (a *App) SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error) {
|
||||||
|
@ -720,6 +720,17 @@ func (c *Client) GetBoardsForTeam(teamID string) ([]*model.Board, *Response) {
|
|||||||
return model.BoardsFromJSON(r.Body), BuildResponse(r)
|
return model.BoardsFromJSON(r.Body), BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) SearchBoardsForUser(teamID, term string, field model.BoardSearchField) ([]*model.Board, *Response) {
|
||||||
|
query := fmt.Sprintf("q=%s&field=%s", term, field)
|
||||||
|
r, err := c.DoAPIGet(c.GetTeamRoute(teamID)+"/boards/search?"+query, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, BuildErrorResponse(r, err)
|
||||||
|
}
|
||||||
|
defer closeBody(r)
|
||||||
|
|
||||||
|
return model.BoardsFromJSON(r.Body), BuildResponse(r)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) SearchBoardsForTeam(teamID, term string) ([]*model.Board, *Response) {
|
func (c *Client) SearchBoardsForTeam(teamID, term string) ([]*model.Board, *Response) {
|
||||||
r, err := c.DoAPIGet(c.GetTeamRoute(teamID)+"/boards/search?q="+term, "")
|
r, err := c.DoAPIGet(c.GetTeamRoute(teamID)+"/boards/search?q="+term, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -271,8 +271,8 @@ func (s *PluginTestStore) GetChannel(teamID, channel string) (*mmModel.Channel,
|
|||||||
return nil, errTestStore
|
return nil, errTestStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PluginTestStore) SearchBoardsForUser(term string, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
func (s *PluginTestStore) SearchBoardsForUser(term string, field model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
||||||
boards, err := s.Store.SearchBoardsForUser(term, userID, includePublicBoards)
|
boards, err := s.Store.SearchBoardsForUser(term, field, userID, includePublicBoards)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
type BoardType string
|
type BoardType string
|
||||||
type BoardRole string
|
type BoardRole string
|
||||||
|
type BoardSearchField string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BoardTypeOpen BoardType = "O"
|
BoardTypeOpen BoardType = "O"
|
||||||
@ -22,6 +23,12 @@ const (
|
|||||||
BoardRoleAdmin BoardRole = "admin"
|
BoardRoleAdmin BoardRole = "admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
BoardSearchFieldNone BoardSearchField = ""
|
||||||
|
BoardSearchFieldTitle BoardSearchField = "title"
|
||||||
|
BoardSearchFieldPropertyName BoardSearchField = "property_name"
|
||||||
|
)
|
||||||
|
|
||||||
// Board groups a set of blocks and its layout
|
// Board groups a set of blocks and its layout
|
||||||
// swagger:model
|
// swagger:model
|
||||||
type Board struct {
|
type Board struct {
|
||||||
@ -392,3 +399,13 @@ type BoardMemberHistoryEntry struct {
|
|||||||
// required: true
|
// required: true
|
||||||
InsertAt time.Time `json:"insertAt"`
|
InsertAt time.Time `json:"insertAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BoardSearchFieldFromString(field string) (BoardSearchField, error) {
|
||||||
|
switch field {
|
||||||
|
case string(BoardSearchFieldTitle):
|
||||||
|
return BoardSearchFieldTitle, nil
|
||||||
|
case string(BoardSearchFieldPropertyName):
|
||||||
|
return BoardSearchFieldPropertyName, nil
|
||||||
|
}
|
||||||
|
return BoardSearchFieldNone, ErrInvalidBoardSearchField
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@ var (
|
|||||||
ErrBoardMemberIsLastAdmin = errors.New("cannot leave a board with no admins")
|
ErrBoardMemberIsLastAdmin = errors.New("cannot leave a board with no admins")
|
||||||
|
|
||||||
ErrRequestEntityTooLarge = errors.New("request entity too large")
|
ErrRequestEntityTooLarge = errors.New("request entity too large")
|
||||||
|
|
||||||
|
ErrInvalidBoardSearchField = errors.New("invalid board search field")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNotFound is an error type that can be returned by store APIs
|
// ErrNotFound is an error type that can be returned by store APIs
|
||||||
|
@ -670,7 +670,7 @@ func (s *MattermostAuthLayer) baseUserQuery(showEmail, showName bool) sq.SelectB
|
|||||||
// term that are either private and which the user is a member of, or
|
// term that are either private and which the user is a member of, or
|
||||||
// they're open, regardless of the user membership.
|
// they're open, regardless of the user membership.
|
||||||
// Search is case-insensitive.
|
// Search is case-insensitive.
|
||||||
func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
func (s *MattermostAuthLayer) SearchBoardsForUser(term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
||||||
// as we're joining three queries, we need to avoid numbered
|
// as we're joining three queries, we need to avoid numbered
|
||||||
// placeholders until the join is done, so we use the default
|
// placeholders until the join is done, so we use the default
|
||||||
// question mark placeholder here
|
// question mark placeholder here
|
||||||
@ -706,14 +706,29 @@ func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePu
|
|||||||
})
|
})
|
||||||
|
|
||||||
if term != "" {
|
if term != "" {
|
||||||
|
if searchField == model.BoardSearchFieldPropertyName {
|
||||||
|
var where, whereTerm string
|
||||||
|
switch s.dbType {
|
||||||
|
case model.PostgresDBType:
|
||||||
|
where = "b.properties->? is not null"
|
||||||
|
whereTerm = term
|
||||||
|
case model.MysqlDBType, model.SqliteDBType:
|
||||||
|
where = "JSON_EXTRACT(b.properties, ?) IS NOT NULL"
|
||||||
|
whereTerm = "$." + term
|
||||||
|
default:
|
||||||
|
where = "b.properties LIKE ?"
|
||||||
|
whereTerm = "%\"" + term + "\"%"
|
||||||
|
}
|
||||||
|
boardMembersQ = boardMembersQ.Where(where, whereTerm)
|
||||||
|
teamMembersQ = teamMembersQ.Where(where, whereTerm)
|
||||||
|
channelMembersQ = channelMembersQ.Where(where, whereTerm)
|
||||||
|
} else { // model.BoardSearchFieldTitle
|
||||||
// break search query into space separated words
|
// break search query into space separated words
|
||||||
// and search for all words.
|
// and search for all words.
|
||||||
// This should later be upgraded to industrial-strength
|
// This should later be upgraded to industrial-strength
|
||||||
// word tokenizer, that uses much more than space
|
// word tokenizer, that uses much more than space
|
||||||
// to break words.
|
// to break words.
|
||||||
|
|
||||||
conditions := sq.And{}
|
conditions := sq.And{}
|
||||||
|
|
||||||
for _, word := range strings.Split(strings.TrimSpace(term), " ") {
|
for _, word := range strings.Split(strings.TrimSpace(term), " ") {
|
||||||
conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"})
|
conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"})
|
||||||
}
|
}
|
||||||
@ -722,6 +737,7 @@ func (s *MattermostAuthLayer) SearchBoardsForUser(term, userID string, includePu
|
|||||||
teamMembersQ = teamMembersQ.Where(conditions)
|
teamMembersQ = teamMembersQ.Where(conditions)
|
||||||
channelMembersQ = channelMembersQ.Where(conditions)
|
channelMembersQ = channelMembersQ.Where(conditions)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
teamMembersSQL, teamMembersArgs, err := teamMembersQ.ToSql()
|
teamMembersSQL, teamMembersArgs, err := teamMembersQ.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1472,18 +1472,18 @@ func (mr *MockStoreMockRecorder) SaveMember(arg0 interface{}) *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SearchBoardsForUser mocks base method.
|
// SearchBoardsForUser mocks base method.
|
||||||
func (m *MockStore) SearchBoardsForUser(arg0, arg1 string, arg2 bool) ([]*model.Board, error) {
|
func (m *MockStore) SearchBoardsForUser(arg0 string, arg1 model.BoardSearchField, arg2 string, arg3 bool) ([]*model.Board, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "SearchBoardsForUser", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "SearchBoardsForUser", arg0, arg1, arg2, arg3)
|
||||||
ret0, _ := ret[0].([]*model.Board)
|
ret0, _ := ret[0].([]*model.Board)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchBoardsForUser indicates an expected call of SearchBoardsForUser.
|
// SearchBoardsForUser indicates an expected call of SearchBoardsForUser.
|
||||||
func (mr *MockStoreMockRecorder) SearchBoardsForUser(arg0, arg1, arg2 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) SearchBoardsForUser(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchBoardsForUser", reflect.TypeOf((*MockStore)(nil).SearchBoardsForUser), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchBoardsForUser", reflect.TypeOf((*MockStore)(nil).SearchBoardsForUser), arg0, arg1, arg2, arg3)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchBoardsForUserInTeam mocks base method.
|
// SearchBoardsForUserInTeam mocks base method.
|
||||||
|
@ -660,7 +660,7 @@ func (s *SQLStore) getMembersForBoard(db sq.BaseRunner, boardID string) ([]*mode
|
|||||||
// term that are either private and which the user is a member of, or
|
// term that are either private and which the user is a member of, or
|
||||||
// they're open, regardless of the user membership.
|
// they're open, regardless of the user membership.
|
||||||
// Search is case-insensitive.
|
// Search is case-insensitive.
|
||||||
func (s *SQLStore) searchBoardsForUser(db sq.BaseRunner, term, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
func (s *SQLStore) searchBoardsForUser(db sq.BaseRunner, term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
||||||
query := s.getQueryBuilder(db).
|
query := s.getQueryBuilder(db).
|
||||||
Select(boardFields("b.")...).
|
Select(boardFields("b.")...).
|
||||||
Distinct().
|
Distinct().
|
||||||
@ -680,20 +680,31 @@ func (s *SQLStore) searchBoardsForUser(db sq.BaseRunner, term, userID string, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
if term != "" {
|
if term != "" {
|
||||||
|
if searchField == model.BoardSearchFieldPropertyName {
|
||||||
|
switch s.dbType {
|
||||||
|
case model.PostgresDBType:
|
||||||
|
where := "b.properties->? is not null"
|
||||||
|
query = query.Where(where, term)
|
||||||
|
case model.MysqlDBType, model.SqliteDBType:
|
||||||
|
where := "JSON_EXTRACT(b.properties, ?) IS NOT NULL"
|
||||||
|
query = query.Where(where, "$."+term)
|
||||||
|
default:
|
||||||
|
where := "b.properties LIKE ?"
|
||||||
|
query = query.Where(where, "%\""+term+"\"%")
|
||||||
|
}
|
||||||
|
} else { // model.BoardSearchFieldTitle
|
||||||
// break search query into space separated words
|
// break search query into space separated words
|
||||||
// and search for all words.
|
// and search for all words.
|
||||||
// This should later be upgraded to industrial-strength
|
// This should later be upgraded to industrial-strength
|
||||||
// word tokenizer, that uses much more than space
|
// word tokenizer, that uses much more than space
|
||||||
// to break words.
|
// to break words.
|
||||||
|
|
||||||
conditions := sq.And{}
|
conditions := sq.And{}
|
||||||
|
|
||||||
for _, word := range strings.Split(strings.TrimSpace(term), " ") {
|
for _, word := range strings.Split(strings.TrimSpace(term), " ") {
|
||||||
conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"})
|
conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"})
|
||||||
}
|
}
|
||||||
|
|
||||||
query = query.Where(conditions)
|
query = query.Where(conditions)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rows, err := query.Query()
|
rows, err := query.Query()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -825,8 +825,8 @@ func (s *SQLStore) SaveMember(bm *model.BoardMember) (*model.BoardMember, error)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLStore) SearchBoardsForUser(term string, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
func (s *SQLStore) SearchBoardsForUser(term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
|
||||||
return s.searchBoardsForUser(s.db, term, userID, includePublicBoards)
|
return s.searchBoardsForUser(s.db, term, searchField, userID, includePublicBoards)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ type Store interface {
|
|||||||
GetMembersForBoard(boardID string) ([]*model.BoardMember, error)
|
GetMembersForBoard(boardID string) ([]*model.BoardMember, error)
|
||||||
GetMembersForUser(userID string) ([]*model.BoardMember, error)
|
GetMembersForUser(userID string) ([]*model.BoardMember, error)
|
||||||
CanSeeUser(seerID string, seenID string) (bool, error)
|
CanSeeUser(seerID string, seenID string) (bool, error)
|
||||||
SearchBoardsForUser(term, userID string, includePublicBoards bool) ([]*model.Board, error)
|
SearchBoardsForUser(term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error)
|
||||||
SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error)
|
SearchBoardsForUserInTeam(teamID, term, userID string) ([]*model.Board, error)
|
||||||
|
|
||||||
// @withTransaction
|
// @withTransaction
|
||||||
|
@ -796,7 +796,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
userID := "user-id-1"
|
userID := "user-id-1"
|
||||||
|
|
||||||
t.Run("should return empty if user is not a member of any board and there are no public boards on the team", func(t *testing.T) {
|
t.Run("should return empty if user is not a member of any board and there are no public boards on the team", func(t *testing.T) {
|
||||||
boards, err := store.SearchBoardsForUser("", userID, true)
|
boards, err := store.SearchBoardsForUser("", model.BoardSearchFieldTitle, userID, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, boards)
|
require.Empty(t, boards)
|
||||||
})
|
})
|
||||||
@ -806,6 +806,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
Type: model.BoardTypeOpen,
|
Type: model.BoardTypeOpen,
|
||||||
Title: "Public Board with admin",
|
Title: "Public Board with admin",
|
||||||
|
Properties: map[string]any{"foo": "bar1"},
|
||||||
}
|
}
|
||||||
_, _, err := store.InsertBoardWithAdmin(board1, userID)
|
_, _, err := store.InsertBoardWithAdmin(board1, userID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -815,6 +816,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
Type: model.BoardTypeOpen,
|
Type: model.BoardTypeOpen,
|
||||||
Title: "Public Board",
|
Title: "Public Board",
|
||||||
|
Properties: map[string]any{"foo": "bar2"},
|
||||||
}
|
}
|
||||||
_, err = store.InsertBoard(board2, userID)
|
_, err = store.InsertBoard(board2, userID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -851,6 +853,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID string
|
TeamID string
|
||||||
UserID string
|
UserID string
|
||||||
Term string
|
Term string
|
||||||
|
SearchField model.BoardSearchField
|
||||||
IncludePublic bool
|
IncludePublic bool
|
||||||
ExpectedBoardIDs []string
|
ExpectedBoardIDs []string
|
||||||
}{
|
}{
|
||||||
@ -859,6 +862,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "",
|
Term: "",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
IncludePublic: true,
|
IncludePublic: true,
|
||||||
ExpectedBoardIDs: []string{board1.ID, board2.ID, board3.ID, board5.ID},
|
ExpectedBoardIDs: []string{board1.ID, board2.ID, board3.ID, board5.ID},
|
||||||
},
|
},
|
||||||
@ -867,6 +871,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "board",
|
Term: "board",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
IncludePublic: true,
|
IncludePublic: true,
|
||||||
ExpectedBoardIDs: []string{board1.ID, board2.ID, board3.ID, board5.ID},
|
ExpectedBoardIDs: []string{board1.ID, board2.ID, board3.ID, board5.ID},
|
||||||
},
|
},
|
||||||
@ -875,6 +880,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "board",
|
Term: "board",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
IncludePublic: false,
|
IncludePublic: false,
|
||||||
ExpectedBoardIDs: []string{board1.ID, board3.ID, board5.ID},
|
ExpectedBoardIDs: []string{board1.ID, board3.ID, board5.ID},
|
||||||
},
|
},
|
||||||
@ -883,6 +889,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "public",
|
Term: "public",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
IncludePublic: true,
|
IncludePublic: true,
|
||||||
ExpectedBoardIDs: []string{board1.ID, board2.ID, board5.ID},
|
ExpectedBoardIDs: []string{board1.ID, board2.ID, board5.ID},
|
||||||
},
|
},
|
||||||
@ -891,6 +898,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID1,
|
TeamID: teamID1,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "priv",
|
Term: "priv",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
IncludePublic: true,
|
IncludePublic: true,
|
||||||
ExpectedBoardIDs: []string{board3.ID},
|
ExpectedBoardIDs: []string{board3.ID},
|
||||||
},
|
},
|
||||||
@ -899,6 +907,25 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
TeamID: teamID2,
|
TeamID: teamID2,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Term: "non-matching-term",
|
Term: "non-matching-term",
|
||||||
|
SearchField: model.BoardSearchFieldTitle,
|
||||||
|
IncludePublic: true,
|
||||||
|
ExpectedBoardIDs: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "should find all boards with a named property",
|
||||||
|
TeamID: teamID1,
|
||||||
|
UserID: userID,
|
||||||
|
Term: "foo",
|
||||||
|
SearchField: model.BoardSearchFieldPropertyName,
|
||||||
|
IncludePublic: true,
|
||||||
|
ExpectedBoardIDs: []string{board1.ID, board2.ID},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "should find no boards with a non-existing named property",
|
||||||
|
TeamID: teamID1,
|
||||||
|
UserID: userID,
|
||||||
|
Term: "bogus",
|
||||||
|
SearchField: model.BoardSearchFieldPropertyName,
|
||||||
IncludePublic: true,
|
IncludePublic: true,
|
||||||
ExpectedBoardIDs: []string{},
|
ExpectedBoardIDs: []string{},
|
||||||
},
|
},
|
||||||
@ -906,7 +933,7 @@ func testSearchBoardsForUser(t *testing.T, store store.Store) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.Name, func(t *testing.T) {
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
boards, err := store.SearchBoardsForUser(tc.Term, tc.UserID, tc.IncludePublic)
|
boards, err := store.SearchBoardsForUser(tc.Term, tc.SearchField, tc.UserID, tc.IncludePublic)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
boardIDs := []string{}
|
boardIDs := []string{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user