1
Fork 0

Write tests for searching

This commit is contained in:
viktorstrate 2021-09-02 18:09:37 +02:00
parent 0ae34829e2
commit adfcf33e79
No known key found for this signature in database
GPG Key ID: 3F855605109C1E8A
4 changed files with 179 additions and 66 deletions

View File

@ -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
}

View File

@ -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)
})
}
}

View File

@ -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"`

View File

@ -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)
}