04fa9222d8
Add 33 new test functions covering annotations, undo system, history formatting, relative date display, and weekday parsing pipeline. Fix ISO date parsing to use ParseInLocation instead of Parse to respect the parser's timezone context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
179 lines
4.6 KiB
Go
179 lines
4.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestAnnotate(t *testing.T) {
|
|
task, err := CreateTask("Annotation test task")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { task.Delete(true) }()
|
|
|
|
// Initially no annotations
|
|
if len(task.Annotations) != 0 {
|
|
t.Fatalf("new task should have 0 annotations, got %d", len(task.Annotations))
|
|
}
|
|
|
|
// Add first annotation
|
|
if err := task.Annotate("First note"); err != nil {
|
|
t.Fatalf("Annotate failed: %v", err)
|
|
}
|
|
if len(task.Annotations) != 1 {
|
|
t.Fatalf("expected 1 annotation, got %d", len(task.Annotations))
|
|
}
|
|
if task.Annotations[0].Text != "First note" {
|
|
t.Errorf("annotation text = %q, want %q", task.Annotations[0].Text, "First note")
|
|
}
|
|
if task.Annotations[0].Timestamp == 0 {
|
|
t.Error("annotation timestamp should be non-zero")
|
|
}
|
|
|
|
// Add second annotation
|
|
if err := task.Annotate("Second note"); err != nil {
|
|
t.Fatalf("Annotate failed: %v", err)
|
|
}
|
|
if len(task.Annotations) != 2 {
|
|
t.Fatalf("expected 2 annotations, got %d", len(task.Annotations))
|
|
}
|
|
if task.Annotations[1].Text != "Second note" {
|
|
t.Errorf("second annotation text = %q, want %q", task.Annotations[1].Text, "Second note")
|
|
}
|
|
}
|
|
|
|
func TestAnnotate_Persistence(t *testing.T) {
|
|
task, err := CreateTask("Annotation persistence test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { task.Delete(true) }()
|
|
|
|
if err := task.Annotate("Persisted note"); err != nil {
|
|
t.Fatalf("Annotate failed: %v", err)
|
|
}
|
|
|
|
// Reload from DB
|
|
loaded, err := GetTask(task.UUID)
|
|
if err != nil {
|
|
t.Fatalf("GetTask failed: %v", err)
|
|
}
|
|
if len(loaded.Annotations) != 1 {
|
|
t.Fatalf("loaded task: expected 1 annotation, got %d", len(loaded.Annotations))
|
|
}
|
|
if loaded.Annotations[0].Text != "Persisted note" {
|
|
t.Errorf("loaded annotation text = %q, want %q", loaded.Annotations[0].Text, "Persisted note")
|
|
}
|
|
}
|
|
|
|
func TestAnnotate_TimestampOrdering(t *testing.T) {
|
|
origTimeNow := timeNow
|
|
defer func() { timeNow = origTimeNow }()
|
|
|
|
task, err := CreateTask("Timestamp ordering test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { timeNow = origTimeNow; task.Delete(true) }()
|
|
|
|
// Add annotations at different times
|
|
t1 := time.Date(2026, 1, 1, 10, 0, 0, 0, time.UTC)
|
|
t2 := time.Date(2026, 1, 1, 11, 0, 0, 0, time.UTC)
|
|
|
|
timeNow = func() time.Time { return t1 }
|
|
task.Annotate("First")
|
|
|
|
timeNow = func() time.Time { return t2 }
|
|
task.Annotate("Second")
|
|
|
|
if task.Annotations[0].Timestamp >= task.Annotations[1].Timestamp {
|
|
t.Error("annotations should be in chronological order")
|
|
}
|
|
}
|
|
|
|
func TestDenotate(t *testing.T) {
|
|
task, err := CreateTask("Denotate test task")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { task.Delete(true) }()
|
|
|
|
task.Annotate("First")
|
|
task.Annotate("Second")
|
|
task.Annotate("Third")
|
|
|
|
// Denotate removes the last
|
|
removed, err := task.Denotate()
|
|
if err != nil {
|
|
t.Fatalf("Denotate failed: %v", err)
|
|
}
|
|
if removed.Text != "Third" {
|
|
t.Errorf("removed text = %q, want %q", removed.Text, "Third")
|
|
}
|
|
if len(task.Annotations) != 2 {
|
|
t.Fatalf("expected 2 annotations after denotate, got %d", len(task.Annotations))
|
|
}
|
|
|
|
// Remove second
|
|
removed, err = task.Denotate()
|
|
if err != nil {
|
|
t.Fatalf("Denotate failed: %v", err)
|
|
}
|
|
if removed.Text != "Second" {
|
|
t.Errorf("removed text = %q, want %q", removed.Text, "Second")
|
|
}
|
|
|
|
// Remove first
|
|
removed, err = task.Denotate()
|
|
if err != nil {
|
|
t.Fatalf("Denotate failed: %v", err)
|
|
}
|
|
if removed.Text != "First" {
|
|
t.Errorf("removed text = %q, want %q", removed.Text, "First")
|
|
}
|
|
|
|
// Nothing left — should error
|
|
_, err = task.Denotate()
|
|
if err == nil {
|
|
t.Error("Denotate on empty annotations should return error")
|
|
}
|
|
}
|
|
|
|
func TestDenotate_Empty(t *testing.T) {
|
|
task, err := CreateTask("Denotate empty test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { task.Delete(true) }()
|
|
|
|
_, err = task.Denotate()
|
|
if err == nil {
|
|
t.Error("Denotate on task with no annotations should return error")
|
|
}
|
|
}
|
|
|
|
func TestDenotate_Persistence(t *testing.T) {
|
|
task, err := CreateTask("Denotate persistence test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
defer func() { task.Delete(true) }()
|
|
|
|
task.Annotate("Keep this")
|
|
task.Annotate("Remove this")
|
|
task.Denotate()
|
|
|
|
// Reload and verify
|
|
loaded, err := GetTask(task.UUID)
|
|
if err != nil {
|
|
t.Fatalf("GetTask failed: %v", err)
|
|
}
|
|
if len(loaded.Annotations) != 1 {
|
|
t.Fatalf("loaded: expected 1 annotation, got %d", len(loaded.Annotations))
|
|
}
|
|
if loaded.Annotations[0].Text != "Keep this" {
|
|
t.Errorf("remaining annotation = %q, want %q", loaded.Annotations[0].Text, "Keep this")
|
|
}
|
|
}
|