The rule editor's value box built its suggestions from libraryStore's whole-library arrays, which made it one more reason to load every track at startup, and left it empty when they had not loaded. SuggestSmartPlaylistValues answers with up to 50 distinct values of a field that contain the typed text, from the same joined row the rules match against, so a suggestion is always something a rule can match. yj-combobox announces its filter text so the editor can ask, debounced and cached per field and text. Refs #279
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package smartplaylist
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
"testing"
|
|
|
|
"yellowjacket/backend/database"
|
|
)
|
|
|
|
// The rule editor's value box asks the backend for what matches the
|
|
// text typed (#279), rather than building every list from the whole
|
|
// library loaded into the frontend.
|
|
func TestSuggestValues(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := database.NewTestDB(t)
|
|
seedSmartPlaylistData(t, db)
|
|
|
|
cases := []struct {
|
|
field, needle string
|
|
want []string
|
|
}{
|
|
// Case-insensitive substring, distinct, sorted.
|
|
{"artist", "q", []string{"QOTSA", "Queen"}},
|
|
{"album", "OPERA", []string{"A Night at the Opera"}},
|
|
// Genres come from the genre table, one value per genre, not
|
|
// from a concatenated per-track column.
|
|
{"genre", "rock", []string{
|
|
"Funk Rock", "Hard Rock", "Progressive Rock", "Rock", "Stoner Rock",
|
|
}},
|
|
// Years are numbers and are suggested as their text.
|
|
{"year", "199", []string{"1990", "1991"}},
|
|
// The needle is literal: a LIKE wildcard in it matches only itself.
|
|
{"title", "%", []string{}},
|
|
{"composer", "_", []string{}},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
got, err := SuggestValues(db, tc.field, tc.needle)
|
|
if err != nil {
|
|
t.Fatalf("SuggestValues(%q, %q): %v", tc.field, tc.needle, err)
|
|
}
|
|
|
|
if !slices.Equal(got, tc.want) {
|
|
t.Errorf("SuggestValues(%q, %q) = %q, want %q", tc.field, tc.needle, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSuggestValuesRefusesFieldsItDoesNotSuggest(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := database.NewTestDB(t)
|
|
|
|
for _, field := range []string{"duration", "file_path", "title; DROP TABLE x"} {
|
|
if _, err := SuggestValues(db, field, ""); !errors.Is(err, errNoSuggestions) {
|
|
t.Errorf("SuggestValues(%q) err = %v, want errNoSuggestions", field, err)
|
|
}
|
|
}
|
|
}
|