package userdict
|
|
import (
|
"encoding/json"
|
"fmt"
|
"os"
|
"path/filepath"
|
"testing"
|
)
|
|
func TestAppendNewReplacementsAppendsEnabledRulesAndPersists0600(t *testing.T) {
|
store := testStore(t)
|
|
added, err := store.AppendNewReplacements([]Replacement{
|
{From: " 点 CSV ", To: " .csv "},
|
{From: "右奥特", To: "右 Alt"},
|
})
|
if err != nil {
|
t.Fatal(err)
|
}
|
if len(added) != 2 {
|
t.Fatalf("expected 2 added entries, got %d", len(added))
|
}
|
if got := store.Apply("点 CSV 和 右奥特"); got != ".csv 和 右 Alt" {
|
t.Fatalf("unexpected applied text: %q", got)
|
}
|
|
info, err := os.Stat(store.path)
|
if err != nil {
|
t.Fatal(err)
|
}
|
if got := info.Mode().Perm(); got != 0600 {
|
t.Fatalf("expected userdict.json mode 0600, got %o", got)
|
}
|
}
|
|
func TestAppendNewReplacementsRejectsDuplicateAndConflictWithoutMutation(t *testing.T) {
|
store := testStore(t)
|
if _, err := store.AppendNewReplacements([]Replacement{{From: "麦克", To: "Mac"}}); err != nil {
|
t.Fatal(err)
|
}
|
|
if _, err := store.AppendNewReplacements([]Replacement{{From: "麦克", To: "Mac"}}); err == nil {
|
t.Fatal("expected duplicate to fail")
|
}
|
if _, err := store.AppendNewReplacements([]Replacement{{From: "麦克", To: "Mike"}}); err == nil {
|
t.Fatal("expected conflict to fail")
|
}
|
|
entries := store.GetAll()
|
if len(entries) != 1 {
|
t.Fatalf("expected dictionary to remain unchanged, got %d entries", len(entries))
|
}
|
if entries[0].From != "麦克" || entries[0].To != "Mac" {
|
t.Fatalf("unexpected entry after failed imports: %+v", entries[0])
|
}
|
}
|
|
func TestAppendNewReplacementsWriteFailureDoesNotMutateMemory(t *testing.T) {
|
store := &Store{
|
path: filepath.Join(t.TempDir(), "missing", "userdict.json"),
|
entries: []Entry{
|
{ID: 1, From: "麦克", To: "Mac", Enabled: true, CreatedAt: 1, UpdatedAt: 1},
|
},
|
}
|
|
if _, err := store.AppendNewReplacements([]Replacement{{From: "点 CSV", To: ".csv"}}); err == nil {
|
t.Fatal("expected write failure")
|
}
|
|
entries := store.GetAll()
|
if len(entries) != 1 {
|
t.Fatalf("expected memory to remain unchanged, got %d entries", len(entries))
|
}
|
if got := store.Apply("麦克 点 CSV"); got != "Mac 点 CSV" {
|
t.Fatalf("unexpected applied text after failed write: %q", got)
|
}
|
}
|
|
func TestLoadOldFromToOnlyFormatDefaultsEnabled(t *testing.T) {
|
path := filepath.Join(t.TempDir(), "userdict.json")
|
data, err := json.Marshal(map[string]any{
|
"replacements": []map[string]string{
|
{"from": "点 CSV", "to": ".csv"},
|
},
|
})
|
if err != nil {
|
t.Fatal(err)
|
}
|
if err := os.WriteFile(path, data, 0600); err != nil {
|
t.Fatal(err)
|
}
|
|
store := &Store{path: path}
|
store.load()
|
|
entries := store.GetAll()
|
if len(entries) != 1 {
|
t.Fatalf("expected one loaded entry, got %d", len(entries))
|
}
|
if !entries[0].Enabled {
|
t.Fatal("expected old format entry to default enabled")
|
}
|
if got := store.Apply("点 CSV"); got != ".csv" {
|
t.Fatalf("unexpected applied text: %q", got)
|
}
|
}
|
|
func TestGetPageClampsAndSortsNewestFirst(t *testing.T) {
|
store := testStore(t)
|
for i := 0; i < 12; i++ {
|
store.entries = append(store.entries, Entry{
|
ID: int64(i + 1),
|
From: fmt.Sprintf("from %02d", i),
|
To: fmt.Sprintf("to %02d", i),
|
Enabled: true,
|
CreatedAt: int64(1000 + i),
|
UpdatedAt: int64(1000 + i),
|
})
|
}
|
|
page := store.GetPage(2, 5)
|
if page.Total != 12 || page.TotalPages != 3 || page.Page != 2 || page.PageSize != 5 {
|
t.Fatalf("unexpected page metadata: %+v", page)
|
}
|
if len(page.Entries) != 5 || page.Entries[0].From != "from 06" || page.Entries[4].From != "from 02" {
|
t.Fatalf("unexpected page entries: %+v", page.Entries)
|
}
|
|
last := store.GetPage(99, 5)
|
if last.Page != 3 || len(last.Entries) != 2 || last.Entries[0].From != "from 01" {
|
t.Fatalf("expected clamped last page, got %+v", last)
|
}
|
|
defaultSize := store.GetPage(1, 0)
|
if defaultSize.PageSize != defaultPageSize {
|
t.Fatalf("expected default page size %d, got %d", defaultPageSize, defaultSize.PageSize)
|
}
|
|
limitedSize := store.GetPage(1, maxPageSize+1)
|
if limitedSize.PageSize != maxPageSize {
|
t.Fatalf("expected max page size %d, got %d", maxPageSize, limitedSize.PageSize)
|
}
|
}
|
|
func TestGetPageHandlesEmptyDictionary(t *testing.T) {
|
store := testStore(t)
|
|
page := store.GetPage(99, 100)
|
if page.Total != 0 || page.TotalPages != 0 || page.Page != 1 || len(page.Entries) != 0 {
|
t.Fatalf("unexpected empty page: %+v", page)
|
}
|
}
|
|
func testStore(t *testing.T) *Store {
|
t.Helper()
|
return &Store{
|
path: filepath.Join(t.TempDir(), "userdict.json"),
|
}
|
}
|