Skip to content

Commit

Permalink
feat: add inverse search filter to bounty cards
Browse files Browse the repository at this point in the history
  • Loading branch information
aliraza556 committed Jan 31, 2025
1 parent 9b76cea commit cbc422e
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 1 deletion.
7 changes: 6 additions & 1 deletion db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2051,6 +2051,7 @@ func (db database) GetWorkspaceBountyCardsData(r *http.Request) []NewBounty {
keys := r.URL.Query()
_, _, sortBy, direction, search := utils.GetPaginationParams(r)
workspaceUuid := keys.Get("workspace_uuid")
inverseSearch := keys.Get("inverse_search") == "true"

orderQuery := ""
searchQuery := ""
Expand All @@ -2071,7 +2072,11 @@ func (db database) GetWorkspaceBountyCardsData(r *http.Request) []NewBounty {
}

if search != "" {
searchQuery = fmt.Sprintf("AND LOWER(title) LIKE %s", "'%"+strings.ToLower(search)+"%'")
if inverseSearch {
searchQuery = fmt.Sprintf("AND LOWER(title) NOT LIKE %s", "'%"+strings.ToLower(search)+"%'")
} else {
searchQuery = fmt.Sprintf("AND LOWER(title) LIKE %s", "'%"+strings.ToLower(search)+"%'")
}
}

if workspaceUuid != "" {
Expand Down
159 changes: 159 additions & 0 deletions handlers/bounty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"net/http/httptest"
"net/url"
"os"
"sort"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -4371,3 +4372,161 @@ func TestDeleteBountyTiming(t *testing.T) {
assert.Nil(t, timing)
})
}


func TestInverseSearchBountyCards(t *testing.T) {
teardownSuite := SetupSuite(t)
defer teardownSuite(t)

mockHttpClient := mocks.NewHttpClient(t)
bHandler := NewBountyHandler(mockHttpClient, db.TestDB)

db.CleanTestData()

workspace := db.Workspace{
ID: 1,
Uuid: "test-workspace-uuid",
Name: "Test Workspace",
Description: "Test Workspace Description",
OwnerPubKey: "test-owner",
}
_, err := db.TestDB.CreateOrEditWorkspace(workspace)
assert.NoError(t, err)

phase := db.FeaturePhase{
Uuid: "test-phase-uuid",
Name: "Test Phase",
FeatureUuid: "test-feature-uuid",
}
db.TestDB.CreateOrEditFeaturePhase(phase)

feature := db.WorkspaceFeatures{
Uuid: "test-feature-uuid",
Name: "Test Feature",
WorkspaceUuid: workspace.Uuid,
}
db.TestDB.CreateOrEditFeature(feature)

now := time.Now()

bounties := []db.NewBounty{
{
ID: 1,
Type: "coding",
Title: "Backend Task",
Description: "Backend development task",
WorkspaceUuid: workspace.Uuid,
PhaseUuid: phase.Uuid,
Show: true,
Created: now.Unix(),
Updated: &now,
OwnerID: "test-owner",
},
{
ID: 2,
Type: "coding",
Title: "Frontend Task",
Description: "Frontend development task",
WorkspaceUuid: workspace.Uuid,
PhaseUuid: phase.Uuid,
Show: true,
Created: now.Unix(),
Updated: &now,
OwnerID: "test-owner",
},
{
ID: 3,
Type: "coding",
Title: "Documentation Task",
Description: "Documentation writing task",
WorkspaceUuid: workspace.Uuid,
PhaseUuid: phase.Uuid,
Show: true,
Created: now.Unix(),
Updated: &now,
OwnerID: "test-owner",
},
}

for _, b := range bounties {
_, err := db.TestDB.CreateOrEditBounty(b)
assert.NoError(t, err)
}

testCases := []struct {
name string
searchTerm string
inverseSearch string
expectedCount int
expectedTitles []string
}{
{
name: "inverse search excludes matching bounties",
searchTerm: "Frontend",
inverseSearch: "true",
expectedCount: 2,
expectedTitles: []string{"Backend Task", "Documentation Task"},
},
{
name: "regular search includes matching bounties",
searchTerm: "Frontend",
inverseSearch: "false",
expectedCount: 1,
expectedTitles: []string{"Frontend Task"},
},
{
name: "inverse search with common term",
searchTerm: "Task",
inverseSearch: "true",
expectedCount: 0,
expectedTitles: []string{},
},
{
name: "case insensitive inverse search",
searchTerm: "BACKEND",
inverseSearch: "true",
expectedCount: 2,
expectedTitles: []string{"Frontend Task", "Documentation Task"},
},
{
name: "empty search term returns all bounties",
searchTerm: "",
inverseSearch: "true",
expectedCount: 3,
expectedTitles: []string{"Backend Task", "Frontend Task", "Documentation Task"},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.GetBountyCards)

url := fmt.Sprintf("/gobounties/bounty-cards?workspace_uuid=%s&search=%s&inverse_search=%s",
workspace.Uuid, url.QueryEscape(tc.searchTerm), tc.inverseSearch)
req, err := http.NewRequest(http.MethodGet, url, nil)
assert.NoError(t, err)

handler.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)

var response []db.BountyCard
err = json.Unmarshal(rr.Body.Bytes(), &response)
assert.NoError(t, err)

assert.Equal(t, tc.expectedCount, len(response),
"Expected %d bounties but got %d", tc.expectedCount, len(response))

responseTitles := make([]string, len(response))
for i, card := range response {
responseTitles[i] = card.Title
}
sort.Strings(responseTitles)
sort.Strings(tc.expectedTitles)

assert.Equal(t, tc.expectedTitles, responseTitles,
"Expected titles do not match response titles")
})
}
}

0 comments on commit cbc422e

Please sign in to comment.