Skip to content

Commit

Permalink
Write tests for searching
Browse files Browse the repository at this point in the history
  • Loading branch information
viktorstrate committed Sep 2, 2021
1 parent 0ae3482 commit adfcf33
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 66 deletions.
73 changes: 73 additions & 0 deletions api/graphql/models/actions/search_actions.go
@@ -0,0 +1,73 @@
package actions

import (
"github.com/photoview/photoview/api/graphql/models"
"github.com/pkg/errors"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

func Search(db *gorm.DB, query string, userID int, _limitMedia *int, _limitAlbums *int) (*models.SearchResult, error) {
limitMedia := 10
limitAlbums := 10

if _limitMedia != nil {
limitMedia = *_limitMedia
}

if _limitAlbums != nil {
limitAlbums = *_limitAlbums
}

wildQuery := "%" + query + "%"

var media []*models.Media

userSubquery := db.Table("user_albums").Where("user_id = ?", userID)
if db.Dialector.Name() == "postgres" {
userSubquery = userSubquery.Where("album_id = \"Album\".id")
} else {
userSubquery = userSubquery.Where("album_id = Album.id")
}

err := db.Joins("Album").
Where("EXISTS (?)", userSubquery).
Where("media.title LIKE ? OR media.path LIKE ?", wildQuery, wildQuery).
Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "(CASE WHEN media.title LIKE ? THEN 2 WHEN media.path LIKE ? THEN 1 END) DESC",
Vars: []interface{}{wildQuery, wildQuery},
WithoutParentheses: true},
}).
Limit(limitMedia).Find(&media).Error

if err != nil {
return nil, errors.Wrapf(err, "searching media")
}

var albums []*models.Album

err = db.
Where("EXISTS (?)", db.Table("user_albums").Where("user_id = ?", userID).Where("album_id = albums.id")).
Where("albums.title LIKE ? OR albums.path LIKE ?", wildQuery, wildQuery).
Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "(CASE WHEN albums.title LIKE ? THEN 2 WHEN albums.path LIKE ? THEN 1 END) DESC",
Vars: []interface{}{wildQuery, wildQuery},
WithoutParentheses: true},
}).
Limit(limitAlbums).
Find(&albums).Error

if err != nil {
return nil, errors.Wrapf(err, "searching albums")
}

result := models.SearchResult{
Query: query,
Media: media,
Albums: albums,
}

return &result, nil
}
102 changes: 102 additions & 0 deletions api/graphql/models/actions/search_actions_test.go
@@ -0,0 +1,102 @@
package actions_test

import (
"fmt"
"testing"

"github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/graphql/models/actions"
"github.com/photoview/photoview/api/test_utils"
"github.com/stretchr/testify/assert"
)

func TestSearch(t *testing.T) {
db := test_utils.DatabaseTest(t)

user, err := models.RegisterUser(db, "user", nil, true)
assert.NoError(t, err)

rootAlbum := models.Album{
Title: "root_album",
Path: "/media/",
}

assert.NoError(t, db.Create(&rootAlbum).Error)
assert.NoError(t, db.Model(&rootAlbum).Association("Owners").Append(user))

type Result struct {
ID int
UserID int
AlbumID int
}

mediaTitles := []string{
"SOME_IMAGE.jpg",
"imageA.jpg",
"imageB.jpg",
"imageC.jpg",
"movie.mp4",
"person.png",
"123.png",
"ABC.gif",
"dog.mov",
"cat.mov",
"IMG_3255.JPG",
"IMG_5532.JPG",
"IMG_5533.JPG",
"IMG_5534.JPG",
"IMG_5535.JPG",
"IMG_5536.JPG",
}

for _, mediaTitle := range mediaTitles {
image := models.Media{
Title: mediaTitle,
Path: fmt.Sprintf("/media/%s", mediaTitle),
AlbumID: rootAlbum.ID,
}
assert.NoError(t, db.Create(&image).Error)
}

type SearchTest = struct {
query string
userID int
limitMedia *int
limitAlbum *int

expectedMediaCount int
expectedAlbumCount int
}

searchTests := []SearchTest{
{
query: "image",
userID: user.ID,
expectedMediaCount: 4,
expectedAlbumCount: 0,
},
{
query: "g",
userID: user.ID,
expectedMediaCount: 10,
expectedAlbumCount: 0,
},
{
query: "media",
userID: user.ID,
expectedMediaCount: 10,
expectedAlbumCount: 1,
},
}

for _, test := range searchTests {
t.Run(fmt.Sprintf("Search query: '%s'", test.query), func(t *testing.T) {
result, err := actions.Search(db, test.query, test.userID, test.limitMedia, test.limitAlbum)
assert.NoError(t, err)

assert.Equal(t, result.Query, test.query)
assert.Len(t, result.Albums, test.expectedAlbumCount)
assert.Len(t, result.Media, test.expectedMediaCount)
})
}
}
2 changes: 1 addition & 1 deletion api/graphql/models/media.go
Expand Up @@ -71,7 +71,7 @@ type MediaURL struct {
Model
MediaID int `gorm:"not null;index"`
Media *Media `gorm:"constraint:OnDelete:CASCADE;"`
MediaName string `gorm:"not null"`
MediaName string `gorm:"not null;index"`
Width int `gorm:"not null"`
Height int `gorm:"not null"`
Purpose MediaPurpose `gorm:"not null;index"`
Expand Down
68 changes: 3 additions & 65 deletions api/graphql/resolvers/search.go
Expand Up @@ -4,78 +4,16 @@ import (
"context"

"github.com/photoview/photoview/api/graphql/auth"
"github.com/pkg/errors"
"gorm.io/gorm/clause"
"github.com/photoview/photoview/api/graphql/models/actions"

"github.com/photoview/photoview/api/graphql/models"
)

func (r *Resolver) Search(ctx context.Context, query string, _limitMedia *int, _limitAlbums *int) (*models.SearchResult, error) {
func (r *Resolver) Search(ctx context.Context, query string, limitMedia *int, limitAlbums *int) (*models.SearchResult, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}

limitMedia := 10
limitAlbums := 10

if _limitMedia != nil {
limitMedia = *_limitMedia
}

if _limitAlbums != nil {
limitAlbums = *_limitAlbums
}

wildQuery := "%" + query + "%"

var media []*models.Media

userSubquery := r.Database.Table("user_albums").Where("user_id = ?", user.ID)
if r.Database.Dialector.Name() == "postgres" {
userSubquery = userSubquery.Where("album_id = \"Album\".id")
} else {
userSubquery = userSubquery.Where("album_id = Album.id")
}

err := r.Database.Joins("Album").
Where("EXISTS (?)", userSubquery).
Where("media.title LIKE ? OR media.path LIKE ?", wildQuery, wildQuery).
Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "(CASE WHEN media.title LIKE ? THEN 2 WHEN media.path LIKE ? THEN 1 END) DESC",
Vars: []interface{}{wildQuery, wildQuery},
WithoutParentheses: true},
}).
Limit(limitMedia).Find(&media).Error

if err != nil {
return nil, errors.Wrapf(err, "searching media")
}

var albums []*models.Album

err = r.Database.
Where("EXISTS (?)", r.Database.Table("user_albums").Where("user_id = ?", user.ID).Where("album_id = albums.id")).
Where("albums.title LIKE ? OR albums.path LIKE ?", wildQuery, wildQuery).
Clauses(clause.OrderBy{
Expression: clause.Expr{
SQL: "(CASE WHEN albums.title LIKE ? THEN 2 WHEN albums.path LIKE ? THEN 1 END) DESC",
Vars: []interface{}{wildQuery, wildQuery},
WithoutParentheses: true},
}).
Limit(limitAlbums).
Find(&albums).Error

if err != nil {
return nil, errors.Wrapf(err, "searching albums")
}

result := models.SearchResult{
Query: query,
Media: media,
Albums: albums,
}

return &result, nil
return actions.Search(r.Database, query, user.ID, limitMedia, limitAlbums)
}

0 comments on commit adfcf33

Please sign in to comment.