173 lines
5.4 KiB
Go
173 lines
5.4 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
|
"github.com/kandev/kandev/internal/user/models"
|
|
)
|
|
|
|
type settingsScanner struct {
|
|
raw string
|
|
}
|
|
|
|
func (s settingsScanner) Scan(dest ...any) error {
|
|
*(dest[0].(*string)) = s.raw
|
|
*(dest[1].(*time.Time)) = time.Time{}
|
|
return nil
|
|
}
|
|
|
|
func TestScanUserSettingsChangesPanelLayoutDefault(t *testing.T) {
|
|
t.Run("empty settings default to tree", func(t *testing.T) {
|
|
settings, err := scanUserSettings(settingsScanner{raw: "{}"}, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if settings.ChangesPanelLayout != "tree" {
|
|
t.Fatalf("expected ChangesPanelLayout=tree, got %q", settings.ChangesPanelLayout)
|
|
}
|
|
})
|
|
|
|
t.Run("missing layout defaults to tree", func(t *testing.T) {
|
|
settings, err := scanUserSettings(settingsScanner{raw: `{"chat_submit_key":"cmd_enter"}`}, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if settings.ChangesPanelLayout != "tree" {
|
|
t.Fatalf("expected ChangesPanelLayout=tree, got %q", settings.ChangesPanelLayout)
|
|
}
|
|
})
|
|
|
|
t.Run("explicit flat is preserved", func(t *testing.T) {
|
|
settings, err := scanUserSettings(settingsScanner{raw: `{"changes_panel_layout":"flat"}`}, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if settings.ChangesPanelLayout != "flat" {
|
|
t.Fatalf("expected ChangesPanelLayout=flat, got %q", settings.ChangesPanelLayout)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestScanUserSettingsSystemMetricsDisplayDefault(t *testing.T) {
|
|
settings, err := scanUserSettings(settingsScanner{raw: "{}"}, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if settings.SystemMetricsDisplay.ShowInTopbar {
|
|
t.Fatal("system metrics display should default to disabled")
|
|
}
|
|
|
|
settings, err = scanUserSettings(settingsScanner{raw: `{"system_metrics_display":{"show_in_topbar":true}}`}, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !settings.SystemMetricsDisplay.ShowInTopbar {
|
|
t.Fatal("expected stored system metrics display preference")
|
|
}
|
|
}
|
|
|
|
func TestSQLiteRepositorySystemMetricsDisplayRoundTrip(t *testing.T) {
|
|
conn, err := sqlx.Open("sqlite3", ":memory:")
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
conn.SetMaxOpenConns(1)
|
|
t.Cleanup(func() { _ = conn.Close() })
|
|
repo, err := newSQLiteRepositoryWithDB(conn, conn)
|
|
if err != nil {
|
|
t.Fatalf("new repo: %v", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
settings, err := repo.GetUserSettings(ctx, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("get defaults: %v", err)
|
|
}
|
|
settings.SystemMetricsDisplay = models.SystemMetricsDisplaySettings{ShowInTopbar: true}
|
|
if err := repo.UpsertUserSettings(ctx, settings); err != nil {
|
|
t.Fatalf("upsert settings: %v", err)
|
|
}
|
|
got, err := repo.GetUserSettings(ctx, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("get settings: %v", err)
|
|
}
|
|
if !got.SystemMetricsDisplay.ShowInTopbar {
|
|
t.Fatal("expected system metrics display preference to round-trip")
|
|
}
|
|
}
|
|
|
|
func TestSQLiteRepositorySidebarViewStateRoundTrip(t *testing.T) {
|
|
conn, err := sqlx.Open("sqlite3", ":memory:")
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
conn.SetMaxOpenConns(1)
|
|
t.Cleanup(func() { _ = conn.Close() })
|
|
repo, err := newSQLiteRepositoryWithDB(conn, conn)
|
|
if err != nil {
|
|
t.Fatalf("new repo: %v", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
settings, err := repo.GetUserSettings(ctx, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("get defaults: %v", err)
|
|
}
|
|
settings.SidebarActiveViewID = "view-1"
|
|
settings.SidebarTaskPrefs = models.SidebarTaskPrefs{
|
|
PinnedTaskIDs: []string{"task-1"},
|
|
OrderedTaskIDs: []string{"task-2", "task-1"},
|
|
SubtaskOrderByParentID: map[string][]string{"task-1": {"sub-1"}},
|
|
}
|
|
settings.TaskCreateLastUsed = models.TaskCreateLastUsed{
|
|
RepositoryID: "repo-1",
|
|
Branch: "main",
|
|
AgentProfileID: "agent-1",
|
|
ExecutorProfileID: "exec-1",
|
|
}
|
|
settings.JiraSavedViews = json.RawMessage(`[{"id":"view-1"}]`)
|
|
settings.GitLabSavedPresets = json.RawMessage(`[{"id":"preset-1"}]`)
|
|
settings.SidebarDraft = &models.SidebarViewDraft{
|
|
BaseViewID: "view-1",
|
|
Filters: []models.SidebarViewClause{{
|
|
ID: "clause-1",
|
|
Dimension: "titleMatch",
|
|
Op: "matches",
|
|
Value: json.RawMessage(`"bug"`),
|
|
}},
|
|
Sort: models.SidebarViewSort{Key: "updatedAt", Direction: "desc"},
|
|
Group: "workflow",
|
|
}
|
|
if err := repo.UpsertUserSettings(ctx, settings); err != nil {
|
|
t.Fatalf("upsert settings: %v", err)
|
|
}
|
|
got, err := repo.GetUserSettings(ctx, DefaultUserID)
|
|
if err != nil {
|
|
t.Fatalf("get settings: %v", err)
|
|
}
|
|
if got.SidebarActiveViewID != "view-1" {
|
|
t.Fatalf("expected active view to round-trip, got %q", got.SidebarActiveViewID)
|
|
}
|
|
if got.SidebarDraft == nil || got.SidebarDraft.Group != "workflow" {
|
|
t.Fatalf("expected sidebar draft to round-trip, got %+v", got.SidebarDraft)
|
|
}
|
|
if got.SidebarTaskPrefs.PinnedTaskIDs[0] != "task-1" {
|
|
t.Fatalf("expected sidebar task prefs to round-trip, got %+v", got.SidebarTaskPrefs)
|
|
}
|
|
if got.TaskCreateLastUsed.Branch != "main" {
|
|
t.Fatalf("expected task-create prefs to round-trip, got %+v", got.TaskCreateLastUsed)
|
|
}
|
|
if string(got.JiraSavedViews) != `[{"id":"view-1"}]` {
|
|
t.Fatalf("expected Jira saved views to round-trip, got %s", string(got.JiraSavedViews))
|
|
}
|
|
if string(got.GitLabSavedPresets) != `[{"id":"preset-1"}]` {
|
|
t.Fatalf("expected GitLab presets to round-trip, got %s", string(got.GitLabSavedPresets))
|
|
}
|
|
}
|