Maintain saved filters in full export/import (#5465)

* Remove ellipsis from full export button
This commit is contained in:
WithoutPants
2024-11-12 16:59:28 +11:00
committed by GitHub
parent 41d1b45fb9
commit a18c538c1f
11 changed files with 484 additions and 9 deletions

19
pkg/savedfilter/export.go Normal file
View File

@@ -0,0 +1,19 @@
package savedfilter
import (
"context"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/jsonschema"
)
// ToJSON converts a SavedFilter object into its JSON equivalent.
func ToJSON(ctx context.Context, filter *models.SavedFilter) (*jsonschema.SavedFilter, error) {
return &jsonschema.SavedFilter{
Name: filter.Name,
Mode: filter.Mode,
FindFilter: filter.FindFilter,
ObjectFilter: filter.ObjectFilter,
UIOptions: filter.UIOptions,
}, nil
}

View File

@@ -0,0 +1,91 @@
package savedfilter
import (
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/jsonschema"
"github.com/stashapp/stash/pkg/models/mocks"
"github.com/stretchr/testify/assert"
"testing"
)
const (
savedFilterID = 1
noImageID = 2
errImageID = 3
errAliasID = 4
withParentsID = 5
errParentsID = 6
)
const (
filterName = "testFilter"
mode = models.FilterModeGalleries
)
var (
findFilter = models.FindFilterType{}
objectFilter = make(map[string]interface{})
uiOptions = make(map[string]interface{})
)
func createSavedFilter(id int) models.SavedFilter {
return models.SavedFilter{
ID: id,
Name: filterName,
Mode: mode,
FindFilter: &findFilter,
ObjectFilter: objectFilter,
UIOptions: uiOptions,
}
}
func createJSONSavedFilter() *jsonschema.SavedFilter {
return &jsonschema.SavedFilter{
Name: filterName,
Mode: mode,
FindFilter: &findFilter,
ObjectFilter: objectFilter,
UIOptions: uiOptions,
}
}
type testScenario struct {
savedFilter models.SavedFilter
expected *jsonschema.SavedFilter
err bool
}
var scenarios []testScenario
func initTestTable() {
scenarios = []testScenario{
{
createSavedFilter(savedFilterID),
createJSONSavedFilter(),
false,
},
}
}
func TestToJSON(t *testing.T) {
initTestTable()
db := mocks.NewDatabase()
for i, s := range scenarios {
savedFilter := s.savedFilter
json, err := ToJSON(testCtx, &savedFilter)
switch {
case !s.err && err != nil:
t.Errorf("[%d] unexpected error: %s", i, err.Error())
case s.err && err == nil:
t.Errorf("[%d] expected error not returned", i)
default:
assert.Equal(t, s.expected, json, "[%d]", i)
}
}
db.AssertExpectations(t)
}

60
pkg/savedfilter/import.go Normal file
View File

@@ -0,0 +1,60 @@
package savedfilter
import (
"context"
"fmt"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/jsonschema"
)
type ImporterReaderWriter interface {
models.SavedFilterWriter
}
type Importer struct {
ReaderWriter ImporterReaderWriter
Input jsonschema.SavedFilter
MissingRefBehaviour models.ImportMissingRefEnum
savedFilter models.SavedFilter
}
func (i *Importer) PreImport(ctx context.Context) error {
i.savedFilter = models.SavedFilter{
Name: i.Input.Name,
Mode: i.Input.Mode,
FindFilter: i.Input.FindFilter,
ObjectFilter: i.Input.ObjectFilter,
UIOptions: i.Input.UIOptions,
}
return nil
}
func (i *Importer) PostImport(ctx context.Context, id int) error {
return nil
}
func (i *Importer) Name() string {
return i.Input.Name
}
func (i *Importer) FindExistingID(ctx context.Context) (*int, error) {
// for now, assume this is only imported in full, so we don't support updating existing filters
return nil, nil
}
func (i *Importer) Create(ctx context.Context) (*int, error) {
err := i.ReaderWriter.Create(ctx, &i.savedFilter)
if err != nil {
return nil, fmt.Errorf("error creating saved filter: %v", err)
}
id := i.savedFilter.ID
return &id, nil
}
func (i *Importer) Update(ctx context.Context, id int) error {
return fmt.Errorf("updating existing saved filters is not supported")
}

View File

@@ -0,0 +1,124 @@
package savedfilter
import (
"context"
"errors"
"testing"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/models/jsonschema"
"github.com/stashapp/stash/pkg/models/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
const (
savedFilterNameErr = "savedFilterNameErr"
existingSavedFilterName = "existingSavedFilterName"
existingFilterID = 100
)
var testCtx = context.Background()
func TestImporterName(t *testing.T) {
i := Importer{
Input: jsonschema.SavedFilter{
Name: filterName,
},
}
assert.Equal(t, filterName, i.Name())
}
func TestImporterPreImport(t *testing.T) {
i := Importer{
Input: jsonschema.SavedFilter{
Name: filterName,
},
}
err := i.PreImport(testCtx)
assert.Nil(t, err)
}
func TestImporterPostImport(t *testing.T) {
db := mocks.NewDatabase()
i := Importer{
ReaderWriter: db.SavedFilter,
Input: jsonschema.SavedFilter{},
}
err := i.PostImport(testCtx, savedFilterID)
assert.Nil(t, err)
db.AssertExpectations(t)
}
func TestImporterFindExistingID(t *testing.T) {
db := mocks.NewDatabase()
i := Importer{
ReaderWriter: db.SavedFilter,
Input: jsonschema.SavedFilter{
Name: filterName,
},
}
id, err := i.FindExistingID(testCtx)
assert.Nil(t, id)
assert.Nil(t, err)
}
func TestCreate(t *testing.T) {
db := mocks.NewDatabase()
savedFilter := models.SavedFilter{
Name: filterName,
}
savedFilterErr := models.SavedFilter{
Name: savedFilterNameErr,
}
i := Importer{
ReaderWriter: db.SavedFilter,
savedFilter: savedFilter,
}
errCreate := errors.New("Create error")
db.SavedFilter.On("Create", testCtx, &savedFilter).Run(func(args mock.Arguments) {
t := args.Get(1).(*models.SavedFilter)
t.ID = savedFilterID
}).Return(nil).Once()
db.SavedFilter.On("Create", testCtx, &savedFilterErr).Return(errCreate).Once()
id, err := i.Create(testCtx)
assert.Equal(t, savedFilterID, *id)
assert.Nil(t, err)
i.savedFilter = savedFilterErr
id, err = i.Create(testCtx)
assert.Nil(t, id)
assert.NotNil(t, err)
db.AssertExpectations(t)
}
func TestUpdate(t *testing.T) {
db := mocks.NewDatabase()
savedFilterErr := models.SavedFilter{
Name: savedFilterNameErr,
}
i := Importer{
ReaderWriter: db.SavedFilter,
savedFilter: savedFilterErr,
}
// Update is not currently supported
err := i.Update(testCtx, existingFilterID)
assert.NotNil(t, err)
}