Add YouTrack pull/push sync with project settings and time tracking.
Wire manual Y menu and CLI sync for issues and work items, persist per-project credentials, and keep local edits until an explicit push. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"task/internal/ticket"
|
||||
)
|
||||
@@ -65,6 +66,43 @@ func TestJSONStoreCreateListUpdate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateAfterMarkSyncedIsDirty(t *testing.T) {
|
||||
store := ticket.NewJSONStore(t.TempDir())
|
||||
created, err := store.Create(ticket.Ticket{
|
||||
Title: "Synced", ProjectID: "inbox", Status: ticket.StatusTodo,
|
||||
Source: ticket.SourceYouTrack, ExternalID: "TAS-1",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := store.MarkSynced(created.ID); err != nil {
|
||||
t.Fatalf("MarkSynced: %v", err)
|
||||
}
|
||||
synced, err := store.Get(created.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if synced.UpdatedAt.After(synced.SyncedAt) {
|
||||
t.Fatalf("freshly marked synced should not be dirty: updated=%v syncedAt=%v",
|
||||
synced.UpdatedAt, synced.SyncedAt)
|
||||
}
|
||||
|
||||
// Simulate UI edit: copy ticket (SyncedAt == UpdatedAt) and change title.
|
||||
edited := synced
|
||||
edited.Title = "Edited locally"
|
||||
time.Sleep(time.Millisecond) // ensure clock can move
|
||||
if err := store.Update(edited); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := store.Get(created.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !got.UpdatedAt.After(got.SyncedAt) {
|
||||
t.Fatalf("edit must bump UpdatedAt past SyncedAt: %v vs %v", got.UpdatedAt, got.SyncedAt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONStoreMigratesLegacyTasksJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
projectDir := filepath.Join(dir, "projects", "inbox")
|
||||
|
||||
Reference in New Issue
Block a user