package vocab import ( "path/filepath" "testing" "gitea.parodia.dev/drwily/petal/internal/db" ) func TestPhraseKey(t *testing.T) { cases := []struct { in, want string }{ {"make a decision", "make a decision"}, {"Make A Decision", "make a decision"}, // shares one namespace with lookups {" make a\ndecision ", "make a decision"}, // the editor's whitespace {"“make a decision.”", "make a decision"}, // punctuation from the sentence around it {"can’t afford it", "can’t afford it"}, // inner marks are part of the chunk {"decision", ""}, // word choice, not a chunk — lookup's job {"", ""}, // {"...", ""}, // {"12 000", ""}, // digits aren't vocabulary {"a b c d e f g", ""}, // a clause wearing a chunk's label {"in one’s own good time again", "in one’s own good time again"}, // six words is still a chunk } for _, tc := range cases { if got := PhraseKey(tc.in); got != tc.want { t.Errorf("PhraseKey(%q) = %q, want %q", tc.in, got, tc.want) } } // The length cap counts runes, not bytes — otherwise a Portuguese chunk well // inside the limit would be dropped for being accented. accented := "ãããããã ãããããã ãããããã ãããããã ãããããã" // 34 runes, 64 bytes if got := PhraseKey(accented); got != accented { t.Errorf("PhraseKey(%d runes / %d bytes) = %q, want it kept", len([]rune(accented)), len(accented), got) } long := "ãããããããããããã ãããããããããããã ãããããããããããã ãããããããããããã ãããããããããããã ãããããããããããã" if got := PhraseKey(long); got != "" { t.Errorf("PhraseKey(%d runes) = %q, want \"\"", len([]rune(long)), got) } } func TestPlantCreatesOnceAndReportsIt(t *testing.T) { database, err := db.Open(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatalf("open db: %v", err) } t.Cleanup(func() { database.Close() }) p := Phrase{Text: "make a decision", Meaning: "why", Example: "I had to make a decision."} created, err := Plant(database, db.LocalUserID, p) if err != nil || !created { t.Fatalf("first plant: created=%v err=%v", created, err) } created, err = Plant(database, db.LocalUserID, p) if err != nil || created { t.Fatalf("second plant: created=%v err=%v, want false", created, err) } // A card that isn't plantable is a silent no-op, not an error: planting hangs // off accepting an edit, and that accept must never fail for a flashcard. created, err = Plant(database, db.LocalUserID, Phrase{Text: "decision"}) if err != nil || created { t.Fatalf("unplantable: created=%v err=%v", created, err) } var n int if err := database.QueryRow(`SELECT count(*) FROM vocab_words WHERE user_id = ?`, db.LocalUserID).Scan(&n); err != nil { t.Fatalf("count: %v", err) } if n != 1 { t.Fatalf("garden has %d cards, want 1", n) } }